QGIS API Documentation 3.32.0-Lima (311a8cb8a6)
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"
40#include "qgsgeometry.h"
42#include "qgslogger.h"
43#include "qgsmaplayerlegend.h"
44#include "qgsmessagelog.h"
45#include "qgsogcutils.h"
46#include "qgspainting.h"
47#include "qgspointxy.h"
48#include "qgsproject.h"
49#include "qgsproviderregistry.h"
50#include "qgsrectangle.h"
51#include "qgsrelationmanager.h"
52#include "qgsweakrelation.h"
53#include "qgsrendercontext.h"
65#include "qgspoint.h"
66#include "qgsrenderer.h"
67#include "qgssymbollayer.h"
68#include "qgsdiagramrenderer.h"
69#include "qgspallabeling.h"
73#include "qgsfeedback.h"
74#include "qgsxmlutils.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#include "qgsthreadingutils.h"
87
88#include <QDir>
89#include <QFile>
90#include <QImage>
91#include <QPainter>
92#include <QPainterPath>
93#include <QPolygonF>
94#include <QProgressDialog>
95#include <QString>
96#include <QDomNode>
97#include <QVector>
98#include <QStringBuilder>
99#include <QUrl>
100#include <QUndoCommand>
101#include <QUrlQuery>
102#include <QUuid>
103#include <QRegularExpression>
104#include <QTimer>
105
106#include <limits>
107#include <optional>
108
110#include "qgssettingsentryimpl.h"
111#include "qgssettingstree.h"
112
118
119
120#ifdef TESTPROVIDERLIB
121#include <dlfcn.h>
122#endif
123
124typedef bool saveStyle_t(
125 const QString &uri,
126 const QString &qmlStyle,
127 const QString &sldStyle,
128 const QString &styleName,
129 const QString &styleDescription,
130 const QString &uiFileContent,
131 bool useAsDefault,
132 QString &errCause
133);
134
135typedef QString loadStyle_t(
136 const QString &uri,
137 QString &errCause
138);
139
140typedef int listStyles_t(
141 const QString &uri,
142 QStringList &ids,
143 QStringList &names,
144 QStringList &descriptions,
145 QString &errCause
146);
147
148typedef QString getStyleById_t(
149 const QString &uri,
150 QString styleID,
151 QString &errCause
152);
153
154typedef bool deleteStyleById_t(
155 const QString &uri,
156 QString styleID,
157 QString &errCause
158);
159
160
161QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
162 const QString &baseName,
163 const QString &providerKey,
164 const QgsVectorLayer::LayerOptions &options )
165 : QgsMapLayer( Qgis::LayerType::Vector, baseName, vectorLayerPath )
166 , mTemporalProperties( new QgsVectorLayerTemporalProperties( this ) )
167 , mElevationProperties( new QgsVectorLayerElevationProperties( this ) )
168 , mAuxiliaryLayer( nullptr )
169 , mAuxiliaryLayerKey( QString() )
170 , mReadExtentFromXml( options.readExtentFromXml )
171 , mRefreshRendererTimer( new QTimer( this ) )
172{
174 mLoadAllStoredStyle = options.loadAllStoredStyles;
175
176 if ( options.fallbackCrs.isValid() )
177 setCrs( options.fallbackCrs, false );
178 mWkbType = options.fallbackWkbType;
179
180 setProviderType( providerKey );
181
182 mGeometryOptions = std::make_unique<QgsGeometryOptions>();
183 mActions = new QgsActionManager( this );
184 mConditionalStyles = new QgsConditionalLayerStyles( this );
185 mStoredExpressionManager = new QgsStoredExpressionManager();
186 mStoredExpressionManager->setParent( this );
187
188 mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
189 mJoinBuffer->setParent( this );
190 connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
191
192 mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
193 // if we're given a provider type, try to create and bind one to this layer
194 if ( !vectorLayerPath.isEmpty() && !mProviderKey.isEmpty() )
195 {
196 QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
197 QgsDataProvider::ReadFlags providerFlags = QgsDataProvider::ReadFlags();
198 if ( options.loadDefaultStyle )
199 {
201 }
202 if ( options.forceReadOnly )
203 {
204 providerFlags |= QgsDataProvider::ForceReadOnly;
205 mDataSourceReadOnly = true;
206 }
207 setDataSource( vectorLayerPath, baseName, providerKey, providerOptions, providerFlags );
208 }
209
210 for ( const QgsField &field : std::as_const( mFields ) )
211 {
212 if ( !mAttributeAliasMap.contains( field.name() ) )
213 mAttributeAliasMap.insert( field.name(), QString() );
214 }
215
216 if ( isValid() )
217 {
218 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
219 if ( !mTemporalProperties->isActive() )
220 {
221 // didn't populate temporal properties from provider metadata, so at least try to setup some initially nice
222 // selections
223 mTemporalProperties->guessDefaultsFromFields( mFields );
224 }
225
226 mElevationProperties->setDefaultsFromLayer( this );
227 }
228
229 connect( this, &QgsVectorLayer::selectionChanged, this, [ = ] { triggerRepaint(); } );
230 connect( QgsProject::instance()->relationManager(), &QgsRelationManager::relationsLoaded, this, &QgsVectorLayer::onRelationsLoaded );
231
235
236 // Default simplify drawing settings
237 QgsSettings settings;
238 mSimplifyMethod.setSimplifyHints( QgsVectorLayer::settingsSimplifyDrawingHints->valueWithDefaultOverride( mSimplifyMethod.simplifyHints() ) );
239 mSimplifyMethod.setSimplifyAlgorithm( QgsVectorLayer::settingsSimplifyAlgorithm->valueWithDefaultOverride( mSimplifyMethod.simplifyAlgorithm() ) );
240 mSimplifyMethod.setThreshold( QgsVectorLayer::settingsSimplifyDrawingTol->valueWithDefaultOverride( mSimplifyMethod.threshold() ) );
241 mSimplifyMethod.setForceLocalOptimization( QgsVectorLayer::settingsSimplifyLocal->valueWithDefaultOverride( mSimplifyMethod.forceLocalOptimization() ) );
242 mSimplifyMethod.setMaximumScale( QgsVectorLayer::settingsSimplifyMaxScale->valueWithDefaultOverride( mSimplifyMethod.maximumScale() ) );
243
244 connect( mRefreshRendererTimer, &QTimer::timeout, this, [ = ] { triggerRepaint( true ); } );
245}
246
248{
249 emit willBeDeleted();
250
251 setValid( false );
252
253 delete mDataProvider;
254 delete mEditBuffer;
255 delete mJoinBuffer;
256 delete mExpressionFieldBuffer;
257 delete mLabeling;
258 delete mDiagramLayerSettings;
259 delete mDiagramRenderer;
260
261 delete mActions;
262
263 delete mRenderer;
264 delete mConditionalStyles;
265 delete mStoredExpressionManager;
266
267 if ( mFeatureCounter )
268 mFeatureCounter->cancel();
269
270 qDeleteAll( mRendererGenerators );
271}
272
274{
276
278 // We get the data source string from the provider when
279 // possible because some providers may have changed it
280 // directly (memory provider does that).
281 QString dataSource;
282 if ( mDataProvider )
283 {
284 dataSource = mDataProvider->dataSourceUri();
285 options.transformContext = mDataProvider->transformContext();
286 }
287 else
288 {
289 dataSource = source();
290 }
291 options.forceReadOnly = mDataSourceReadOnly;
292 QgsVectorLayer *layer = new QgsVectorLayer( dataSource, name(), mProviderKey, options );
293 if ( mDataProvider && layer->dataProvider() )
294 {
295 layer->dataProvider()->handlePostCloneOperations( mDataProvider );
296 }
297 QgsMapLayer::clone( layer );
298
299 QList<QgsVectorLayerJoinInfo> joins = vectorJoins();
300 const auto constJoins = joins;
301 for ( const QgsVectorLayerJoinInfo &join : constJoins )
302 {
303 // do not copy join information for auxiliary layer
304 if ( !auxiliaryLayer()
305 || ( auxiliaryLayer() && auxiliaryLayer()->id() != join.joinLayerId() ) )
306 layer->addJoin( join );
307 }
308
309 if ( mDataProvider )
310 layer->setProviderEncoding( mDataProvider->encoding() );
314 layer->setReadOnly( isReadOnly() );
319
320 const auto constActions = actions()->actions();
321 for ( const QgsAction &action : constActions )
322 {
323 layer->actions()->addAction( action );
324 }
325
326 if ( auto *lRenderer = renderer() )
327 {
328 layer->setRenderer( lRenderer->clone() );
329 }
330
331 if ( auto *lLabeling = labeling() )
332 {
333 layer->setLabeling( lLabeling->clone() );
334 }
336
338
339 if ( auto *lDiagramRenderer = diagramRenderer() )
340 {
341 layer->setDiagramRenderer( lDiagramRenderer->clone() );
342 }
343
344 if ( auto *lDiagramLayerSettings = diagramLayerSettings() )
345 {
346 layer->setDiagramLayerSettings( *lDiagramLayerSettings );
347 }
348
349 for ( int i = 0; i < fields().count(); i++ )
350 {
351 layer->setFieldAlias( i, attributeAlias( i ) );
353 layer->setEditorWidgetSetup( i, editorWidgetSetup( i ) );
356
357 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> constraints = fieldConstraintsAndStrength( i );
358 auto constraintIt = constraints.constBegin();
359 for ( ; constraintIt != constraints.constEnd(); ++ constraintIt )
360 {
361 layer->setFieldConstraint( i, constraintIt.key(), constraintIt.value() );
362 }
363
364 if ( fields().fieldOrigin( i ) == QgsFields::OriginExpression )
365 {
366 layer->addExpressionField( expressionField( i ), fields().at( i ) );
367 }
368 }
369
371
372 if ( auto *lAuxiliaryLayer = auxiliaryLayer() )
373 layer->setAuxiliaryLayer( lAuxiliaryLayer->clone( layer ) );
374
375 layer->mElevationProperties = mElevationProperties->clone();
376 layer->mElevationProperties->setParent( layer );
377
378 return layer;
379}
380
382{
384
385 if ( mDataProvider )
386 {
387 return mDataProvider->storageType();
388 }
389 return QString();
390}
391
392
394{
396
397 if ( mDataProvider )
398 {
399 return mDataProvider->capabilitiesString();
400 }
401 return QString();
402}
403
405{
407
408 return mDataProvider && mDataProvider->isSqlQuery();
409}
410
411Qgis::VectorLayerTypeFlags QgsVectorLayer::vectorLayerTypeFlags() const
412{
414
415 return mDataProvider ? mDataProvider->vectorLayerTypeFlags() : Qgis::VectorLayerTypeFlags();
416}
417
419{
421
422 if ( mDataProvider )
423 {
424 return mDataProvider->dataComment();
425 }
426 return QString();
427}
428
430{
432
433 return crs();
434}
435
437{
439
440 return name();
441}
442
444{
445 // non fatal for now -- the QgsVirtualLayerTask class is not thread safe and calls this
447
448 if ( mDataProvider )
449 {
450 mDataProvider->reloadData();
451 updateFields();
452 }
453}
454
456{
457 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
459
460 return new QgsVectorLayerRenderer( this, rendererContext );
461}
462
463
464void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter &p, Qgis::VertexMarkerType type, int m )
465{
466 switch ( type )
467 {
469 p.setPen( QColor( 50, 100, 120, 200 ) );
470 p.setBrush( QColor( 200, 200, 210, 120 ) );
471 p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
472 break;
473
475 p.setPen( QColor( 255, 0, 0 ) );
476 p.drawLine( x - m, y + m, x + m, y - m );
477 p.drawLine( x - m, y - m, x + m, y + m );
478 break;
479
481 break;
482 }
483}
484
486{
488
489 mSelectedFeatureIds.insert( fid );
490 mPreviousSelectedFeatureIds.clear();
491
492 emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
493}
494
495void QgsVectorLayer::select( const QgsFeatureIds &featureIds )
496{
498
499 mSelectedFeatureIds.unite( featureIds );
500 mPreviousSelectedFeatureIds.clear();
501
502 emit selectionChanged( featureIds, QgsFeatureIds(), false );
503}
504
506{
508
509 mSelectedFeatureIds.remove( fid );
510 mPreviousSelectedFeatureIds.clear();
511
512 emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
513}
514
516{
518
519 mSelectedFeatureIds.subtract( featureIds );
520 mPreviousSelectedFeatureIds.clear();
521
522 emit selectionChanged( QgsFeatureIds(), featureIds, false );
523}
524
526{
528
529 // normalize the rectangle
530 rect.normalize();
531
532 QgsFeatureIds newSelection;
533
535 .setFilterRect( rect )
537 .setNoAttributes() );
538
539 QgsFeature feat;
540 while ( features.nextFeature( feat ) )
541 {
542 newSelection << feat.id();
543 }
544 features.close();
545
546 selectByIds( newSelection, behavior );
547}
548
549void QgsVectorLayer::selectByExpression( const QString &expression, Qgis::SelectBehavior behavior, QgsExpressionContext *context )
550{
552
553 QgsFeatureIds newSelection;
554
555 std::optional< QgsExpressionContext > defaultContext;
556 if ( !context )
557 {
558 defaultContext.emplace( QgsExpressionContextUtils::globalProjectLayerScopes( this ) );
559 context = &defaultContext.value();
560 }
561
563 {
565 .setExpressionContext( *context )
568
569 QgsFeatureIterator features = getFeatures( request );
570
571 if ( behavior == Qgis::SelectBehavior::AddToSelection )
572 {
573 newSelection = selectedFeatureIds();
574 }
575 QgsFeature feat;
576 while ( features.nextFeature( feat ) )
577 {
578 newSelection << feat.id();
579 }
580 features.close();
581 }
583 {
584 QgsExpression exp( expression );
585 exp.prepare( context );
586
587 QgsFeatureIds oldSelection = selectedFeatureIds();
588 QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( oldSelection );
589
590 //refine request
591 if ( !exp.needsGeometry() )
594
595 QgsFeatureIterator features = getFeatures( request );
596 QgsFeature feat;
597 while ( features.nextFeature( feat ) )
598 {
599 context->setFeature( feat );
600 bool matches = exp.evaluate( context ).toBool();
601
602 if ( matches && behavior == Qgis::SelectBehavior::IntersectSelection )
603 {
604 newSelection << feat.id();
605 }
606 else if ( !matches && behavior == Qgis::SelectBehavior::RemoveFromSelection )
607 {
608 newSelection << feat.id();
609 }
610 }
611 }
612
613 selectByIds( newSelection );
614}
615
617{
619
620 QgsFeatureIds newSelection;
621
622 switch ( behavior )
623 {
625 newSelection = ids;
626 break;
627
629 newSelection = mSelectedFeatureIds + ids;
630 break;
631
633 newSelection = mSelectedFeatureIds - ids;
634 break;
635
637 newSelection = mSelectedFeatureIds.intersect( ids );
638 break;
639 }
640
641 QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - newSelection;
642 mSelectedFeatureIds = newSelection;
643 mPreviousSelectedFeatureIds.clear();
644
645 emit selectionChanged( newSelection, deselectedFeatures, true );
646}
647
648void QgsVectorLayer::modifySelection( const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds )
649{
651
652 QgsFeatureIds intersectingIds = selectIds & deselectIds;
653 if ( !intersectingIds.isEmpty() )
654 {
655 QgsDebugMsgLevel( QStringLiteral( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." ), 3 );
656 }
657
658 mSelectedFeatureIds -= deselectIds;
659 mSelectedFeatureIds += selectIds;
660 mPreviousSelectedFeatureIds.clear();
661
662 emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
663}
664
666{
668
670 ids.subtract( mSelectedFeatureIds );
671 selectByIds( ids );
672}
673
675{
677
679}
680
682{
684
685 // normalize the rectangle
686 rect.normalize();
687
689 .setFilterRect( rect )
691 .setNoAttributes() );
692
693 QgsFeatureIds selectIds;
694 QgsFeatureIds deselectIds;
695
696 QgsFeature fet;
697 while ( fit.nextFeature( fet ) )
698 {
699 if ( mSelectedFeatureIds.contains( fet.id() ) )
700 {
701 deselectIds << fet.id();
702 }
703 else
704 {
705 selectIds << fet.id();
706 }
707 }
708
709 modifySelection( selectIds, deselectIds );
710}
711
713{
715
716 if ( mSelectedFeatureIds.isEmpty() )
717 return;
718
719 const QgsFeatureIds previous = mSelectedFeatureIds;
721 mPreviousSelectedFeatureIds = previous;
722}
723
725{
727
728 if ( mPreviousSelectedFeatureIds.isEmpty() || !mSelectedFeatureIds.empty() )
729 return;
730
731 selectByIds( mPreviousSelectedFeatureIds );
732}
733
735{
736 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
738
739 return mDataProvider;
740}
741
743{
744 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
746
747 return mDataProvider;
748}
749
751{
753
754 return mTemporalProperties;
755}
756
758{
760
761 return mElevationProperties;
762}
763
765{
767
768 QgsProfileRequest modifiedRequest( request );
769 modifiedRequest.expressionContext().appendScope( createExpressionContextScope() );
770 return new QgsVectorLayerProfileGenerator( this, modifiedRequest );
771}
772
773void QgsVectorLayer::setProviderEncoding( const QString &encoding )
774{
776
777 if ( isValid() && mDataProvider && mDataProvider->encoding() != encoding )
778 {
779 mDataProvider->setEncoding( encoding );
780 updateFields();
781 }
782}
783
785{
787
788 delete mDiagramRenderer;
789 mDiagramRenderer = r;
790 emit rendererChanged();
791 emit styleChanged();
792}
793
795{
796 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
798
799 return QgsWkbTypes::geometryType( mWkbType );
800}
801
803{
805
806 return mWkbType;
807}
808
810{
812
813 if ( !isValid() || !isSpatial() || mSelectedFeatureIds.isEmpty() || !mDataProvider ) //no selected features
814 {
815 return QgsRectangle( 0, 0, 0, 0 );
816 }
817
818 QgsRectangle r, retval;
819 retval.setMinimal();
820
821 QgsFeature fet;
822 if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
823 {
825 .setFilterFids( mSelectedFeatureIds )
826 .setNoAttributes() );
827
828 while ( fit.nextFeature( fet ) )
829 {
830 if ( !fet.hasGeometry() )
831 continue;
832 r = fet.geometry().boundingBox();
833 retval.combineExtentWith( r );
834 }
835 }
836 else
837 {
839 .setNoAttributes() );
840
841 while ( fit.nextFeature( fet ) )
842 {
843 if ( mSelectedFeatureIds.contains( fet.id() ) )
844 {
845 if ( fet.hasGeometry() )
846 {
847 r = fet.geometry().boundingBox();
848 retval.combineExtentWith( r );
849 }
850 }
851 }
852 }
853
854 if ( retval.width() == 0.0 || retval.height() == 0.0 )
855 {
856 // If all of the features are at the one point, buffer the
857 // rectangle a bit. If they are all at zero, do something a bit
858 // more crude.
859
860 if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
861 retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
862 {
863 retval.set( -1.0, -1.0, 1.0, 1.0 );
864 }
865 }
866
867 return retval;
868}
869
871{
872 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
874
875 return mLabelsEnabled && static_cast< bool >( mLabeling );
876}
877
879{
881
882 mLabelsEnabled = enabled;
883}
884
886{
887 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
889
890 if ( !mDiagramRenderer || !mDiagramLayerSettings )
891 return false;
892
893 QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
894 if ( !settingList.isEmpty() )
895 {
896 return settingList.at( 0 ).enabled;
897 }
898 return false;
899}
900
901long long QgsVectorLayer::featureCount( const QString &legendKey ) const
902{
904
905 if ( !mSymbolFeatureCounted )
906 return -1;
907
908 return mSymbolFeatureCountMap.value( legendKey, -1 );
909}
910
911QgsFeatureIds QgsVectorLayer::symbolFeatureIds( const QString &legendKey ) const
912{
914
915 if ( !mSymbolFeatureCounted )
916 return QgsFeatureIds();
917
918 return mSymbolFeatureIdMap.value( legendKey, QgsFeatureIds() );
919}
921{
923
924 if ( ( mSymbolFeatureCounted || mFeatureCounter ) && !( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
925 return mFeatureCounter;
926
927 mSymbolFeatureCountMap.clear();
928 mSymbolFeatureIdMap.clear();
929
930 if ( !isValid() )
931 {
932 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer" ), 3 );
933 return mFeatureCounter;
934 }
935 if ( !mDataProvider )
936 {
937 QgsDebugMsgLevel( QStringLiteral( "invoked with null mDataProvider" ), 3 );
938 return mFeatureCounter;
939 }
940 if ( !mRenderer )
941 {
942 QgsDebugMsgLevel( QStringLiteral( "invoked with null mRenderer" ), 3 );
943 return mFeatureCounter;
944 }
945
946 if ( !mFeatureCounter || ( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
947 {
948 mFeatureCounter = new QgsVectorLayerFeatureCounter( this, QgsExpressionContext(), storeSymbolFids );
949 connect( mFeatureCounter, &QgsTask::taskCompleted, this, &QgsVectorLayer::onFeatureCounterCompleted, Qt::UniqueConnection );
950 connect( mFeatureCounter, &QgsTask::taskTerminated, this, &QgsVectorLayer::onFeatureCounterTerminated, Qt::UniqueConnection );
951 QgsApplication::taskManager()->addTask( mFeatureCounter );
952 }
953
954 return mFeatureCounter;
955}
956
958{
960
961 // do not update extent by default when trust project option is activated
962 if ( force || !mReadExtentFromXml || ( mReadExtentFromXml && mXmlExtent.isNull() ) )
963 mValidExtent = false;
964}
965
967{
969
971 mValidExtent = true;
972}
973
974void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature )
975{
977
978 if ( !mDefaultValueOnUpdateFields.isEmpty() )
979 {
980 if ( !feature.isValid() )
981 feature = getFeature( fid );
982
983 int size = mFields.size();
984 for ( int idx : std::as_const( mDefaultValueOnUpdateFields ) )
985 {
986 if ( idx < 0 || idx >= size )
987 continue;
988
989 feature.setAttribute( idx, defaultValue( idx, feature ) );
990 updateFeature( feature, true );
991 }
992 }
993}
994
996{
998
999 QgsRectangle rect;
1000 rect.setMinimal();
1001
1002 if ( !isSpatial() )
1003 return rect;
1004
1005 if ( !mValidExtent && mLazyExtent && mReadExtentFromXml && !mXmlExtent.isNull() )
1006 {
1007 updateExtent( mXmlExtent );
1008 mValidExtent = true;
1009 mLazyExtent = false;
1010 }
1011
1012 if ( !mValidExtent && mLazyExtent && mDataProvider && mDataProvider->isValid() )
1013 {
1014 // store the extent
1015 updateExtent( mDataProvider->extent() );
1016 mValidExtent = true;
1017 mLazyExtent = false;
1018
1019 // show the extent
1020 QgsDebugMsgLevel( QStringLiteral( "Extent of layer: %1" ).arg( mExtent.toString() ), 3 );
1021 }
1022
1023 if ( mValidExtent )
1024 return QgsMapLayer::extent();
1025
1026 if ( !isValid() || !mDataProvider )
1027 {
1028 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
1029 return rect;
1030 }
1031
1032 if ( !mEditBuffer ||
1033 ( !mDataProvider->transaction() && ( mEditBuffer->deletedFeatureIds().isEmpty() && mEditBuffer->changedGeometries().isEmpty() ) ) ||
1035 {
1036 mDataProvider->updateExtents();
1037
1038 // get the extent of the layer from the provider
1039 // but only when there are some features already
1040 if ( mDataProvider->featureCount() != 0 )
1041 {
1042 const QgsRectangle r = mDataProvider->extent();
1043 rect.combineExtentWith( r );
1044 }
1045
1046 if ( mEditBuffer && !mDataProvider->transaction() )
1047 {
1048 const auto addedFeatures = mEditBuffer->addedFeatures();
1049 for ( QgsFeatureMap::const_iterator it = addedFeatures.constBegin(); it != addedFeatures.constEnd(); ++it )
1050 {
1051 if ( it->hasGeometry() )
1052 {
1053 const QgsRectangle r = it->geometry().boundingBox();
1054 rect.combineExtentWith( r );
1055 }
1056 }
1057 }
1058 }
1059 else
1060 {
1062 .setNoAttributes() );
1063
1064 QgsFeature fet;
1065 while ( fit.nextFeature( fet ) )
1066 {
1067 if ( fet.hasGeometry() && fet.geometry().type() != Qgis::GeometryType::Unknown )
1068 {
1069 const QgsRectangle bb = fet.geometry().boundingBox();
1070 rect.combineExtentWith( bb );
1071 }
1072 }
1073 }
1074
1075 if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
1076 {
1077 // special case when there are no features in provider nor any added
1078 rect = QgsRectangle(); // use rectangle with zero coordinates
1079 }
1080
1081 updateExtent( rect );
1082 mValidExtent = true;
1083
1084 // Send this (hopefully) up the chain to the map canvas
1085 emit recalculateExtents();
1086
1087 return rect;
1088}
1089
1091{
1093
1094 return extent();
1095}
1096
1098{
1100
1101 if ( !isValid() || !mDataProvider )
1102 {
1103 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
1104 return customProperty( QStringLiteral( "storedSubsetString" ) ).toString();
1105 }
1106 return mDataProvider->subsetString();
1107}
1108
1109bool QgsVectorLayer::setSubsetString( const QString &subset )
1110{
1112
1113 if ( !isValid() || !mDataProvider )
1114 {
1115 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider or while editing" ), 3 );
1116 setCustomProperty( QStringLiteral( "storedSubsetString" ), subset );
1117 return false;
1118 }
1119 else if ( mEditBuffer )
1120 {
1121 QgsDebugMsgLevel( QStringLiteral( "invoked while editing" ), 3 );
1122 return false;
1123 }
1124
1125 if ( subset == mDataProvider->subsetString() )
1126 return true;
1127
1128 bool res = mDataProvider->setSubsetString( subset );
1129
1130 // get the updated data source string from the provider
1131 mDataSource = mDataProvider->dataSourceUri();
1132 updateExtents();
1133 updateFields();
1134
1135 if ( res )
1136 {
1137 emit subsetStringChanged();
1139 }
1140
1141 return res;
1142}
1143
1145{
1146 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
1148
1149 if ( isValid() && mDataProvider && !mEditBuffer && ( isSpatial() && geometryType() != Qgis::GeometryType::Point ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
1150 {
1151 double maximumSimplificationScale = mSimplifyMethod.maximumScale();
1152
1153 // check maximum scale at which generalisation should be carried out
1154 return !( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale );
1155 }
1156 return false;
1157}
1158
1160{
1162
1163 return mConditionalStyles;
1164}
1165
1167{
1168 // non fatal for now -- the aggregate expression functions are not thread safe and call this
1170
1171 if ( !isValid() || !mDataProvider )
1172 return QgsFeatureIterator();
1173
1174 return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
1175}
1176
1178{
1180
1181 QgsFeature feature;
1183 if ( feature.isValid() )
1184 return feature.geometry();
1185 else
1186 return QgsGeometry();
1187}
1188
1190{
1192
1193 if ( !isValid() || !mEditBuffer || !mDataProvider )
1194 return false;
1195
1196
1197 if ( mGeometryOptions->isActive() )
1198 {
1199 QgsGeometry geom = feature.geometry();
1200 mGeometryOptions->apply( geom );
1201 feature.setGeometry( geom );
1202 }
1203
1204 bool success = mEditBuffer->addFeature( feature );
1205
1206 if ( success )
1207 {
1208 updateExtents();
1209
1210 if ( mJoinBuffer->containsJoins() )
1211 success = mJoinBuffer->addFeature( feature );
1212 }
1213
1214 return success;
1215}
1216
1217bool QgsVectorLayer::updateFeature( QgsFeature &updatedFeature, bool skipDefaultValues )
1218{
1220
1221 if ( !mEditBuffer || !mDataProvider )
1222 {
1223 return false;
1224 }
1225
1226 QgsFeature currentFeature = getFeature( updatedFeature.id() );
1227 if ( currentFeature.isValid() )
1228 {
1229 bool hasChanged = false;
1230 bool hasError = false;
1231
1232 if ( ( updatedFeature.hasGeometry() || currentFeature.hasGeometry() ) && !updatedFeature.geometry().equals( currentFeature.geometry() ) )
1233 {
1234 QgsGeometry geometry = updatedFeature.geometry();
1235 if ( changeGeometry( updatedFeature.id(), geometry, true ) )
1236 {
1237 hasChanged = true;
1238 updatedFeature.setGeometry( geometry );
1239 }
1240 else
1241 {
1242 QgsDebugMsgLevel( QStringLiteral( "geometry of feature %1 could not be changed." ).arg( updatedFeature.id() ), 3 );
1243 }
1244 }
1245
1246 QgsAttributes fa = updatedFeature.attributes();
1247 QgsAttributes ca = currentFeature.attributes();
1248
1249 for ( int attr = 0; attr < fa.count(); ++attr )
1250 {
1251 if ( !qgsVariantEqual( fa.at( attr ), ca.at( attr ) ) )
1252 {
1253 if ( changeAttributeValue( updatedFeature.id(), attr, fa.at( attr ), ca.at( attr ), true ) )
1254 {
1255 hasChanged = true;
1256 }
1257 else
1258 {
1259 QgsDebugMsgLevel( QStringLiteral( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( updatedFeature.id() ), 3 );
1260 hasError = true;
1261 }
1262 }
1263 }
1264 if ( hasChanged && !mDefaultValueOnUpdateFields.isEmpty() && !skipDefaultValues )
1265 updateDefaultValues( updatedFeature.id(), updatedFeature );
1266
1267 return !hasError;
1268 }
1269 else
1270 {
1271 QgsDebugMsgLevel( QStringLiteral( "feature %1 could not be retrieved" ).arg( updatedFeature.id() ), 3 );
1272 return false;
1273 }
1274}
1275
1276
1277bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
1278{
1280
1281 if ( !isValid() || !mEditBuffer || !mDataProvider )
1282 return false;
1283
1284 QgsVectorLayerEditUtils utils( this );
1285 bool result = utils.insertVertex( x, y, atFeatureId, beforeVertex );
1286 if ( result )
1287 updateExtents();
1288 return result;
1289}
1290
1291
1292bool QgsVectorLayer::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
1293{
1295
1296 if ( !isValid() || !mEditBuffer || !mDataProvider )
1297 return false;
1298
1299 QgsVectorLayerEditUtils utils( this );
1300 bool result = utils.insertVertex( point, atFeatureId, beforeVertex );
1301 if ( result )
1302 updateExtents();
1303 return result;
1304}
1305
1306
1307bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
1308{
1310
1311 if ( !isValid() || !mEditBuffer || !mDataProvider )
1312 return false;
1313
1314 QgsVectorLayerEditUtils utils( this );
1315 bool result = utils.moveVertex( x, y, atFeatureId, atVertex );
1316
1317 if ( result )
1318 updateExtents();
1319 return result;
1320}
1321
1322bool QgsVectorLayer::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
1323{
1325
1326 if ( !isValid() || !mEditBuffer || !mDataProvider )
1327 return false;
1328
1329 QgsVectorLayerEditUtils utils( this );
1330 bool result = utils.moveVertex( p, atFeatureId, atVertex );
1331
1332 if ( result )
1333 updateExtents();
1334 return result;
1335}
1336
1338{
1340
1341 if ( !isValid() || !mEditBuffer || !mDataProvider )
1343
1344 QgsVectorLayerEditUtils utils( this );
1345 Qgis::VectorEditResult result = utils.deleteVertex( featureId, vertex );
1346
1347 if ( result == Qgis::VectorEditResult::Success )
1348 updateExtents();
1349 return result;
1350}
1351
1352
1354{
1356
1357 if ( !isValid() || !mDataProvider || !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
1358 {
1359 return false;
1360 }
1361
1362 if ( !isEditable() )
1363 {
1364 return false;
1365 }
1366
1367 int deleted = 0;
1368 int count = mSelectedFeatureIds.size();
1369 // Make a copy since deleteFeature modifies mSelectedFeatureIds
1370 QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
1371 for ( QgsFeatureId fid : std::as_const( selectedFeatures ) )
1372 {
1373 deleted += deleteFeature( fid, context ); // removes from selection
1374 }
1375
1377 updateExtents();
1378
1379 if ( deletedCount )
1380 {
1381 *deletedCount = deleted;
1382 }
1383
1384 return deleted == count;
1385}
1386
1387static const QgsPointSequence vectorPointXY2pointSequence( const QVector<QgsPointXY> &points )
1388{
1389 QgsPointSequence pts;
1390 pts.reserve( points.size() );
1391 QVector<QgsPointXY>::const_iterator it = points.constBegin();
1392 while ( it != points.constEnd() )
1393 {
1394 pts.append( QgsPoint( *it ) );
1395 ++it;
1396 }
1397 return pts;
1398}
1399Qgis::GeometryOperationResult QgsVectorLayer::addRing( const QVector<QgsPointXY> &ring, QgsFeatureId *featureId )
1400{
1402
1403 return addRing( vectorPointXY2pointSequence( ring ), featureId );
1404}
1405
1407{
1409
1410 if ( !isValid() || !mEditBuffer || !mDataProvider )
1412
1413 QgsVectorLayerEditUtils utils( this );
1415
1416 //first try with selected features
1417 if ( !mSelectedFeatureIds.isEmpty() )
1418 {
1419 result = utils.addRing( ring, mSelectedFeatureIds, featureId );
1420 }
1421
1423 {
1424 //try with all intersecting features
1425 result = utils.addRing( ring, QgsFeatureIds(), featureId );
1426 }
1427
1428 return result;
1429}
1430
1432{
1434
1435 if ( !isValid() || !mEditBuffer || !mDataProvider )
1436 {
1437 delete ring;
1439 }
1440
1441 if ( !ring )
1442 {
1444 }
1445
1446 if ( !ring->isClosed() )
1447 {
1448 delete ring;
1450 }
1451
1452 QgsVectorLayerEditUtils utils( this );
1454
1455 //first try with selected features
1456 if ( !mSelectedFeatureIds.isEmpty() )
1457 {
1458 result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), mSelectedFeatureIds, featureId );
1459 }
1460
1462 {
1463 //try with all intersecting features
1464 result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), QgsFeatureIds(), featureId );
1465 }
1466
1467 delete ring;
1468 return result;
1469}
1470
1472{
1474
1475 QgsPointSequence pts;
1476 pts.reserve( points.size() );
1477 for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd() ; ++it )
1478 {
1479 pts.append( QgsPoint( *it ) );
1480 }
1481 return addPart( pts );
1482}
1483
1484#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1485Qgis::GeometryOperationResult QgsVectorLayer::addPart( const QVector<QgsPointXY> &points )
1486{
1488
1489 return addPart( vectorPointXY2pointSequence( points ) );
1490}
1491#endif
1492
1494{
1496
1497 if ( !isValid() || !mEditBuffer || !mDataProvider )
1499
1500 //number of selected features must be 1
1501
1502 if ( mSelectedFeatureIds.empty() )
1503 {
1504 QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
1506 }
1507 else if ( mSelectedFeatureIds.size() > 1 )
1508 {
1509 QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
1511 }
1512
1513 QgsVectorLayerEditUtils utils( this );
1514 Qgis::GeometryOperationResult result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1515
1517 updateExtents();
1518 return result;
1519}
1520
1522{
1524
1525 if ( !isValid() || !mEditBuffer || !mDataProvider )
1527
1528 //number of selected features must be 1
1529
1530 if ( mSelectedFeatureIds.empty() )
1531 {
1532 QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
1534 }
1535 else if ( mSelectedFeatureIds.size() > 1 )
1536 {
1537 QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
1539 }
1540
1541 QgsVectorLayerEditUtils utils( this );
1542 Qgis::GeometryOperationResult result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
1543
1545 updateExtents();
1546 return result;
1547}
1548
1549// TODO QGIS 4.0 -- this should return Qgis::GeometryOperationResult, not int
1550int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1551{
1553
1554 if ( !isValid() || !mEditBuffer || !mDataProvider )
1555 return static_cast< int >( Qgis::GeometryOperationResult::LayerNotEditable );
1556
1557 QgsVectorLayerEditUtils utils( this );
1558 int result = utils.translateFeature( featureId, dx, dy );
1559
1560 if ( result == static_cast< int >( Qgis::GeometryOperationResult::Success ) )
1561 updateExtents();
1562 return result;
1563}
1564
1565Qgis::GeometryOperationResult QgsVectorLayer::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1566{
1568
1569 return splitParts( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1570}
1571
1573{
1575
1576 if ( !isValid() || !mEditBuffer || !mDataProvider )
1578
1579 QgsVectorLayerEditUtils utils( this );
1580 return utils.splitParts( splitLine, topologicalEditing );
1581}
1582
1583Qgis::GeometryOperationResult QgsVectorLayer::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1584{
1586
1587 return splitFeatures( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1588}
1589
1591{
1593
1594 QgsLineString splitLineString( splitLine );
1595 QgsPointSequence topologyTestPoints;
1596 bool preserveCircular = false;
1597 return splitFeatures( &splitLineString, topologyTestPoints, preserveCircular, topologicalEditing );
1598}
1599
1600Qgis::GeometryOperationResult QgsVectorLayer::splitFeatures( const QgsCurve *curve, QgsPointSequence &topologyTestPoints, bool preserveCircular, bool topologicalEditing )
1601{
1603
1604 if ( !isValid() || !mEditBuffer || !mDataProvider )
1606
1607 QgsVectorLayerEditUtils utils( this );
1608 return utils.splitFeatures( curve, topologyTestPoints, preserveCircular, topologicalEditing );
1609}
1610
1612{
1614
1615 if ( !isValid() || !mEditBuffer || !mDataProvider )
1616 return -1;
1617
1618 QgsVectorLayerEditUtils utils( this );
1619 return utils.addTopologicalPoints( geom );
1620}
1621
1623{
1625
1626 return addTopologicalPoints( QgsPoint( p ) );
1627}
1628
1630{
1632
1633 if ( !isValid() || !mEditBuffer || !mDataProvider )
1634 return -1;
1635
1636 QgsVectorLayerEditUtils utils( this );
1637 return utils.addTopologicalPoints( p );
1638}
1639
1641{
1643
1644 if ( !mValid || !mEditBuffer || !mDataProvider )
1645 return -1;
1646
1647 QgsVectorLayerEditUtils utils( this );
1648 return utils.addTopologicalPoints( ps );
1649}
1650
1652{
1654
1655 if ( mLabeling == labeling )
1656 return;
1657
1658 delete mLabeling;
1659 mLabeling = labeling;
1660}
1661
1663{
1665
1666 if ( project() && project()->transactionMode() == Qgis::TransactionMode::BufferedGroups )
1667 return project()->startEditing( this );
1668
1669 if ( !isValid() || !mDataProvider )
1670 {
1671 return false;
1672 }
1673
1674 // allow editing if provider supports any of the capabilities
1675 if ( !supportsEditing() )
1676 {
1677 return false;
1678 }
1679
1680 if ( mEditBuffer )
1681 {
1682 // editing already underway
1683 return false;
1684 }
1685
1686 mDataProvider->enterUpdateMode();
1687
1688 emit beforeEditingStarted();
1689
1690 createEditBuffer();
1691
1692 updateFields();
1693
1694 emit editingStarted();
1695
1696 return true;
1697}
1698
1700{
1702
1703 if ( mDataProvider )
1704 mDataProvider->setTransformContext( transformContext );
1705}
1706
1708{
1710
1711 return mDataProvider ? mDataProvider->hasSpatialIndex() : QgsFeatureSource::SpatialIndexUnknown;
1712}
1713
1715{
1717
1718 if ( mRenderer )
1719 if ( !mRenderer->accept( visitor ) )
1720 return false;
1721
1722 if ( mLabeling )
1723 if ( !mLabeling->accept( visitor ) )
1724 return false;
1725
1726 return true;
1727}
1728
1729bool QgsVectorLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1730{
1732
1733 QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsVectorLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1734
1735 //process provider key
1736 QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1737
1738 if ( pkeyNode.isNull() )
1739 {
1740 mProviderKey.clear();
1741 }
1742 else
1743 {
1744 QDomElement pkeyElt = pkeyNode.toElement();
1745 mProviderKey = pkeyElt.text();
1746 }
1747
1748 // determine type of vector layer
1749 if ( !mProviderKey.isNull() )
1750 {
1751 // if the provider string isn't empty, then we successfully
1752 // got the stored provider
1753 }
1754 else if ( mDataSource.contains( QLatin1String( "dbname=" ) ) )
1755 {
1756 mProviderKey = QStringLiteral( "postgres" );
1757 }
1758 else
1759 {
1760 mProviderKey = QStringLiteral( "ogr" );
1761 }
1762
1763 const QDomElement elem = layer_node.toElement();
1765
1766 mDataSourceReadOnly = mReadFlags & QgsMapLayer::FlagForceReadOnly;
1767 QgsDataProvider::ReadFlags flags = providerReadFlags( layer_node, mReadFlags );
1768
1769 if ( ( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) || !setDataProvider( mProviderKey, options, flags ) )
1770 {
1772 {
1773 QgsDebugError( QStringLiteral( "Could not set data provider for layer %1" ).arg( publicSource() ) );
1774 }
1775
1776 // for invalid layer sources, we fallback to stored wkbType if available
1777 if ( elem.hasAttribute( QStringLiteral( "wkbType" ) ) )
1778 mWkbType = qgsEnumKeyToValue( elem.attribute( QStringLiteral( "wkbType" ) ), mWkbType );
1779 }
1780
1781 QDomElement pkeyElem = pkeyNode.toElement();
1782 if ( !pkeyElem.isNull() )
1783 {
1784 QString encodingString = pkeyElem.attribute( QStringLiteral( "encoding" ) );
1785 if ( mDataProvider && !encodingString.isEmpty() )
1786 {
1787 mDataProvider->setEncoding( encodingString );
1788 }
1789 }
1790
1791 // load vector joins - does not resolve references to layers yet
1792 mJoinBuffer->readXml( layer_node );
1793
1794 updateFields();
1795
1796 // If style doesn't include a legend, we'll need to make a default one later...
1797 mSetLegendFromStyle = false;
1798
1799 QString errorMsg;
1800 if ( !readSymbology( layer_node, errorMsg, context ) )
1801 {
1802 return false;
1803 }
1804
1805 readStyleManager( layer_node );
1806
1807 QDomNode depsNode = layer_node.namedItem( QStringLiteral( "dataDependencies" ) );
1808 QDomNodeList depsNodes = depsNode.childNodes();
1809 QSet<QgsMapLayerDependency> sources;
1810 for ( int i = 0; i < depsNodes.count(); i++ )
1811 {
1812 QString source = depsNodes.at( i ).toElement().attribute( QStringLiteral( "id" ) );
1813 sources << QgsMapLayerDependency( source );
1814 }
1815 setDependencies( sources );
1816
1817 if ( !mSetLegendFromStyle )
1819
1820 // read extent
1822 {
1823 mReadExtentFromXml = true;
1824 }
1825 if ( mReadExtentFromXml )
1826 {
1827 const QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
1828 if ( !extentNode.isNull() )
1829 {
1830 mXmlExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
1831 }
1832 }
1833
1834 // auxiliary layer
1835 const QDomNode asNode = layer_node.namedItem( QStringLiteral( "auxiliaryLayer" ) );
1836 const QDomElement asElem = asNode.toElement();
1837 if ( !asElem.isNull() )
1838 {
1839 mAuxiliaryLayerKey = asElem.attribute( QStringLiteral( "key" ) );
1840 }
1841
1842 // QGIS Server WMS Dimensions
1843 mServerProperties->readXml( layer_node );
1844
1845 return isValid(); // should be true if read successfully
1846
1847} // void QgsVectorLayer::readXml
1848
1849
1850void QgsVectorLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider,
1851 const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1852{
1854
1855 Qgis::GeometryType geomType = geometryType();
1856
1857 mDataSource = dataSource;
1858 setName( baseName );
1859 setDataProvider( provider, options, flags );
1860
1861 if ( !isValid() )
1862 {
1863 return;
1864 }
1865
1866 // Always set crs
1868
1869 bool loadDefaultStyleFlag = false;
1871 {
1872 loadDefaultStyleFlag = true;
1873 }
1874
1875 // reset style if loading default style, style is missing, or geometry type is has changed (and layer is valid)
1876 if ( !renderer() || !legend() || ( isValid() && geomType != geometryType() ) || loadDefaultStyleFlag )
1877 {
1878 std::unique_ptr< QgsScopedRuntimeProfile > profile;
1879 if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
1880 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Load layer style" ), QStringLiteral( "projectload" ) );
1881
1882 bool defaultLoadedFlag = false;
1883
1884 // defer style changed signal until we've set the renderer, labeling, everything.
1885 // we don't want multiple signals!
1886 ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
1887
1888 // need to check whether the default style included a legend, and if not, we need to make a default legend
1889 // later...
1890 mSetLegendFromStyle = false;
1891
1892 // first check if there is a default style / propertysheet defined
1893 // for this layer and if so apply it
1894 // this should take precedence over all
1895 if ( !defaultLoadedFlag && loadDefaultStyleFlag )
1896 {
1897 loadDefaultStyle( defaultLoadedFlag );
1898 }
1899
1900 if ( loadDefaultStyleFlag && !defaultLoadedFlag && isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1901 {
1902 // if we didn't load a default style for this layer, try to create a renderer directly from the data provider
1903 std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1904 if ( defaultRenderer )
1905 {
1906 defaultLoadedFlag = true;
1907 setRenderer( defaultRenderer.release() );
1908 }
1909 }
1910
1911 // if the default style failed to load or was disabled use some very basic defaults
1912 if ( !defaultLoadedFlag && isSpatial() )
1913 {
1914 // add single symbol renderer
1916 }
1917
1918 if ( !mSetLegendFromStyle )
1920
1921 if ( mDataProvider->capabilities() & QgsVectorDataProvider::CreateLabeling )
1922 {
1923 std::unique_ptr< QgsAbstractVectorLayerLabeling > defaultLabeling( mDataProvider->createLabeling() );
1924 if ( defaultLabeling )
1925 {
1926 setLabeling( defaultLabeling.release() );
1927 setLabelsEnabled( true );
1928 }
1929 }
1930
1931 styleChangedSignalBlocker.release();
1933 }
1934}
1935
1936QString QgsVectorLayer::loadDefaultStyle( bool &resultFlag )
1937{
1939
1940 // first try to load a user-defined default style - this should always take precedence
1941 QString styleXml = QgsMapLayer::loadDefaultStyle( resultFlag );
1942
1943 if ( resultFlag )
1944 {
1945 // Try to load all stored styles from DB
1946 if ( mLoadAllStoredStyle && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
1947 {
1948 QStringList ids, names, descriptions;
1949 QString errorMessage;
1950 // Get the number of styles related to current layer.
1951 const int relatedStylesCount { listStylesInDatabase( ids, names, descriptions, errorMessage ) };
1952 Q_ASSERT( ids.count() == names.count() );
1953 const QString currentStyleName { mStyleManager->currentStyle() };
1954 for ( int i = 0; i < relatedStylesCount; ++i )
1955 {
1956 if ( names.at( i ) == currentStyleName )
1957 {
1958 continue;
1959 }
1960 errorMessage.clear();
1961 const QString styleXml { getStyleFromDatabase( ids.at( i ), errorMessage ) };
1962 if ( ! styleXml.isEmpty() && errorMessage.isEmpty() )
1963 {
1964 mStyleManager->addStyle( names.at( i ), QgsMapLayerStyle( styleXml ) );
1965 }
1966 else
1967 {
1968 QgsDebugMsgLevel( QStringLiteral( "Error retrieving style %1 from DB: %2" ).arg( ids.at( i ), errorMessage ), 2 );
1969 }
1970 }
1971 }
1972 return styleXml ;
1973 }
1974
1975 if ( isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1976 {
1977 // otherwise try to create a renderer directly from the data provider
1978 std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1979 if ( defaultRenderer )
1980 {
1981 resultFlag = true;
1982 setRenderer( defaultRenderer.release() );
1983 return QString();
1984 }
1985 }
1986
1987 return QString();
1988}
1989
1990bool QgsVectorLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1991{
1993
1994 mProviderKey = provider;
1995 delete mDataProvider;
1996
1997 // For Postgres provider primary key unicity is tested at construction time,
1998 // so it has to be set before initializing the provider,
1999 // this manipulation is necessary to preserve default behavior when
2000 // "trust layer metadata" project level option is set and checkPrimaryKeyUnicity
2001 // was not explicitly passed in the uri
2002 if ( provider.compare( QLatin1String( "postgres" ) ) == 0 )
2003 {
2004 const QString checkUnicityKey { QStringLiteral( "checkPrimaryKeyUnicity" ) };
2006 if ( ! uri.hasParam( checkUnicityKey ) )
2007 {
2008 uri.setParam( checkUnicityKey, mReadExtentFromXml ? "0" : "1" );
2009 mDataSource = uri.uri( false );
2010 }
2011 }
2012
2013 std::unique_ptr< QgsScopedRuntimeProfile > profile;
2014 if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
2015 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), QStringLiteral( "projectload" ) );
2016
2017 if ( mPreloadedProvider )
2018 mDataProvider = qobject_cast< QgsVectorDataProvider * >( mPreloadedProvider.release() );
2019 else
2020 mDataProvider = qobject_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, mDataSource, options, flags ) );
2021
2022 if ( !mDataProvider )
2023 {
2024 setValid( false );
2025 QgsDebugMsgLevel( QStringLiteral( "Unable to get data provider" ), 2 );
2026 return false;
2027 }
2028
2029 mDataProvider->setParent( this );
2030 connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
2031
2032 QgsDebugMsgLevel( QStringLiteral( "Instantiated the data provider plugin" ), 2 );
2033
2034 setValid( mDataProvider->isValid() );
2035 if ( !isValid() )
2036 {
2037 QgsDebugMsgLevel( QStringLiteral( "Invalid provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
2038 return false;
2039 }
2040
2041 if ( profile )
2042 profile->switchTask( tr( "Read layer metadata" ) );
2044 {
2045 // we combine the provider metadata with the layer's existing metadata, so as not to reset any user customizations to the metadata
2046 // back to the default if a layer's data source is changed
2047 QgsLayerMetadata newMetadata = mDataProvider->layerMetadata();
2048 // this overwrites the provider metadata with any properties which are non-empty from the existing layer metadata
2049 newMetadata.combine( &mMetadata );
2050
2051 setMetadata( newMetadata );
2052 QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
2053 }
2054
2055 // TODO: Check if the provider has the capability to send fullExtentCalculated
2056 connect( mDataProvider, &QgsVectorDataProvider::fullExtentCalculated, this, [ = ] { updateExtents(); } );
2057
2058 // get and store the feature type
2059 mWkbType = mDataProvider->wkbType();
2060
2061 // before we update the layer fields from the provider, we first copy any default set alias and
2062 // editor widget config from the data provider fields, if present
2063 const QgsFields providerFields = mDataProvider->fields();
2064 for ( const QgsField &field : providerFields )
2065 {
2066 // we only copy defaults from the provider if we aren't overriding any configuration made in the layer
2067 if ( !field.editorWidgetSetup().isNull() && mFieldWidgetSetups.value( field.name() ).isNull() )
2068 {
2069 mFieldWidgetSetups[ field.name() ] = field.editorWidgetSetup();
2070 }
2071 if ( !field.alias().isEmpty() && mAttributeAliasMap.value( field.name() ).isEmpty() )
2072 {
2073 mAttributeAliasMap[ field.name() ] = field.alias();
2074 }
2075 if ( !mAttributeSplitPolicy.contains( field.name() ) )
2076 {
2077 mAttributeSplitPolicy[ field.name() ] = field.splitPolicy();
2078 }
2079 }
2080
2081 if ( profile )
2082 profile->switchTask( tr( "Read layer fields" ) );
2083 updateFields();
2084
2085 if ( mProviderKey == QLatin1String( "postgres" ) )
2086 {
2087 // update datasource from data provider computed one
2088 mDataSource = mDataProvider->dataSourceUri( false );
2089
2090 QgsDebugMsgLevel( QStringLiteral( "Beautifying layer name %1" ).arg( name() ), 3 );
2091
2092 // adjust the display name for postgres layers
2093 const thread_local QRegularExpression reg( R"lit("[^"]+"\."([^"] + )"( \‍([^)]+\))?)lit" );
2094 const QRegularExpressionMatch match = reg.match( name() );
2095 if ( match.hasMatch() )
2096 {
2097 QStringList stuff = match.capturedTexts();
2098 QString lName = stuff[1];
2099
2100 const QMap<QString, QgsMapLayer *> &layers = QgsProject::instance()->mapLayers();
2101
2102 QMap<QString, QgsMapLayer *>::const_iterator it;
2103 for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
2104 ;
2105
2106 if ( it != layers.constEnd() && stuff.size() > 2 )
2107 {
2108 lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
2109 }
2110
2111 if ( !lName.isEmpty() )
2112 setName( lName );
2113 }
2114 QgsDebugMsgLevel( QStringLiteral( "Beautified layer name %1" ).arg( name() ), 3 );
2115 }
2116 else if ( mProviderKey == QLatin1String( "osm" ) )
2117 {
2118 // make sure that the "observer" has been removed from URI to avoid crashes
2119 mDataSource = mDataProvider->dataSourceUri();
2120 }
2121 else if ( provider == QLatin1String( "ogr" ) )
2122 {
2123 // make sure that the /vsigzip or /vsizip is added to uri, if applicable
2124 mDataSource = mDataProvider->dataSourceUri();
2125 if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
2126 mDataSource.chop( 10 );
2127 }
2128 else if ( provider == QLatin1String( "memory" ) )
2129 {
2130 // required so that source differs between memory layers
2131 mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
2132 }
2133 else if ( provider == QLatin1String( "hana" ) )
2134 {
2135 // update datasource from data provider computed one
2136 mDataSource = mDataProvider->dataSourceUri( false );
2137 }
2138
2139 connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::emitDataChanged );
2141
2142 return true;
2143} // QgsVectorLayer:: setDataProvider
2144
2145
2146
2147
2148/* virtual */
2149bool QgsVectorLayer::writeXml( QDomNode &layer_node,
2150 QDomDocument &document,
2151 const QgsReadWriteContext &context ) const
2152{
2154
2155 // first get the layer element so that we can append the type attribute
2156
2157 QDomElement mapLayerNode = layer_node.toElement();
2158
2159 if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
2160 {
2161 QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
2162 return false;
2163 }
2164
2165 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( Qgis::LayerType::Vector ) );
2166
2167 // set the geometry type
2168 mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
2169 mapLayerNode.setAttribute( QStringLiteral( "wkbType" ), qgsEnumValueToKey( wkbType() ) );
2170
2171 // add provider node
2172 if ( mDataProvider )
2173 {
2174 QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
2175 provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
2176 QDomText providerText = document.createTextNode( providerType() );
2177 provider.appendChild( providerText );
2178 layer_node.appendChild( provider );
2179 }
2180
2181 //save joins
2182 mJoinBuffer->writeXml( layer_node, document );
2183
2184 // dependencies
2185 QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
2186 const auto constDependencies = dependencies();
2187 for ( const QgsMapLayerDependency &dep : constDependencies )
2188 {
2190 continue;
2191 QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
2192 depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
2193 dependenciesElement.appendChild( depElem );
2194 }
2195 layer_node.appendChild( dependenciesElement );
2196
2197 // change dependencies
2198 QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
2199 for ( const QgsMapLayerDependency &dep : constDependencies )
2200 {
2201 if ( dep.type() != QgsMapLayerDependency::DataDependency )
2202 continue;
2203 QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
2204 depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
2205 dataDependenciesElement.appendChild( depElem );
2206 }
2207 layer_node.appendChild( dataDependenciesElement );
2208
2209 // save expression fields
2210 mExpressionFieldBuffer->writeXml( layer_node, document );
2211
2212 writeStyleManager( layer_node, document );
2213
2214 // auxiliary layer
2215 QDomElement asElem = document.createElement( QStringLiteral( "auxiliaryLayer" ) );
2216 if ( mAuxiliaryLayer )
2217 {
2218 const QString pkField = mAuxiliaryLayer->joinInfo().targetFieldName();
2219 asElem.setAttribute( QStringLiteral( "key" ), pkField );
2220 }
2221 layer_node.appendChild( asElem );
2222
2223 // save QGIS Server properties (WMS Dimension, metadata URLS...)
2224 mServerProperties->writeXml( layer_node, document );
2225
2226 // renderer specific settings
2227 QString errorMsg;
2228 return writeSymbology( layer_node, document, errorMsg, context );
2229}
2230
2231QString QgsVectorLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
2232{
2234
2235 if ( providerType() == QLatin1String( "memory" ) )
2236 {
2237 // Refetch the source from the provider, because adding fields actually changes the source for this provider.
2238 return dataProvider()->dataSourceUri();
2239 }
2240
2242}
2243
2244QString QgsVectorLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
2245{
2247
2248 return QgsProviderRegistry::instance()->relativeToAbsoluteUri( provider, source, context );
2249}
2250
2251
2252
2254{
2256
2258 mJoinBuffer->resolveReferences( project );
2259}
2260
2261
2262bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage,
2263 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2264{
2266
2267 if ( categories.testFlag( Fields ) )
2268 {
2269 if ( !mExpressionFieldBuffer )
2270 mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
2271 mExpressionFieldBuffer->readXml( layerNode );
2272
2273 updateFields();
2274 }
2275
2276 if ( categories.testFlag( Relations ) )
2277 {
2278 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Relations" ) );
2279
2280 const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };
2281
2282 // Restore referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
2283 QDomNodeList referencedLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencedLayers" ) );
2284 if ( referencedLayersNodeList.size() > 0 )
2285 {
2286 const QDomNodeList relationNodes { referencedLayersNodeList.at( 0 ).childNodes() };
2287 for ( int i = 0; i < relationNodes.length(); ++i )
2288 {
2289 const QDomElement relationElement = relationNodes.at( i ).toElement();
2290
2291 mWeakRelations.push_back( QgsWeakRelation::readXml( this, QgsWeakRelation::Referencing, relationElement, resolver ) );
2292 }
2293 }
2294
2295 // Restore referencing layers: relations where "this" is the parent layer (the referenced part where the FK points to)
2296 QDomNodeList referencingLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencingLayers" ) );
2297 if ( referencingLayersNodeList.size() > 0 )
2298 {
2299 const QDomNodeList relationNodes { referencingLayersNodeList.at( 0 ).childNodes() };
2300 for ( int i = 0; i < relationNodes.length(); ++i )
2301 {
2302 const QDomElement relationElement = relationNodes.at( i ).toElement();
2303 mWeakRelations.push_back( QgsWeakRelation::readXml( this, QgsWeakRelation::Referenced, relationElement, resolver ) );
2304 }
2305 }
2306 }
2307
2308 QDomElement layerElement = layerNode.toElement();
2309
2310 readCommonStyle( layerElement, context, categories );
2311
2312 readStyle( layerNode, errorMessage, context, categories );
2313
2314 if ( categories.testFlag( MapTips ) )
2315 {
2316 QDomElement mapTipElem = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement();
2317 setMapTipTemplate( mapTipElem.text() );
2318 setMapTipsEnabled( mapTipElem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt() == 1 );
2319 }
2320
2321 if ( categories.testFlag( LayerConfiguration ) )
2322 mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
2323
2324 // Try to migrate pre QGIS 3.0 display field property
2325 QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
2326 if ( mFields.lookupField( displayField ) < 0 )
2327 {
2328 // if it's not a field, it's a maptip
2329 if ( mMapTipTemplate.isEmpty() && categories.testFlag( MapTips ) )
2330 mMapTipTemplate = displayField;
2331 }
2332 else
2333 {
2334 if ( mDisplayExpression.isEmpty() && categories.testFlag( LayerConfiguration ) )
2335 mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
2336 }
2337
2338 // process the attribute actions
2339 if ( categories.testFlag( Actions ) )
2340 mActions->readXml( layerNode );
2341
2342 if ( categories.testFlag( Fields ) )
2343 {
2344 // IMPORTANT - we don't clear mAttributeAliasMap here, as it may contain aliases which are coming direct
2345 // from the data provider. Instead we leave any existing aliases and only overwrite them if the style
2346 // has a specific value for that field's alias
2347 QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
2348 if ( !aliasesNode.isNull() )
2349 {
2350 QDomElement aliasElem;
2351
2352 QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
2353 for ( int i = 0; i < aliasNodeList.size(); ++i )
2354 {
2355 aliasElem = aliasNodeList.at( i ).toElement();
2356
2357 QString field;
2358 if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
2359 {
2360 field = aliasElem.attribute( QStringLiteral( "field" ) );
2361 }
2362 else
2363 {
2364 int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
2365
2366 if ( index >= 0 && index < fields().count() )
2367 field = fields().at( index ).name();
2368 }
2369
2370 QString alias;
2371
2372 if ( !aliasElem.attribute( QStringLiteral( "name" ) ).isEmpty() )
2373 {
2374 //if it has alias
2375 alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), aliasElem.attribute( QStringLiteral( "name" ) ) );
2376 QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + aliasElem.attribute( QStringLiteral( "name" ) ), 3 );
2377 }
2378 else
2379 {
2380 //if it has no alias, it should be the fields translation
2381 alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), field );
2382 QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + field, 3 );
2383 //if it gets the exact field value, there has been no translation (or not even translation loaded) - so no alias should be generated;
2384 if ( alias == aliasElem.attribute( QStringLiteral( "field" ) ) )
2385 alias.clear();
2386 }
2387
2388 QgsDebugMsgLevel( "field " + field + " origalias " + aliasElem.attribute( QStringLiteral( "name" ) ) + " trans " + alias, 3 );
2389 mAttributeAliasMap.insert( field, alias );
2390 }
2391 }
2392
2393 // IMPORTANT - we don't clear mAttributeSplitPolicy here, as it may contain policies which are coming direct
2394 // from the data provider. Instead we leave any existing policies and only overwrite them if the style
2395 // has a specific value for that field's policy
2396 const QDomNode splitPoliciesNode = layerNode.namedItem( QStringLiteral( "splitPolicies" ) );
2397 if ( !splitPoliciesNode.isNull() )
2398 {
2399 const QDomNodeList splitPolicyNodeList = splitPoliciesNode.toElement().elementsByTagName( QStringLiteral( "policy" ) );
2400 for ( int i = 0; i < splitPolicyNodeList.size(); ++i )
2401 {
2402 const QDomElement splitPolicyElem = splitPolicyNodeList.at( i ).toElement();
2403 const QString field = splitPolicyElem.attribute( QStringLiteral( "field" ) );
2404 const Qgis::FieldDomainSplitPolicy policy = qgsEnumKeyToValue( splitPolicyElem.attribute( QStringLiteral( "policy" ) ), Qgis::FieldDomainSplitPolicy::Duplicate );
2405 mAttributeSplitPolicy.insert( field, policy );
2406 }
2407 }
2408
2409 // default expressions
2410 mDefaultExpressionMap.clear();
2411 QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
2412 if ( !defaultsNode.isNull() )
2413 {
2414 QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
2415 for ( int i = 0; i < defaultNodeList.size(); ++i )
2416 {
2417 QDomElement defaultElem = defaultNodeList.at( i ).toElement();
2418
2419 QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
2420 QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
2421 bool applyOnUpdate = defaultElem.attribute( QStringLiteral( "applyOnUpdate" ), QStringLiteral( "0" ) ) == QLatin1String( "1" );
2422 if ( field.isEmpty() || expression.isEmpty() )
2423 continue;
2424
2425 mDefaultExpressionMap.insert( field, QgsDefaultValue( expression, applyOnUpdate ) );
2426 }
2427 }
2428
2429 // constraints
2430 mFieldConstraints.clear();
2431 mFieldConstraintStrength.clear();
2432 QDomNode constraintsNode = layerNode.namedItem( QStringLiteral( "constraints" ) );
2433 if ( !constraintsNode.isNull() )
2434 {
2435 QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2436 for ( int i = 0; i < constraintNodeList.size(); ++i )
2437 {
2438 QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2439
2440 QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2441 int constraints = constraintElem.attribute( QStringLiteral( "constraints" ), QStringLiteral( "0" ) ).toInt();
2442 if ( field.isEmpty() || constraints == 0 )
2443 continue;
2444
2445 mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
2446
2447 int uniqueStrength = constraintElem.attribute( QStringLiteral( "unique_strength" ), QStringLiteral( "1" ) ).toInt();
2448 int notNullStrength = constraintElem.attribute( QStringLiteral( "notnull_strength" ), QStringLiteral( "1" ) ).toInt();
2449 int expStrength = constraintElem.attribute( QStringLiteral( "exp_strength" ), QStringLiteral( "1" ) ).toInt();
2450
2451 mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
2452 mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
2453 mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
2454 }
2455 }
2456 mFieldConstraintExpressions.clear();
2457 QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral( "constraintExpressions" ) );
2458 if ( !constraintExpressionsNode.isNull() )
2459 {
2460 QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2461 for ( int i = 0; i < constraintNodeList.size(); ++i )
2462 {
2463 QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2464
2465 QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2466 QString exp = constraintElem.attribute( QStringLiteral( "exp" ), QString() );
2467 QString desc = constraintElem.attribute( QStringLiteral( "desc" ), QString() );
2468 if ( field.isEmpty() || exp.isEmpty() )
2469 continue;
2470
2471 mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
2472 }
2473 }
2474
2475 updateFields();
2476 }
2477
2478 // load field configuration
2479 if ( categories.testFlag( Fields ) || categories.testFlag( Forms ) )
2480 {
2481 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Forms" ) );
2482
2483 QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
2484 QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
2485 for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
2486 {
2487 const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
2488 const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
2489
2490 QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
2491
2492 if ( categories.testFlag( Fields ) )
2493 mFieldConfigurationFlags[fieldName] = qgsFlagKeysToValue( fieldConfigElement.attribute( QStringLiteral( "configurationFlags" ) ), QgsField::ConfigurationFlag::None );
2494
2495 // Load editor widget configuration
2496 if ( categories.testFlag( Forms ) )
2497 {
2498 const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
2499 const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
2500 const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
2501 QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
2502 if ( widgetType == QLatin1String( "ValueRelation" ) )
2503 {
2504 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() );
2505 }
2506 QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
2507 mFieldWidgetSetups[fieldName] = setup;
2508 }
2509 }
2510 }
2511
2512 // Legacy reading for QGIS 3.14 and older projects
2513 // Attributes excluded from WMS and WFS
2514 if ( categories.testFlag( Fields ) )
2515 {
2516 const QList<QPair<QString, QgsField::ConfigurationFlag>> legacyConfig
2517 {
2518 qMakePair( QStringLiteral( "excludeAttributesWMS" ), QgsField::ConfigurationFlag::HideFromWms ),
2519 qMakePair( QStringLiteral( "excludeAttributesWFS" ), QgsField::ConfigurationFlag::HideFromWfs )
2520 };
2521 for ( const auto &config : legacyConfig )
2522 {
2523 QDomNode excludeNode = layerNode.namedItem( config.first );
2524 if ( !excludeNode.isNull() )
2525 {
2526 QDomNodeList attributeNodeList = excludeNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
2527 for ( int i = 0; i < attributeNodeList.size(); ++i )
2528 {
2529 QString fieldName = attributeNodeList.at( i ).toElement().text();
2530 if ( !mFieldConfigurationFlags.contains( fieldName ) )
2531 mFieldConfigurationFlags[fieldName] = config.second;
2532 else
2533 mFieldConfigurationFlags[fieldName].setFlag( config.second, true );
2534 }
2535 }
2536 }
2537 }
2538
2539 if ( categories.testFlag( GeometryOptions ) )
2540 mGeometryOptions->readXml( layerNode.namedItem( QStringLiteral( "geometryOptions" ) ) );
2541
2542 if ( categories.testFlag( Forms ) )
2543 mEditFormConfig.readXml( layerNode, context );
2544
2545 if ( categories.testFlag( AttributeTable ) )
2546 {
2547 mAttributeTableConfig.readXml( layerNode );
2548 mConditionalStyles->readXml( layerNode, context );
2549 mStoredExpressionManager->readXml( layerNode );
2550 }
2551
2552 if ( categories.testFlag( CustomProperties ) )
2553 readCustomProperties( layerNode, QStringLiteral( "variable" ) );
2554
2555 QDomElement mapLayerNode = layerNode.toElement();
2556 if ( categories.testFlag( LayerConfiguration )
2557 && mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
2558 mReadOnly = true;
2559
2560 updateFields();
2561
2562 if ( categories.testFlag( Legend ) )
2563 {
2564 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Legend" ) );
2565
2566 const QDomElement legendElem = layerNode.firstChildElement( QStringLiteral( "legend" ) );
2567 if ( !legendElem.isNull() )
2568 {
2569 std::unique_ptr< QgsMapLayerLegend > legend( QgsMapLayerLegend::defaultVectorLegend( this ) );
2570 legend->readXml( legendElem, context );
2571 setLegend( legend.release() );
2572 mSetLegendFromStyle = true;
2573 }
2574 }
2575
2576 return true;
2577}
2578
2579bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage,
2580 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2581{
2583
2584 bool result = true;
2585 emit readCustomSymbology( node.toElement(), errorMessage );
2586
2587 // we must try to restore a renderer if our geometry type is unknown
2588 // as this allows the renderer to be correctly restored even for layers
2589 // with broken sources
2590 if ( isSpatial() || mWkbType == Qgis::WkbType::Unknown )
2591 {
2592 // defer style changed signal until we've set the renderer, labeling, everything.
2593 // we don't want multiple signals!
2594 ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
2595
2596 // try renderer v2 first
2597 if ( categories.testFlag( Symbology ) )
2598 {
2599 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Symbology" ) );
2600
2601 QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
2602 if ( !rendererElement.isNull() )
2603 {
2604 QgsFeatureRenderer *r = QgsFeatureRenderer::load( rendererElement, context );
2605 if ( r )
2606 {
2607 setRenderer( r );
2608 }
2609 else
2610 {
2611 result = false;
2612 }
2613 }
2614 // make sure layer has a renderer - if none exists, fallback to a default renderer
2615 if ( isSpatial() && !renderer() )
2616 {
2618 }
2619 }
2620
2621 // read labeling definition
2622 if ( categories.testFlag( Labeling ) )
2623 {
2624 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Labeling" ) );
2625
2626 QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
2628 if ( labelingElement.isNull() ||
2629 ( labelingElement.attribute( QStringLiteral( "type" ) ) == QLatin1String( "simple" ) && labelingElement.firstChildElement( QStringLiteral( "settings" ) ).isNull() ) )
2630 {
2631 // make sure we have custom properties for labeling for 2.x projects
2632 // (custom properties should be already loaded when reading the whole layer from XML,
2633 // but when reading style, custom properties are not read)
2634 readCustomProperties( node, QStringLiteral( "labeling" ) );
2635
2636 // support for pre-QGIS 3 labeling configurations written in custom properties
2637 labeling = readLabelingFromCustomProperties();
2638 }
2639 else
2640 {
2641 labeling = QgsAbstractVectorLayerLabeling::create( labelingElement, context );
2642 }
2644
2645 if ( node.toElement().hasAttribute( QStringLiteral( "labelsEnabled" ) ) )
2646 mLabelsEnabled = node.toElement().attribute( QStringLiteral( "labelsEnabled" ) ).toInt();
2647 else
2648 mLabelsEnabled = true;
2649 }
2650
2651 if ( categories.testFlag( Symbology ) )
2652 {
2653 // get and set the blend mode if it exists
2654 QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
2655 if ( !blendModeNode.isNull() )
2656 {
2657 QDomElement e = blendModeNode.toElement();
2658 setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
2659 }
2660
2661 // get and set the feature blend mode if it exists
2662 QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
2663 if ( !featureBlendModeNode.isNull() )
2664 {
2665 QDomElement e = featureBlendModeNode.toElement();
2666 setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
2667 }
2668 }
2669
2670 // get and set the layer transparency and scale visibility if they exists
2671 if ( categories.testFlag( Rendering ) )
2672 {
2673 QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
2674 if ( !layerTransparencyNode.isNull() )
2675 {
2676 QDomElement e = layerTransparencyNode.toElement();
2677 setOpacity( 1.0 - e.text().toInt() / 100.0 );
2678 }
2679 QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
2680 if ( !layerOpacityNode.isNull() )
2681 {
2682 QDomElement e = layerOpacityNode.toElement();
2683 setOpacity( e.text().toDouble() );
2684 }
2685
2686 const bool hasScaleBasedVisibiliy { node.attributes().namedItem( QStringLiteral( "hasScaleBasedVisibilityFlag" ) ).nodeValue() == '1' };
2687 setScaleBasedVisibility( hasScaleBasedVisibiliy );
2688 bool ok;
2689 const double maxScale { node.attributes().namedItem( QStringLiteral( "maxScale" ) ).nodeValue().toDouble( &ok ) };
2690 if ( ok )
2691 {
2692 setMaximumScale( maxScale );
2693 }
2694 const double minScale { node.attributes().namedItem( QStringLiteral( "minScale" ) ).nodeValue().toDouble( &ok ) };
2695 if ( ok )
2696 {
2697 setMinimumScale( minScale );
2698 }
2699
2700 QDomElement e = node.toElement();
2701
2702 // get the simplification drawing settings
2703 mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
2704 mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
2705 mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
2706 mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
2707 mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
2708
2709 if ( mRenderer )
2710 mRenderer->setReferenceScale( e.attribute( QStringLiteral( "symbologyReferenceScale" ), QStringLiteral( "-1" ) ).toDouble() );
2711 }
2712
2713 //diagram renderer and diagram layer settings
2714 if ( categories.testFlag( Diagrams ) )
2715 {
2716 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Diagrams" ) );
2717
2718 delete mDiagramRenderer;
2719 mDiagramRenderer = nullptr;
2720 QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
2721 if ( !singleCatDiagramElem.isNull() )
2722 {
2723 mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
2724 mDiagramRenderer->readXml( singleCatDiagramElem, context );
2725 }
2726 QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
2727 if ( !linearDiagramElem.isNull() )
2728 {
2729 if ( linearDiagramElem.hasAttribute( QStringLiteral( "classificationAttribute" ) ) )
2730 {
2731 // fix project from before QGIS 3.0
2732 int idx = linearDiagramElem.attribute( QStringLiteral( "classificationAttribute" ) ).toInt();
2733 if ( idx >= 0 && idx < mFields.count() )
2734 linearDiagramElem.setAttribute( QStringLiteral( "classificationField" ), mFields.at( idx ).name() );
2735 }
2736
2737 mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2738 mDiagramRenderer->readXml( linearDiagramElem, context );
2739 }
2740
2741 if ( mDiagramRenderer )
2742 {
2743 QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
2744 if ( !diagramSettingsElem.isNull() )
2745 {
2746 bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral( "xPosColumn" ) );
2747 bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral( "yPosColumn" ) );
2748 bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral( "showColumn" ) );
2749 if ( oldXPos || oldYPos || oldShow )
2750 {
2751 // fix project from before QGIS 3.0
2753 if ( oldXPos )
2754 {
2755 int xPosColumn = diagramSettingsElem.attribute( QStringLiteral( "xPosColumn" ) ).toInt();
2756 if ( xPosColumn >= 0 && xPosColumn < mFields.count() )
2757 ddp.setProperty( QgsDiagramLayerSettings::PositionX, QgsProperty::fromField( mFields.at( xPosColumn ).name(), true ) );
2758 }
2759 if ( oldYPos )
2760 {
2761 int yPosColumn = diagramSettingsElem.attribute( QStringLiteral( "yPosColumn" ) ).toInt();
2762 if ( yPosColumn >= 0 && yPosColumn < mFields.count() )
2763 ddp.setProperty( QgsDiagramLayerSettings::PositionY, QgsProperty::fromField( mFields.at( yPosColumn ).name(), true ) );
2764 }
2765 if ( oldShow )
2766 {
2767 int showColumn = diagramSettingsElem.attribute( QStringLiteral( "showColumn" ) ).toInt();
2768 if ( showColumn >= 0 && showColumn < mFields.count() )
2769 ddp.setProperty( QgsDiagramLayerSettings::Show, QgsProperty::fromField( mFields.at( showColumn ).name(), true ) );
2770 }
2771 QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral( "properties" ) );
2773 {
2774 { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
2775 { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
2776 { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean ) },
2777 };
2778 ddp.writeXml( propertiesElem, defs );
2779 diagramSettingsElem.appendChild( propertiesElem );
2780 }
2781
2782 delete mDiagramLayerSettings;
2783 mDiagramLayerSettings = new QgsDiagramLayerSettings();
2784 mDiagramLayerSettings->readXml( diagramSettingsElem );
2785 }
2786 }
2787 }
2788 // end diagram
2789
2790 styleChangedSignalBlocker.release();
2792 }
2793 return result;
2794}
2795
2796
2797bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2798 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2799{
2801
2802 QDomElement layerElement = node.toElement();
2803 writeCommonStyle( layerElement, doc, context, categories );
2804
2805 ( void )writeStyle( node, doc, errorMessage, context, categories );
2806
2807 if ( categories.testFlag( GeometryOptions ) )
2808 mGeometryOptions->writeXml( node );
2809
2810 if ( categories.testFlag( Legend ) && legend() )
2811 {
2812 QDomElement legendElement = legend()->writeXml( doc, context );
2813 if ( !legendElement.isNull() )
2814 node.appendChild( legendElement );
2815 }
2816
2817 // Relation information for both referenced and referencing sides
2818 if ( categories.testFlag( Relations ) )
2819 {
2820 // Store referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
2821 QDomElement referencedLayersElement = doc.createElement( QStringLiteral( "referencedLayers" ) );
2822 node.appendChild( referencedLayersElement );
2823
2824 const QList<QgsRelation> referencingRelations { QgsProject::instance()->relationManager()->referencingRelations( this ) };
2825 for ( const QgsRelation &rel : referencingRelations )
2826 {
2827 switch ( rel.type() )
2828 {
2830 QgsWeakRelation::writeXml( this, QgsWeakRelation::Referencing, rel, referencedLayersElement, doc );
2831 break;
2833 break;
2834 }
2835 }
2836
2837 // Store referencing layers: relations where "this" is the parent layer (the referenced part, that holds the FK)
2838 QDomElement referencingLayersElement = doc.createElement( QStringLiteral( "referencingLayers" ) );
2839 node.appendChild( referencedLayersElement );
2840
2841 const QList<QgsRelation> referencedRelations { QgsProject::instance()->relationManager()->referencedRelations( this ) };
2842 for ( const QgsRelation &rel : referencedRelations )
2843 {
2844 switch ( rel.type() )
2845 {
2847 QgsWeakRelation::writeXml( this, QgsWeakRelation::Referenced, rel, referencingLayersElement, doc );
2848 break;
2850 break;
2851 }
2852 }
2853 }
2854
2855 // write field configurations
2856 if ( categories.testFlag( Fields ) || categories.testFlag( Forms ) )
2857 {
2858 QDomElement fieldConfigurationElement;
2859 // field configuration flag
2860 fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
2861 node.appendChild( fieldConfigurationElement );
2862
2863 for ( const QgsField &field : std::as_const( mFields ) )
2864 {
2865 QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
2866 fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
2867 fieldConfigurationElement.appendChild( fieldElement );
2868
2869 if ( categories.testFlag( Fields ) )
2870 {
2871 fieldElement.setAttribute( QStringLiteral( "configurationFlags" ), qgsFlagValueToKeys( field.configurationFlags() ) );
2872 }
2873
2874 if ( categories.testFlag( Forms ) )
2875 {
2877
2878 // TODO : wrap this part in an if to only save if it was user-modified
2879 QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
2880 fieldElement.appendChild( editWidgetElement );
2881 editWidgetElement.setAttribute( QStringLiteral( "type" ), field.editorWidgetSetup().type() );
2882 QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
2883
2884 editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
2885 editWidgetElement.appendChild( editWidgetConfigElement );
2886 // END TODO : wrap this part in an if to only save if it was user-modified
2887 }
2888 }
2889 }
2890
2891 if ( categories.testFlag( Fields ) )
2892 {
2893 //attribute aliases
2894 QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
2895 for ( const QgsField &field : std::as_const( mFields ) )
2896 {
2897 QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
2898 aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
2899 aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
2900 aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
2901 aliasElem.appendChild( aliasEntryElem );
2902 }
2903 node.appendChild( aliasElem );
2904
2905 //split policies
2906 {
2907 QDomElement splitPoliciesElement = doc.createElement( QStringLiteral( "splitPolicies" ) );
2908 for ( const QgsField &field : std::as_const( mFields ) )
2909 {
2910 QDomElement splitPolicyElem = doc.createElement( QStringLiteral( "policy" ) );
2911 splitPolicyElem.setAttribute( QStringLiteral( "field" ), field.name() );
2912 splitPolicyElem.setAttribute( QStringLiteral( "policy" ), qgsEnumValueToKey( field.splitPolicy() ) );
2913 splitPoliciesElement.appendChild( splitPolicyElem );
2914 }
2915 node.appendChild( splitPoliciesElement );
2916 }
2917
2918 //default expressions
2919 QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
2920 for ( const QgsField &field : std::as_const( mFields ) )
2921 {
2922 QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
2923 defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
2924 defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() );
2925 defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2926 defaultsElem.appendChild( defaultElem );
2927 }
2928 node.appendChild( defaultsElem );
2929
2930 // constraints
2931 QDomElement constraintsElem = doc.createElement( QStringLiteral( "constraints" ) );
2932 for ( const QgsField &field : std::as_const( mFields ) )
2933 {
2934 QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
2935 constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
2936 constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
2937 constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
2938 constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
2939 constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
2940 constraintsElem.appendChild( constraintElem );
2941 }
2942 node.appendChild( constraintsElem );
2943
2944 // constraint expressions
2945 QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral( "constraintExpressions" ) );
2946 for ( const QgsField &field : std::as_const( mFields ) )
2947 {
2948 QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraint" ) );
2949 constraintExpressionElem.setAttribute( QStringLiteral( "field" ), field.name() );
2950 constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
2951 constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
2952 constraintExpressionsElem.appendChild( constraintExpressionElem );
2953 }
2954 node.appendChild( constraintExpressionsElem );
2955
2956 // save expression fields
2957 if ( !mExpressionFieldBuffer )
2958 {
2959 // can happen when saving style on a invalid layer
2961 dummy.writeXml( node, doc );
2962 }
2963 else
2964 {
2965 mExpressionFieldBuffer->writeXml( node, doc );
2966 }
2967 }
2968
2969 // add attribute actions
2970 if ( categories.testFlag( Actions ) )
2971 mActions->writeXml( node );
2972
2973 if ( categories.testFlag( AttributeTable ) )
2974 {
2975 mAttributeTableConfig.writeXml( node );
2976 mConditionalStyles->writeXml( node, doc, context );
2977 mStoredExpressionManager->writeXml( node );
2978 }
2979
2980 if ( categories.testFlag( Forms ) )
2981 mEditFormConfig.writeXml( node, context );
2982
2983 // save readonly state
2984 if ( categories.testFlag( LayerConfiguration ) )
2985 node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
2986
2987 // save preview expression
2988 if ( categories.testFlag( LayerConfiguration ) )
2989 {
2990 QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
2991 QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2992 prevExpElem.appendChild( prevExpText );
2993 node.appendChild( prevExpElem );
2994 }
2995
2996 // save map tip
2997 if ( categories.testFlag( MapTips ) )
2998 {
2999 QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
3000 mapTipElem.setAttribute( QStringLiteral( "enabled" ), mapTipsEnabled() );
3001 QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
3002 mapTipElem.appendChild( mapTipText );
3003 node.toElement().appendChild( mapTipElem );
3004 }
3005
3006 return true;
3007}
3008
3009bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
3010 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
3011{
3013
3014 QDomElement mapLayerNode = node.toElement();
3015
3016 emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
3017
3018 // we must try to write the renderer if our geometry type is unknown
3019 // as this allows the renderer to be correctly restored even for layers
3020 // with broken sources
3021 if ( isSpatial() || mWkbType == Qgis::WkbType::Unknown )
3022 {
3023 if ( categories.testFlag( Symbology ) )
3024 {
3025 if ( mRenderer )
3026 {
3027 QDomElement rendererElement = mRenderer->save( doc, context );
3028 node.appendChild( rendererElement );
3029 }
3030 }
3031
3032 if ( categories.testFlag( Labeling ) )
3033 {
3034 if ( mLabeling )
3035 {
3036 QDomElement labelingElement = mLabeling->save( doc, context );
3037 node.appendChild( labelingElement );
3038 }
3039 mapLayerNode.setAttribute( QStringLiteral( "labelsEnabled" ), mLabelsEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
3040 }
3041
3042 // save the simplification drawing settings
3043 if ( categories.testFlag( Rendering ) )
3044 {
3045 mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
3046 mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
3047 mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
3048 mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
3049 mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
3050 }
3051
3052 //save customproperties
3053 if ( categories.testFlag( CustomProperties ) )
3054 {
3055 writeCustomProperties( node, doc );
3056 }
3057
3058 if ( categories.testFlag( Symbology ) )
3059 {
3060 // add the blend mode field
3061 QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
3062 QDomText blendModeText = doc.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
3063 blendModeElem.appendChild( blendModeText );
3064 node.appendChild( blendModeElem );
3065
3066 // add the feature blend mode field
3067 QDomElement featureBlendModeElem = doc.createElement( QStringLiteral( "featureBlendMode" ) );
3068 QDomText featureBlendModeText = doc.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) ) );
3069 featureBlendModeElem.appendChild( featureBlendModeText );
3070 node.appendChild( featureBlendModeElem );
3071 }
3072
3073 // add the layer opacity and scale visibility
3074 if ( categories.testFlag( Rendering ) )
3075 {
3076 QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
3077 QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
3078 layerOpacityElem.appendChild( layerOpacityText );
3079 node.appendChild( layerOpacityElem );
3080 mapLayerNode.setAttribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ), hasScaleBasedVisibility() ? 1 : 0 );
3081 mapLayerNode.setAttribute( QStringLiteral( "maxScale" ), maximumScale() );
3082 mapLayerNode.setAttribute( QStringLiteral( "minScale" ), minimumScale() );
3083
3084 mapLayerNode.setAttribute( QStringLiteral( "symbologyReferenceScale" ), mRenderer ? mRenderer->referenceScale() : -1 );
3085 }
3086
3087 if ( categories.testFlag( Diagrams ) && mDiagramRenderer )
3088 {
3089 mDiagramRenderer->writeXml( mapLayerNode, doc, context );
3090 if ( mDiagramLayerSettings )
3091 mDiagramLayerSettings->writeXml( mapLayerNode, doc );
3092 }
3093 }
3094 return true;
3095}
3096
3097bool QgsVectorLayer::readSld( const QDomNode &node, QString &errorMessage )
3098{
3100
3101 // get the Name element
3102 QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
3103 if ( nameElem.isNull() )
3104 {
3105 errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
3106 }
3107
3108 if ( isSpatial() )
3109 {
3110 QgsFeatureRenderer *r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
3111 if ( !r )
3112 return false;
3113
3114 // defer style changed signal until we've set the renderer, labeling, everything.
3115 // we don't want multiple signals!
3116 ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
3117
3118 setRenderer( r );
3119
3120 // labeling
3121 readSldLabeling( node );
3122
3123 styleChangedSignalBlocker.release();
3125 }
3126 return true;
3127}
3128
3129bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props ) const
3130{
3132
3133 Q_UNUSED( errorMessage )
3134
3135 QVariantMap localProps = QVariantMap( props );
3137 {
3139 }
3140
3141 if ( isSpatial() )
3142 {
3143 // store the Name element
3144 QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
3145 nameNode.appendChild( doc.createTextNode( name() ) );
3146 node.appendChild( nameNode );
3147
3148 QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
3149 node.appendChild( userStyleElem );
3150
3151 QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
3152 nameElem.appendChild( doc.createTextNode( name() ) );
3153
3154 userStyleElem.appendChild( nameElem );
3155
3156 QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
3157 userStyleElem.appendChild( featureTypeStyleElem );
3158
3159 mRenderer->toSld( doc, featureTypeStyleElem, localProps );
3160 if ( labelsEnabled() )
3161 {
3162 mLabeling->toSld( featureTypeStyleElem, localProps );
3163 }
3164 }
3165 return true;
3166}
3167
3168
3169bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry &geom, bool skipDefaultValue )
3170{
3172
3173 if ( !mEditBuffer || !mDataProvider )
3174 {
3175 return false;
3176 }
3177
3178 if ( mGeometryOptions->isActive() )
3179 mGeometryOptions->apply( geom );
3180
3181 updateExtents();
3182
3183 bool result = mEditBuffer->changeGeometry( fid, geom );
3184
3185 if ( result )
3186 {
3187 updateExtents();
3188 if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
3189 updateDefaultValues( fid );
3190 }
3191 return result;
3192}
3193
3194
3195bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
3196{
3198
3199 bool result = false;
3200
3201 switch ( fields().fieldOrigin( field ) )
3202 {
3204 result = mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
3205 if ( result )
3206 emit attributeValueChanged( fid, field, newValue );
3207 break;
3208
3212 {
3213 if ( mEditBuffer && mDataProvider )
3214 result = mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
3215 break;
3216 }
3217
3219 break;
3220 }
3221
3222 if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3223 updateDefaultValues( fid );
3224
3225 return result;
3226}
3227
3228bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues, bool skipDefaultValues )
3229{
3231
3232 bool result = true;
3233
3234 QgsAttributeMap newValuesJoin;
3235 QgsAttributeMap oldValuesJoin;
3236
3237 QgsAttributeMap newValuesNotJoin;
3238 QgsAttributeMap oldValuesNotJoin;
3239
3240 for ( auto it = newValues.constBegin(); it != newValues.constEnd(); ++it )
3241 {
3242 const int field = it.key();
3243 const QVariant newValue = it.value();
3244 QVariant oldValue;
3245
3246 if ( oldValues.contains( field ) )
3247 oldValue = oldValues[field];
3248
3249 switch ( fields().fieldOrigin( field ) )
3250 {
3252 newValuesJoin[field] = newValue;
3253 oldValuesJoin[field] = oldValue;
3254 break;
3255
3259 {
3260 newValuesNotJoin[field] = newValue;
3261 oldValuesNotJoin[field] = oldValue;
3262 break;
3263 }
3264
3266 break;
3267 }
3268 }
3269
3270 if ( ! newValuesJoin.isEmpty() && mJoinBuffer )
3271 {
3272 result = mJoinBuffer->changeAttributeValues( fid, newValuesJoin, oldValuesJoin );
3273 }
3274
3275 if ( ! newValuesNotJoin.isEmpty() )
3276 {
3277 if ( mEditBuffer && mDataProvider )
3278 result &= mEditBuffer->changeAttributeValues( fid, newValuesNotJoin, oldValues );
3279 else
3280 result = false;
3281 }
3282
3283 if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3284 {
3285 updateDefaultValues( fid );
3286 }
3287
3288 return result;
3289}
3290
3292{
3294
3295 if ( !mEditBuffer || !mDataProvider )
3296 return false;
3297
3298 return mEditBuffer->addAttribute( field );
3299}
3300
3302{
3304
3305 if ( attIndex < 0 || attIndex >= fields().count() )
3306 return;
3307
3308 QString name = fields().at( attIndex ).name();
3309 mFields[ attIndex ].setAlias( QString() );
3310 if ( mAttributeAliasMap.contains( name ) )
3311 {
3312 mAttributeAliasMap.remove( name );
3313 updateFields();
3314 mEditFormConfig.setFields( mFields );
3315 emit layerModified();
3316 }
3317}
3318
3319bool QgsVectorLayer::renameAttribute( int index, const QString &newName )
3320{
3322
3323 if ( index < 0 || index >= fields().count() )
3324 return false;
3325
3326 switch ( mFields.fieldOrigin( index ) )
3327 {
3329 {
3330 if ( mExpressionFieldBuffer )
3331 {
3332 int oi = mFields.fieldOriginIndex( index );
3333 mExpressionFieldBuffer->renameExpression( oi, newName );
3334 updateFields();
3335 return true;
3336 }
3337 else
3338 {
3339 return false;
3340 }
3341 }
3342
3345
3346 if ( !mEditBuffer || !mDataProvider )
3347 return false;
3348
3349 return mEditBuffer->renameAttribute( index, newName );
3350
3353 return false;
3354
3355 }
3356
3357 return false; // avoid warning
3358}
3359
3360void QgsVectorLayer::setFieldAlias( int attIndex, const QString &aliasString )
3361{
3363
3364 if ( attIndex < 0 || attIndex >= fields().count() )
3365 return;
3366
3367 QString name = fields().at( attIndex ).name();
3368
3369 mAttributeAliasMap.insert( name, aliasString );
3370 mFields[ attIndex ].setAlias( aliasString );
3371 mEditFormConfig.setFields( mFields );
3372 emit layerModified(); // TODO[MD]: should have a different signal?
3373}
3374
3375QString QgsVectorLayer::attributeAlias( int index ) const
3376{
3378
3379 if ( index < 0 || index >= fields().count() )
3380 return QString();
3381
3382 return fields().at( index ).alias();
3383}
3384
3386{
3388
3389 if ( index >= 0 && index < mFields.count() )
3390 return mFields.at( index ).displayName();
3391 else
3392 return QString();
3393}
3394
3396{
3398
3399 return mAttributeAliasMap;
3400}
3401
3403{
3405
3406 if ( index < 0 || index >= fields().count() )
3407 return;
3408
3409 const QString name = fields().at( index ).name();
3410
3411 mAttributeSplitPolicy.insert( name, policy );
3412 mFields[ index ].setSplitPolicy( policy );
3413 mEditFormConfig.setFields( mFields );
3414 emit layerModified(); // TODO[MD]: should have a different signal?
3415}
3416
3418{
3420
3421 QSet<QString> excludeList;
3422 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3423 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3424 {
3425 if ( flagsIt->testFlag( QgsField::ConfigurationFlag::HideFromWms ) )
3426 {
3427 excludeList << flagsIt.key();
3428 }
3429 }
3430 return excludeList;
3431}
3432
3433void QgsVectorLayer::setExcludeAttributesWms( const QSet<QString> &att )
3434{
3436
3437 QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
3438 for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
3439 {
3440 flagsIt->setFlag( QgsField::ConfigurationFlag::HideFromWms, att.contains( flagsIt.key() ) );
3441 }
3442 updateFields();
3443}
3444
3446{
3448
3449 QSet<QString> excludeList;
3450 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3451 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3452 {
3453 if ( flagsIt->testFlag( QgsField::ConfigurationFlag::HideFromWfs ) )
3454 {
3455 excludeList << flagsIt.key();
3456 }
3457 }
3458 return excludeList;
3459}
3460
3461void QgsVectorLayer::setExcludeAttributesWfs( const QSet<QString> &att )
3462{
3464
3465 QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
3466 for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
3467 {
3468 flagsIt->setFlag( QgsField::ConfigurationFlag::HideFromWfs, att.contains( flagsIt.key() ) );
3469 }
3470 updateFields();
3471}
3472
3474{
3476
3477 if ( index < 0 || index >= fields().count() )
3478 return false;
3479
3480 if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
3481 {
3482 removeExpressionField( index );
3483 return true;
3484 }
3485
3486 if ( !mEditBuffer || !mDataProvider )
3487 return false;
3488
3489 return mEditBuffer->deleteAttribute( index );
3490}
3491
3492bool QgsVectorLayer::deleteAttributes( const QList<int> &attrs )
3493{
3495
3496 bool deleted = false;
3497
3498 // Remove multiple occurrences of same attribute
3499 QList<int> attrList = qgis::setToList( qgis::listToSet( attrs ) );
3500
3501 std::sort( attrList.begin(), attrList.end(), std::greater<int>() );
3502
3503 for ( int attr : std::as_const( attrList ) )
3504 {
3505 if ( deleteAttribute( attr ) )
3506 {
3507 deleted = true;
3508 }
3509 }
3510
3511 return deleted;
3512}
3513
3514bool QgsVectorLayer::deleteFeatureCascade( QgsFeatureId fid, QgsVectorLayer::DeleteContext *context )
3515{
3517
3518 if ( !mEditBuffer )
3519 return false;
3520
3521 if ( context && context->cascade )
3522 {
3523 const QList<QgsRelation> relations = context->project->relationManager()->referencedRelations( this );
3524 const bool hasRelationsOrJoins = !relations.empty() || mJoinBuffer->containsJoins();
3525 if ( hasRelationsOrJoins )
3526 {
3527 if ( context->mHandledFeatures.contains( this ) )
3528 {
3529 QgsFeatureIds &handledFeatureIds = context->mHandledFeatures[ this ];
3530 if ( handledFeatureIds.contains( fid ) )
3531 {
3532 // avoid endless recursion
3533 return false;
3534 }
3535 else
3536 {
3537 // add feature id
3538 handledFeatureIds << fid;
3539 }
3540 }
3541 else
3542 {
3543 // add layer and feature id
3544 context->mHandledFeatures.insert( this, QgsFeatureIds() << fid );
3545 }
3546
3547 for ( const QgsRelation &relation : relations )
3548 {
3549 //check if composition (and not association)
3550 switch ( relation.strength() )
3551 {
3553 {
3554 //get features connected over this relation
3555 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( getFeature( fid ) );
3556 QgsFeatureIds childFeatureIds;
3557 QgsFeature childFeature;
3558 while ( relatedFeaturesIt.nextFeature( childFeature ) )
3559 {
3560 childFeatureIds.insert( childFeature.id() );
3561 }
3562 if ( childFeatureIds.count() > 0 )
3563 {
3564 relation.referencingLayer()->startEditing();
3565 relation.referencingLayer()->deleteFeatures( childFeatureIds, context );
3566 }
3567 break;
3568 }
3569
3571 break;
3572 }
3573 }
3574 }
3575 }
3576
3577 if ( mJoinBuffer->containsJoins() )
3578 mJoinBuffer->deleteFeature( fid, context );
3579
3580 bool res = mEditBuffer->deleteFeature( fid );
3581
3582 return res;
3583}
3584
3586{
3588
3589 if ( !mEditBuffer )
3590 return false;
3591
3592 bool res = deleteFeatureCascade( fid, context );
3593
3594 if ( res )
3595 {
3596 updateExtents();
3597 }
3598
3599 return res;
3600}
3601
3603{
3605
3606 bool res = true;
3607
3608 if ( ( context && context->cascade ) || mJoinBuffer->containsJoins() )
3609 {
3610 // should ideally be "deleteFeaturesCascade" for performance!
3611 for ( QgsFeatureId fid : fids )
3612 res = deleteFeatureCascade( fid, context ) && res;
3613 }
3614 else
3615 {
3616 res = mEditBuffer && mEditBuffer->deleteFeatures( fids );
3617 }
3618
3619 if ( res )
3620 {
3621 mSelectedFeatureIds.subtract( fids ); // remove it from selection
3622 updateExtents();
3623 }
3624
3625 return res;
3626}
3627
3629{
3630 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
3632
3633 return mFields;
3634}
3635
3637{
3639
3640 QgsAttributeList pkAttributesList;
3641 if ( !mDataProvider )
3642 return pkAttributesList;
3643
3644 QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
3645 for ( int i = 0; i < mFields.count(); ++i )
3646 {
3647 if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
3648 providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
3649 pkAttributesList << i;
3650 }
3651
3652 return pkAttributesList;
3653}
3654
3656{
3658
3659 if ( !mDataProvider )
3660 return static_cast< long long >( Qgis::FeatureCountState::UnknownCount );
3661 return mDataProvider->featureCount() +
3662 ( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->addedFeatures().size() - mEditBuffer->deletedFeatureIds().size() : 0 );
3663}
3664
3666{
3668
3669 const QgsFeatureIds deletedFeatures( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->deletedFeatureIds() : QgsFeatureIds() );
3670 const QgsFeatureMap addedFeatures( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->addedFeatures() : QgsFeatureMap() );
3671
3672 if ( mEditBuffer && !deletedFeatures.empty() )
3673 {
3674 if ( addedFeatures.size() > deletedFeatures.size() )
3675 return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3676 else
3677 return QgsFeatureSource::FeatureAvailability::FeaturesMaybeAvailable;
3678 }
3679
3680 if ( ( !mEditBuffer || addedFeatures.empty() ) && mDataProvider && mDataProvider->empty() )
3681 return QgsFeatureSource::FeatureAvailability::NoFeaturesAvailable;
3682 else
3683 return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3684}
3685
3686bool QgsVectorLayer::commitChanges( bool stopEditing )
3687{
3689
3690 if ( project() && project()->transactionMode() == Qgis::TransactionMode::BufferedGroups )
3691 return project()->commitChanges( mCommitErrors, stopEditing, this );
3692
3693 mCommitErrors.clear();
3694
3695 if ( !mDataProvider )
3696 {
3697 mCommitErrors << tr( "ERROR: no provider" );
3698 return false;
3699 }
3700
3701 if ( !mEditBuffer )
3702 {
3703 mCommitErrors << tr( "ERROR: layer not editable" );
3704 return false;
3705 }
3706
3707 emit beforeCommitChanges( stopEditing );
3708
3709 if ( !mAllowCommit )
3710 return false;
3711
3712 mCommitChangesActive = true;
3713
3714 bool success = false;
3715 if ( mEditBuffer->editBufferGroup() )
3716 success = mEditBuffer->editBufferGroup()->commitChanges( mCommitErrors, stopEditing );
3717 else
3718 success = mEditBuffer->commitChanges( mCommitErrors );
3719
3720 mCommitChangesActive = false;
3721
3722 if ( !mDeletedFids.empty() )
3723 {
3724 emit featuresDeleted( mDeletedFids );
3725 mDeletedFids.clear();
3726 }
3727
3728 if ( success )
3729 {
3730 if ( stopEditing )
3731 {
3732 clearEditBuffer();
3733 }
3734 undoStack()->clear();
3735 emit afterCommitChanges();
3736 if ( stopEditing )
3737 emit editingStopped();
3738 }
3739 else
3740 {
3741 QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( QLatin1String( "\n " ) ) ) );
3742 }
3743
3744 updateFields();
3745
3746 mDataProvider->updateExtents();
3747 mDataProvider->leaveUpdateMode();
3748
3749 // This second call is required because OGR provider with JSON
3750 // driver might have changed fields order after the call to
3751 // leaveUpdateMode
3752 if ( mFields.names() != mDataProvider->fields().names() )
3753 {
3754 updateFields();
3755 }
3756
3758
3759 return success;
3760}
3761
3763{
3765
3766 return mCommitErrors;
3767}
3768
3769bool QgsVectorLayer::rollBack( bool deleteBuffer )
3770{
3772
3773 if ( project() && project()->transactionMode() == Qgis::TransactionMode::BufferedGroups )
3774 return project()->rollBack( mCommitErrors, deleteBuffer, this );
3775
3776 if ( !mEditBuffer )
3777 {
3778 return false;
3779 }
3780
3781 if ( !mDataProvider )
3782 {
3783 mCommitErrors << tr( "ERROR: no provider" );
3784 return false;
3785 }
3786
3787 bool rollbackExtent = !mDataProvider->transaction() && ( !mEditBuffer->deletedFeatureIds().isEmpty() ||
3788 !mEditBuffer->addedFeatures().isEmpty() ||
3789 !mEditBuffer->changedGeometries().isEmpty() );
3790
3791 emit beforeRollBack();
3792
3793 mEditBuffer->rollBack();
3794
3795 emit afterRollBack();
3796
3797 if ( isModified() )
3798 {
3799 // new undo stack roll back method
3800 // old method of calling every undo could cause many canvas refreshes
3801 undoStack()->setIndex( 0 );
3802 }
3803
3804 updateFields();
3805
3806 if ( deleteBuffer )
3807 {
3808 delete mEditBuffer;
3809 mEditBuffer = nullptr;
3810 undoStack()->clear();
3811 }
3812 emit editingStopped();
3813
3814 if ( rollbackExtent )
3815 updateExtents();
3816
3817 mDataProvider->leaveUpdateMode();
3818
3820 return true;
3821}
3822
3824{
3826
3827 return mSelectedFeatureIds.size();
3828}
3829
3831{
3832 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
3834
3835 return mSelectedFeatureIds;
3836}
3837
3839{
3841
3842 QgsFeatureList features;
3843 features.reserve( mSelectedFeatureIds.count() );
3844 QgsFeature f;
3845
3847
3848 while ( it.nextFeature( f ) )
3849 {
3850 features.push_back( f );
3851 }
3852
3853 return features;
3854}
3855
3857{
3859
3860 if ( mSelectedFeatureIds.isEmpty() )
3861 return QgsFeatureIterator();
3862
3863 if ( geometryType() == Qgis::GeometryType::Null )
3865
3866 if ( mSelectedFeatureIds.count() == 1 )
3867 request.setFilterFid( *mSelectedFeatureIds.constBegin() );
3868 else
3869 request.setFilterFids( mSelectedFeatureIds );
3870
3871 return getFeatures( request );
3872}
3873
3875{
3877
3878 if ( !mEditBuffer || !mDataProvider )
3879 return false;
3880
3881 if ( mGeometryOptions->isActive() )
3882 {
3883 for ( auto feature = features.begin(); feature != features.end(); ++feature )
3884 {
3885 QgsGeometry geom = feature->geometry();
3886 mGeometryOptions->apply( geom );
3887 feature->setGeometry( geom );
3888 }
3889 }
3890
3891 bool res = mEditBuffer->addFeatures( features );
3892 updateExtents();
3893
3894 if ( res && mJoinBuffer->containsJoins() )
3895 res = mJoinBuffer->addFeatures( features );
3896
3897 return res;
3898}
3899
3901{
3903
3904 // if layer is not spatial, it has not CRS!
3905 setCrs( ( isSpatial() && mDataProvider ) ? mDataProvider->crs() : QgsCoordinateReferenceSystem() );
3906}
3907
3909{
3911
3913 if ( exp.isField() )
3914 {
3915 return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
3916 }
3917
3918 return QString();
3919}
3920
3921void QgsVectorLayer::setDisplayExpression( const QString &displayExpression )
3922{
3924
3925 if ( mDisplayExpression == displayExpression )
3926 return;
3927
3928 mDisplayExpression = displayExpression;
3930}
3931
3933{
3935
3936 if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
3937 {
3938 return mDisplayExpression;
3939 }
3940 else
3941 {
3942 const QString candidateName = QgsVectorLayerUtils::guessFriendlyIdentifierField( mFields );
3943 if ( !candidateName.isEmpty() )
3944 {
3945 return QgsExpression::quotedColumnRef( candidateName );
3946 }
3947 else
3948 {
3949 return QString();
3950 }
3951 }
3952}
3953
3955{
3957
3958 // display expressions are used as a fallback when no explicit map tip template is set
3959 return mapTipsEnabled() && ( !mapTipTemplate().isEmpty() || !displayExpression().isEmpty() );
3960}
3961
3963{
3965
3966 return ( mEditBuffer && mDataProvider );
3967}
3968
3970{
3971 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
3973
3975 return t != Qgis::GeometryType::Null && t != Qgis::GeometryType::Unknown;
3976}
3977
3978bool QgsVectorLayer::isReadOnly() const
3979{
3981
3982 return mDataSourceReadOnly || mReadOnly;
3983}
3984
3985bool QgsVectorLayer::setReadOnly( bool readonly )
3986{
3988
3989 // exit if the layer is in editing mode
3990 if ( readonly && mEditBuffer )
3991 return false;
3992
3993 // exit if the data source is in read-only mode
3994 if ( !readonly && mDataSourceReadOnly )
3995 return false;
3996
3997 mReadOnly = readonly;
3998 emit readOnlyChanged();
3999 return true;
4000}
4001
4003{
4005
4006 if ( ! mDataProvider )
4007 return false;
4008
4009 if ( mDataSourceReadOnly )
4010 return false;
4011
4012 return mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities && ! mReadOnly;
4013}
4014
4016{
4018
4019 emit beforeModifiedCheck();
4020 return mEditBuffer && mEditBuffer->isModified();
4021}
4022
4023bool QgsVectorLayer::isAuxiliaryField( int index, int &srcIndex ) const
4024{
4026
4027 bool auxiliaryField = false;
4028 srcIndex = -1;
4029
4030 if ( !auxiliaryLayer() )
4031 return auxiliaryField;
4032
4033 if ( index >= 0 && fields().fieldOrigin( index ) == QgsFields::OriginJoin )
4034 {
4035 const QgsVectorLayerJoinInfo *info = mJoinBuffer->joinForFieldIndex( index, fields(), srcIndex );
4036
4037 if ( info && info->joinLayerId() == auxiliaryLayer()->id() )
4038 auxiliaryField = true;
4039 }
4040
4041 return auxiliaryField;
4042}
4043
4045{
4047
4048 // we must allow setting a renderer if our geometry type is unknown
4049 // as this allows the renderer to be correctly set even for layers
4050 // with broken sources
4051 if ( !isSpatial() && mWkbType != Qgis::WkbType::Unknown )
4052 return;
4053
4054 if ( r != mRenderer )
4055 {
4056 delete mRenderer;
4057 mRenderer = r;
4058 mSymbolFeatureCounted = false;
4059 mSymbolFeatureCountMap.clear();
4060 mSymbolFeatureIdMap.clear();
4061
4062 if ( mRenderer )
4063 {
4064 const double refreshRate = QgsSymbolLayerUtils::rendererFrameRate( mRenderer );
4065 if ( refreshRate <= 0 )
4066 {
4067 mRefreshRendererTimer->stop();
4068 mRefreshRendererTimer->setInterval( 0 );
4069 }
4070 else
4071 {
4072 mRefreshRendererTimer->setInterval( 1000 / refreshRate );
4073 mRefreshRendererTimer->start();
4074 }
4075 }
4076
4077 emit rendererChanged();
4079 }
4080}
4081
4083{
4085
4086 if ( generator )
4087 {
4088 mRendererGenerators << generator;
4089 }
4090}
4091
4093{
4095
4096 for ( int i = mRendererGenerators.count() - 1; i >= 0; --i )
4097 {
4098 if ( mRendererGenerators.at( i )->id() == id )
4099 {
4100 delete mRendererGenerators.at( i );
4101 mRendererGenerators.removeAt( i );
4102 }
4103 }
4104}
4105
4106QList<const QgsFeatureRendererGenerator *> QgsVectorLayer::featureRendererGenerators() const
4107{
4108 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
4110
4111 QList< const QgsFeatureRendererGenerator * > res;
4112 for ( const QgsFeatureRendererGenerator *generator : mRendererGenerators )
4113 res << generator;
4114 return res;
4115}
4116
4117void QgsVectorLayer::beginEditCommand( const QString &text )
4118{
4120
4121 if ( !mDataProvider )
4122 {
4123 return;
4124 }
4125 if ( mDataProvider->transaction() )
4126 {
4127 QString ignoredError;
4128 mDataProvider->transaction()->createSavepoint( ignoredError );
4129 }
4130 undoStack()->beginMacro( text );
4131 mEditCommandActive = true;
4132 emit editCommandStarted( text );
4133}
4134
4136{
4138
4139 if ( !mDataProvider )
4140 {
4141 return;
4142 }
4143 undoStack()->endMacro();
4144 mEditCommandActive = false;
4145 if ( !mDeletedFids.isEmpty() )
4146 {
4147 if ( selectedFeatureCount() > 0 )
4148 {
4149 mSelectedFeatureIds.subtract( mDeletedFids );
4150 }
4151 emit featuresDeleted( mDeletedFids );
4152 mDeletedFids.clear();
4153 }
4154 emit editCommandEnded();
4155}
4156
4158{
4160
4161 if ( !mDataProvider )
4162 {
4163 return;
4164 }
4165 undoStack()->endMacro();
4166 undoStack()->undo();
4167
4168 // it's not directly possible to pop the last command off the stack (the destroyed one)
4169 // and delete, so we add a dummy obsolete command to force this to occur.
4170 // Pushing the new command deletes the destroyed one, and since the new
4171 // command is obsolete it's automatically deleted by the undo stack.
4172 std::unique_ptr< QUndoCommand > command = std::make_unique< QUndoCommand >();
4173 command->setObsolete( true );
4174 undoStack()->push( command.release() );
4175
4176 mEditCommandActive = false;
4177 mDeletedFids.clear();
4178 emit editCommandDestroyed();
4179}
4180
4182{
4184
4185 return mJoinBuffer->addJoin( joinInfo );
4186}
4187
4188bool QgsVectorLayer::removeJoin( const QString &joinLayerId )
4189{
4191
4192 return mJoinBuffer->removeJoin( joinLayerId );
4193}
4194
4195const QList< QgsVectorLayerJoinInfo > QgsVectorLayer::vectorJoins() const
4196{
4198
4199 return mJoinBuffer->vectorJoins();
4200}
4201
4202int QgsVectorLayer::addExpressionField( const QString &exp, const QgsField &fld )
4203{
4205
4206 emit beforeAddingExpressionField( fld.name() );
4207 mExpressionFieldBuffer->addExpression( exp, fld );
4208 updateFields();
4209 int idx = mFields.indexFromName( fld.name() );
4210 emit attributeAdded( idx );
4211 return idx;
4212}
4213
4215{
4217
4218 emit beforeRemovingExpressionField( index );
4219 int oi = mFields.fieldOriginIndex( index );
4220 mExpressionFieldBuffer->removeExpression( oi );
4221 updateFields();
4222 emit attributeDeleted( index );
4223}
4224
4225QString QgsVectorLayer::expressionField( int index ) const
4226{
4228
4229 if ( mFields.fieldOrigin( index ) != QgsFields::OriginExpression )
4230 return QString();
4231
4232 int oi = mFields.fieldOriginIndex( index );
4233 if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
4234 return QString();
4235
4236 return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
4237}
4238
4239void QgsVectorLayer::updateExpressionField( int index, const QString &exp )
4240{
4242
4243 int oi = mFields.fieldOriginIndex( index );
4244 mExpressionFieldBuffer->updateExpression( oi, exp );
4245}
4246
4248{
4249 // non fatal for now -- the QgsVirtualLayerTask class is not thread safe and calls this
4251
4252 if ( !mDataProvider )
4253 return;
4254
4255 QgsFields oldFields = mFields;
4256
4257 mFields = mDataProvider->fields();
4258
4259 // added / removed fields
4260 if ( mEditBuffer )
4261 mEditBuffer->updateFields( mFields );
4262
4263 // joined fields
4264 if ( mJoinBuffer->containsJoins() )
4265 mJoinBuffer->updateFields( mFields );
4266
4267 if ( mExpressionFieldBuffer )
4268 mExpressionFieldBuffer->updateFields( mFields );
4269
4270 // set aliases and default values
4271 for ( auto aliasIt = mAttributeAliasMap.constBegin(); aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
4272 {
4273 int index = mFields.lookupField( aliasIt.key() );
4274 if ( index < 0 )
4275 continue;
4276
4277 mFields[ index ].setAlias( aliasIt.value() );
4278 }
4279
4280 for ( auto splitPolicyIt = mAttributeSplitPolicy.constBegin(); splitPolicyIt != mAttributeSplitPolicy.constEnd(); ++splitPolicyIt )
4281 {
4282 int index = mFields.lookupField( splitPolicyIt.key() );
4283 if ( index < 0 )
4284 continue;
4285
4286 mFields[ index ].setSplitPolicy( splitPolicyIt.value() );
4287 }
4288
4289 // Update configuration flags
4290 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
4291 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
4292 {
4293 int index = mFields.lookupField( flagsIt.key() );
4294 if ( index < 0 )
4295 continue;
4296
4297 mFields[index].setConfigurationFlags( flagsIt.value() );
4298 }
4299
4300 // Update default values
4301 mDefaultValueOnUpdateFields.clear();
4302 QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
4303 for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
4304 {
4305 int index = mFields.lookupField( defaultIt.key() );
4306 if ( index < 0 )
4307 continue;
4308
4309 mFields[ index ].setDefaultValueDefinition( defaultIt.value() );
4310 if ( defaultIt.value().applyOnUpdate() )
4311 mDefaultValueOnUpdateFields.insert( index );
4312 }
4313
4314 QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
4315 for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
4316 {
4317 int index = mFields.lookupField( constraintIt.key() );
4318 if ( index < 0 )
4319 continue;
4320
4321 QgsFieldConstraints constraints = mFields.at( index ).constraints();
4322
4323 // always keep provider constraints intact
4324 if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
4326 if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
4328 if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
4330 mFields[ index ].setConstraints( constraints );
4331 }
4332
4333 QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
4334 for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
4335 {
4336 int index = mFields.lookupField( constraintExpIt.key() );
4337 if ( index < 0 )
4338 continue;
4339
4340 QgsFieldConstraints constraints = mFields.at( index ).constraints();
4341
4342 // always keep provider constraints intact
4344 continue;
4345
4346 constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
4347 mFields[ index ].setConstraints( constraints );
4348 }
4349
4350 QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
4351 for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
4352 {
4353 int index = mFields.lookupField( constraintStrengthIt.key().first );
4354 if ( index < 0 )
4355 continue;
4356
4357 QgsFieldConstraints constraints = mFields.at( index ).constraints();
4358
4359 // always keep provider constraints intact
4361 continue;
4362
4363 constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
4364 mFields[ index ].setConstraints( constraints );
4365 }
4366
4367 auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
4368 for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
4369 {
4370 int index = mFields.indexOf( fieldWidgetIterator.key() );
4371 if ( index < 0 )
4372 continue;
4373
4374 mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
4375 }
4376
4377 if ( oldFields != mFields )
4378 {
4379 emit updatedFields();
4380 mEditFormConfig.setFields( mFields );
4381 }
4382
4383}
4384
4385QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature &feature, QgsExpressionContext *context ) const
4386{
4388
4389 if ( index < 0 || index >= mFields.count() || !mDataProvider )
4390 return QVariant();
4391
4392 QString expression = mFields.at( index ).defaultValueDefinition().expression();
4393 if ( expression.isEmpty() )
4394 return mDataProvider->defaultValue( index );
4395
4396 QgsExpressionContext *evalContext = context;
4397 std::unique_ptr< QgsExpressionContext > tempContext;
4398 if ( !evalContext )
4399 {
4400 // no context passed, so we create a default one
4402 evalContext = tempContext.get();
4403 }
4404
4405 if ( feature.isValid() )
4406 {
4408 featScope->setFeature( feature );
4409 featScope->setFields( feature.fields() );
4410 evalContext->appendScope( featScope );
4411 }
4412
4413 QVariant val;
4414 QgsExpression exp( expression );
4415 exp.prepare( evalContext );
4416 if ( exp.hasEvalError() )
4417 {
4418 QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
4419 }
4420 else
4421 {
4422 val = exp.evaluate( evalContext );
4423 }
4424
4425 if ( feature.isValid() )
4426 {
4427 delete evalContext->popScope();
4428 }
4429
4430 return val;
4431}
4432
4434{
4436
4437 if ( index < 0 || index >= mFields.count() )
4438 return;
4439
4440 if ( definition.isValid() )
4441 {
4442 mDefaultExpressionMap.insert( mFields.at( index ).name(), definition );
4443 }
4444 else
4445 {
4446 mDefaultExpressionMap.remove( mFields.at( index ).name() );
4447 }
4448 updateFields();
4449}
4450
4452{
4454
4455 if ( index < 0 || index >= mFields.count() )
4456 return QgsDefaultValue();
4457 else
4458 return mFields.at( index ).defaultValueDefinition();
4459}
4460
4461QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
4462{
4464
4465 QSet<QVariant> uniqueValues;
4466 if ( !mDataProvider )
4467 {
4468 return uniqueValues;
4469 }
4470
4471 QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4472 switch ( origin )
4473 {
4475 return uniqueValues;
4476
4477 case QgsFields::OriginProvider: //a provider field
4478 {
4479 uniqueValues = mDataProvider->uniqueValues( index, limit );
4480
4481 if ( mEditBuffer && ! mDataProvider->transaction() )
4482 {
4483 QSet<QString> vals;
4484 const auto constUniqueValues = uniqueValues;
4485 for ( const QVariant &v : constUniqueValues )
4486 {
4487 vals << v.toString();
4488 }
4489
4490 QgsFeatureMap added = mEditBuffer->addedFeatures();
4491 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4492 while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
4493 {
4494 addedIt.next();
4495 QVariant v = addedIt.value().attribute( index );
4496 if ( v.isValid() )
4497 {
4498 QString vs = v.toString();
4499 if ( !vals.contains( vs ) )
4500 {
4501 vals << vs;
4502 uniqueValues << v;
4503 }
4504 }
4505 }
4506
4507 QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4508 while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
4509 {
4510 it.next();
4511 QVariant v = it.value().value( index );
4512 if ( v.isValid() )
4513 {
4514 QString vs = v.toString();
4515 if ( !vals.contains( vs ) )
4516 {
4517 vals << vs;
4518 uniqueValues << v;
4519 }
4520 }
4521 }
4522 }
4523
4524 return uniqueValues;
4525 }
4526
4528 // the layer is editable, but in certain cases it can still be avoided going through all features
4529 if ( mDataProvider->transaction() || (
4530 mEditBuffer->deletedFeatureIds().isEmpty() &&
4531 mEditBuffer->addedFeatures().isEmpty() &&
4532 !mEditBuffer->deletedAttributeIds().contains( index ) &&
4533 mEditBuffer->changedAttributeValues().isEmpty() ) )
4534 {
4535 uniqueValues = mDataProvider->uniqueValues( index, limit );
4536 return uniqueValues;
4537 }
4539 //we need to go through each feature
4542 {
4543 QgsAttributeList attList;
4544 attList << index;
4545
4548 .setSubsetOfAttributes( attList ) );
4549
4550 QgsFeature f;
4551 QVariant currentValue;
4552 QHash<QString, QVariant> val;
4553 while ( fit.nextFeature( f ) )
4554 {
4555 currentValue = f.attribute( index );
4556 val.insert( currentValue.toString(), currentValue );
4557 if ( limit >= 0 && val.size() >= limit )
4558 {
4559 break;
4560 }
4561 }
4562
4563 return qgis::listToSet( val.values() );
4564 }
4565 }
4566
4567 Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
4568 return uniqueValues;
4569}
4570
4571QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
4572{
4574
4575 QStringList results;
4576 if ( !mDataProvider )
4577 {
4578 return results;
4579 }
4580
4581 QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4582 switch ( origin )
4583 {
4585 return results;
4586
4587 case QgsFields::OriginProvider: //a provider field
4588 {
4589 results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
4590
4591 if ( mEditBuffer && ! mDataProvider->transaction() )
4592 {
4593 QgsFeatureMap added = mEditBuffer->addedFeatures();
4594 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4595 while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
4596 {
4597 addedIt.next();
4598 QVariant v = addedIt.value().attribute( index );
4599 if ( v.isValid() )
4600 {
4601 QString vs = v.toString();
4602 if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4603 {
4604 results << vs;
4605 }
4606 }
4607 }
4608
4609 QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4610 while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
4611 {
4612 it.next();
4613 QVariant v = it.value().value( index );
4614 if ( v.isValid() )
4615 {
4616 QString vs = v.toString();
4617 if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4618 {
4619 results << vs;
4620 }
4621 }
4622 }
4623 }
4624
4625 return results;
4626 }
4627
4629 // the layer is editable, but in certain cases it can still be avoided going through all features
4630 if ( mDataProvider->transaction() || ( mEditBuffer->deletedFeatureIds().isEmpty() &&
4631 mEditBuffer->addedFeatures().isEmpty() &&
4632 !mEditBuffer->deletedAttributeIds().contains( index ) &&
4633 mEditBuffer->changedAttributeValues().isEmpty() ) )
4634 {
4635 return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
4636 }
4638 //we need to go through each feature
4641 {
4642 QgsAttributeList attList;
4643 attList << index;
4644
4645 QgsFeatureRequest request;
4646 request.setSubsetOfAttributes( attList );
4648 QString fieldName = mFields.at( index ).name();
4649 request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
4650 QgsFeatureIterator fit = getFeatures( request );
4651
4652 QgsFeature f;
4653 QString currentValue;
4654 while ( fit.nextFeature( f ) )
4655 {
4656 currentValue = f.attribute( index ).toString();
4657 if ( !results.contains( currentValue ) )
4658 results << currentValue;
4659
4660 if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
4661 {
4662 break;
4663 }
4664 }
4665
4666 return results;
4667 }
4668 }
4669
4670 Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
4671 return results;
4672}
4673
4674QVariant QgsVectorLayer::minimumValue( int index ) const
4675{
4677
4678 QVariant minimum;
4679 minimumOrMaximumValue( index, &minimum, nullptr );
4680 return minimum;
4681}
4682
4683QVariant QgsVectorLayer::maximumValue( int index ) const
4684{
4686
4687 QVariant maximum;
4688 minimumOrMaximumValue( index, nullptr, &maximum );
4689 return maximum;
4690}
4691
4692void QgsVectorLayer::minimumAndMaximumValue( int index, QVariant &minimum, QVariant &maximum ) const
4693{
4695
4696 minimumOrMaximumValue( index, &minimum, &maximum );
4697}
4698
4699void QgsVectorLayer::minimumOrMaximumValue( int index, QVariant *minimum, QVariant *maximum ) const
4700{
4702
4703 if ( minimum )
4704 *minimum = QVariant();
4705 if ( maximum )
4706 *maximum = QVariant();
4707
4708 if ( !mDataProvider )
4709 {
4710 return;
4711 }
4712
4713 QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4714
4715 switch ( origin )
4716 {
4718 {
4719 return;
4720 }
4721
4722 case QgsFields::OriginProvider: //a provider field
4723 {
4724 if ( minimum )
4725 *minimum = mDataProvider->minimumValue( index );
4726 if ( maximum )
4727 *maximum = mDataProvider->maximumValue( index );
4728 if ( mEditBuffer && ! mDataProvider->transaction() )
4729 {
4730 const QgsFeatureMap added = mEditBuffer->addedFeatures();
4731 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4732 while ( addedIt.hasNext() )
4733 {
4734 addedIt.next();
4735 const QVariant v = addedIt.value().attribute( index );
4736 if ( minimum && v.isValid() && qgsVariantLessThan( v, *minimum ) )
4737 *minimum = v;
4738 if ( maximum && v.isValid() && qgsVariantGreaterThan( v, *maximum ) )
4739 *maximum = v;
4740 }
4741
4742 QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4743 while ( it.hasNext() )
4744 {
4745 it.next();
4746 const QVariant v = it.value().value( index );
4747 if ( minimum && v.isValid() && qgsVariantLessThan( v, *minimum ) )
4748 *minimum = v;
4749 if ( maximum && v.isValid() && qgsVariantGreaterThan( v, *maximum ) )
4750 *maximum = v;
4751 }
4752 }
4753 return;
4754 }
4755
4757 {
4758 // the layer is editable, but in certain cases it can still be avoided going through all features
4759 if ( mDataProvider->transaction() || ( mEditBuffer->deletedFeatureIds().isEmpty() &&
4760 mEditBuffer->addedFeatures().isEmpty() &&
4761 !mEditBuffer->deletedAttributeIds().contains( index ) &&
4762 mEditBuffer->changedAttributeValues().isEmpty() ) )
4763 {
4764 if ( minimum )
4765 *minimum = mDataProvider->minimumValue( index );
4766 if ( maximum )
4767 *maximum = mDataProvider->maximumValue( index );
4768 return;
4769 }
4770 }
4772 // no choice but to go through all features
4775 {
4776 // we need to go through each feature
4777 QgsAttributeList attList;
4778 attList << index;
4779
4782 .setSubsetOfAttributes( attList ) );
4783
4784 QgsFeature f;
4785 bool firstValue = true;
4786 while ( fit.nextFeature( f ) )
4787 {
4788 const QVariant currentValue = f.attribute( index );
4789 if ( QgsVariantUtils::isNull( currentValue ) )
4790 continue;
4791
4792 if ( firstValue )
4793 {
4794 if ( minimum )
4795 *minimum = currentValue;
4796 if ( maximum )
4797 *maximum = currentValue;
4798 firstValue = false;
4799 }
4800 else
4801 {
4802 if ( minimum && currentValue.isValid() && qgsVariantLessThan( currentValue, *minimum ) )
4803 *minimum = currentValue;
4804 if ( maximum && currentValue.isValid() && qgsVariantGreaterThan( currentValue, *maximum ) )
4805 *maximum = currentValue;
4806 }
4807 }
4808 return;
4809 }
4810 }
4811
4812 Q_ASSERT_X( false, "QgsVectorLayer::minimumOrMaximumValue()", "Unknown source of the field!" );
4813}
4814
4815void QgsVectorLayer::createEditBuffer()
4816{
4818
4819 if ( mEditBuffer )
4820 clearEditBuffer();
4821
4822 if ( mDataProvider->transaction() )
4823 {
4824 mEditBuffer = new QgsVectorLayerEditPassthrough( this );
4825
4826 connect( mDataProvider->transaction(), &QgsTransaction::dirtied, this, &QgsVectorLayer::onDirtyTransaction, Qt::UniqueConnection );
4827 }
4828 else
4829 {
4830 mEditBuffer = new QgsVectorLayerEditBuffer( this );
4831 }
4832 // forward signals
4833 connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::invalidateSymbolCountedFlag );
4834 connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::layerModified ); // TODO[MD]: necessary?
4835 //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
4837 connect( mEditBuffer, &QgsVectorLayerEditBuffer::featureDeleted, this, &QgsVectorLayer::onFeatureDeleted );
4848
4849}
4850
4851void QgsVectorLayer::clearEditBuffer()
4852{
4854
4855 delete mEditBuffer;
4856 mEditBuffer = nullptr;
4857}
4858
4859QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression,
4861 bool *ok, QgsFeatureIds *fids, QgsFeedback *feedback, QString *error ) const
4862{
4863 // non fatal for now -- the aggregate expression functions are not thread safe and call this
4865
4866 if ( ok )
4867 *ok = false;
4868 if ( error )
4869 error->clear();
4870
4871 if ( !mDataProvider )
4872 {
4873 if ( error )
4874 *error = tr( "Layer is invalid" );
4875 return QVariant();
4876 }
4877
4878 // test if we are calculating based on a field
4879 const int attrIndex = QgsExpression::expressionToLayerFieldIndex( fieldOrExpression, this );
4880 if ( attrIndex >= 0 )
4881 {
4882 // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
4883 // to the provider itself
4884 QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
4885 if ( origin == QgsFields::OriginProvider )
4886 {
4887 bool providerOk = false;
4888 QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk, fids );
4889 if ( providerOk )
4890 {
4891 // provider handled calculation
4892 if ( ok )
4893 *ok = true;
4894 return val;
4895 }
4896 }
4897 }
4898
4899 // fallback to using aggregate calculator to determine aggregate
4900 QgsAggregateCalculator c( this );
4901 if ( fids )
4902 c.setFidsFilter( *fids );
4903 c.setParameters( parameters );
4904 bool aggregateOk = false;
4905 const QVariant result = c.calculate( aggregate, fieldOrExpression, context, &aggregateOk, feedback );
4906 if ( ok )
4907 *ok = aggregateOk;
4908 if ( !aggregateOk && error )
4909 *error = c.lastError();
4910
4911 return result;
4912}
4913
4914void QgsVectorLayer::setFeatureBlendMode( QPainter::CompositionMode featureBlendMode )
4915{
4917
4918 if ( mFeatureBlendMode == featureBlendMode )
4919 return;
4920
4921 mFeatureBlendMode = featureBlendMode;
4924}
4925
4926QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
4927{
4928 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
4930
4931 return mFeatureBlendMode;
4932}
4933
4934void QgsVectorLayer::readSldLabeling( const QDomNode &node )
4935{
4937
4938 setLabeling( nullptr ); // start with no labeling
4939 setLabelsEnabled( false );
4940
4941 QDomElement element = node.toElement();
4942 if ( element.isNull() )
4943 return;
4944
4945 QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
4946 if ( userStyleElem.isNull() )
4947 {
4948 QgsDebugMsgLevel( QStringLiteral( "Info: UserStyle element not found." ), 4 );
4949 return;
4950 }
4951
4952 QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
4953 if ( featTypeStyleElem.isNull() )
4954 {
4955 QgsDebugMsgLevel( QStringLiteral( "Info: FeatureTypeStyle element not found." ), 4 );
4956 return;
4957 }
4958
4959 // create empty FeatureTypeStyle element to merge TextSymbolizer's Rule's from all FeatureTypeStyle's
4960 QDomElement mergedFeatTypeStyle = featTypeStyleElem.cloneNode( false ).toElement();
4961
4962 // use the RuleRenderer when more rules are present or the rule
4963 // has filters or min/max scale denominators set,
4964 // otherwise use the Simple labeling
4965 bool needRuleBasedLabeling = false;
4966 int ruleCount = 0;
4967
4968 while ( !featTypeStyleElem.isNull() )
4969 {
4970 QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral( "Rule" ) );
4971 while ( !ruleElem.isNull() )
4972 {
4973 // test rule children element to check if we need to create RuleRenderer
4974 // and if the rule has a symbolizer
4975 bool hasTextSymbolizer = false;
4976 bool hasRuleBased = false;
4977 QDomElement ruleChildElem = ruleElem.firstChildElement();
4978 while ( !ruleChildElem.isNull() )
4979 {
4980 // rule has filter or min/max scale denominator, use the RuleRenderer
4981 if ( ruleChildElem.localName() == QLatin1String( "Filter" ) ||
4982 ruleChildElem.localName() == QLatin1String( "MinScaleDenominator" ) ||
4983 ruleChildElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
4984 {
4985 hasRuleBased = true;
4986 }
4987 // rule has a renderer symbolizer, not a text symbolizer
4988 else if ( ruleChildElem.localName() == QLatin1String( "TextSymbolizer" ) )
4989 {
4990 QgsDebugMsgLevel( QStringLiteral( "Info: TextSymbolizer element found" ), 4 );
4991 hasTextSymbolizer = true;
4992 }
4993
4994 ruleChildElem = ruleChildElem.nextSiblingElement();
4995 }
4996
4997 if ( hasTextSymbolizer )
4998 {
4999 ruleCount++;
5000
5001 // append a clone of all Rules to the merged FeatureTypeStyle element
5002 mergedFeatTypeStyle.appendChild( ruleElem.cloneNode().toElement() );
5003
5004 if ( hasRuleBased )
5005 {
5006 QgsDebugMsgLevel( QStringLiteral( "Info: Filter or Min/MaxScaleDenominator element found: need a RuleBasedLabeling" ), 4 );
5007 needRuleBasedLabeling = true;
5008 }
5009 }
5010
5011 // more rules present, use the RuleRenderer
5012 if ( ruleCount > 1 )
5013 {
5014 QgsDebugMsgLevel( QStringLiteral( "Info: More Rule elements found: need a RuleBasedLabeling" ), 4 );
5015 needRuleBasedLabeling = true;
5016 }
5017
5018 // not use the rule based labeling if no rules with textSymbolizer
5019 if ( ruleCount == 0 )
5020 {
5021 needRuleBasedLabeling = false;
5022 }
5023
5024 ruleElem = ruleElem.nextSiblingElement( QStringLiteral( "Rule" ) );
5025 }
5026 featTypeStyleElem = featTypeStyleElem.nextSiblingElement( QStringLiteral( "FeatureTypeStyle" ) );
5027 }
5028
5029 if ( ruleCount == 0 )
5030 {
5031 QgsDebugMsgLevel( QStringLiteral( "Info: No TextSymbolizer element." ), 4 );
5032 return;
5033 }
5034
5035 QDomElement ruleElem = mergedFeatTypeStyle.firstChildElement( QStringLiteral( "Rule" ) );
5036
5037 if ( needRuleBasedLabeling )
5038 {
5039 QgsDebugMsgLevel( QStringLiteral( "Info: rule based labeling" ), 4 );
5040 QgsRuleBasedLabeling::Rule *rootRule = new QgsRuleBasedLabeling::Rule( nullptr );
5041 while ( !ruleElem.isNull() )
5042 {
5043
5044 QString label, description, filterExp;
5045 int scaleMinDenom = 0, scaleMaxDenom = 0;
5046 QgsPalLayerSettings settings;
5047
5048 // retrieve the Rule element child nodes
5049 QDomElement childElem = ruleElem.firstChildElement();
5050 while ( !childElem.isNull() )
5051 {
5052 if ( childElem.localName() == QLatin1String( "Name" ) )
5053 {
5054 // <se:Name> tag contains the rule identifier,
5055 // so prefer title tag for the label property value
5056 if ( label.isEmpty() )
5057 label = childElem.firstChild().nodeValue();
5058 }
5059 else if ( childElem.localName() == QLatin1String( "Description" ) )
5060 {
5061 // <se:Description> can contains a title and an abstract
5062 QDomElement titleElem = childElem.firstChildElement( QStringLiteral( "Title" ) );
5063 if ( !titleElem.isNull() )
5064 {
5065 label = titleElem.firstChild().nodeValue();
5066 }
5067
5068 QDomElement abstractElem = childElem.firstChildElement( QStringLiteral( "Abstract" ) );
5069 if ( !abstractElem.isNull() )
5070 {
5071 description = abstractElem.firstChild().nodeValue();
5072 }
5073 }
5074 else if ( childElem.localName() == QLatin1String( "Abstract" ) )
5075 {
5076 // <sld:Abstract> (v1.0)
5077 description = childElem.firstChild().nodeValue();
5078 }
5079 else if ( childElem.localName() == QLatin1String( "Title" ) )
5080 {
5081 // <sld:Title> (v1.0)
5082 label = childElem.firstChild().nodeValue();
5083 }
5084 else if ( childElem.localName() == QLatin1String( "Filter" ) )
5085 {
5087 if ( filter )
5088 {
5089 if ( filter->hasParserError() )
5090 {
5091 QgsDebugMsgLevel( QStringLiteral( "SLD Filter parsing error: %1" ).arg( filter->parserErrorString() ), 3 );
5092 }
5093 else
5094 {
5095 filterExp = filter->expression();
5096 }
5097 delete filter;
5098 }
5099 }
5100 else if ( childElem.localName() == QLatin1String( "MinScaleDenominator" ) )
5101 {
5102 bool ok;
5103 int v = childElem.firstChild().nodeValue().toInt( &ok );
5104 if ( ok )
5105 scaleMinDenom = v;
5106 }
5107 else if ( childElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
5108 {
5109 bool ok;
5110 int v = childElem.firstChild().nodeValue().toInt( &ok );
5111 if ( ok )
5112 scaleMaxDenom = v;
5113 }
5114 else if ( childElem.localName() == QLatin1String( "TextSymbolizer" ) )
5115 {
5116 readSldTextSymbolizer( childElem, settings );
5117 }
5118
5119 childElem = childElem.nextSiblingElement();
5120 }
5121
5122 QgsRuleBasedLabeling::Rule *ruleLabeling = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings( settings ), scaleMinDenom, scaleMaxDenom, filterExp, label );
5123 rootRule->appendChild( ruleLabeling );
5124
5125 ruleElem = ruleElem.nextSiblingElement();
5126 }
5127
5128 setLabeling( new QgsRuleBasedLabeling( rootRule ) );
5129 setLabelsEnabled( true );
5130 }
5131 else
5132 {
5133 QgsDebugMsgLevel( QStringLiteral( "Info: simple labeling" ), 4 );
5134 // retrieve the TextSymbolizer element child node
5135 QDomElement textSymbolizerElem = ruleElem.firstChildElement( QStringLiteral( "TextSymbolizer" ) );
5137 if ( readSldTextSymbolizer( textSymbolizerElem, s ) )
5138 {
5140 setLabelsEnabled( true );
5141 }
5142 }
5143}
5144
5145bool QgsVectorLayer::readSldTextSymbolizer( const QDomNode &node, QgsPalLayerSettings &settings ) const
5146{
5148
5149 if ( node.localName() != QLatin1String( "TextSymbolizer" ) )
5150 {
5151 QgsDebugMsgLevel( QStringLiteral( "Not a TextSymbolizer element: %1" ).arg( node.localName() ), 3 );
5152 return false;
5153 }
5154 QDomElement textSymbolizerElem = node.toElement();
5155 // Label
5156 QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
5157 if ( !labelElem.isNull() )
5158 {
5159 QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
5160 if ( !propertyNameElem.isNull() )
5161 {
5162 // set labeling defaults
5163
5164 // label attribute
5165 QString labelAttribute = propertyNameElem.text();
5166 settings.fieldName = labelAttribute;
5167 settings.isExpression = false;
5168
5169 int fieldIndex = mFields.lookupField( labelAttribute );
5170 if ( fieldIndex == -1 )
5171 {
5172 // label attribute is not in columns, check if it is an expression
5173 QgsExpression exp( labelAttribute );
5174 if ( !exp.hasEvalError() )
5175 {
5176 settings.isExpression = true;
5177 }
5178 else
5179 {
5180 QgsDebugMsgLevel( QStringLiteral( "SLD label attribute error: %1" ).arg( exp.evalErrorString() ), 3 );
5181 }
5182 }
5183 }
5184 else
5185 {
5186 QgsDebugMsgLevel( QStringLiteral( "Info: PropertyName element not found." ), 4 );
5187 return false;
5188 }
5189 }
5190 else
5191 {
5192 QgsDebugMsgLevel( QStringLiteral( "Info: Label element not found." ), 4 );
5193 return false;
5194 }
5195
5196 Qgis::RenderUnit sldUnitSize = Qgis::RenderUnit::Pixels;
5197 if ( textSymbolizerElem.hasAttribute( QStringLiteral( "uom" ) ) )
5198 {
5199 sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( textSymbolizerElem.attribute( QStringLiteral( "uom" ) ) );
5200 }
5201
5202 QString fontFamily = QStringLiteral( "Sans-Serif" );
5203 int fontPointSize = 10;
5204 Qgis::RenderUnit fontUnitSize = Qgis::RenderUnit::Points;
5205 int fontWeight = -1;
5206 bool fontItalic = false;
5207 bool fontUnderline = false;
5208
5209 // Font
5210 QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
5211 if ( !fontElem.isNull() )
5212 {
5213 QgsStringMap fontSvgParams = QgsSymbolLayerUtils::getSvgParameterList( fontElem );
5214 for ( QgsStringMap::iterator it = fontSvgParams.begin(); it != fontSvgParams.end(); ++it )
5215 {
5216 QgsDebugMsgLevel( QStringLiteral( "found fontSvgParams %1: %2" ).arg( it.key(), it.value() ), 4 );
5217
5218 if ( it.key() == QLatin1String( "font-family" ) )
5219 {
5220 fontFamily = it.value();
5221 }
5222 else if ( it.key() == QLatin1String( "font-style" ) )
5223 {
5224 fontItalic = ( it.value() == QLatin1String( "italic" ) ) || ( it.value() == QLatin1String( "Italic" ) );
5225 }
5226 else if ( it.key() == QLatin1String( "font-size" ) )
5227 {
5228 bool ok;
5229 int fontSize = it.value().toInt( &ok );
5230 if ( ok )
5231 {
5232 fontPointSize = fontSize;
5233 fontUnitSize = sldUnitSize;
5234 }
5235 }
5236 else if ( it.key() == QLatin1String( "font-weight" ) )
5237 {
5238 if ( ( it.value() == QLatin1String( "bold" ) ) || ( it.value() == QLatin1String( "Bold" ) ) )
5239 fontWeight = QFont::Bold;
5240 }
5241 else if ( it.key() == QLatin1String( "font-underline" ) )
5242 {
5243 fontUnderline = ( it.value() == QLatin1String( "underline" ) ) || ( it.value() == QLatin1String( "Underline" ) );
5244 }
5245 }
5246 }
5247
5248 QgsTextFormat format;
5249 QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
5250 font.setUnderline( fontUnderline );
5251 format.setFont( font );
5252 format.setSize( fontPointSize );
5253 format.setSizeUnit( fontUnitSize );
5254
5255 // Fill
5256 QDomElement fillElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) );
5257 QColor textColor;
5258 Qt::BrushStyle textBrush = Qt::SolidPattern;
5259 QgsSymbolLayerUtils::fillFromSld( fillElem, textBrush, textColor );
5260 if ( textColor.isValid() )
5261 {
5262 QgsDebugMsgLevel( QStringLiteral( "Info: textColor %1." ).arg( QVariant( textColor ).toString() ), 4 );
5263 format.setColor( textColor );
5264 }
5265
5266 QgsTextBufferSettings bufferSettings;
5267
5268 // Halo
5269 QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
5270 if ( !haloElem.isNull() )
5271 {
5272 bufferSettings.setEnabled( true );
5273 bufferSettings.setSize( 1 );
5274
5275 QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
5276 if ( !radiusElem.isNull() )
5277 {
5278 bool ok;
5279 double bufferSize = radiusElem.text().toDouble( &ok );
5280 if ( ok )
5281 {
5282 bufferSettings.setSize( bufferSize );
5283 bufferSettings.setSizeUnit( sldUnitSize );
5284 }
5285 }
5286
5287 QDomElement haloFillElem = haloElem.firstChildElement( QStringLiteral( "Fill" ) );
5288 QColor bufferColor;
5289 Qt::BrushStyle bufferBrush = Qt::SolidPattern;
5290 QgsSymbolLayerUtils::fillFromSld( haloFillElem, bufferBrush, bufferColor );
5291 if ( bufferColor.isValid() )
5292 {
5293 QgsDebugMsgLevel( QStringLiteral( "Info: bufferColor %1." ).arg( QVariant( bufferColor ).toString() ), 4 );
5294 bufferSettings.setColor( bufferColor );
5295 }
5296 }
5297
5298 // LabelPlacement
5299 QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
5300 if ( !labelPlacementElem.isNull() )
5301 {
5302 // PointPlacement
5303 QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
5304 if ( !pointPlacementElem.isNull() )
5305 {
5307 if ( geometryType() == Qgis::GeometryType::Line )
5308 {
5310 }
5311
5312 QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
5313 if ( !displacementElem.isNull() )
5314 {
5315 QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
5316 if ( !displacementXElem.isNull() )
5317 {
5318 bool ok;
5319 double xOffset = displacementXElem.text().toDouble( &ok );
5320 if ( ok )
5321 {
5322 settings.xOffset = xOffset;
5323 settings.offsetUnits = sldUnitSize;
5324 }
5325 }
5326 QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
5327 if ( !displacementYElem.isNull() )
5328 {
5329 bool ok;
5330 double yOffset = displacementYElem.text().toDouble( &ok );
5331 if ( ok )
5332 {
5333 settings.yOffset = yOffset;
5334 settings.offsetUnits = sldUnitSize;
5335 }
5336 }
5337 }
5338 QDomElement anchorPointElem = pointPlacementElem.firstChildElement( QStringLiteral( "AnchorPoint" ) );
5339 if ( !anchorPointElem.isNull() )
5340 {
5341 QDomElement anchorPointXElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointX" ) );
5342 if ( !anchorPointXElem.isNull() )
5343 {
5344 bool ok;
5345 double xOffset = anchorPointXElem.text().toDouble( &ok );
5346 if ( ok )
5347 {
5348 settings.xOffset = xOffset;
5349 settings.offsetUnits = sldUnitSize;
5350 }
5351 }
5352 QDomElement anchorPointYElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointY" ) );
5353 if ( !anchorPointYElem.isNull() )
5354 {
5355 bool ok;
5356 double yOffset = anchorPointYElem.text().toDouble( &ok );
5357 if ( ok )
5358 {
5359 settings.yOffset = yOffset;
5360 settings.offsetUnits = sldUnitSize;
5361 }
5362 }
5363 }
5364
5365 QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
5366 if ( !rotationElem.isNull() )
5367 {
5368 bool ok;
5369 double rotation = rotationElem.text().toDouble( &ok );
5370 if ( ok )
5371 {
5372 settings.angleOffset = 360 - rotation;
5373 }
5374 }
5375 }
5376 else
5377 {
5378 // PointPlacement
5379 QDomElement linePlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "LinePlacement" ) );
5380 if ( !linePlacementElem.isNull() )
5381 {
5383 }
5384 }
5385 }
5386
5387 // read vendor options
5388 QgsStringMap vendorOptions;
5389 QDomElement vendorOptionElem = textSymbolizerElem.firstChildElement( QStringLiteral( "VendorOption" ) );
5390 while ( !vendorOptionElem.isNull() && vendorOptionElem.localName() == QLatin1String( "VendorOption" ) )
5391 {
5392 QString optionName = vendorOptionElem.attribute( QStringLiteral( "name" ) );
5393 QString optionValue;
5394 if ( vendorOptionElem.firstChild().nodeType() == QDomNode::TextNode )
5395 {
5396 optionValue = vendorOptionElem.firstChild().nodeValue();
5397 }
5398 else
5399 {
5400 if ( vendorOptionElem.firstChild().nodeType() == QDomNode::ElementNode &&
5401 vendorOptionElem.firstChild().localName() == QLatin1String( "Literal" ) )
5402 {
5403 QgsDebugMsgLevel( vendorOptionElem.firstChild().localName(), 2 );
5404 optionValue = vendorOptionElem.firstChild().firstChild().nodeValue();
5405 }
5406 else
5407 {
5408 QgsDebugError( QStringLiteral( "unexpected child of %1 named %2" ).arg( vendorOptionElem.localName(), optionName ) );
5409 }
5410 }
5411
5412 if ( !optionName.isEmpty() && !optionValue.isEmpty() )
5413 {
5414 vendorOptions[ optionName ] = optionValue;
5415 }
5416
5417 vendorOptionElem = vendorOptionElem.nextSiblingElement();
5418 }
5419 if ( !vendorOptions.isEmpty() )
5420 {
5421 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
5422 {
5423 if ( it.key() == QLatin1String( "underlineText" ) && it.value() == QLatin1String( "true" ) )
5424 {
5425 font.setUnderline( true );
5426 format.setFont( font );
5427 }
5428 else if ( it.key() == QLatin1String( "strikethroughText" ) && it.value() == QLatin1String( "true" ) )
5429 {
5430 font.setStrikeOut( true );
5431 format.setFont( font );
5432 }
5433 else if ( it.key() == QLatin1String( "maxDisplacement" ) )
5434 {
5436 }
5437 else if ( it.key() == QLatin1String( "followLine" ) && it.value() == QLatin1String( "true" ) )
5438 {
5439 if ( geometryType() == Qgis::GeometryType::Polygon )
5440 {
5442 }
5443 else
5444 {
5446 }
5447 }
5448 else if ( it.key() == QLatin1String( "maxAngleDelta" ) )
5449 {
5450 bool ok;
5451 double angle = it.value().toDouble( &ok );
5452 if ( ok )
5453 {
5454 settings.maxCurvedCharAngleIn = angle;
5455 settings.maxCurvedCharAngleOut = angle;
5456 }
5457 }
5458 // miscellaneous options
5459 else if ( it.key() == QLatin1String( "conflictResolution" ) && it.value() == QLatin1String( "false" ) )
5460 {
5462 }
5463 else if ( it.key() == QLatin1String( "forceLeftToRight" ) && it.value() == QLatin1String( "false" ) )
5464 {
5465 settings.upsidedownLabels = Qgis::UpsideDownLabelHandling::AlwaysAllowUpsideDown;
5466 }
5467 else if ( it.key() == QLatin1String( "group" ) && it.value() == QLatin1String( "yes" ) )
5468 {
5469 settings.lineSettings().setMergeLines( true );
5470 }
5471 else if ( it.key() == QLatin1String( "labelAllGroup" ) && it.value() == QLatin1String( "true" ) )
5472 {
5473 settings.lineSettings().setMergeLines( true );
5474 }
5475 }
5476 }
5477
5478 format.setBuffer( bufferSettings );
5479 settings.setFormat( format );
5480 return true;
5481}
5482
5484{
5486
5487 return mEditFormConfig;
5488}
5489
5491{
5493
5494 if ( mEditFormConfig == editFormConfig )
5495 return;
5496
5497 mEditFormConfig = editFormConfig;
5498 mEditFormConfig.onRelationsLoaded();
5499 emit editFormConfigChanged();
5500}
5501
5503{
5505
5506 QgsAttributeTableConfig config = mAttributeTableConfig;
5507
5508 if ( config.isEmpty() )
5509 config.update( fields() );
5510
5511 return config;
5512}
5513
5515{
5517
5518 if ( mAttributeTableConfig != attributeTableConfig )
5519 {
5520 mAttributeTableConfig = attributeTableConfig;
5521 emit configChanged();
5522 }
5523}
5524
5526{
5527 // called in a non-thread-safe way in some cases when calculating aggregates in a different thread
5529
5531}
5532
5534{
5536
5538}
5539
5541{
5543
5544 if ( !mDiagramLayerSettings )
5545 mDiagramLayerSettings = new QgsDiagramLayerSettings();
5546 *mDiagramLayerSettings = s;
5547}
5548
5550{
5552
5553 QgsLayerMetadataFormatter htmlFormatter( metadata() );
5554 QString myMetadata = QStringLiteral( "<html><head></head>\n<body>\n" );
5555
5556 myMetadata += generalHtmlMetadata();
5557
5558 // Begin Provider section
5559 myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
5560 myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
5561
5562 // storage type
5563 if ( !storageType().isEmpty() )
5564 {
5565 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Storage" ) + QStringLiteral( "</td><td>" ) + storageType() + QStringLiteral( "</td></tr>\n" );
5566 }
5567
5568 // comment
5569 if ( !dataComment().isEmpty() )
5570 {
5571 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Comment" ) + QStringLiteral( "</td><td>" ) + dataComment() + QStringLiteral( "</td></tr>\n" );
5572 }
5573
5574 // encoding
5575 const QgsVectorDataProvider *provider = dataProvider();
5576 if ( provider )
5577 {
5578 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Encoding" ) + QStringLiteral( "</td><td>" ) + provider->encoding() + QStringLiteral( "</td></tr>\n" );
5579 }
5580
5581 if ( isSpatial() )
5582 {
5583 // geom type
5585 if ( static_cast<int>( type ) < 0 || static_cast< int >( type ) > static_cast< int >( Qgis::GeometryType::Null ) )
5586 {
5587 QgsDebugMsgLevel( QStringLiteral( "Invalid vector type" ), 2 );
5588 }
5589 else
5590 {
5591 QString typeString( QStringLiteral( "%1 (%2)" ).arg( QgsWkbTypes::geometryDisplayString( geometryType() ),
5593 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Geometry" ) + QStringLiteral( "</td><td>" ) + typeString + QStringLiteral( "</td></tr>\n" );
5594 }
5595
5596 // Extent
5597 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
5598 }
5599
5600 // feature count
5601 QLocale locale = QLocale();
5602 locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
5603 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
5604 + tr( "Feature count" ) + QStringLiteral( "</td><td>" )
5605 + ( featureCount() == -1 ? tr( "unknown" ) : locale.toString( static_cast<qlonglong>( featureCount() ) ) )
5606 + QStringLiteral( "</td></tr>\n" );
5607
5608 // End Provider section
5609 myMetadata += QLatin1String( "</table>\n<br><br>" );
5610
5611 if ( isSpatial() )
5612 {
5613 // CRS
5614 myMetadata += crsHtmlMetadata();
5615 }
5616
5617 // identification section
5618 myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
5619 myMetadata += htmlFormatter.identificationSectionHtml( );
5620 myMetadata += QLatin1String( "<br><br>\n" );
5621
5622 // extent section
5623 myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
5624 myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
5625 myMetadata += QLatin1String( "<br><br>\n" );
5626
5627 // Start the Access section
5628 myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
5629 myMetadata += htmlFormatter.accessSectionHtml( );
5630 myMetadata += QLatin1String( "<br><br>\n" );
5631
5632 // Fields section
5633 myMetadata += QStringLiteral( "<h1>" ) + tr( "Fields" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
5634
5635 // primary key
5637 if ( !pkAttrList.isEmpty() )
5638 {
5639 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Primary key attributes" ) + QStringLiteral( "</td><td>" );
5640 const auto constPkAttrList = pkAttrList;
5641 for ( int idx : constPkAttrList )
5642 {
5643 myMetadata += fields().at( idx ).name() + ' ';
5644 }
5645 myMetadata += QLatin1String( "</td></tr>\n" );
5646 }
5647
5648 const QgsFields myFields = fields();
5649
5650 // count fields
5651 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Count" ) + QStringLiteral( "</td><td>" ) + QString::number( myFields.size() ) + QStringLiteral( "</td></tr>\n" );
5652
5653 myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
5654 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" );
5655
5656 for ( int i = 0; i < myFields.size(); ++i )
5657 {
5658 QgsField myField = myFields.at( i );
5659 QString rowClass;
5660 if ( i % 2 )
5661 rowClass = QStringLiteral( "class=\"odd-row\"" );
5662 myMetadata += QLatin1String( "<tr " ) + rowClass + QLatin1String( "><td>" ) + myField.displayNameWithAlias() + 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" );
5663 }
5664
5665 //close field list
5666 myMetadata += QLatin1String( "</table>\n<br><br>" );
5667
5668 // Start the contacts section
5669 myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
5670 myMetadata += htmlFormatter.contactsSectionHtml( );
5671 myMetadata += QLatin1String( "<br><br>\n" );
5672
5673 // Start the links section
5674 myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
5675 myMetadata += htmlFormatter.linksSectionHtml( );
5676 myMetadata += QLatin1String( "<br><br>\n" );
5677
5678 // Start the history section
5679 myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
5680 myMetadata += htmlFormatter.historySectionHtml( );
5681 myMetadata += QLatin1String( "<br><br>\n" );
5682
5683 myMetadata += QLatin1String( "\n</body>\n</html>\n" );
5684 return myMetadata;
5685}
5686
5687void QgsVectorLayer::invalidateSymbolCountedFlag()
5688{
5690
5691 mSymbolFeatureCounted = false;
5692}
5693
5694void QgsVectorLayer::onFeatureCounterCompleted()
5695{
5697
5698 onSymbolsCounted();
5699 mFeatureCounter = nullptr;
5700}
5701
5702void QgsVectorLayer::onFeatureCounterTerminated()
5703{
5705
5706 mFeatureCounter = nullptr;
5707}
5708
5709void QgsVectorLayer::onJoinedFieldsChanged()
5710{
5712
5713 // some of the fields of joined layers have changed -> we need to update this layer's fields too
5714 updateFields();
5715}
5716
5717void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
5718{
5720
5721 if ( mEditCommandActive || mCommitChangesActive )
5722 {
5723 mDeletedFids << fid;
5724 }
5725 else
5726 {
5727 mSelectedFeatureIds.remove( fid );
5728 emit featuresDeleted( QgsFeatureIds() << fid );
5729 }
5730
5731 emit featureDeleted( fid );
5732}
5733
5734void QgsVectorLayer::onRelationsLoaded()
5735{
5737
5738 mEditFormConfig.onRelationsLoaded();
5739}
5740
5741void QgsVectorLayer::onSymbolsCounted()
5742{
5744
5745 if ( mFeatureCounter )
5746 {
5747 mSymbolFeatureCounted = true;
5748 mSymbolFeatureCountMap = mFeatureCounter->symbolFeatureCountMap();
5749 mSymbolFeatureIdMap = mFeatureCounter->symbolFeatureIdMap();
5751 }
5752}
5753
5754QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
5755{
5757
5759}
5760
5761QList<QgsWeakRelation> QgsVectorLayer::weakRelations() const
5762{
5764
5765 return mWeakRelations;
5766}
5767
5768void QgsVectorLayer::setWeakRelations( const QList<QgsWeakRelation> &relations )
5769{
5771
5772 mWeakRelations = relations;
5773}
5774
5775int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
5776{
5778
5779 return QgsProviderRegistry::instance()->listStyles( mProviderKey, mDataSource, ids, names, descriptions, msgError );
5780}
5781
5782QString QgsVectorLayer::getStyleFromDatabase( const QString &styleId, QString &msgError )
5783{
5785
5786 return QgsProviderRegistry::instance()->getStyleById( mProviderKey, mDataSource, styleId, msgError );
5787}
5788
5789bool QgsVectorLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgError )
5790{
5792
5794}
5795
5796void QgsVectorLayer::saveStyleToDatabase( const QString &name, const QString &description,
5797 bool useAsDefault, const QString &uiFileContent, QString &msgError, QgsMapLayer::StyleCategories categories )
5798{
5800
5801 QString sldStyle, qmlStyle;
5802 QDomDocument qmlDocument, sldDocument;
5803 QgsReadWriteContext context;
5804 exportNamedStyle( qmlDocument, msgError, context, categories );
5805 if ( !msgError.isNull() )
5806 {
5807 return;
5808 }
5809 qmlStyle = qmlDocument.toString();
5810
5811 this->exportSldStyle( sldDocument, msgError );
5812 if ( !msgError.isNull() )
5813 {
5814 return;
5815 }
5816 sldStyle = sldDocument.toString();
5817
5819 mDataSource, qmlStyle, sldStyle, name,
5820 description, uiFileContent, useAsDefault, msgError );
5821}
5822
5823QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, QgsMapLayer::StyleCategories categories )
5824{
5826
5827 return loadNamedStyle( theURI, resultFlag, false, categories );
5828}
5829
5830bool QgsVectorLayer::loadAuxiliaryLayer( const QgsAuxiliaryStorage &storage, const QString &key )
5831{
5833
5834 bool rc = false;
5835
5836 QString joinKey = mAuxiliaryLayerKey;
5837 if ( !key.isEmpty() )
5838 joinKey = key;
5839
5840 if ( storage.isValid() && !joinKey.isEmpty() )
5841 {
5842 QgsAuxiliaryLayer *alayer = nullptr;
5843
5844 int idx = fields().lookupField( joinKey );
5845
5846 if ( idx >= 0 )
5847 {
5848 alayer = storage.createAuxiliaryLayer( fields().field( idx ), this );
5849
5850 if ( alayer )
5851 {
5852 setAuxiliaryLayer( alayer );
5853 rc = true;
5854 }
5855 }
5856 }
5857
5858 return rc;
5859}
5860
5862{
5864
5865 mAuxiliaryLayerKey.clear();
5866
5867 if ( mAuxiliaryLayer )
5868 removeJoin( mAuxiliaryLayer->id() );
5869
5870 if ( alayer )
5871 {
5872 addJoin( alayer->joinInfo() );
5873
5874 if ( !alayer->isEditable() )
5875 alayer->startEditing();
5876
5877 mAuxiliaryLayerKey = alayer->joinInfo().targetFieldName();
5878 }
5879
5880 mAuxiliaryLayer.reset( alayer );
5881 if ( mAuxiliaryLayer )
5882 mAuxiliaryLayer->setParent( this );
5883 updateFields();
5884}
5885
5887{
5889
5890 return mAuxiliaryLayer.get();
5891}
5892
5894{
5896
5897 return mAuxiliaryLayer.get();
5898}
5899
5900QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB, QgsMapLayer::StyleCategories categories )
5901{
5903
5904 QgsDataSourceUri dsUri( theURI );
5905 QString returnMessage;
5906 QString qml, errorMsg;
5907 QString styleName;
5908 if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
5909 {
5911 }
5912
5913 // Style was successfully loaded from provider storage
5914 if ( !qml.isEmpty() )
5915 {
5916 QDomDocument myDocument( QStringLiteral( "qgis" ) );
5917 myDocument.setContent( qml );
5918 resultFlag = importNamedStyle( myDocument, errorMsg );
5919 returnMessage = QObject::tr( "Loaded from Provider" );
5920 }
5921 else
5922 {
5923 returnMessage = QgsMapLayer::loadNamedStyle( theURI, resultFlag, categories );
5924 }
5925
5926 if ( ! styleName.isEmpty() )
5927 {
5928 styleManager()->renameStyle( styleManager()->currentStyle(), styleName );
5929 }
5930
5931 if ( resultFlag )
5932 emit styleLoaded( categories );
5933
5934 return returnMessage;
5935}
5936
5937QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
5938{
5940
5941 if ( mDataProvider )
5942 return mDataProvider->dependencies() + mDependencies;
5943 return mDependencies;
5944}
5945
5946void QgsVectorLayer::emitDataChanged()
5947{
5949
5950 if ( mDataChangedFired )
5951 return;
5952
5953 updateExtents(); // reset cached extent to reflect data changes
5954
5955 mDataChangedFired = true;
5956 emit dataChanged();
5957 mDataChangedFired = false;
5958}
5959
5960void QgsVectorLayer::onAfterCommitChangesDependency()
5961{
5963
5964 mDataChangedFired = true;
5965 reload();
5966 mDataChangedFired = false;
5967}
5968
5969bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
5970{
5972
5973 QSet<QgsMapLayerDependency> deps;
5974 const auto constODeps = oDeps;
5975 for ( const QgsMapLayerDependency &dep : constODeps )
5976 {
5977 if ( dep.origin() == QgsMapLayerDependency::FromUser )
5978 deps << dep;
5979 }
5980
5981 QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
5982
5983 // disconnect layers that are not present in the list of dependencies anymore
5984 for ( const QgsMapLayerDependency &dep : std::as_const( mDependencies ) )
5985 {
5986 QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
5987 if ( !lyr )
5988 continue;
5989 disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
5990 disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
5991 disconnect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
5992 disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
5994 disconnect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency );
5995 }
5996
5997 // assign new dependencies
5998 if ( mDataProvider )
5999 mDependencies = mDataProvider->dependencies() + deps;
6000 else
6001 mDependencies = deps;
6002 emit dependenciesChanged();
6003
6004 // connect to new layers
6005 for ( const QgsMapLayerDependency &dep : std::as_const( mDependencies ) )
6006 {
6007 QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
6008 if ( !lyr )
6009 continue;
6010 connect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
6011 connect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
6012 connect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
6013 connect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
6015 connect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency );
6016 }
6017
6018 // if new layers are present, emit a data change
6019 if ( ! toAdd.isEmpty() )
6020 emitDataChanged();
6021
6022 return true;
6023}
6024
6025QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
6026{
6028
6029 if ( fieldIndex < 0 || fieldIndex >= mFields.count() || !mDataProvider )
6030 return QgsFieldConstraints::Constraints();
6031
6032 QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
6033
6034 // make sure provider constraints are always present!
6035 if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
6036 {
6037 constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
6038 }
6039
6040 return constraints;
6041}
6042
6043QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> QgsVectorLayer::fieldConstraintsAndStrength( int fieldIndex ) const
6044{
6046
6047 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
6048
6049 if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
6050 return m;
6051
6052 QString name = mFields.at( fieldIndex ).name();
6053
6054 QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator conIt = mFieldConstraintStrength.constBegin();
6055 for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
6056 {
6057 if ( conIt.key().first == name )
6058 {
6059 m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
6060 }
6061 }
6062
6063 return m;
6064}
6065
6067{
6069
6070 if ( index < 0 || index >= mFields.count() )
6071 return;
6072
6073 QString name = mFields.at( index ).name();
6074
6075 // add constraint to existing constraints
6076 QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, QgsFieldConstraints::Constraints() );
6077 constraints |= constraint;
6078 mFieldConstraints.insert( name, constraints );
6079
6080 mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
6081
6082 updateFields();
6083}
6084
6086{
6088
6089 if ( index < 0 || index >= mFields.count() )
6090 return;
6091
6092 QString name = mFields.at( index ).name();
6093
6094 // remove constraint from existing constraints
6095 QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, QgsFieldConstraints::Constraints() );
6096 constraints &= ~constraint;
6097 mFieldConstraints.insert( name, constraints );
6098
6099 mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
6100
6101 updateFields();
6102}
6103
6105{
6107
6108 if ( index < 0 || index >= mFields.count() )
6109 return QString();
6110
6111 return mFields.at( index ).constraints().constraintExpression();
6112}
6113
6115{
6117
6118 if ( index < 0 || index >= mFields.count() )
6119 return QString();
6120
6121 return mFields.at( index ).constraints().constraintDescription();
6122}
6123
6124void QgsVectorLayer::setConstraintExpression( int index, const QString &expression, const QString &description )
6125{
6127
6128 if ( index < 0 || index >= mFields.count() )
6129 return;
6130
6131 if ( expression.isEmpty() )
6132 {
6133 mFieldConstraintExpressions.remove( mFields.at( index ).name() );
6134 }
6135 else
6136 {
6137 mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
6138 }
6139 updateFields();
6140}
6141
6142void QgsVectorLayer::setFieldConfigurationFlags( int index, QgsField::ConfigurationFlags flags )
6143{
6145
6146 if ( index < 0 || index >= mFields.count() )
6147 return;
6148
6149 mFieldConfigurationFlags.insert( mFields.at( index ).name(), flags );
6150 updateFields();
6151}
6152
6154{
6156
6157 if ( index < 0 || index >= mFields.count() )
6158 return;
6159 QgsField::ConfigurationFlags flags = mFields.at( index ).configurationFlags();
6160 flags.setFlag( flag, active );
6162}
6163
6164QgsField::ConfigurationFlags QgsVectorLayer::fieldConfigurationFlags( int index ) const
6165{
6167
6168 if ( index < 0 || index >= mFields.count() )
6170
6171 return mFields.at( index ).configurationFlags();
6172}
6173
6175{
6177
6178 if ( index < 0 || index >= mFields.count() )
6179 return;
6180
6181 if ( setup.isNull() )
6182 mFieldWidgetSetups.remove( mFields.at( index ).name() );
6183 else
6184 mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
6185 updateFields();
6186}
6187
6189{
6191
6192 if ( index < 0 || index >= mFields.count() )
6193 return QgsEditorWidgetSetup();
6194
6195 return mFields.at( index ).editorWidgetSetup();
6196}
6197
6198QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties()
6199{
6201
6203 if ( customProperty( QStringLiteral( "labeling" ) ).toString() == QLatin1String( "pal" ) )
6204 {
6205 if ( customProperty( QStringLiteral( "labeling/enabled" ), QVariant( false ) ).toBool() )
6206 {
6207 // try to load from custom properties
6208 QgsPalLayerSettings settings;
6209 settings.readFromLayerCustomProperties( this );
6210 labeling = new QgsVectorLayerSimpleLabeling( settings );
6211 }
6212
6213 // also clear old-style labeling config
6214 removeCustomProperty( QStringLiteral( "labeling" ) );
6215 const auto constCustomPropertyKeys = customPropertyKeys();
6216 for ( const QString &key : constCustomPropertyKeys )
6217 {
6218 if ( key.startsWith( QLatin1String( "labeling/" ) ) )
6219 removeCustomProperty( key );
6220 }
6221 }
6222
6223 return labeling;
6224}
6225
6227{
6229
6230 return mAllowCommit;
6231}
6232
6233void QgsVectorLayer::setAllowCommit( bool allowCommit )
6234{
6236
6237 if ( mAllowCommit == allowCommit )
6238 return;
6239
6240 mAllowCommit = allowCommit;
6241 emit allowCommitChanged();
6242}
6243
6245{
6247
6248 return mGeometryOptions.get();
6249}
6250
6251void QgsVectorLayer::setReadExtentFromXml( bool readExtentFromXml )
6252{
6254
6255 mReadExtentFromXml = readExtentFromXml;
6256}
6257
6259{
6261
6262 return mReadExtentFromXml;
6263}
6264
6265void QgsVectorLayer::onDirtyTransaction( const QString &sql, const QString &name )
6266{
6268
6270 if ( tr && mEditBuffer )
6271 {
6272 qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql, name );
6273 }
6274}
6275
6276QList<QgsVectorLayer *> QgsVectorLayer::DeleteContext::handledLayers( bool includeAuxiliaryLayers ) const
6277{
6278 QList<QgsVectorLayer *> layers;
6279 QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
6280 for ( i = mHandledFeatures.begin(); i != mHandledFeatures.end(); ++i )
6281 {
6282 if ( includeAuxiliaryLayers || !qobject_cast< QgsAuxiliaryLayer * >( i.key() ) )
6283 layers.append( i.key() );
6284 }
6285 return layers;
6286}
6287
6289{
6290 return mHandledFeatures[layer];
6291}
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:54
@ 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:1424
@ 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...
FieldDomainSplitPolicy
Split policy for field domains.
Definition: qgis.h:2446
@ Duplicate
Duplicate original value.
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition: qgis.h:3227
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition: qgis.h:227
@ Generated
A generated relation is a child of a polymorphic relation.
@ Normal
A normal relation.
static const float DEFAULT_MAPTOPIXEL_THRESHOLD
Default threshold between map coordinates and device coordinates for map2pixel simplification.
Definition: qgis.h:3700
RenderUnit
Rendering size units.
Definition: qgis.h:3441
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
Definition: qgis.h:1229
@ SemiTransparentCircle
Semi-transparent circle marker.
@ Cross
Cross marker.
VectorEditResult
Flags which control feature selection behavior.
Definition: qgis.h:1214
@ Success
Edit operation was successful.
@ InvalidLayer
Edit failed due to invalid layer.
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:154
@ Unknown
Unknown.
@ 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:1167
@ 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(Qgis::AttributeActionType 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:37
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.
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.
@ 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.
bool useEstimatedMetadata() const
Returns true if estimated metadata should be used for the connection.
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.
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)
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(Qgis::GeometryType geomType)
Returns a new renderer - used by default in vector layers.
Definition: qgsrenderer.cpp:73
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:336
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:502
void setReferenceScale(double scale)
Sets the symbology reference scale.
Definition: qgsrenderer.h:518
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...
static QgsFeatureRenderer * loadSld(const QDomNode &node, Qgis::GeometryType geomType, QString &errorMessage)
Create a new renderer according to the information contained in the UserStyle element of a SLD style ...
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:262
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:230
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:216
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:335
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:167
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:53
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:150
QString name
Definition: qgsfield.h:62
int precision
Definition: qgsfield.h:59
int length
Definition: qgsfield.h:58
QString displayNameWithAlias() const
Returns the name to use when displaying this field and adds the alias in parenthesis if it is defined...
Definition: qgsfield.cpp:96
Qgis::FieldDomainSplitPolicy splitPolicy() const
Returns the field's split policy, which indicates how field values should be handled during a split o...
Definition: qgsfield.cpp:729
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:88
ConfigurationFlags configurationFlags
Definition: qgsfield.h:66
QString alias
Definition: qgsfield.h:63
QgsDefaultValue defaultValueDefinition
Definition: qgsfield.h:64
QString comment
Definition: qgsfield.h:61
QgsFieldConstraints constraints
Definition: qgsfield.h:65
ConfigurationFlag
Configuration flags for fields These flags are meant to be user-configurable and are not describing a...
Definition: qgsfield.h:82
@ 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:714
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:359
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.
Qgis::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.
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:131
This class models dependencies with or between map layers.
Base class for storage of map layer elevation properties.
static QString typeToString(Qgis::LayerType 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.
bool renameStyle(const QString &name, const QString &newName)
Rename a stored style to a different name.
Stores style information (renderer, opacity, labeling, diagrams etc.) applicable to a map layer.
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:2099
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.
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:2238
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
Qgis::LayerType type
Definition: qgsmaplayer.h:80
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:2060
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:2073
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.
std::unique_ptr< QgsDataProvider > mPreloadedProvider
Optionally used when loading a project, it is released when the layer is effectively created.
Definition: qgsmaplayer.h:2136
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:2032
void setMapTipsEnabled(bool enabled)
Enable or disable map tips for this layer.
@ FlagReadExtentFromXml
Read extent from xml and skip get extent from provider.
Definition: qgsmaplayer.h:636
@ FlagForceReadOnly
Force open as read only.
Definition: qgsmaplayer.h:637
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:634
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:2078
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.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
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.
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
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.
bool mapTipsEnabled
Definition: qgsmaplayer.h:84
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:2029
@ GeometryOptions
Geometry validation configuration.
Definition: qgsmaplayer.h:174
@ AttributeTable
Attribute table settings: choice and order of columns, conditional styling.
Definition: qgsmaplayer.h:171
@ LayerConfiguration
General configuration: identifiable, removable, searchable, display expression, read-only.
Definition: qgsmaplayer.h:162
@ Symbology
Symbology.
Definition: qgsmaplayer.h:163
@ MapTips
Map tips.
Definition: qgsmaplayer.h:169
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:172
@ Relations
Relations.
Definition: qgsmaplayer.h:175
@ CustomProperties
Custom properties (by plugins for instance)
Definition: qgsmaplayer.h:173
@ Actions
Actions.
Definition: qgsmaplayer.h:168
@ Forms
Feature form.
Definition: qgsmaplayer.h:167
@ Fields
Aliases, widgets, WMS/WFS, expressions, constraints, virtual fields.
Definition: qgsmaplayer.h:166
@ Legend
Legend settings (since QGIS 3.16)
Definition: qgsmaplayer.h:177
@ Diagrams
Diagrams.
Definition: qgsmaplayer.h:170
@ Labeling
Labeling.
Definition: qgsmaplayer.h:165
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.
QString mapTipTemplate
Definition: qgsmaplayer.h:83
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:2085
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
static QgsDataProvider::ReadFlags providerReadFlags(const QDomNode &layerNode, QgsMapLayer::ReadFlags layerReadFlags)
Returns provider read flag deduced from layer read flags layerReadFlags and a dom node layerNode that...
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 Qgis::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(Qgis::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
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.
double angleOffset
Label rotation, in degrees clockwise.
double maxCurvedCharAngleOut
Maximum angle between outside curved label characters (valid range -20.0 to -95.0)
Qgis::RenderUnit offsetUnits
Units for offsets of label.
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.
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...
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:107
QgsRelationManager * relationManager
Definition: qgsproject.h:117
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:746
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:484
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:772
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:725
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 absoluteToRelativeUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts absolute path(s) to relative path(s) in the given provider-specific 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.
QString loadStoredStyle(const QString &providerKey, const QString &uri, QString &styleName, QString &errCause)
Loads a layer style from the provider storage, reporting its name.
QString relativeToAbsoluteUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
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.
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.
A boolean settings entry.
A double settings entry.
static QgsSettingsTreeNode * sTreeQgis
This class is a composition of two QSettings instances:
Definition: qgssettings.h:63
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 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)
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
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 setSizeUnit(Qgis::RenderUnit unit)
Sets the units used for the buffer size.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
void setSize(double size)
Sets the size of the buffer.
Container for all settings relating to text rendering.
Definition: qgstextformat.h:42
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 setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the size of rendered text.
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
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.
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....
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.
Qgis::WkbType wkbType() const override=0
Returns the geometry type which is returned by this layer.
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 deleteFeatures(const QgsFeatureIds &fid)
Deletes a set of features from the layer (but does not commit it)
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.
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...
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.
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.
bool hasMapTips() const FINAL
Returns true if the layer contains map tips.
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.
static const QgsSettingsEntryEnumFlag< QgsVectorSimplifyMethod::SimplifyHints > * settingsSimplifyDrawingHints
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 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)
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.
static const QgsSettingsEntryDouble * settingsSimplifyMaxScale
~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).
static const QgsSettingsEntryBool * settingsSimplifyLocal
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.
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
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.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
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...
static const QgsSettingsEntryEnumFlag< QgsVectorSimplifyMethod::SimplifyAlgorithm > * settingsSimplifyAlgorithm
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...
static const QgsSettingsEntryDouble * settingsSimplifyDrawingTol
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
void setFieldSplitPolicy(int index, Qgis::FieldDomainSplitPolicy policy)
Sets a split policy for the field with the specified index.
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 QString geometryDisplayString(Qgis::GeometryType type) SIP_HOLDGIL
Returns a display string for a geometry type.
static Qgis::GeometryType geometryType(Qgis::WkbType type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:865
static QString displayString(Qgis::WkbType 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
@ UnknownCount
Provider returned an unknown feature count.
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:247
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:120
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:188
#define FALLTHROUGH
Definition: qgis.h:4599
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:4211
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition: qgis.h:4192
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
Definition: qgis.h:4250
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:4272
QMap< QString, QString > QgsStringMap
Definition: qgis.h:4533
QVector< QgsPoint > QgsPointSequence
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:42
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:920
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:27
const QgsField & field
Definition: qgsfield.h:554
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugError(str)
Definition: qgslogger.h:38
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:50
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS_NON_FATAL
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
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.
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.
Qgis::WkbType fallbackWkbType
Fallback geometry type.
bool loadAllStoredStyles
Controls whether the stored styles will be all loaded.