101 #include <QPainterPath>
103 #include <QProgressDialog>
107 #include <QStringBuilder>
109 #include <QUndoCommand>
112 #include <QRegularExpression>
118 #ifdef TESTPROVIDERLIB
124 const QString &qmlStyle,
125 const QString &sldStyle,
126 const QString &styleName,
127 const QString &styleDescription,
128 const QString &uiFileContent,
142 QStringList &descriptions,
160 const QString &baseName,
161 const QString &providerKey,
166 , mAuxiliaryLayer( nullptr )
167 , mAuxiliaryLayerKey( QString() )
168 , mReadExtentFromXml( options.readExtentFromXml )
169 , mRefreshRendererTimer( new QTimer( this ) )
179 mGeometryOptions = std::make_unique<QgsGeometryOptions>();
183 mStoredExpressionManager->setParent(
this );
186 mJoinBuffer->setParent(
this );
191 if ( !vectorLayerPath.isEmpty() && !
mProviderKey.isEmpty() )
194 QgsDataProvider::ReadFlags providerFlags = QgsDataProvider::ReadFlags();
199 setDataSource( vectorLayerPath, baseName, providerKey, providerOptions, providerFlags );
204 if ( !mAttributeAliasMap.contains(
field.
name() ) )
205 mAttributeAliasMap.insert(
field.
name(), QString() );
211 if ( !mTemporalProperties->
isActive() )
232 mSimplifyMethod.
setThreshold( settings.
value( QStringLiteral(
"qgis/simplifyDrawingTol" ), mSimplifyMethod.
threshold() ).toFloat() );
236 connect( mRefreshRendererTimer, &QTimer::timeout,
this, [ = ] {
triggerRepaint(
true ); } );
245 delete mDataProvider;
248 delete mExpressionFieldBuffer;
250 delete mDiagramLayerSettings;
251 delete mDiagramRenderer;
256 delete mConditionalStyles;
257 delete mStoredExpressionManager;
259 if ( mFeatureCounter )
260 mFeatureCounter->
cancel();
262 qDeleteAll( mRendererGenerators );
288 QList<QgsVectorLayerJoinInfo> joins =
vectorJoins();
289 const auto constJoins = joins;
309 for (
const QgsAction &action : constActions )
346 auto constraintIt = constraints.constBegin();
347 for ( ; constraintIt != constraints.constEnd(); ++ constraintIt )
363 layer->mElevationProperties = mElevationProperties->
clone();
364 layer->mElevationProperties->setParent( layer );
390 return mDataProvider && mDataProvider->
isSqlQuery();
437 p.setPen( QColor( 50, 100, 120, 200 ) );
438 p.setBrush( QColor( 200, 200, 210, 120 ) );
439 p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
443 p.setPen( QColor( 255, 0, 0 ) );
444 p.drawLine( x - m, y + m, x + m, y - m );
445 p.drawLine( x - m, y - m, x + m, y + m );
455 mSelectedFeatureIds.insert( fid );
456 mPreviousSelectedFeatureIds.clear();
463 mSelectedFeatureIds.unite( featureIds );
464 mPreviousSelectedFeatureIds.clear();
471 mSelectedFeatureIds.remove( fid );
472 mPreviousSelectedFeatureIds.clear();
479 mSelectedFeatureIds.subtract( featureIds );
480 mPreviousSelectedFeatureIds.clear();
493 .setFilterRect( rect )
495 .setNoAttributes() );
500 newSelection << feat.
id();
511 std::optional< QgsExpressionContext > defaultContext;
515 context = &defaultContext.value();
534 newSelection << feat.
id();
556 bool matches = exp.
evaluate( context ).toBool();
560 newSelection << feat.
id();
564 newSelection << feat.
id();
583 newSelection = mSelectedFeatureIds + ids;
587 newSelection = mSelectedFeatureIds - ids;
591 newSelection = mSelectedFeatureIds.intersect( ids );
595 QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - newSelection;
596 mSelectedFeatureIds = newSelection;
597 mPreviousSelectedFeatureIds.clear();
605 if ( !intersectingIds.isEmpty() )
607 QgsDebugMsgLevel( QStringLiteral(
"Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." ), 3 );
610 mSelectedFeatureIds -= deselectIds;
611 mSelectedFeatureIds += selectIds;
612 mPreviousSelectedFeatureIds.clear();
620 ids.subtract( mSelectedFeatureIds );
635 .setFilterRect( rect )
637 .setNoAttributes() );
645 if ( mSelectedFeatureIds.contains( fet.
id() ) )
647 deselectIds << fet.
id();
651 selectIds << fet.
id();
660 if ( mSelectedFeatureIds.isEmpty() )
665 mPreviousSelectedFeatureIds = previous;
670 if ( mPreviousSelectedFeatureIds.isEmpty() || !mSelectedFeatureIds.empty() )
678 return mDataProvider;
683 return mDataProvider;
688 return mTemporalProperties;
693 return mElevationProperties;
705 if (
isValid() && mDataProvider && mDataProvider->
encoding() != encoding )
714 delete mDiagramRenderer;
715 mDiagramRenderer = r;
732 if ( !
isValid() || !
isSpatial() || mSelectedFeatureIds.isEmpty() || !mDataProvider )
744 .setFilterFids( mSelectedFeatureIds )
745 .setNoAttributes() );
758 .setNoAttributes() );
762 if ( mSelectedFeatureIds.contains( fet.
id() ) )
773 if ( retval.
width() == 0.0 || retval.
height() == 0.0 )
782 retval.
set( -1.0, -1.0, 1.0, 1.0 );
791 return mLabelsEnabled &&
static_cast< bool >( mLabeling );
796 mLabelsEnabled = enabled;
801 if ( !mDiagramRenderer || !mDiagramLayerSettings )
804 QList<QgsDiagramSettings> settingList = mDiagramRenderer->
diagramSettings();
805 if ( !settingList.isEmpty() )
807 return settingList.at( 0 ).enabled;
814 if ( !mSymbolFeatureCounted )
817 return mSymbolFeatureCountMap.value( legendKey, -1 );
822 if ( !mSymbolFeatureCounted )
825 return mSymbolFeatureIdMap.value( legendKey,
QgsFeatureIds() );
829 if ( ( mSymbolFeatureCounted || mFeatureCounter ) && !( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
830 return mFeatureCounter;
832 mSymbolFeatureCountMap.clear();
833 mSymbolFeatureIdMap.clear();
838 return mFeatureCounter;
840 if ( !mDataProvider )
843 return mFeatureCounter;
848 return mFeatureCounter;
851 if ( !mFeatureCounter || ( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
854 connect( mFeatureCounter, &
QgsTask::taskCompleted,
this, &QgsVectorLayer::onFeatureCounterCompleted, Qt::UniqueConnection );
855 connect( mFeatureCounter, &
QgsTask::taskTerminated,
this, &QgsVectorLayer::onFeatureCounterTerminated, Qt::UniqueConnection );
859 return mFeatureCounter;
865 if ( force || !mReadExtentFromXml || ( mReadExtentFromXml && mXmlExtent.
isNull() ) )
866 mValidExtent =
false;
877 if ( !mDefaultValueOnUpdateFields.isEmpty() )
882 int size = mFields.
size();
883 for (
int idx : std::as_const( mDefaultValueOnUpdateFields ) )
885 if ( idx < 0 || idx >= size )
902 if ( !mValidExtent && mLazyExtent && mReadExtentFromXml && !mXmlExtent.
isNull() )
904 updateExtent( mXmlExtent );
909 if ( !mValidExtent && mLazyExtent && mDataProvider && mDataProvider->
isValid() )
912 updateExtent( mDataProvider->
extent() );
917 QgsDebugMsgLevel( QStringLiteral(
"Extent of layer: %1" ).arg( mExtent.toString() ), 3 );
923 if ( !
isValid() || !mDataProvider )
925 QgsDebugMsgLevel( QStringLiteral(
"invoked with invalid layer or null mDataProvider" ), 3 );
943 if ( mEditBuffer && !mDataProvider->
transaction() )
946 for ( QgsFeatureMap::const_iterator it = addedFeatures.constBegin(); it != addedFeatures.constEnd(); ++it )
948 if ( it->hasGeometry() )
959 .setNoAttributes() );
978 updateExtent( rect );
994 if ( !
isValid() || !mDataProvider )
996 QgsDebugMsgLevel( QStringLiteral(
"invoked with invalid layer or null mDataProvider" ), 3 );
997 return customProperty( QStringLiteral(
"storedSubsetString" ) ).toString();
1004 if ( !
isValid() || !mDataProvider )
1006 QgsDebugMsgLevel( QStringLiteral(
"invoked with invalid layer or null mDataProvider or while editing" ), 3 );
1010 else if ( mEditBuffer )
1039 double maximumSimplificationScale = mSimplifyMethod.
maximumScale();
1042 return !( maximumSimplificationScale > 1 && renderContext.
rendererScale() <= maximumSimplificationScale );
1049 return mConditionalStyles;
1054 if ( !
isValid() || !mDataProvider )
1072 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1076 if ( mGeometryOptions->isActive() )
1079 mGeometryOptions->apply( geom );
1083 bool success = mEditBuffer->
addFeature( feature );
1090 success = mJoinBuffer->
addFeature( feature );
1098 if ( !mEditBuffer || !mDataProvider )
1104 if ( currentFeature.
isValid() )
1106 bool hasChanged =
false;
1107 bool hasError =
false;
1119 QgsDebugMsgLevel( QStringLiteral(
"geometry of feature %1 could not be changed." ).arg( updatedFeature.
id() ), 3 );
1126 for (
int attr = 0; attr < fa.count(); ++attr )
1136 QgsDebugMsgLevel( QStringLiteral(
"attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( updatedFeature.
id() ), 3 );
1141 if ( hasChanged && !mDefaultValueOnUpdateFields.isEmpty() && !skipDefaultValues )
1142 updateDefaultValues( updatedFeature.
id(), updatedFeature );
1148 QgsDebugMsgLevel( QStringLiteral(
"feature %1 could not be retrieved" ).arg( updatedFeature.
id() ), 3 );
1156 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1160 bool result = utils.
insertVertex( x, y, atFeatureId, beforeVertex );
1169 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1173 bool result = utils.
insertVertex( point, atFeatureId, beforeVertex );
1182 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1186 bool result = utils.
moveVertex( x, y, atFeatureId, atVertex );
1195 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1199 bool result = utils.
moveVertex( p, atFeatureId, atVertex );
1208 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1233 int count = mSelectedFeatureIds.size();
1246 *deletedCount = deleted;
1249 return deleted == count;
1252 static const QgsPointSequence vectorPointXY2pointSequence(
const QVector<QgsPointXY> &points )
1255 pts.reserve( points.size() );
1256 QVector<QgsPointXY>::const_iterator it = points.constBegin();
1257 while ( it != points.constEnd() )
1266 return addRing( vectorPointXY2pointSequence( ring ), featureId );
1271 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1278 if ( !mSelectedFeatureIds.isEmpty() )
1280 result = utils.
addRing( ring, mSelectedFeatureIds, featureId );
1294 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1315 if ( !mSelectedFeatureIds.isEmpty() )
1317 result = utils.
addRing(
static_cast< QgsCurve *
>( ring->
clone() ), mSelectedFeatureIds, featureId );
1333 pts.reserve( points.size() );
1334 for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd() ; ++it )
1341 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1344 return addPart( vectorPointXY2pointSequence( points ) );
1350 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1355 if ( mSelectedFeatureIds.empty() )
1360 else if ( mSelectedFeatureIds.size() > 1 )
1376 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1381 if ( mSelectedFeatureIds.empty() )
1386 else if ( mSelectedFeatureIds.size() > 1 )
1403 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1416 return splitParts( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1421 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1425 return utils.
splitParts( splitLine, topologicalEditing );
1430 return splitFeatures( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1437 bool preserveCircular =
false;
1438 return splitFeatures( &splitLineString, topologyTestPoints, preserveCircular, topologicalEditing );
1443 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1447 return utils.
splitFeatures( curve, topologyTestPoints, preserveCircular, topologicalEditing );
1452 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1466 if ( !
isValid() || !mEditBuffer || !mDataProvider )
1475 if ( !
mValid || !mEditBuffer || !mDataProvider )
1496 if ( !
isValid() || !mDataProvider )
1528 if ( mDataProvider )
1540 if ( !mRenderer->
accept( visitor ) )
1544 if ( !mLabeling->
accept( visitor ) )
1555 QDomNode pkeyNode = layer_node.namedItem( QStringLiteral(
"provider" ) );
1557 if ( pkeyNode.isNull() )
1563 QDomElement pkeyElt = pkeyNode.toElement();
1573 else if (
mDataSource.contains( QLatin1String(
"dbname=" ) ) )
1583 QgsDataProvider::ReadFlags
flags;
1594 const QDomElement elem = layer_node.toElement();
1597 if ( elem.hasAttribute( QStringLiteral(
"wkbType" ) ) )
1598 mWkbType =
qgsEnumKeyToValue( elem.attribute( QStringLiteral(
"wkbType" ) ), mWkbType );
1601 QDomElement pkeyElem = pkeyNode.toElement();
1602 if ( !pkeyElem.isNull() )
1604 QString encodingString = pkeyElem.attribute( QStringLiteral(
"encoding" ) );
1605 if ( mDataProvider && !encodingString.isEmpty() )
1612 mJoinBuffer->
readXml( layer_node );
1617 mSetLegendFromStyle =
false;
1627 QDomNode depsNode = layer_node.namedItem( QStringLiteral(
"dataDependencies" ) );
1628 QDomNodeList depsNodes = depsNode.childNodes();
1629 QSet<QgsMapLayerDependency> sources;
1630 for (
int i = 0; i < depsNodes.count(); i++ )
1632 QString
source = depsNodes.at( i ).toElement().attribute( QStringLiteral(
"id" ) );
1637 if ( !mSetLegendFromStyle )
1643 mReadExtentFromXml =
true;
1645 if ( mReadExtentFromXml )
1647 const QDomNode extentNode = layer_node.namedItem( QStringLiteral(
"extent" ) );
1648 if ( !extentNode.isNull() )
1655 const QDomNode asNode = layer_node.namedItem( QStringLiteral(
"auxiliaryLayer" ) );
1656 const QDomElement asElem = asNode.toElement();
1657 if ( !asElem.isNull() )
1659 mAuxiliaryLayerKey = asElem.attribute( QStringLiteral(
"key" ) );
1663 mServerProperties->readXml( layer_node );
1670 void QgsVectorLayer::setDataSourcePrivate(
const QString &dataSource,
const QString &baseName,
const QString &provider,
1677 setDataProvider( provider, options,
flags );
1687 bool loadDefaultStyleFlag =
false;
1690 loadDefaultStyleFlag =
true;
1696 std::unique_ptr< QgsScopedRuntimeProfile > profile;
1698 profile = std::make_unique< QgsScopedRuntimeProfile >( tr(
"Load layer style" ), QStringLiteral(
"projectload" ) );
1700 bool defaultLoadedFlag =
false;
1708 mSetLegendFromStyle =
false;
1713 if ( !defaultLoadedFlag && loadDefaultStyleFlag )
1721 std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->
createRenderer() );
1722 if ( defaultRenderer )
1724 defaultLoadedFlag =
true;
1730 if ( !defaultLoadedFlag &&
isSpatial() )
1736 if ( !mSetLegendFromStyle )
1741 std::unique_ptr< QgsAbstractVectorLayerLabeling > defaultLabeling( mDataProvider->
createLabeling() );
1742 if ( defaultLabeling )
1749 styleChangedSignalBlocker.release();
1764 std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->
createRenderer() );
1765 if ( defaultRenderer )
1779 delete mDataProvider;
1786 if ( provider.compare( QLatin1String(
"postgres" ) ) == 0 )
1788 const QString checkUnicityKey { QStringLiteral(
"checkPrimaryKeyUnicity" ) };
1790 if ( ! uri.hasParam( checkUnicityKey ) )
1792 uri.setParam( checkUnicityKey, mReadExtentFromXml ?
"0" :
"1" );
1797 std::unique_ptr< QgsScopedRuntimeProfile > profile;
1799 profile = std::make_unique< QgsScopedRuntimeProfile >( tr(
"Create %1 provider" ).arg( provider ), QStringLiteral(
"projectload" ) );
1802 if ( !mDataProvider )
1809 mDataProvider->setParent(
this );
1812 QgsDebugMsgLevel( QStringLiteral(
"Instantiated the data provider plugin" ), 2 );
1822 profile->switchTask( tr(
"Read layer metadata" ) );
1829 newMetadata.
combine( &mMetadata );
1832 QgsDebugMsgLevel( QStringLiteral(
"Set Data provider QgsLayerMetadata identifier[%1]" ).arg(
metadata().identifier() ), 4 );
1839 mWkbType = mDataProvider->
wkbType();
1858 profile->switchTask( tr(
"Read layer fields" ) );
1869 const QRegularExpression reg( R
"lit("[^"]+"\."([^"] + )"( \([^)]+\))?)lit" );
1870 const QRegularExpressionMatch match = reg.match(
name() );
1871 if ( match.hasMatch() )
1873 QStringList stuff = match.capturedTexts();
1874 QString lName = stuff[1];
1878 QMap<QString, QgsMapLayer *>::const_iterator it;
1879 for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1882 if ( it != layers.constEnd() && stuff.size() > 2 )
1884 lName +=
'.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1887 if ( !lName.isEmpty() )
1897 else if ( provider == QLatin1String(
"ogr" ) )
1901 if (
mDataSource.right( 10 ) == QLatin1String(
"|layerid=0" ) )
1904 else if ( provider == QLatin1String(
"memory" ) )
1909 else if ( provider == QLatin1String(
"hana" ) )
1926 QDomDocument &document,
1931 QDomElement mapLayerNode = layer_node.toElement();
1933 if ( mapLayerNode.isNull() || (
"maplayer" != mapLayerNode.nodeName() ) )
1946 if ( mDataProvider )
1948 QDomElement provider = document.createElement( QStringLiteral(
"provider" ) );
1949 provider.setAttribute( QStringLiteral(
"encoding" ), mDataProvider->
encoding() );
1950 QDomText providerText = document.createTextNode(
providerType() );
1951 provider.appendChild( providerText );
1952 layer_node.appendChild( provider );
1956 mJoinBuffer->
writeXml( layer_node, document );
1959 QDomElement dependenciesElement = document.createElement( QStringLiteral(
"layerDependencies" ) );
1965 QDomElement depElem = document.createElement( QStringLiteral(
"layer" ) );
1966 depElem.setAttribute( QStringLiteral(
"id" ), dep.layerId() );
1967 dependenciesElement.appendChild( depElem );
1969 layer_node.appendChild( dependenciesElement );
1972 QDomElement dataDependenciesElement = document.createElement( QStringLiteral(
"dataDependencies" ) );
1977 QDomElement depElem = document.createElement( QStringLiteral(
"layer" ) );
1978 depElem.setAttribute( QStringLiteral(
"id" ), dep.layerId() );
1979 dataDependenciesElement.appendChild( depElem );
1981 layer_node.appendChild( dataDependenciesElement );
1984 mExpressionFieldBuffer->
writeXml( layer_node, document );
1989 QDomElement asElem = document.createElement( QStringLiteral(
"auxiliaryLayer" ) );
1990 if ( mAuxiliaryLayer )
1992 const QString pkField = mAuxiliaryLayer->joinInfo().targetFieldName();
1993 asElem.setAttribute( QStringLiteral(
"key" ), pkField );
1995 layer_node.appendChild( asElem );
1998 mServerProperties->writeXml( layer_node, document );
2002 return writeSymbology( layer_node, document, errorMsg, context );
2019 QStringList theURIParts = src.split(
'|' );
2021 src = theURIParts.join( QLatin1Char(
'|' ) );
2025 QStringList theURIParts = src.split(
'?' );
2027 src = theURIParts.join( QLatin1Char(
'?' ) );
2029 else if (
providerType() == QLatin1String(
"delimitedtext" ) )
2031 QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2033 urlDest.setQuery( urlSource.query() );
2034 src = QString::fromLatin1( urlDest.toEncoded() );
2036 else if (
providerType() == QLatin1String(
"memory" ) )
2041 else if (
providerType() == QLatin1String(
"virtual" ) )
2043 QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2044 QStringList theURIParts;
2046 QUrlQuery query = QUrlQuery( urlSource.query() );
2047 QList<QPair<QString, QString> > queryItems = query.queryItems();
2049 for (
int i = 0; i < queryItems.size(); i++ )
2051 QString key = queryItems.at( i ).first;
2052 QString value = queryItems.at( i ).second;
2053 if ( key == QLatin1String(
"layer" ) )
2056 theURIParts = value.split(
':' );
2057 theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
2059 if ( theURIParts[0] == QLatin1String(
"delimitedtext" ) )
2061 QUrl urlSource = QUrl( theURIParts[1] );
2063 urlDest.setQuery( urlSource.query() );
2064 theURIParts[1] = QUrl::toPercentEncoding( urlDest.toString(), QByteArray(
"" ), QByteArray(
":" ) );
2069 theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
2072 queryItems[i].second = theURIParts.join( QLatin1Char(
':' ) ) ;
2076 query.setQueryItems( queryItems );
2078 QUrl urlDest = QUrl( urlSource );
2079 urlDest.setQuery( query.query() );
2080 src = QString::fromLatin1( urlDest.toEncoded() );
2094 if ( provider == QLatin1String(
"spatialite" ) )
2100 else if ( provider == QLatin1String(
"ogr" ) )
2102 QStringList theURIParts = src.split(
'|' );
2104 src = theURIParts.join( QLatin1Char(
'|' ) );
2106 else if ( provider == QLatin1String(
"gpx" ) )
2108 QStringList theURIParts = src.split(
'?' );
2110 src = theURIParts.join( QLatin1Char(
'?' ) );
2112 else if ( provider == QLatin1String(
"delimitedtext" ) )
2114 QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2116 if ( !src.startsWith( QLatin1String(
"file:" ) ) )
2118 QUrl file = QUrl::fromLocalFile( src.left( src.indexOf(
'?' ) ) );
2119 urlSource.setScheme( QStringLiteral(
"file" ) );
2120 urlSource.setPath( file.path() );
2123 QUrl urlDest = QUrl::fromLocalFile( context.
pathResolver().
readPath( urlSource.toLocalFile() ) );
2124 urlDest.setQuery( urlSource.query() );
2125 src = QString::fromLatin1( urlDest.toEncoded() );
2127 else if ( provider == QLatin1String(
"virtual" ) )
2129 QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2130 QStringList theURIParts;
2132 QUrlQuery query = QUrlQuery( urlSource.query() );
2133 QList<QPair<QString, QString> > queryItems = query.queryItems();
2135 for (
int i = 0; i < queryItems.size(); i++ )
2137 QString key = queryItems.at( i ).first;
2138 QString value = queryItems.at( i ).second;
2139 if ( key == QLatin1String(
"layer" ) )
2142 theURIParts = value.split(
':' );
2143 theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
2145 if ( theURIParts[0] == QLatin1String(
"delimitedtext" ) )
2147 QUrl urlSource = QUrl( theURIParts[1] );
2149 if ( !theURIParts[1].startsWith( QLatin1String(
"file:" ) ) )
2151 QUrl file = QUrl::fromLocalFile( theURIParts[1].left( theURIParts[1].indexOf(
'?' ) ) );
2152 urlSource.setScheme( QStringLiteral(
"file" ) );
2153 urlSource.setPath( file.path() );
2156 QUrl urlDest = QUrl::fromLocalFile( context.
pathResolver().
readPath( urlSource.toLocalFile() ) );
2157 urlDest.setQuery( urlSource.query() );
2159 theURIParts[1] = urlDest.toString();
2166 theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
2167 queryItems[i].second = theURIParts.join( QLatin1Char(
':' ) ) ;
2171 query.setQueryItems( queryItems );
2173 QUrl urlDest = QUrl( urlSource );
2174 urlDest.setQuery( query.query() );
2175 src = QString::fromLatin1( urlDest.toEncoded() );
2197 if ( categories.testFlag(
Fields ) )
2199 if ( !mExpressionFieldBuffer )
2201 mExpressionFieldBuffer->
readXml( layerNode );
2213 QDomNodeList referencedLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral(
"referencedLayers" ) );
2214 if ( referencedLayersNodeList.size() > 0 )
2216 const QDomNodeList relationNodes { referencedLayersNodeList.at( 0 ).childNodes() };
2217 for (
int i = 0; i < relationNodes.length(); ++i )
2219 const QDomElement relationElement = relationNodes.at( i ).toElement();
2226 QDomNodeList referencingLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral(
"referencingLayers" ) );
2227 if ( referencingLayersNodeList.size() > 0 )
2229 const QDomNodeList relationNodes { referencingLayersNodeList.at( 0 ).childNodes() };
2230 for (
int i = 0; i < relationNodes.length(); ++i )
2232 const QDomElement relationElement = relationNodes.at( i ).toElement();
2238 QDomElement layerElement = layerNode.toElement();
2242 readStyle( layerNode, errorMessage, context, categories );
2244 if ( categories.testFlag(
MapTips ) )
2245 mMapTipTemplate = layerNode.namedItem( QStringLiteral(
"mapTip" ) ).toElement().text();
2248 mDisplayExpression = layerNode.namedItem( QStringLiteral(
"previewExpression" ) ).toElement().text();
2251 QString
displayField = layerNode.namedItem( QStringLiteral(
"displayfield" ) ).toElement().text();
2255 if ( mMapTipTemplate.isEmpty() && categories.testFlag(
MapTips ) )
2265 if ( categories.testFlag(
Actions ) )
2266 mActions->
readXml( layerNode );
2268 if ( categories.testFlag(
Fields ) )
2273 QDomNode aliasesNode = layerNode.namedItem( QStringLiteral(
"aliases" ) );
2274 if ( !aliasesNode.isNull() )
2276 QDomElement aliasElem;
2278 QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral(
"alias" ) );
2279 for (
int i = 0; i < aliasNodeList.size(); ++i )
2281 aliasElem = aliasNodeList.at( i ).toElement();
2284 if ( aliasElem.hasAttribute( QStringLiteral(
"field" ) ) )
2286 field = aliasElem.attribute( QStringLiteral(
"field" ) );
2290 int index = aliasElem.attribute( QStringLiteral(
"index" ) ).toInt();
2292 if ( index >= 0 && index <
fields().count() )
2298 if ( !aliasElem.attribute( QStringLiteral(
"name" ) ).isEmpty() )
2301 alias = context.
projectTranslator()->
translate( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral(
"id" ) ).toElement().text() ), aliasElem.attribute( QStringLiteral(
"name" ) ) );
2302 QgsDebugMsgLevel(
"context" + QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral(
"id" ) ).toElement().text() ) +
" source " + aliasElem.attribute( QStringLiteral(
"name" ) ), 3 );
2307 alias = context.
projectTranslator()->
translate( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral(
"id" ) ).toElement().text() ),
field );
2308 QgsDebugMsgLevel(
"context" + QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral(
"id" ) ).toElement().text() ) +
" source " +
field, 3 );
2310 if ( alias == aliasElem.attribute( QStringLiteral(
"field" ) ) )
2314 QgsDebugMsgLevel(
"field " +
field +
" origalias " + aliasElem.attribute( QStringLiteral(
"name" ) ) +
" trans " + alias, 3 );
2315 mAttributeAliasMap.insert(
field, alias );
2320 mDefaultExpressionMap.clear();
2321 QDomNode defaultsNode = layerNode.namedItem( QStringLiteral(
"defaults" ) );
2322 if ( !defaultsNode.isNull() )
2324 QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral(
"default" ) );
2325 for (
int i = 0; i < defaultNodeList.size(); ++i )
2327 QDomElement defaultElem = defaultNodeList.at( i ).toElement();
2329 QString
field = defaultElem.attribute( QStringLiteral(
"field" ), QString() );
2330 QString expression = defaultElem.attribute( QStringLiteral(
"expression" ), QString() );
2331 bool applyOnUpdate = defaultElem.attribute( QStringLiteral(
"applyOnUpdate" ), QStringLiteral(
"0" ) ) == QLatin1String(
"1" );
2332 if (
field.isEmpty() || expression.isEmpty() )
2340 mFieldConstraints.clear();
2341 mFieldConstraintStrength.clear();
2342 QDomNode constraintsNode = layerNode.namedItem( QStringLiteral(
"constraints" ) );
2343 if ( !constraintsNode.isNull() )
2345 QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral(
"constraint" ) );
2346 for (
int i = 0; i < constraintNodeList.size(); ++i )
2348 QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2350 QString
field = constraintElem.attribute( QStringLiteral(
"field" ), QString() );
2351 int constraints = constraintElem.attribute( QStringLiteral(
"constraints" ), QStringLiteral(
"0" ) ).toInt();
2352 if (
field.isEmpty() || constraints == 0 )
2355 mFieldConstraints.insert(
field,
static_cast< QgsFieldConstraints::Constraints
>( constraints ) );
2357 int uniqueStrength = constraintElem.attribute( QStringLiteral(
"unique_strength" ), QStringLiteral(
"1" ) ).toInt();
2358 int notNullStrength = constraintElem.attribute( QStringLiteral(
"notnull_strength" ), QStringLiteral(
"1" ) ).toInt();
2359 int expStrength = constraintElem.attribute( QStringLiteral(
"exp_strength" ), QStringLiteral(
"1" ) ).toInt();
2366 mFieldConstraintExpressions.clear();
2367 QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral(
"constraintExpressions" ) );
2368 if ( !constraintExpressionsNode.isNull() )
2370 QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral(
"constraint" ) );
2371 for (
int i = 0; i < constraintNodeList.size(); ++i )
2373 QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2375 QString
field = constraintElem.attribute( QStringLiteral(
"field" ), QString() );
2376 QString exp = constraintElem.attribute( QStringLiteral(
"exp" ), QString() );
2377 QString desc = constraintElem.attribute( QStringLiteral(
"desc" ), QString() );
2378 if (
field.isEmpty() || exp.isEmpty() )
2381 mFieldConstraintExpressions.insert(
field, qMakePair( exp, desc ) );
2389 if ( categories.testFlag(
Fields ) || categories.testFlag(
Forms ) )
2393 QDomElement widgetsElem = layerNode.namedItem( QStringLiteral(
"fieldConfiguration" ) ).toElement();
2394 QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral(
"field" ) );
2395 for (
int i = 0; i < fieldConfigurationElementList.size(); ++i )
2397 const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
2398 const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral(
"editWidget" ) ).at( 0 ).toElement();
2400 QString fieldName = fieldConfigElement.attribute( QStringLiteral(
"name" ) );
2402 if ( categories.testFlag(
Fields ) )
2406 if ( categories.testFlag(
Forms ) )
2408 const QString widgetType = fieldWidgetElement.attribute( QStringLiteral(
"type" ) );
2409 const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral(
"config" ) ).at( 0 ).toElement();
2410 const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
2412 if ( widgetType == QLatin1String(
"ValueRelation" ) )
2414 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() );
2417 mFieldWidgetSetups[fieldName] = setup;
2424 if ( categories.testFlag(
Fields ) )
2426 const QList<QPair<QString, QgsField::ConfigurationFlag>> legacyConfig
2431 for (
const auto &config : legacyConfig )
2433 QDomNode excludeNode = layerNode.namedItem( config.first );
2434 if ( !excludeNode.isNull() )
2436 QDomNodeList attributeNodeList = excludeNode.toElement().elementsByTagName( QStringLiteral(
"attribute" ) );
2437 for (
int i = 0; i < attributeNodeList.size(); ++i )
2439 QString fieldName = attributeNodeList.at( i ).toElement().text();
2440 if ( !mFieldConfigurationFlags.contains( fieldName ) )
2441 mFieldConfigurationFlags[fieldName] = config.second;
2443 mFieldConfigurationFlags[fieldName].setFlag( config.second,
true );
2450 mGeometryOptions->readXml( layerNode.namedItem( QStringLiteral(
"geometryOptions" ) ) );
2452 if ( categories.testFlag(
Forms ) )
2453 mEditFormConfig.
readXml( layerNode, context );
2457 mAttributeTableConfig.
readXml( layerNode );
2458 mConditionalStyles->
readXml( layerNode, context );
2459 mStoredExpressionManager->
readXml( layerNode );
2465 QDomElement mapLayerNode = layerNode.toElement();
2467 && mapLayerNode.attribute( QStringLiteral(
"readOnly" ), QStringLiteral(
"0" ) ).toInt() == 1 )
2472 if ( categories.testFlag(
Legend ) )
2476 const QDomElement legendElem = layerNode.firstChildElement( QStringLiteral(
"legend" ) );
2477 if ( !legendElem.isNull() )
2482 mSetLegendFromStyle =
true;
2510 if ( !rendererElement.isNull() )
2530 if ( categories.testFlag(
Labeling ) )
2534 QDomElement labelingElement = node.firstChildElement( QStringLiteral(
"labeling" ) );
2536 if ( labelingElement.isNull() ||
2537 ( labelingElement.attribute( QStringLiteral(
"type" ) ) == QLatin1String(
"simple" ) && labelingElement.firstChildElement( QStringLiteral(
"settings" ) ).isNull() ) )
2545 labeling = readLabelingFromCustomProperties();
2553 if ( node.toElement().hasAttribute( QStringLiteral(
"labelsEnabled" ) ) )
2554 mLabelsEnabled = node.toElement().attribute( QStringLiteral(
"labelsEnabled" ) ).toInt();
2556 mLabelsEnabled =
true;
2562 QDomNode blendModeNode = node.namedItem( QStringLiteral(
"blendMode" ) );
2563 if ( !blendModeNode.isNull() )
2565 QDomElement e = blendModeNode.toElement();
2570 QDomNode featureBlendModeNode = node.namedItem( QStringLiteral(
"featureBlendMode" ) );
2571 if ( !featureBlendModeNode.isNull() )
2573 QDomElement e = featureBlendModeNode.toElement();
2581 QDomNode layerTransparencyNode = node.namedItem( QStringLiteral(
"layerTransparency" ) );
2582 if ( !layerTransparencyNode.isNull() )
2584 QDomElement e = layerTransparencyNode.toElement();
2585 setOpacity( 1.0 - e.text().toInt() / 100.0 );
2587 QDomNode layerOpacityNode = node.namedItem( QStringLiteral(
"layerOpacity" ) );
2588 if ( !layerOpacityNode.isNull() )
2590 QDomElement e = layerOpacityNode.toElement();
2594 const bool hasScaleBasedVisibiliy { node.attributes().namedItem( QStringLiteral(
"hasScaleBasedVisibilityFlag" ) ).nodeValue() ==
'1' };
2597 const double maxScale { node.attributes().namedItem( QStringLiteral(
"maxScale" ) ).nodeValue().toDouble( &ok ) };
2602 const double minScale { node.attributes().namedItem( QStringLiteral(
"minScale" ) ).nodeValue().toDouble( &ok ) };
2608 QDomElement e = node.toElement();
2611 mSimplifyMethod.
setSimplifyHints(
static_cast< QgsVectorSimplifyMethod::SimplifyHints
>( e.attribute( QStringLiteral(
"simplifyDrawingHints" ), QStringLiteral(
"1" ) ).toInt() ) );
2613 mSimplifyMethod.
setThreshold( e.attribute( QStringLiteral(
"simplifyDrawingTol" ), QStringLiteral(
"1" ) ).toFloat() );
2614 mSimplifyMethod.
setForceLocalOptimization( e.attribute( QStringLiteral(
"simplifyLocal" ), QStringLiteral(
"1" ) ).toInt() );
2615 mSimplifyMethod.
setMaximumScale( e.attribute( QStringLiteral(
"simplifyMaxScale" ), QStringLiteral(
"1" ) ).toFloat() );
2618 mRenderer->
setReferenceScale( e.attribute( QStringLiteral(
"symbologyReferenceScale" ), QStringLiteral(
"-1" ) ).toDouble() );
2622 if ( categories.testFlag(
Diagrams ) )
2626 delete mDiagramRenderer;
2627 mDiagramRenderer =
nullptr;
2628 QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral(
"SingleCategoryDiagramRenderer" ) );
2629 if ( !singleCatDiagramElem.isNull() )
2632 mDiagramRenderer->
readXml( singleCatDiagramElem, context );
2634 QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral(
"LinearlyInterpolatedDiagramRenderer" ) );
2635 if ( !linearDiagramElem.isNull() )
2637 if ( linearDiagramElem.hasAttribute( QStringLiteral(
"classificationAttribute" ) ) )
2640 int idx = linearDiagramElem.attribute( QStringLiteral(
"classificationAttribute" ) ).toInt();
2641 if ( idx >= 0 && idx < mFields.
count() )
2642 linearDiagramElem.setAttribute( QStringLiteral(
"classificationField" ), mFields.
at( idx ).
name() );
2646 mDiagramRenderer->
readXml( linearDiagramElem, context );
2649 if ( mDiagramRenderer )
2651 QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral(
"DiagramLayerSettings" ) );
2652 if ( !diagramSettingsElem.isNull() )
2654 bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral(
"xPosColumn" ) );
2655 bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral(
"yPosColumn" ) );
2656 bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral(
"showColumn" ) );
2657 if ( oldXPos || oldYPos || oldShow )
2663 int xPosColumn = diagramSettingsElem.attribute( QStringLiteral(
"xPosColumn" ) ).toInt();
2664 if ( xPosColumn >= 0 && xPosColumn < mFields.
count() )
2669 int yPosColumn = diagramSettingsElem.attribute( QStringLiteral(
"yPosColumn" ) ).toInt();
2670 if ( yPosColumn >= 0 && yPosColumn < mFields.
count() )
2675 int showColumn = diagramSettingsElem.attribute( QStringLiteral(
"showColumn" ) ).toInt();
2676 if ( showColumn >= 0 && showColumn < mFields.
count() )
2679 QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral(
"properties" ) );
2686 ddp.
writeXml( propertiesElem, defs );
2687 diagramSettingsElem.appendChild( propertiesElem );
2690 delete mDiagramLayerSettings;
2692 mDiagramLayerSettings->
readXml( diagramSettingsElem );
2698 styleChangedSignalBlocker.release();
2708 QDomElement layerElement = node.toElement();
2711 ( void )
writeStyle( node, doc, errorMessage, context, categories );
2714 mGeometryOptions->writeXml( node );
2719 if ( !legendElement.isNull() )
2720 node.appendChild( legendElement );
2727 QDomElement referencedLayersElement = doc.createElement( QStringLiteral(
"referencedLayers" ) );
2728 node.appendChild( referencedLayersElement );
2731 for (
const auto &rel : constReferencingRelations )
2740 QDomElement referencingLayersElement = doc.createElement( QStringLiteral(
"referencingLayers" ) );
2741 node.appendChild( referencedLayersElement );
2744 for (
const auto &rel : constReferencedRelations )
2755 if ( categories.testFlag(
Fields ) || categories.testFlag(
Forms ) )
2757 QDomElement fieldConfigurationElement;
2759 fieldConfigurationElement = doc.createElement( QStringLiteral(
"fieldConfiguration" ) );
2760 node.appendChild( fieldConfigurationElement );
2764 QDomElement fieldElement = doc.createElement( QStringLiteral(
"field" ) );
2765 fieldElement.setAttribute( QStringLiteral(
"name" ),
field.
name() );
2766 fieldConfigurationElement.appendChild( fieldElement );
2768 if ( categories.testFlag(
Fields ) )
2773 if ( categories.testFlag(
Forms ) )
2778 QDomElement editWidgetElement = doc.createElement( QStringLiteral(
"editWidget" ) );
2779 fieldElement.appendChild( editWidgetElement );
2781 QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral(
"config" ) );
2784 editWidgetElement.appendChild( editWidgetConfigElement );
2790 if ( categories.testFlag(
Fields ) )
2793 QDomElement aliasElem = doc.createElement( QStringLiteral(
"aliases" ) );
2796 QDomElement aliasEntryElem = doc.createElement( QStringLiteral(
"alias" ) );
2797 aliasEntryElem.setAttribute( QStringLiteral(
"field" ),
field.
name() );
2799 aliasEntryElem.setAttribute( QStringLiteral(
"name" ),
field.
alias() );
2800 aliasElem.appendChild( aliasEntryElem );
2802 node.appendChild( aliasElem );
2805 QDomElement defaultsElem = doc.createElement( QStringLiteral(
"defaults" ) );
2808 QDomElement defaultElem = doc.createElement( QStringLiteral(
"default" ) );
2809 defaultElem.setAttribute( QStringLiteral(
"field" ),
field.
name() );
2812 defaultsElem.appendChild( defaultElem );
2814 node.appendChild( defaultsElem );
2817 QDomElement constraintsElem = doc.createElement( QStringLiteral(
"constraints" ) );
2820 QDomElement constraintElem = doc.createElement( QStringLiteral(
"constraint" ) );
2821 constraintElem.setAttribute( QStringLiteral(
"field" ),
field.
name() );
2826 constraintsElem.appendChild( constraintElem );
2828 node.appendChild( constraintsElem );
2831 QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral(
"constraintExpressions" ) );
2834 QDomElement constraintExpressionElem = doc.createElement( QStringLiteral(
"constraint" ) );
2835 constraintExpressionElem.setAttribute( QStringLiteral(
"field" ),
field.
name() );
2838 constraintExpressionsElem.appendChild( constraintExpressionElem );
2840 node.appendChild( constraintExpressionsElem );
2843 if ( !mExpressionFieldBuffer )
2851 mExpressionFieldBuffer->
writeXml( node, doc );
2856 if ( categories.testFlag(
Actions ) )
2861 mAttributeTableConfig.
writeXml( node );
2862 mConditionalStyles->
writeXml( node, doc, context );
2863 mStoredExpressionManager->
writeXml( node );
2866 if ( categories.testFlag(
Forms ) )
2867 mEditFormConfig.
writeXml( node, context );
2871 node.toElement().setAttribute( QStringLiteral(
"readOnly" ), mReadOnly );
2876 QDomElement prevExpElem = doc.createElement( QStringLiteral(
"previewExpression" ) );
2877 QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2878 prevExpElem.appendChild( prevExpText );
2879 node.appendChild( prevExpElem );
2883 if ( categories.testFlag(
MapTips ) )
2885 QDomElement mapTipElem = doc.createElement( QStringLiteral(
"mapTip" ) );
2886 QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
2887 mapTipElem.appendChild( mapTipText );
2888 node.toElement().appendChild( mapTipElem );
2897 QDomElement mapLayerNode = node.toElement();
2910 QDomElement rendererElement = mRenderer->
save( doc, context );
2911 node.appendChild( rendererElement );
2915 if ( categories.testFlag(
Labeling ) )
2919 QDomElement labelingElement = mLabeling->
save( doc, context );
2920 node.appendChild( labelingElement );
2922 mapLayerNode.setAttribute( QStringLiteral(
"labelsEnabled" ), mLabelsEnabled ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
2928 mapLayerNode.setAttribute( QStringLiteral(
"simplifyDrawingHints" ), QString::number( mSimplifyMethod.
simplifyHints() ) );
2929 mapLayerNode.setAttribute( QStringLiteral(
"simplifyAlgorithm" ), QString::number( mSimplifyMethod.
simplifyAlgorithm() ) );
2930 mapLayerNode.setAttribute( QStringLiteral(
"simplifyDrawingTol" ), QString::number( mSimplifyMethod.
threshold() ) );
2931 mapLayerNode.setAttribute( QStringLiteral(
"simplifyLocal" ), mSimplifyMethod.
forceLocalOptimization() ? 1 : 0 );
2932 mapLayerNode.setAttribute( QStringLiteral(
"simplifyMaxScale" ), QString::number( mSimplifyMethod.
maximumScale() ) );
2944 QDomElement blendModeElem = doc.createElement( QStringLiteral(
"blendMode" ) );
2946 blendModeElem.appendChild( blendModeText );
2947 node.appendChild( blendModeElem );
2950 QDomElement featureBlendModeElem = doc.createElement( QStringLiteral(
"featureBlendMode" ) );
2952 featureBlendModeElem.appendChild( featureBlendModeText );
2953 node.appendChild( featureBlendModeElem );
2959 QDomElement layerOpacityElem = doc.createElement( QStringLiteral(
"layerOpacity" ) );
2960 QDomText layerOpacityText = doc.createTextNode( QString::number(
opacity() ) );
2961 layerOpacityElem.appendChild( layerOpacityText );
2962 node.appendChild( layerOpacityElem );
2963 mapLayerNode.setAttribute( QStringLiteral(
"hasScaleBasedVisibilityFlag" ),
hasScaleBasedVisibility() ? 1 : 0 );
2964 mapLayerNode.setAttribute( QStringLiteral(
"maxScale" ),
maximumScale() );
2965 mapLayerNode.setAttribute( QStringLiteral(
"minScale" ),
minimumScale() );
2967 mapLayerNode.setAttribute( QStringLiteral(
"symbologyReferenceScale" ), mRenderer ? mRenderer->
referenceScale() : -1 );
2970 if ( categories.testFlag(
Diagrams ) && mDiagramRenderer )
2972 mDiagramRenderer->
writeXml( mapLayerNode, doc, context );
2973 if ( mDiagramLayerSettings )
2974 mDiagramLayerSettings->
writeXml( mapLayerNode, doc );
2983 QDomElement nameElem = node.firstChildElement( QStringLiteral(
"Name" ) );
2984 if ( nameElem.isNull() )
2986 errorMessage = QStringLiteral(
"Warning: Name element not found within NamedLayer while it's required." );
3002 readSldLabeling( node );
3004 styleChangedSignalBlocker.release();
3012 Q_UNUSED( errorMessage )
3014 QVariantMap localProps = QVariantMap( props );
3023 QDomElement nameNode = doc.createElement( QStringLiteral(
"se:Name" ) );
3024 nameNode.appendChild( doc.createTextNode(
name() ) );
3025 node.appendChild( nameNode );
3027 QDomElement userStyleElem = doc.createElement( QStringLiteral(
"UserStyle" ) );
3028 node.appendChild( userStyleElem );
3030 QDomElement nameElem = doc.createElement( QStringLiteral(
"se:Name" ) );
3031 nameElem.appendChild( doc.createTextNode(
name() ) );
3033 userStyleElem.appendChild( nameElem );
3035 QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral(
"se:FeatureTypeStyle" ) );
3036 userStyleElem.appendChild( featureTypeStyleElem );
3038 mRenderer->
toSld( doc, featureTypeStyleElem, localProps );
3041 mLabeling->
toSld( featureTypeStyleElem, localProps );
3050 if ( !mEditBuffer || !mDataProvider )
3055 if ( mGeometryOptions->isActive() )
3056 mGeometryOptions->apply( geom );
3065 if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
3066 updateDefaultValues( fid );
3074 bool result =
false;
3088 if ( mEditBuffer && mDataProvider )
3097 if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3098 updateDefaultValues( fid );
3113 for (
auto it = newValues.constBegin(); it != newValues.constEnd(); ++it )
3115 const int field = it.key();
3116 const QVariant newValue = it.value();
3119 if ( oldValues.contains(
field ) )
3120 oldValue = oldValues[
field];
3125 newValuesJoin[
field] = newValue;
3126 oldValuesJoin[
field] = oldValue;
3133 newValuesNotJoin[
field] = newValue;
3134 oldValuesNotJoin[
field] = oldValue;
3143 if ( ! newValuesJoin.isEmpty() && mJoinBuffer )
3148 if ( ! newValuesNotJoin.isEmpty() && mEditBuffer && mDataProvider )
3153 if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3155 updateDefaultValues( fid );
3163 if ( !mEditBuffer || !mDataProvider )
3171 if ( attIndex < 0 || attIndex >=
fields().count() )
3175 mFields[ attIndex ].setAlias( QString() );
3176 if ( mAttributeAliasMap.contains(
name ) )
3178 mAttributeAliasMap.remove(
name );
3180 mEditFormConfig.setFields( mFields );
3187 if ( index < 0 || index >=
fields().count() )
3194 if ( mExpressionFieldBuffer )
3210 if ( !mEditBuffer || !mDataProvider )
3226 if ( attIndex < 0 || attIndex >=
fields().count() )
3231 mAttributeAliasMap.insert(
name, aliasString );
3232 mFields[ attIndex ].setAlias( aliasString );
3233 mEditFormConfig.setFields( mFields );
3239 if ( index < 0 || index >=
fields().count() )
3247 if ( index >= 0 && index < mFields.
count() )
3255 return mAttributeAliasMap;
3260 QSet<QString> excludeList;
3261 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3262 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3266 excludeList << flagsIt.key();
3274 QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
3275 for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
3284 QSet<QString> excludeList;
3285 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3286 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3290 excludeList << flagsIt.key();
3298 QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
3299 for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
3308 if ( index < 0 || index >=
fields().count() )
3317 if ( !mEditBuffer || !mDataProvider )
3325 bool deleted =
false;
3328 QList<int> attrList = qgis::setToList( qgis::listToSet( attrs ) );
3330 std::sort( attrList.begin(), attrList.end(), std::greater<int>() );
3332 for (
int attr : std::as_const( attrList ) )
3348 if ( context && context->
cascade )
3351 const bool hasRelationsOrJoins = !relations.empty() || mJoinBuffer->
containsJoins();
3352 if ( hasRelationsOrJoins )
3357 if ( handledFeatureIds.contains( fid ) )
3365 handledFeatureIds << fid;
3383 while ( relatedFeaturesIt.
nextFeature( childFeature ) )
3385 childFeatureIds.insert( childFeature.
id() );
3387 if ( childFeatureIds.count() > 0 )
3389 relation.referencingLayer()->startEditing();
3390 relation.referencingLayer()->deleteFeatures( childFeatureIds, context );
3410 bool res = deleteFeatureCascade( fid, context );
3423 const auto constFids = fids;
3425 res = deleteFeatureCascade( fid, context ) && res;
3429 mSelectedFeatureIds.subtract( fids );
3444 if ( !mDataProvider )
3445 return pkAttributesList;
3448 for (
int i = 0; i < mFields.
count(); ++i )
3452 pkAttributesList << i;
3455 return pkAttributesList;
3460 if ( !mDataProvider )
3471 if ( mEditBuffer && !deletedFeatures.empty() )
3473 if ( addedFeatures.size() > deletedFeatures.size() )
3474 return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3476 return QgsFeatureSource::FeatureAvailability::FeaturesMaybeAvailable;
3479 if ( ( !mEditBuffer || addedFeatures.empty() ) && mDataProvider && mDataProvider->
empty() )
3480 return QgsFeatureSource::FeatureAvailability::NoFeaturesAvailable;
3482 return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3490 mCommitErrors.clear();
3492 if ( !mDataProvider )
3494 mCommitErrors << tr(
"ERROR: no provider" );
3500 mCommitErrors << tr(
"ERROR: layer not editable" );
3506 if ( !mAllowCommit )
3509 mCommitChangesActive =
true;
3511 bool success =
false;
3517 mCommitChangesActive =
false;
3519 if ( !mDeletedFids.empty() )
3522 mDeletedFids.clear();
3561 return mCommitErrors;
3574 if ( !mDataProvider )
3576 mCommitErrors << tr(
"ERROR: no provider" );
3602 mEditBuffer =
nullptr;
3607 if ( rollbackExtent )
3618 return mSelectedFeatureIds.size();
3623 return mSelectedFeatureIds;
3629 features.reserve( mSelectedFeatureIds.count() );
3632 if ( mSelectedFeatureIds.count() <= 8 )
3636 const auto constMSelectedFeatureIds = mSelectedFeatureIds;
3649 features.push_back( f );
3658 if ( mSelectedFeatureIds.isEmpty() )
3664 if ( mSelectedFeatureIds.count() == 1 )
3665 request.
setFilterFid( *mSelectedFeatureIds.constBegin() );
3674 if ( !mEditBuffer || !mDataProvider )
3677 if ( mGeometryOptions->isActive() )
3679 for (
auto feature = features.begin(); feature != features.end(); ++feature )
3682 mGeometryOptions->apply( geom );
3724 if ( !mDisplayExpression.isEmpty() || mFields.
isEmpty() )
3726 return mDisplayExpression;
3731 if ( !candidateName.isEmpty() )
3744 return ( mEditBuffer && mDataProvider );
3753 bool QgsVectorLayer::isReadOnly()
const
3761 if ( readonly && mEditBuffer )
3764 mReadOnly = readonly;
3771 if ( ! mDataProvider )
3780 return mEditBuffer && mEditBuffer->
isModified();
3785 bool auxiliaryField =
false;
3789 return auxiliaryField;
3796 auxiliaryField =
true;
3799 return auxiliaryField;
3810 if ( r != mRenderer )
3814 mSymbolFeatureCounted =
false;
3815 mSymbolFeatureCountMap.clear();
3816 mSymbolFeatureIdMap.clear();
3821 if ( refreshRate <= 0 )
3823 mRefreshRendererTimer->stop();
3824 mRefreshRendererTimer->setInterval( 0 );
3828 mRefreshRendererTimer->setInterval( 1000 / refreshRate );
3829 mRefreshRendererTimer->start();
3842 mRendererGenerators << generator;
3848 for (
int i = mRendererGenerators.count() - 1; i >= 0; --i )
3850 if ( mRendererGenerators.at( i )->id() ==
id )
3852 delete mRendererGenerators.at( i );
3853 mRendererGenerators.removeAt( i );
3860 QList< const QgsFeatureRendererGenerator * > res;
3868 if ( !mDataProvider )
3874 QString ignoredError;
3878 mEditCommandActive =
true;
3884 if ( !mDataProvider )
3889 mEditCommandActive =
false;
3890 if ( !mDeletedFids.isEmpty() )
3894 mSelectedFeatureIds.subtract( mDeletedFids );
3897 mDeletedFids.clear();
3904 if ( !mDataProvider )
3915 std::unique_ptr< QUndoCommand > command = std::make_unique< QUndoCommand >();
3916 command->setObsolete(
true );
3919 mEditCommandActive =
false;
3920 mDeletedFids.clear();
3926 return mJoinBuffer->
addJoin( joinInfo );
3932 return mJoinBuffer->
removeJoin( joinLayerId );
3965 if ( oi < 0 || oi >= mExpressionFieldBuffer->
expressions().size() )
3968 return mExpressionFieldBuffer->
expressions().at( oi ).cachedExpression.expression();
3979 if ( !mDataProvider )
3984 mFields = mDataProvider->
fields();
3994 if ( mExpressionFieldBuffer )
3998 QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
3999 for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
4005 mFields[ index ].setAlias( aliasIt.value() );
4009 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
4010 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
4016 mFields[index].setConfigurationFlags( flagsIt.value() );
4020 mDefaultValueOnUpdateFields.clear();
4021 QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
4022 for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
4024 int index = mFields.
lookupField( defaultIt.key() );
4028 mFields[ index ].setDefaultValueDefinition( defaultIt.value() );
4029 if ( defaultIt.value().applyOnUpdate() )
4030 mDefaultValueOnUpdateFields.insert( index );
4033 QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
4034 for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
4036 int index = mFields.
lookupField( constraintIt.key() );
4049 mFields[ index ].setConstraints( constraints );
4052 QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
4053 for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
4055 int index = mFields.
lookupField( constraintExpIt.key() );
4066 mFields[ index ].setConstraints( constraints );
4070 for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
4072 int index = mFields.
lookupField( constraintStrengthIt.key().first );
4082 constraints.
setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
4083 mFields[ index ].setConstraints( constraints );
4086 auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
4087 for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
4089 int index = mFields.
indexOf( fieldWidgetIterator.key() );
4093 mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
4096 if ( oldFields != mFields )
4099 mEditFormConfig.setFields( mFields );
4107 if ( index < 0 || index >= mFields.
count() || !mDataProvider )
4111 if ( expression.isEmpty() )
4115 std::unique_ptr< QgsExpressionContext > tempContext;
4120 evalContext = tempContext.get();
4153 if ( index < 0 || index >= mFields.
count() )
4158 mDefaultExpressionMap.insert( mFields.
at( index ).
name(), definition );
4162 mDefaultExpressionMap.remove( mFields.
at( index ).
name() );
4169 if ( index < 0 || index >= mFields.
count() )
4178 if ( !mDataProvider )
4193 if ( mEditBuffer && ! mDataProvider->
transaction() )
4197 for (
const QVariant &v : constUniqueValues )
4199 vals << v.toString();
4203 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4204 while ( addedIt.hasNext() && ( limit < 0 ||
uniqueValues.count() < limit ) )
4207 QVariant v = addedIt.value().attribute( index );
4210 QString vs = v.toString();
4211 if ( !vals.contains( vs ) )
4220 while ( it.hasNext() && ( limit < 0 ||
uniqueValues.count() < limit ) )
4223 QVariant v = it.value().value( index );
4226 QString vs = v.toString();
4227 if ( !vals.contains( vs ) )
4260 .setSubsetOfAttributes( attList ) );
4263 QVariant currentValue;
4264 QHash<QString, QVariant> val;
4268 val.insert( currentValue.toString(), currentValue );
4269 if ( limit >= 0 && val.size() >= limit )
4275 return qgis::listToSet( val.values() );
4279 Q_ASSERT_X(
false,
"QgsVectorLayer::uniqueValues()",
"Unknown source of the field!" );
4285 QStringList results;
4286 if ( !mDataProvider )
4301 if ( mEditBuffer && ! mDataProvider->
transaction() )
4304 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4305 while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->
isCanceled() ) )
4308 QVariant v = addedIt.value().attribute( index );
4311 QString vs = v.toString();
4312 if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4320 while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->
isCanceled() ) )
4323 QVariant v = it.value().value( index );
4326 QString vs = v.toString();
4327 if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4358 QString fieldName = mFields.
at( index ).
name();
4359 request.
setFilterExpression( QStringLiteral(
"\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
4363 QString currentValue;
4366 currentValue = f.
attribute( index ).toString();
4367 if ( !results.contains( currentValue ) )
4368 results << currentValue;
4370 if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->
isCanceled() ) )
4380 Q_ASSERT_X(
false,
"QgsVectorLayer::uniqueStringsMatching()",
"Unknown source of the field!" );
4387 minimumOrMaximumValue( index, &minimum,
nullptr );
4394 minimumOrMaximumValue( index,
nullptr, &maximum );
4400 minimumOrMaximumValue( index, &minimum, &maximum );
4403 void QgsVectorLayer::minimumOrMaximumValue(
int index, QVariant *minimum, QVariant *maximum )
const
4406 *minimum = QVariant();
4408 *maximum = QVariant();
4410 if ( !mDataProvider )
4430 if ( mEditBuffer && ! mDataProvider->
transaction() )
4433 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4434 while ( addedIt.hasNext() )
4437 const QVariant v = addedIt.value().attribute( index );
4445 while ( it.hasNext() )
4448 const QVariant v = it.value().value( index );
4484 .setSubsetOfAttributes( attList ) );
4487 bool firstValue =
true;
4490 const QVariant currentValue = f.
attribute( index );
4491 if ( currentValue.isNull() )
4497 *minimum = currentValue;
4499 *maximum = currentValue;
4504 if ( minimum && currentValue.isValid() &&
qgsVariantLessThan( currentValue, *minimum ) )
4505 *minimum = currentValue;
4507 *maximum = currentValue;
4514 Q_ASSERT_X(
false,
"QgsVectorLayer::minimumOrMaximumValue()",
"Unknown source of the field!" );
4517 void QgsVectorLayer::createEditBuffer()
4551 void QgsVectorLayer::clearEditBuffer()
4554 mEditBuffer =
nullptr;
4566 if ( !mDataProvider )
4569 *
error = tr(
"Layer is invalid" );
4575 if ( attrIndex >= 0 )
4582 bool providerOk =
false;
4583 QVariant val = mDataProvider->
aggregate(
aggregate, attrIndex, parameters, context, providerOk, fids );
4597 c.setFidsFilter( *fids );
4598 c.setParameters( parameters );
4599 bool aggregateOk =
false;
4600 const QVariant result =
c.calculate(
aggregate, fieldOrExpression, context, &aggregateOk, feedback );
4603 if ( !aggregateOk &&
error )
4621 return mFeatureBlendMode;
4624 void QgsVectorLayer::readSldLabeling(
const QDomNode &node )
4629 QDomElement element = node.toElement();
4630 if ( element.isNull() )
4633 QDomElement userStyleElem = element.firstChildElement( QStringLiteral(
"UserStyle" ) );
4634 if ( userStyleElem.isNull() )
4636 QgsDebugMsgLevel( QStringLiteral(
"Info: UserStyle element not found." ), 4 );
4640 QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral(
"FeatureTypeStyle" ) );
4641 if ( featTypeStyleElem.isNull() )
4643 QgsDebugMsgLevel( QStringLiteral(
"Info: FeatureTypeStyle element not found." ), 4 );
4648 QDomElement mergedFeatTypeStyle = featTypeStyleElem.cloneNode(
false ).toElement();
4653 bool needRuleBasedLabeling =
false;
4656 while ( !featTypeStyleElem.isNull() )
4658 QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral(
"Rule" ) );
4659 while ( !ruleElem.isNull() )
4663 bool hasTextSymbolizer =
false;
4664 bool hasRuleBased =
false;
4665 QDomElement ruleChildElem = ruleElem.firstChildElement();
4666 while ( !ruleChildElem.isNull() )
4669 if ( ruleChildElem.localName() == QLatin1String(
"Filter" ) ||
4670 ruleChildElem.localName() == QLatin1String(
"MinScaleDenominator" ) ||
4671 ruleChildElem.localName() == QLatin1String(
"MaxScaleDenominator" ) )
4673 hasRuleBased =
true;
4676 else if ( ruleChildElem.localName() == QLatin1String(
"TextSymbolizer" ) )
4678 QgsDebugMsgLevel( QStringLiteral(
"Info: TextSymbolizer element found" ), 4 );
4679 hasTextSymbolizer =
true;
4682 ruleChildElem = ruleChildElem.nextSiblingElement();
4685 if ( hasTextSymbolizer )
4690 mergedFeatTypeStyle.appendChild( ruleElem.cloneNode().toElement() );
4694 QgsDebugMsgLevel( QStringLiteral(
"Info: Filter or Min/MaxScaleDenominator element found: need a RuleBasedLabeling" ), 4 );
4695 needRuleBasedLabeling =
true;
4700 if ( ruleCount > 1 )
4702 QgsDebugMsgLevel( QStringLiteral(
"Info: More Rule elements found: need a RuleBasedLabeling" ), 4 );
4703 needRuleBasedLabeling =
true;
4707 if ( ruleCount == 0 )
4709 needRuleBasedLabeling =
false;
4712 ruleElem = ruleElem.nextSiblingElement( QStringLiteral(
"Rule" ) );
4714 featTypeStyleElem = featTypeStyleElem.nextSiblingElement( QStringLiteral(
"FeatureTypeStyle" ) );
4717 if ( ruleCount == 0 )
4719 QgsDebugMsgLevel( QStringLiteral(
"Info: No TextSymbolizer element." ), 4 );
4723 QDomElement ruleElem = mergedFeatTypeStyle.firstChildElement( QStringLiteral(
"Rule" ) );
4725 if ( needRuleBasedLabeling )
4729 while ( !ruleElem.isNull() )
4732 QString label, description, filterExp;
4733 int scaleMinDenom = 0, scaleMaxDenom = 0;
4737 QDomElement childElem = ruleElem.firstChildElement();
4738 while ( !childElem.isNull() )
4740 if ( childElem.localName() == QLatin1String(
"Name" ) )
4744 if ( label.isEmpty() )
4745 label = childElem.firstChild().nodeValue();
4747 else if ( childElem.localName() == QLatin1String(
"Description" ) )
4750 QDomElement titleElem = childElem.firstChildElement( QStringLiteral(
"Title" ) );
4751 if ( !titleElem.isNull() )
4753 label = titleElem.firstChild().nodeValue();
4756 QDomElement abstractElem = childElem.firstChildElement( QStringLiteral(
"Abstract" ) );
4757 if ( !abstractElem.isNull() )
4759 description = abstractElem.firstChild().nodeValue();
4762 else if ( childElem.localName() == QLatin1String(
"Abstract" ) )
4765 description = childElem.firstChild().nodeValue();
4767 else if ( childElem.localName() == QLatin1String(
"Title" ) )
4770 label = childElem.firstChild().nodeValue();
4772 else if ( childElem.localName() == QLatin1String(
"Filter" ) )
4788 else if ( childElem.localName() == QLatin1String(
"MinScaleDenominator" ) )
4791 int v = childElem.firstChild().nodeValue().toInt( &ok );
4795 else if ( childElem.localName() == QLatin1String(
"MaxScaleDenominator" ) )
4798 int v = childElem.firstChild().nodeValue().toInt( &ok );
4802 else if ( childElem.localName() == QLatin1String(
"TextSymbolizer" ) )
4804 readSldTextSymbolizer( childElem, settings );
4807 childElem = childElem.nextSiblingElement();
4813 ruleElem = ruleElem.nextSiblingElement();
4823 QDomElement textSymbolizerElem = ruleElem.firstChildElement( QStringLiteral(
"TextSymbolizer" ) );
4825 if ( readSldTextSymbolizer( textSymbolizerElem, s ) )
4833 bool QgsVectorLayer::readSldTextSymbolizer(
const QDomNode &node,
QgsPalLayerSettings &settings )
const
4835 if ( node.localName() != QLatin1String(
"TextSymbolizer" ) )
4837 QgsDebugMsgLevel( QStringLiteral(
"Not a TextSymbolizer element: %1" ).arg( node.localName() ), 3 );
4840 QDomElement textSymbolizerElem = node.toElement();
4842 QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral(
"Label" ) );
4843 if ( !labelElem.isNull() )
4845 QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral(
"PropertyName" ) );
4846 if ( !propertyNameElem.isNull() )
4851 QString labelAttribute = propertyNameElem.text();
4855 int fieldIndex = mFields.
lookupField( labelAttribute );
4856 if ( fieldIndex == -1 )
4860 if ( !exp.hasEvalError() )
4866 QgsDebugMsgLevel( QStringLiteral(
"SLD label attribute error: %1" ).arg( exp.evalErrorString() ), 3 );
4872 QgsDebugMsgLevel( QStringLiteral(
"Info: PropertyName element not found." ), 4 );
4883 if ( textSymbolizerElem.hasAttribute( QStringLiteral(
"uom" ) ) )
4888 QString fontFamily = QStringLiteral(
"Sans-Serif" );
4889 int fontPointSize = 10;
4891 int fontWeight = -1;
4892 bool fontItalic =
false;
4893 bool fontUnderline =
false;
4896 QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral(
"Font" ) );
4897 if ( !fontElem.isNull() )
4900 for ( QgsStringMap::iterator it = fontSvgParams.begin(); it != fontSvgParams.end(); ++it )
4902 QgsDebugMsgLevel( QStringLiteral(
"found fontSvgParams %1: %2" ).arg( it.key(), it.value() ), 4 );
4904 if ( it.key() == QLatin1String(
"font-family" ) )
4906 fontFamily = it.value();
4908 else if ( it.key() == QLatin1String(
"font-style" ) )
4910 fontItalic = ( it.value() == QLatin1String(
"italic" ) ) || ( it.value() == QLatin1String(
"Italic" ) );
4912 else if ( it.key() == QLatin1String(
"font-size" ) )
4915 int fontSize = it.value().toInt( &ok );
4918 fontPointSize = fontSize;
4919 fontUnitSize = sldUnitSize;
4922 else if ( it.key() == QLatin1String(
"font-weight" ) )
4924 if ( ( it.value() == QLatin1String(
"bold" ) ) || ( it.value() == QLatin1String(
"Bold" ) ) )
4925 fontWeight = QFont::Bold;
4927 else if ( it.key() == QLatin1String(
"font-underline" ) )
4929 fontUnderline = ( it.value() == QLatin1String(
"underline" ) ) || ( it.value() == QLatin1String(
"Underline" ) );
4935 QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
4936 font.setUnderline( fontUnderline );
4938 format.
setSize( fontPointSize );
4942 QDomElement fillElem = textSymbolizerElem.firstChildElement( QStringLiteral(
"Fill" ) );
4944 Qt::BrushStyle textBrush = Qt::SolidPattern;
4946 if ( textColor.isValid() )
4948 QgsDebugMsgLevel( QStringLiteral(
"Info: textColor %1." ).arg( QVariant( textColor ).toString() ), 4 );
4955 QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral(
"Halo" ) );
4956 if ( !haloElem.isNull() )
4961 QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral(
"Radius" ) );
4962 if ( !radiusElem.isNull() )
4965 double bufferSize = radiusElem.text().toDouble( &ok );
4968 bufferSettings.
setSize( bufferSize );
4973 QDomElement haloFillElem = haloElem.firstChildElement( QStringLiteral(
"Fill" ) );
4975 Qt::BrushStyle bufferBrush = Qt::SolidPattern;
4977 if ( bufferColor.isValid() )
4979 QgsDebugMsgLevel( QStringLiteral(
"Info: bufferColor %1." ).arg( QVariant( bufferColor ).toString() ), 4 );
4980 bufferSettings.
setColor( bufferColor );
4985 QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral(
"LabelPlacement" ) );
4986 if ( !labelPlacementElem.isNull() )
4989 QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral(
"PointPlacement" ) );
4990 if ( !pointPlacementElem.isNull() )
4998 QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral(
"Displacement" ) );
4999 if ( !displacementElem.isNull() )
5001 QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
5002 if ( !displacementXElem.isNull() )
5005 double xOffset = displacementXElem.text().toDouble( &ok );
5012 QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
5013 if ( !displacementYElem.isNull() )
5016 double yOffset = displacementYElem.text().toDouble( &ok );
5024 QDomElement anchorPointElem = pointPlacementElem.firstChildElement( QStringLiteral(
"AnchorPoint" ) );
5025 if ( !anchorPointElem.isNull() )
5027 QDomElement anchorPointXElem = anchorPointElem.firstChildElement( QStringLiteral(
"AnchorPointX" ) );
5028 if ( !anchorPointXElem.isNull() )
5031 double xOffset = anchorPointXElem.text().toDouble( &ok );
5038 QDomElement anchorPointYElem = anchorPointElem.firstChildElement( QStringLiteral(
"AnchorPointY" ) );
5039 if ( !anchorPointYElem.isNull() )
5042 double yOffset = anchorPointYElem.text().toDouble( &ok );
5051 QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral(
"Rotation" ) );
5052 if ( !rotationElem.isNull() )
5055 double rotation = rotationElem.text().toDouble( &ok );
5065 QDomElement linePlacementElem = labelPlacementElem.firstChildElement( QStringLiteral(
"LinePlacement" ) );
5066 if ( !linePlacementElem.isNull() )
5075 QDomElement vendorOptionElem = textSymbolizerElem.firstChildElement( QStringLiteral(
"VendorOption" ) );
5076 while ( !vendorOptionElem.isNull() && vendorOptionElem.localName() == QLatin1String(
"VendorOption" ) )
5078 QString optionName = vendorOptionElem.attribute( QStringLiteral(
"name" ) );
5079 QString optionValue;
5080 if ( vendorOptionElem.firstChild().nodeType() == QDomNode::TextNode )
5082 optionValue = vendorOptionElem.firstChild().nodeValue();
5086 if ( vendorOptionElem.firstChild().nodeType() == QDomNode::ElementNode &&
5087 vendorOptionElem.firstChild().localName() == QLatin1String(
"Literal" ) )
5089 QgsDebugMsg( vendorOptionElem.firstChild().localName() );
5090 optionValue = vendorOptionElem.firstChild().firstChild().nodeValue();
5094 QgsDebugMsg( QStringLiteral(
"unexpected child of %1 named %2" ).arg( vendorOptionElem.localName(), optionName ) );
5098 if ( !optionName.isEmpty() && !optionValue.isEmpty() )
5100 vendorOptions[ optionName ] = optionValue;
5103 vendorOptionElem = vendorOptionElem.nextSiblingElement();
5105 if ( !vendorOptions.isEmpty() )
5107 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
5109 if ( it.key() == QLatin1String(
"underlineText" ) && it.value() == QLatin1String(
"true" ) )
5111 font.setUnderline(
true );
5114 else if ( it.key() == QLatin1String(
"strikethroughText" ) && it.value() == QLatin1String(
"true" ) )
5116 font.setStrikeOut(
true );
5119 else if ( it.key() == QLatin1String(
"maxDisplacement" ) )
5123 else if ( it.key() == QLatin1String(
"followLine" ) && it.value() == QLatin1String(
"true" ) )
5134 else if ( it.key() == QLatin1String(
"maxAngleDelta" ) )
5137 double angle = it.value().toDouble( &ok );
5145 else if ( it.key() == QLatin1String(
"conflictResolution" ) && it.value() == QLatin1String(
"false" ) )
5149 else if ( it.key() == QLatin1String(
"forceLeftToRight" ) && it.value() == QLatin1String(
"false" ) )
5151 settings.
upsidedownLabels = Qgis::UpsideDownLabelHandling::AlwaysAllowUpsideDown;
5153 else if ( it.key() == QLatin1String(
"group" ) && it.value() == QLatin1String(
"yes" ) )
5157 else if ( it.key() == QLatin1String(
"labelAllGroup" ) && it.value() == QLatin1String(
"true" ) )
5171 return mEditFormConfig;
5180 mEditFormConfig.onRelationsLoaded();
5186 return mMapTipTemplate;
5191 if ( mMapTipTemplate == mapTip )
5194 mMapTipTemplate = mapTip;
5229 if ( !mDiagramLayerSettings )
5231 *mDiagramLayerSettings = s;
5237 QString myMetadata = QStringLiteral(
"<html><head></head>\n<body>\n" );
5242 myMetadata += QStringLiteral(
"<h1>" ) + tr(
"Information from provider" ) + QStringLiteral(
"</h1>\n<hr>\n" );
5243 myMetadata += QLatin1String(
"<table class=\"list-view\">\n" );
5248 myMetadata += QStringLiteral(
"<tr><td class=\"highlight\">" ) + tr(
"Storage" ) + QStringLiteral(
"</td><td>" ) +
storageType() + QStringLiteral(
"</td></tr>\n" );
5254 myMetadata += QStringLiteral(
"<tr><td class=\"highlight\">" ) + tr(
"Comment" ) + QStringLiteral(
"</td><td>" ) +
dataComment() + QStringLiteral(
"</td></tr>\n" );
5261 myMetadata += QStringLiteral(
"<tr><td class=\"highlight\">" ) + tr(
"Encoding" ) + QStringLiteral(
"</td><td>" ) + provider->
encoding() + QStringLiteral(
"</td></tr>\n" );
5276 myMetadata += QStringLiteral(
"<tr><td class=\"highlight\">" ) + tr(
"Geometry" ) + QStringLiteral(
"</td><td>" ) + typeString + QStringLiteral(
"</td></tr>\n" );
5280 myMetadata += QStringLiteral(
"<tr><td class=\"highlight\">" ) + tr(
"Extent" ) + QStringLiteral(
"</td><td>" ) +
extent().
toString() + QStringLiteral(
"</td></tr>\n" );
5284 QLocale locale = QLocale();
5285 locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
5286 myMetadata += QStringLiteral(
"<tr><td class=\"highlight\">" )
5287 + tr(
"Feature count" ) + QStringLiteral(
"</td><td>" )
5289 + QStringLiteral(
"</td></tr>\n" );
5292 myMetadata += QLatin1String(
"</table>\n<br><br>" );
5301 myMetadata += QStringLiteral(
"<h1>" ) + tr(
"Identification" ) + QStringLiteral(
"</h1>\n<hr>\n" );
5303 myMetadata += QLatin1String(
"<br><br>\n" );
5306 myMetadata += QStringLiteral(
"<h1>" ) + tr(
"Extent" ) + QStringLiteral(
"</h1>\n<hr>\n" );
5308 myMetadata += QLatin1String(
"<br><br>\n" );
5311 myMetadata += QStringLiteral(
"<h1>" ) + tr(
"Access" ) + QStringLiteral(
"</h1>\n<hr>\n" );
5313 myMetadata += QLatin1String(
"<br><br>\n" );
5316 myMetadata += QStringLiteral(
"<h1>" ) + tr(
"Fields" ) + QStringLiteral(
"</h1>\n<hr>\n<table class=\"list-view\">\n" );
5320 if ( !pkAttrList.isEmpty() )
5322 myMetadata += QStringLiteral(
"<tr><td class=\"highlight\">" ) + tr(
"Primary key attributes" ) + QStringLiteral(
"</td><td>" );
5323 const auto constPkAttrList = pkAttrList;
5324 for (
int idx : constPkAttrList )
5328 myMetadata += QLatin1String(
"</td></tr>\n" );
5334 myMetadata += QStringLiteral(
"<tr><td class=\"highlight\">" ) + tr(
"Count" ) + QStringLiteral(
"</td><td>" ) + QString::number( myFields.
size() ) + QStringLiteral(
"</td></tr>\n" );
5336 myMetadata += QLatin1String(
"</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
5337 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" );
5339 for (
int i = 0; i < myFields.
size(); ++i )
5344 rowClass = QStringLiteral(
"class=\"odd-row\"" );
5345 myMetadata += QLatin1String(
"<tr " ) + rowClass + QLatin1String(
"><td>" ) + myField.
name() + QLatin1String(
"</td><td>" ) + myField.
typeName() + QLatin1String(
"</td><td>" ) + QString::number( myField.
length() ) + QLatin1String(
"</td><td>" ) + QString::number( myField.
precision() ) + QLatin1String(
"</td><td>" ) + myField.
comment() + QLatin1String(
"</td></tr>\n" );
5349 myMetadata += QLatin1String(
"</table>\n<br><br>" );
5352 myMetadata += QStringLiteral(
"<h1>" ) + tr(
"Contacts" ) + QStringLiteral(
"</h1>\n<hr>\n" );
5354 myMetadata += QLatin1String(
"<br><br>\n" );
5357 myMetadata += QStringLiteral(
"<h1>" ) + tr(
"Links" ) + QStringLiteral(
"</h1>\n<hr>\n" );
5359 myMetadata += QLatin1String(
"<br><br>\n" );
5362 myMetadata += QStringLiteral(
"<h1>" ) + tr(
"History" ) + QStringLiteral(
"</h1>\n<hr>\n" );
5364 myMetadata += QLatin1String(
"<br><br>\n" );
5366 myMetadata += QLatin1String(
"\n</body>\n</html>\n" );
5370 void QgsVectorLayer::invalidateSymbolCountedFlag()
5372 mSymbolFeatureCounted =
false;
5375 void QgsVectorLayer::onFeatureCounterCompleted()
5378 mFeatureCounter =
nullptr;
5381 void QgsVectorLayer::onFeatureCounterTerminated()
5383 mFeatureCounter =
nullptr;
5386 void QgsVectorLayer::onJoinedFieldsChanged()
5392 void QgsVectorLayer::onFeatureDeleted(
QgsFeatureId fid )
5394 if ( mEditCommandActive || mCommitChangesActive )
5396 mDeletedFids << fid;
5400 mSelectedFeatureIds.remove( fid );
5407 void QgsVectorLayer::onRelationsLoaded()
5409 mEditFormConfig.onRelationsLoaded();
5412 void QgsVectorLayer::onSymbolsCounted()
5414 if ( mFeatureCounter )
5416 mSymbolFeatureCounted =
true;
5430 return mWeakRelations;
5450 bool useAsDefault,
const QString &uiFileContent, QString &msgError, QgsMapLayer::StyleCategories categories )
5453 QString sldStyle, qmlStyle;
5454 QDomDocument qmlDocument, sldDocument;
5457 if ( !msgError.isNull() )
5461 qmlStyle = qmlDocument.toString();
5464 if ( !msgError.isNull() )
5468 sldStyle = sldDocument.toString();
5472 description, uiFileContent, useAsDefault, msgError );
5486 QString joinKey = mAuxiliaryLayerKey;
5487 if ( !key.isEmpty() )
5490 if ( storage.
isValid() && !joinKey.isEmpty() )
5513 mAuxiliaryLayerKey.clear();
5515 if ( mAuxiliaryLayer )
5528 mAuxiliaryLayer.reset( alayer );
5529 if ( mAuxiliaryLayer )
5530 mAuxiliaryLayer->setParent(
this );
5536 return mAuxiliaryLayer.get();
5541 return mAuxiliaryLayer.get();
5547 QString returnMessage;
5548 QString qml, errorMsg;
5553 if ( !qml.isEmpty() )
5555 QDomDocument myDocument( QStringLiteral(
"qgis" ) );
5556 myDocument.setContent( qml );
5558 returnMessage = QObject::tr(
"Loaded from Provider" );
5568 return returnMessage;
5573 if ( mDataProvider )
5578 void QgsVectorLayer::emitDataChanged()
5580 if ( mDataChangedFired )
5585 mDataChangedFired =
true;
5587 mDataChangedFired =
false;
5590 void QgsVectorLayer::onAfterCommitChangesDependency()
5592 mDataChangedFired =
true;
5594 mDataChangedFired =
false;
5599 QSet<QgsMapLayerDependency> deps;
5600 const auto constODeps = oDeps;
5607 QSet<QgsMapLayerDependency> toAdd = deps -
dependencies();
5624 if ( mDataProvider )
5645 if ( ! toAdd.isEmpty() )
5653 if ( fieldIndex < 0 || fieldIndex >= mFields.
count() || !mDataProvider )
5654 return QgsFieldConstraints::Constraints();
5669 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
5671 if ( fieldIndex < 0 || fieldIndex >= mFields.
count() )
5674 QString
name = mFields.
at( fieldIndex ).
name();
5677 for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
5679 if ( conIt.key().first ==
name )
5681 m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
5690 if ( index < 0 || index >= mFields.
count() )
5696 QgsFieldConstraints::Constraints constraints = mFieldConstraints.value(
name, QgsFieldConstraints::Constraints() );
5697 constraints |= constraint;
5698 mFieldConstraints.insert(
name, constraints );
5700 mFieldConstraintStrength.insert( qMakePair(
name, constraint ), strength );
5707 if ( index < 0 || index >= mFields.
count() )
5713 QgsFieldConstraints::Constraints constraints = mFieldConstraints.value(
name, QgsFieldConstraints::Constraints() );
5714 constraints &= ~constraint;
5715 mFieldConstraints.insert(
name, constraints );
5717 mFieldConstraintStrength.remove( qMakePair(
name, constraint ) );
5724 if ( index < 0 || index >= mFields.
count() )
5732 if ( index < 0 || index >= mFields.
count() )
5740 if ( index < 0 || index >= mFields.
count() )
5743 if ( expression.isEmpty() )
5745 mFieldConstraintExpressions.remove( mFields.
at( index ).
name() );
5749 mFieldConstraintExpressions.insert( mFields.
at( index ).
name(), qMakePair( expression, description ) );
5756 if ( index < 0 || index >= mFields.
count() )
5759 mFieldConfigurationFlags.insert( mFields.
at( index ).
name(),
flags );
5765 if ( index < 0 || index >= mFields.
count() )
5768 flags.setFlag( flag, active );
5775 if ( index < 0 || index >= mFields.
count() )
5783 if ( index < 0 || index >= mFields.
count() )
5787 mFieldWidgetSetups.remove( mFields.
at( index ).
name() );
5789 mFieldWidgetSetups.insert( mFields.
at( index ).
name(), setup );
5796 if ( index < 0 || index >= mFields.
count() )
5805 if (
customProperty( QStringLiteral(
"labeling" ) ).toString() == QLatin1String(
"pal" ) )
5807 if (
customProperty( QStringLiteral(
"labeling/enabled" ), QVariant(
false ) ).toBool() )
5811 settings.readFromLayerCustomProperties(
this );
5818 for (
const QString &key : constCustomPropertyKeys )
5820 if ( key.startsWith( QLatin1String(
"labeling/" ) ) )
5830 return mAllowCommit;
5844 return mGeometryOptions.get();
5854 return mReadExtentFromXml;
5857 void QgsVectorLayer::onDirtyTransaction(
const QString &sql,
const QString &name )
5860 if ( tr && mEditBuffer )
5862 qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql,
name );
5868 QList<QgsVectorLayer *> layers;
5869 QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
5872 if ( includeAuxiliaryLayers || !qobject_cast< QgsAuxiliaryLayer * >( i.key() ) )
5873 layers.append( i.key() );
5880 return mHandledFeatures[layer];
GeometryOperationResult
Success or failure of a geometry operation.
@ 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...
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
@ SemiTransparentCircle
Semi-transparent circle marker.
VectorEditResult
Specifies the result of a vector layer edit operation.
@ Success
Edit operation was successful.
@ InvalidLayer
Edit failed due to invalid layer.
@ AllowOverlapIfRequired
Avoids overlapping labels when possible, but permit overlaps if labels for features cannot otherwise ...
SelectBehavior
Specifies how a selection should be applied.
@ SetSelection
Set selection, removing any existing selection.
@ AddToSelection
Add selection to current selection.
@ IntersectSelection
Modify current selection to include only select features which match.
@ RemoveFromSelection
Remove from current selection.
Abstract base class for objects which generate elevation profiles.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
virtual void toSld(QDomNode &parent, const QVariantMap &props) const
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings.
static QgsAbstractVectorLayerLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Try to create instance of an implementation based on the XML data.
virtual QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const =0
Returns labeling configuration as XML element.
Storage and management of actions associated with a layer.
bool writeXml(QDomNode &layer_node) const
Writes the actions out in XML format.
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
QUuid addAction(QgsAction::ActionType type, const QString &name, const QString &command, bool capture=false)
Add an action with the given name and action details.
bool readXml(const QDomNode &layer_node)
Reads the actions in in XML format.
Utility class that encapsulates an action based on vector attributes.
Utility class for calculating aggregates for a field (or expression) over the features from a vector ...
Aggregate
Available aggregates to calculate.
static QgsRuntimeProfiler * profiler()