74#include <QApplication>
79#include <QTemporaryFile>
82#include <QStandardPaths>
84#include <QRegularExpression>
105 QStringList keyTokens = QStringList( scope );
106#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
107 keyTokens += key.split(
'/', QString::SkipEmptyParts );
109 keyTokens += key.split(
'/', Qt::SkipEmptyParts );
113 keyTokens.push_front( QStringLiteral(
"properties" ) );
116 for (
int i = 0; i < keyTokens.size(); ++i )
118 const QString keyToken = keyTokens.at( i );
122 const thread_local QRegularExpression sInvalidRegexp = QRegularExpression( QStringLiteral(
"([^:A-Z_a-z\\x{C0}-\\x{D6}\\x{D8}-\\x{F6}\\x{F8}-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}\\-\\.0-9\\x{B7}\\x{0300}-\\x{036F}\\x{203F}-\\x{2040}]|^[^:A-Z_a-z\\x{C0}-\\x{D6}\\x{D8}-\\x{F6}\\x{F8}-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}])" ) );
123 if ( keyToken.contains( sInvalidRegexp ) )
125 const QString errorString = QObject::tr(
"Entry token invalid : '%1'. The token will not be saved to file." ).arg( keyToken );
153 while ( !keySequence.isEmpty() )
157 if ( keySequence.first() == currentProperty->
name() )
160 keySequence.pop_front();
162 if ( 1 == keySequence.count() )
165 return currentProperty->
find( keySequence.front() );
167 else if ( keySequence.isEmpty() )
172 return currentProperty;
174 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
176 if ( nextProperty->
isKey() )
180 else if ( nextProperty->
isValue() && 1 == keySequence.count() )
186 return currentProperty;
224 const QVariant &value,
225 bool &propertiesModified )
234 propertiesModified =
false;
235 while ( ! keySequence.isEmpty() )
239 if ( keySequence.first() == currentProperty->
name() )
242 keySequence.pop_front();
246 if ( 1 == keySequence.count() )
249 if ( !property || property->value() != value )
251 currentProperty->
setValue( keySequence.front(), value );
252 propertiesModified =
true;
255 return currentProperty;
259 else if ( keySequence.isEmpty() )
261 if ( currentProperty->
value() != value )
264 propertiesModified =
true;
267 return currentProperty;
269 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
273 if ( currentProperty )
284 if ( ( newPropertyKey = currentProperty->
addKey( keySequence.first() ) ) )
286 currentProperty = newPropertyKey;
318 while ( ! keySequence.isEmpty() )
322 if ( keySequence.first() == currentProperty->
name() )
325 keySequence.pop_front();
329 if ( 1 == keySequence.count() )
331 currentProperty->
removeKey( keySequence.front() );
336 else if ( keySequence.isEmpty() )
338 previousQgsPropertyKey->
removeKey( currentProperty->
name() );
340 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
342 previousQgsPropertyKey = currentProperty;
345 if ( currentProperty )
369 , mCapabilities( capabilities )
372 , mSnappingConfig( this )
389 mProperties.
setName( QStringLiteral(
"properties" ) );
392 mMainAnnotationLayer->setParent(
this );
406 this, [ = ](
const QStringList &
layers ) { mProjectScope.reset(); emit layersWillBeRemoved( layers ); } );
408 this, [ = ](
const QList<QgsMapLayer *> &
layers ) { mProjectScope.reset(); emit layersWillBeRemoved( layers ); } );
410 this, [ = ](
const QString & layer ) { mProjectScope.reset(); emit layerWillBeRemoved( layer ); } );
412 this, [ = ](
QgsMapLayer * layer ) { mProjectScope.reset(); emit layerWillBeRemoved( layer ); } );
414 [ = ](
const QStringList &
layers ) { mProjectScope.reset(); emit layersRemoved( layers ); } );
416 [ = ](
const QString & layer ) { mProjectScope.reset(); emit layerRemoved( layer ); } );
418 [ = ]() { mProjectScope.reset(); emit removeAll(); } );
420 [ = ](
const QList< QgsMapLayer * > &
layers ) { mProjectScope.reset(); emit layersAdded( layers ); } );
422 [ = ](
QgsMapLayer * layer ) { mProjectScope.reset(); emit layerWasAdded( layer ); } );
430 [ = ](
const QList<QgsMapLayer *> &
layers )
432 for ( const auto &layer : layers )
434 disconnect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager, &QgsRelationManager::updateRelationsStatus );
439 [ = ](
const QList<QgsMapLayer *> &layers )
441 for ( const auto &layer : layers )
443 connect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager, &QgsRelationManager::updateRelationsStatus );
452 mStyleSettings->combinedStyleModel()->addDefaultStyle();
458 mIsBeingDeleted =
true;
461 delete mBadLayerHandler;
462 delete mRelationManager;
463 delete mLayerTreeRegistryBridge;
465 if (
this == sProject )
496 mProjectScope.reset();
507 return mMetadata.
title();
516 if ( oldEvaluateDefaultValues != newEvaluateDefaultValues )
519 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
521 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
530 if ( oldTrustLayerMetadata != newTrustLayerMetadata )
533 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
535 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
537 vl->setReadExtentFromXml( newTrustLayerMetadata );
542 if ( mFlags !=
flags )
553 Qgis::ProjectFlags newFlags = mFlags;
557 newFlags &= ~(
static_cast< int >( flag ) );
572 return mSaveUserFull;
579 return mSaveDateTime;
600 if ( dirty && mDirtyBlockCount > 0 )
606 if ( mDirty == dirty )
617 if ( path == mHomePath )
621 mCachedHomePath.clear();
622 mProjectScope.reset();
633 const QList<QgsAttributeEditorElement *> elements = parent->
children();
641 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:formcontainers" ).arg( layerId ), container->
name() );
643 if ( !container->
children().empty() )
658 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1" ).arg( layer->layerId() ), layer->name() );
675 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( vlayer->
id() ), fieldName );
690 const QList<QgsLayerTreeGroup *> groupLayers = mRootGroup->
findGroups();
693 translationContext->
registerTranslation( QStringLiteral(
"project:layergroups" ), groupLayer->name() );
697 const QList<QgsRelation> &relations = mRelationManager->
relations().values();
700 translationContext->
registerTranslation( QStringLiteral(
"project:relations" ), relation.name() );
708 mDataDefinedServerProperties = properties;
715 return mDataDefinedServerProperties;
722 switch ( mTransactionMode )
743 switch ( mTransactionMode )
750 commitErrors.append( tr(
"Trying to commit changes without a layer specified. This only works if the transaction mode is buffered" ) );
759 return mEditBufferGroup.
commitChanges( commitErrors, stopEditing );
769 switch ( mTransactionMode )
776 rollbackErrors.append( tr(
"Trying to roll back changes without a layer specified. This only works if the transaction mode is buffered" ) );
779 bool success = vectorLayer->
rollBack( stopEditing );
785 return mEditBufferGroup.
rollBack( rollbackErrors, stopEditing );
795 if ( name == mFile.fileName() )
798 const QString oldHomePath =
homePath();
800 mFile.setFileName( name );
801 mCachedHomePath.clear();
802 mProjectScope.reset();
806 const QString newHomePath =
homePath();
807 if ( newHomePath != oldHomePath )
818 return mFile.fileName();
825 mOriginalPath = path;
832 return mOriginalPath;
839 return QFileInfo( mFile );
857 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
862 return QFileInfo( mFile.fileName() ).lastModified();
873 if ( mFile.fileName().isEmpty() )
876 return QFileInfo( mFile.fileName() ).absolutePath();
887 if ( mFile.fileName().isEmpty() )
890 return QFileInfo( mFile.fileName() ).absoluteFilePath();
901 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
906 return QFileInfo( mFile.fileName() ).completeBaseName();
914 const bool absolutePaths =
readBoolEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
925 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
true );
928 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
948 writeEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ),
crs.
isValid() ? 1 : 0 );
949 mProjectScope.reset();
960 if ( adjustEllipsoid )
969 if ( !
crs().isValid() )
972 return readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ),
geoNone() );
979 if (
ellipsoid ==
readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ) ) )
982 mProjectScope.reset();
992 return mTransformContext;
999 if ( context == mTransformContext )
1002 mTransformContext = context;
1003 mProjectScope.reset();
1006 for (
auto &layer : mLayerStore.get()->mapLayers() )
1008 layer->setTransformContext( context );
1017 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
1019 mProjectScope.reset();
1020 mFile.setFileName( QString() );
1023 mSaveUserFull.clear();
1024 mSaveDateTime = QDateTime();
1027 mCachedHomePath.clear();
1029 mFlags = Qgis::ProjectFlags();
1031 mCustomVariables.clear();
1035 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_new_projects" ),
false,
QgsSettings::Core ).toBool() )
1054 mEmbeddedLayers.clear();
1055 mRelationManager->
clear();
1056 mAnnotationManager->clear();
1057 mLayoutManager->clear();
1058 m3DViewsManager->clear();
1059 mBookmarkManager->
clear();
1060 mViewSettings->
reset();
1061 mTimeSettings->
reset();
1062 mElevationProperties->
reset();
1063 mDisplaySettings->
reset();
1064 mGpsSettings->
reset();
1065 mSnappingConfig.
reset();
1073 mLabelingEngineSettings->clear();
1079 mStyleSettings->
reset();
1083 if ( !mIsBeingDeleted )
1091 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/Automatic" ),
true );
1092 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/DecimalPlaces" ), 2 );
1094 const bool defaultRelativePaths = mSettings.
value( QStringLiteral(
"/qgis/defaultProjectPathsRelative" ),
true ).toBool();
1097 int red = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_red" ), 255 ).toInt();
1098 int green = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_green" ), 255 ).toInt();
1099 int blue = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_blue" ), 255 ).toInt();
1102 red = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_red" ), 255 ).toInt();
1103 green = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_green" ), 255 ).toInt();
1104 blue = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_blue" ), 0 ).toInt();
1105 const int alpha = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_alpha" ), 255 ).toInt();
1111 mRootGroup->
clear();
1112 if ( mMainAnnotationLayer )
1113 mMainAnnotationLayer->
reset();
1115 snapSingleBlocker.release();
1117 if ( !mBlockSnappingUpdates )
1129 topQgsPropertyKey.
dump();
1162 const QDomElement propertiesElem = doc.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
1164 if ( propertiesElem.isNull() )
1169 const QDomNodeList scopes = propertiesElem.childNodes();
1171 if ( propertiesElem.firstChild().isNull() )
1173 QgsDebugMsg( QStringLiteral(
"empty ``properties'' XML tag ... bailing" ) );
1177 if ( ! project_properties.
readXml( propertiesElem ) )
1179 QgsDebugMsg( QStringLiteral(
"Project_properties.readXml() failed" ) );
1193 const QDomElement ddElem = doc.documentElement().firstChildElement( QStringLiteral(
"dataDefinedServerProperties" ) );
1194 if ( !ddElem.isNull() )
1196 if ( !ddServerProperties.
readXml( ddElem, dataDefinedServerPropertyDefinitions ) )
1198 QgsDebugMsg( QStringLiteral(
"dataDefinedServerProperties.readXml() failed" ) );
1201 return ddServerProperties;
1208static void _getTitle(
const QDomDocument &doc, QString &title )
1210 const QDomElement titleNode = doc.documentElement().firstChildElement( QStringLiteral(
"title" ) );
1214 if ( titleNode.isNull() )
1220 if ( !titleNode.hasChildNodes() )
1226 const QDomNode titleTextNode = titleNode.firstChild();
1228 if ( !titleTextNode.isText() )
1234 const QDomText titleText = titleTextNode.toText();
1236 title = titleText.data();
1240static void readProjectFileMetadata(
const QDomDocument &doc, QString &lastUser, QString &lastUserFull, QDateTime &lastSaveDateTime )
1242 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1246 QgsDebugMsg( QStringLiteral(
"unable to find qgis element" ) );
1250 const QDomNode qgisNode = nl.item( 0 );
1252 const QDomElement qgisElement = qgisNode.toElement();
1253 lastUser = qgisElement.attribute( QStringLiteral(
"saveUser" ), QString() );
1254 lastUserFull = qgisElement.attribute( QStringLiteral(
"saveUserFull" ), QString() );
1255 lastSaveDateTime = QDateTime::fromString( qgisElement.attribute( QStringLiteral(
"saveDateTime" ), QString() ), Qt::ISODate );
1260 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1264 QgsDebugMsg( QStringLiteral(
" unable to find qgis element in project file" ) );
1268 const QDomNode qgisNode = nl.item( 0 );
1270 const QDomElement qgisElement = qgisNode.toElement();
1271 QgsProjectVersion projectVersion( qgisElement.attribute( QStringLiteral(
"version" ) ) );
1272 return projectVersion;
1279 return mSnappingConfig;
1298 if ( mAvoidIntersectionsMode == mode )
1301 mAvoidIntersectionsMode = mode;
1305bool QgsProject::_getMapLayers(
const QDomDocument &doc, QList<QDomNode> &brokenNodes, Qgis::ProjectReadFlags flags )
1312 QDomElement layerElement = doc.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
1316 if ( layerElement.isNull() )
1326 bool returnStatus =
true;
1329 while ( ! layerElement.isNull() )
1332 layerElement = layerElement.nextSiblingElement( QStringLiteral(
"maplayer" ) );
1338 if ( depSorter.hasCycle() )
1342 if ( depSorter.hasMissingDependency() )
1343 returnStatus =
false;
1347 const QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
1348 const int totalLayerCount = sortedLayerNodes.count();
1351 for (
const QDomNode &node : sortedLayerNodes )
1353 const QDomElement element = node.toElement();
1355 const QString name =
translate( QStringLiteral(
"project:layers:%1" ).arg( node.namedItem( QStringLiteral(
"id" ) ).toElement().text() ), node.namedItem( QStringLiteral(
"layername" ) ).toElement().text() );
1356 if ( !name.isNull() )
1357 emit
loadingLayer( tr(
"Loading layer %1" ).arg( name ) );
1359 profile.switchTask( name );
1361 if ( element.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
1363 createEmbeddedLayer( element.attribute( QStringLiteral(
"id" ) ),
readPath( element.attribute( QStringLiteral(
"project" ) ) ), brokenNodes,
true,
flags );
1372 if ( !addLayer( element, brokenNodes, context,
flags ) )
1374 returnStatus =
false;
1377 if ( !messages.isEmpty() )
1386 return returnStatus;
1389bool QgsProject::addLayer(
const QDomElement &layerElem, QList<QDomNode> &brokenNodes,
QgsReadWriteContext &context, Qgis::ProjectReadFlags flags )
1393 const QString type = layerElem.attribute( QStringLiteral(
"type" ) );
1395 std::unique_ptr<QgsMapLayer>
mapLayer;
1403 QgsDebugMsg( QStringLiteral(
"Unknown layer type \"%1\"" ).arg( type ) );
1407 switch ( layerType )
1409 case Qgis::LayerType::Vector:
1410 mapLayer = std::make_unique<QgsVectorLayer>();
1413 case Qgis::LayerType::Raster:
1414 mapLayer = std::make_unique<QgsRasterLayer>();
1417 case Qgis::LayerType::Mesh:
1418 mapLayer = std::make_unique<QgsMeshLayer>();
1421 case Qgis::LayerType::VectorTile:
1422 mapLayer = std::make_unique<QgsVectorTileLayer>();
1425 case Qgis::LayerType::PointCloud:
1426 mapLayer = std::make_unique<QgsPointCloudLayer>();
1429 case Qgis::LayerType::Plugin:
1431 const QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
1436 case Qgis::LayerType::Annotation:
1439 mapLayer = std::make_unique<QgsAnnotationLayer>( QString(), options );
1443 case Qgis::LayerType::Group:
1446 mapLayer = std::make_unique<QgsGroupLayer>( QString(), options );
1453 QgsDebugMsg( QStringLiteral(
"Unable to create layer" ) );
1461 const QString layerId { layerElem.namedItem( QStringLiteral(
"id" ) ).toElement().text() };
1462 Q_ASSERT( ! layerId.isEmpty() );
1466 QgsMapLayer::ReadFlags layerFlags = QgsMapLayer::ReadFlags();
1467 if (
flags & Qgis::ProjectReadFlag::DontResolveLayers )
1476 profile.switchTask( tr(
"Load layer source" ) );
1483 if ( vl->dataProvider() )
1490 profile.switchTask( tr(
"Add layer to project" ) );
1491 QList<QgsMapLayer *> newLayers;
1493 if ( layerIsValid ||
flags & Qgis::ProjectReadFlag::DontResolveLayers )
1503 vLayer->joinBuffer()->resolveReferences(
this );
1511 QgsDebugMsg(
"Unable to load " + type +
" layer" );
1512 brokenNodes.push_back( layerElem );
1515 const bool wasEditable = layerElem.attribute( QStringLiteral(
"editable" ), QStringLiteral(
"0" ) ).toInt();
1527 if ( ! layerWasStored )
1532 return layerIsValid;
1539 mFile.setFileName( filename );
1540 mCachedHomePath.clear();
1541 mProjectScope.reset();
1550 const QString filename = mFile.fileName();
1555 QTemporaryFile inDevice;
1556 if ( !inDevice.open() )
1558 setError( tr(
"Unable to open %1" ).arg( inDevice.fileName() ) );
1564 if ( !storage->readProject( filename, &inDevice, context ) )
1566 QString err = tr(
"Unable to open %1" ).arg( filename );
1567 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
1568 if ( !messages.isEmpty() )
1569 err += QStringLiteral(
"\n\n" ) + messages.last().message();
1573 returnValue = unzip( inDevice.fileName(),
flags );
1579 returnValue = unzip( mFile.fileName(),
flags );
1584 const QFileInfo finfo( mFile.fileName() );
1585 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
1586 if ( QFile( attachmentsZip ).exists() )
1588 std::unique_ptr<QgsArchive> archive(
new QgsArchive() );
1589 if ( archive->unzip( attachmentsZip ) )
1591 mArchive = std::move( archive );
1594 returnValue = readProjectFile( mFile.fileName(),
flags );
1600 mFile.setFileName( filename );
1601 mCachedHomePath.clear();
1602 mProjectScope.reset();
1607 mTranslator.reset(
nullptr );
1614bool QgsProject::readProjectFile(
const QString &filename, Qgis::ProjectReadFlags flags )
1619 ScopedIntIncrementor snapSignalBlock( &mBlockSnappingUpdates );
1621 QFile projectFile( filename );
1629 if ( QFile( QStringLiteral(
"%1/%2.qm" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) ).exists() )
1631 mTranslator.reset(
new QTranslator() );
1632 ( void )mTranslator->load( localeFileName, QFileInfo( projectFile.fileName() ).absolutePath() );
1635 profile.switchTask( tr(
"Reading project file" ) );
1636 std::unique_ptr<QDomDocument> doc(
new QDomDocument( QStringLiteral(
"qgis" ) ) );
1638 if ( !projectFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
1640 projectFile.close();
1642 setError( tr(
"Unable to open %1" ).arg( projectFile.fileName() ) );
1651 if ( !doc->setContent( &projectFile, &errorMsg, &line, &column ) )
1653 const QString errorString = tr(
"Project file read error in file %1: %2 at line %3 column %4" )
1654 .arg( projectFile.fileName(), errorMsg ).arg( line ).arg( column );
1658 projectFile.close();
1660 setError( errorString );
1665 projectFile.close();
1673 profile.switchTask( tr(
"Updating project file" ) );
1674 if ( thisVersion > fileVersion )
1676 const bool isOlderMajorVersion = fileVersion.
majorVersion() < thisVersion.majorVersion();
1678 if ( isOlderMajorVersion )
1681 "version of qgis (saved in " + fileVersion.
text() +
1683 "). Problems may occur." );
1694 projectFile.updateRevision( thisVersion );
1696 else if ( fileVersion > thisVersion )
1699 "version of qgis (saved in " + fileVersion.
text() +
1701 "). Problems may occur." );
1707 profile.switchTask( tr(
"Creating auxiliary storage" ) );
1708 const QString
fileName = mFile.fileName();
1709 std::unique_ptr<QgsAuxiliaryStorage> aStorage = std::move( mAuxiliaryStorage );
1710 std::unique_ptr<QgsArchive> archive = std::move( mArchive );
1712 mAuxiliaryStorage = std::move( aStorage );
1713 mArchive = std::move( archive );
1715 mCachedHomePath.clear();
1716 mProjectScope.reset();
1717 mSaveVersion = fileVersion;
1720 profile.switchTask( tr(
"Reading properties" ) );
1729 dump_( mProperties );
1734 _getTitle( *doc, oldTitle );
1736 readProjectFileMetadata( *doc, mSaveUser, mSaveUserFull, mSaveDateTime );
1738 const QDomNodeList homePathNl = doc->elementsByTagName( QStringLiteral(
"homePath" ) );
1739 if ( homePathNl.count() > 0 )
1741 const QDomElement homePathElement = homePathNl.at( 0 ).toElement();
1742 const QString
homePath = homePathElement.attribute( QStringLiteral(
"path" ) );
1752 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), 255 ),
1753 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), 255 ) );
1756 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), 255 ),
1757 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), 255 ),
1758 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), 255 ) );
1762 const QString distanceUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), QString() );
1763 if ( !distanceUnitString.isEmpty() )
1766 const QString areaUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), QString() );
1767 if ( !areaUnitString.isEmpty() )
1776 if (
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ), 0 ) )
1779 const QDomNode srsNode = doc->documentElement().namedItem( QStringLiteral(
"projectCrs" ) );
1780 if ( !srsNode.isNull() )
1782 projectCrs.
readXml( srsNode );
1787 const QString projCrsString =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSProj4String" ) );
1788 const long currentCRS =
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSID" ), -1 );
1789 const QString authid =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCrs" ) );
1792 const bool isUserAuthId = authid.startsWith( QLatin1String(
"USER:" ), Qt::CaseInsensitive );
1793 if ( !authid.isEmpty() && !isUserAuthId )
1797 if ( !projectCrs.
isValid() && currentCRS >= 0 )
1803 if ( !projCrsString.isEmpty() && ( authid.isEmpty() || isUserAuthId ) && ( !projectCrs.
isValid() || projectCrs.
toProj() != projCrsString ) )
1817 QStringList datumErrors;
1818 if ( !mTransformContext.
readXml( doc->documentElement(), context, datumErrors ) && !datumErrors.empty() )
1825 const QDomNode elevationShadingNode = doc->documentElement().namedItem( QStringLiteral(
"elevation-shading-renderer" ) );
1826 if ( !elevationShadingNode.isNull() )
1828 mElevationShadingRenderer.
readXml( elevationShadingNode.toElement(), context );
1835 const QStringList variableNames =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ) );
1836 const QStringList variableValues =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ) );
1838 mCustomVariables.clear();
1839 if ( variableNames.length() == variableValues.length() )
1841 for (
int i = 0; i < variableNames.length(); ++i )
1843 mCustomVariables.insert( variableNames.at( i ), variableValues.at( i ) );
1848 QgsMessageLog::logMessage( tr(
"Project Variables Invalid" ), tr(
"The project contains invalid variable settings." ) );
1851 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectMetadata" ) );
1853 if ( !element.isNull() )
1862 if ( mMetadata.
title().isEmpty() && !oldTitle.isEmpty() )
1870 element = doc->documentElement().firstChildElement( QStringLiteral(
"transaction" ) );
1871 if ( !element.isNull() )
1878 element = doc->documentElement().firstChildElement( QStringLiteral(
"autotransaction" ) );
1879 if ( ! element.isNull() )
1881 mTransactionMode =
static_cast<Qgis::TransactionMode>( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() );
1886 profile.switchTask( tr(
"Loading layer tree" ) );
1889 QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
1890 if ( !layerTreeElem.isNull() )
1902 mLayerTreeRegistryBridge->
setEnabled(
false );
1905 profile.switchTask( tr(
"Reading map layers" ) );
1907 loadProjectFlags( doc.get() );
1909 QList<QDomNode> brokenNodes;
1910 const bool clean = _getMapLayers( *doc, brokenNodes,
flags );
1913 if ( !clean && !(
flags & Qgis::ProjectReadFlag::DontResolveLayers ) )
1915 QgsDebugMsg( QStringLiteral(
"Unable to get map layers from project file." ) );
1917 if ( !brokenNodes.isEmpty() )
1919 QgsDebugMsg(
"there are " + QString::number( brokenNodes.size() ) +
" broken layers" );
1927 mMainAnnotationLayer->
readLayerXml( doc->documentElement().firstChildElement( QStringLiteral(
"main-annotation-layer" ) ), context );
1931 profile.switchTask( tr(
"Loading embedded layers" ) );
1932 loadEmbeddedNodes( mRootGroup,
flags );
1936 profile.switchTask( tr(
"Resolving layer references" ) );
1937 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
1938 for ( QMap<QString, QgsMapLayer *>::iterator it =
layers.begin(); it !=
layers.end(); ++it )
1940 it.value()->resolveReferences(
this );
1943 mLayerTreeRegistryBridge->
setEnabled(
true );
1946 profile.switchTask( tr(
"Resolving references" ) );
1957 if ( !layerTreeElem.isNull() )
1963 const QDomElement layerTreeCanvasElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-canvas" ) );
1964 if ( !layerTreeCanvasElem.isNull( ) )
1972 const QStringList requiredLayerIds =
readListEntry( QStringLiteral(
"RequiredLayers" ), QStringLiteral(
"Layers" ) );
1973 for (
const QString &layerId : requiredLayerIds )
1980 const QStringList disabledLayerIds =
readListEntry( QStringLiteral(
"Identify" ), QStringLiteral(
"/disabledLayers" ) );
1981 for (
const QString &layerId : disabledLayerIds )
1994 QString styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1995 if ( !styleName.isEmpty() )
2000 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
2001 if ( !styleName.isEmpty() )
2006 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
2007 if ( !styleName.isEmpty() )
2012 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
2013 if ( !styleName.isEmpty() )
2023 double opacity = 1.0;
2026 double alpha =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ), 255, &ok );
2028 opacity = alpha / 255.0;
2029 double newOpacity =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ), 1.0, &ok );
2031 opacity = newOpacity;
2035 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
2036 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
2037 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
2038 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
2039 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/RandomColors" ) );
2040 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ) );
2041 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ) );
2047 if ( !(
flags & Qgis::ProjectReadFlag::DontStoreOriginalStyles ) )
2049 profile.switchTask( tr(
"Storing original layer properties" ) );
2055 profile.switchTask( tr(
"Loading map themes" ) );
2058 mMapThemeCollection->readXml( *doc );
2060 profile.switchTask( tr(
"Loading label settings" ) );
2061 mLabelingEngineSettings->readSettingsFromProject(
this );
2064 profile.switchTask( tr(
"Loading annotations" ) );
2065 mAnnotationManager->readXml( doc->documentElement(), context );
2066 if ( !(
flags & Qgis::ProjectReadFlag::DontLoadLayouts ) )
2068 profile.switchTask( tr(
"Loading layouts" ) );
2069 mLayoutManager->readXml( doc->documentElement(), *doc );
2072 if ( !(
flags & Qgis::ProjectReadFlag::DontLoad3DViews ) )
2074 profile.switchTask( tr(
"Loading 3D Views" ) );
2075 m3DViewsManager->readXml( doc->documentElement(), *doc );
2078 profile.switchTask( tr(
"Loading bookmarks" ) );
2079 mBookmarkManager->
readXml( doc->documentElement(), *doc );
2082 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2083 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); ++it )
2085 it.value()->setDependencies( it.value()->dependencies() );
2088 profile.switchTask( tr(
"Loading snapping settings" ) );
2092 profile.switchTask( tr(
"Loading view settings" ) );
2095 const QStringList scales =
readListEntry( QStringLiteral(
"Scales" ), QStringLiteral(
"/ScalesList" ) );
2096 QVector<double> res;
2097 for (
const QString &scale : scales )
2099 const QStringList parts = scale.split(
':' );
2100 if ( parts.size() != 2 )
2104 const double denominator = QLocale().toDouble( parts[1], &ok );
2111 const QDomElement viewSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectViewSettings" ) );
2112 if ( !viewSettingsElement.isNull() )
2113 mViewSettings->
readXml( viewSettingsElement, context );
2116 profile.switchTask( tr(
"Loading style properties" ) );
2117 const QDomElement styleSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectStyleSettings" ) );
2118 if ( !styleSettingsElement.isNull() )
2119 mStyleSettings->
readXml( styleSettingsElement, context,
flags );
2122 profile.switchTask( tr(
"Loading temporal settings" ) );
2123 const QDomElement timeSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectTimeSettings" ) );
2124 if ( !timeSettingsElement.isNull() )
2125 mTimeSettings->
readXml( timeSettingsElement, context );
2128 profile.switchTask( tr(
"Loading elevation properties" ) );
2129 const QDomElement elevationPropertiesElement = doc->documentElement().firstChildElement( QStringLiteral(
"ElevationProperties" ) );
2130 if ( !elevationPropertiesElement.isNull() )
2131 mElevationProperties->
readXml( elevationPropertiesElement, context );
2134 profile.switchTask( tr(
"Loading display settings" ) );
2136 const QDomElement displaySettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectDisplaySettings" ) );
2137 if ( !displaySettingsElement.isNull() )
2138 mDisplaySettings->
readXml( displaySettingsElement, context );
2141 profile.switchTask( tr(
"Loading GPS settings" ) );
2143 const QDomElement gpsSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectGpsSettings" ) );
2144 if ( !gpsSettingsElement.isNull() )
2145 mGpsSettings->
readXml( gpsSettingsElement, context );
2149 profile.switchTask( tr(
"Updating variables" ) );
2151 profile.switchTask( tr(
"Updating CRS" ) );
2156 profile.switchTask( tr(
"Reading external settings" ) );
2160 profile.switchTask( tr(
"Updating interface" ) );
2162 snapSignalBlock.release();
2163 if ( !mBlockSnappingUpdates )
2174 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUser ), 2 );
2175 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUserFull ), 2 );
2184 const QString newFileName( QStringLiteral(
"%1/%2.qgs" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) );
2190 QgsMessageLog::logMessage( tr(
"Translated project saved with locale prefix %1" ).arg( newFileName ), QObject::tr(
"Project translation" ), Qgis::MessageLevel::Success );
2194 QgsMessageLog::logMessage( tr(
"Error saving translated project with locale prefix %1" ).arg( newFileName ), QObject::tr(
"Project translation" ), Qgis::MessageLevel::Critical );
2199 const QMap<QString, QgsMapLayer *> loadedLayers =
mapLayers();
2200 for (
auto it = loadedLayers.constBegin(); it != loadedLayers.constEnd(); ++it )
2202 if ( it.value()->isValid() && it.value()->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2204 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( it.value() ) )
2206 it.value()->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2213bool QgsProject::loadEmbeddedNodes(
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
2218 const auto constChildren = group->
children();
2224 if ( childGroup->
customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2227 const QString projectPath =
readPath( childGroup->
customProperty( QStringLiteral(
"embedded_project" ) ).toString() );
2228 childGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectPath );
2232 QList<QgsLayerTreeNode *> clonedChildren;
2233 const QList<QgsLayerTreeNode *> constChildren = newGroup->
children();
2234 clonedChildren.reserve( constChildren.size() );
2236 clonedChildren << newGroupChild->clone();
2244 loadEmbeddedNodes( childGroup,
flags );
2249 if ( child->customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2251 QList<QDomNode> brokenNodes;
2254 valid = valid &&
false;
2269 return mCustomVariables;
2276 if ( variables == mCustomVariables )
2280 QStringList variableNames;
2281 QStringList variableValues;
2283 QVariantMap::const_iterator it = variables.constBegin();
2284 for ( ; it != variables.constEnd(); ++it )
2286 variableNames << it.key();
2287 variableValues << it.value().toString();
2290 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ), variableNames );
2291 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ), variableValues );
2293 mCustomVariables = variables;
2294 mProjectScope.reset();
2303 *mLabelingEngineSettings = settings;
2311 return *mLabelingEngineSettings;
2318 mProjectScope.reset();
2319 return mLayerStore.get();
2326 return mLayerStore.get();
2333 QList<QgsVectorLayer *>
layers;
2334 const QStringList layerIds =
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), QStringList() );
2335 const auto constLayerIds = layerIds;
2336 for (
const QString &layerId : constLayerIds )
2349 list.reserve(
layers.size() );
2351 list << layer->id();
2352 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), list );
2374 if ( mProjectScope )
2376 std::unique_ptr< QgsExpressionContextScope > projectScope = std::make_unique< QgsExpressionContextScope >( *mProjectScope );
2380 return projectScope.release();
2383 mProjectScope = std::make_unique< QgsExpressionContextScope >( QObject::tr(
"Project" ) );
2387 QVariantMap::const_iterator it = vars.constBegin();
2389 for ( ; it != vars.constEnd(); ++it )
2391 mProjectScope->setVariable( it.key(), it.value(),
true );
2395 if ( projectPath.isEmpty() )
2396 projectPath = mOriginalPath;
2397 const QString projectFolder = QFileInfo( projectPath ).path();
2398 const QString projectFilename = QFileInfo( projectPath ).fileName();
2399 const QString projectBasename =
baseName();
2428 QVariantMap keywords;
2430 for (
auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
2432 keywords.insert( it.key(), it.value() );
2437 QVariantList layersIds;
2439 const QMap<QString, QgsMapLayer *> layersInProject = mLayerStore->mapLayers();
2440 layersIds.reserve( layersInProject.count() );
2441 layers.reserve( layersInProject.count() );
2442 for (
auto it = layersInProject.constBegin(); it != layersInProject.constEnd(); ++it )
2444 layersIds << it.value()->id();
2450 mProjectScope->addFunction( QStringLiteral(
"project_color" ),
new GetNamedProjectColor(
this ) );
2455void QgsProject::onMapLayersAdded(
const QList<QgsMapLayer *> &layers )
2459 const QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2461 const auto constLayers =
layers;
2464 if ( ! layer->isValid() )
2470 for ( QMap<QString, QgsMapLayer *>::const_iterator it = existingMaps.cbegin(); it != existingMaps.cend(); ++it )
2472 const QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
2473 if ( deps.contains( layer->id() ) )
2476 it.value()->setDependencies( deps );
2481 updateTransactionGroups();
2487void QgsProject::onMapLayersRemoved(
const QList<QgsMapLayer *> &layers )
2495void QgsProject::cleanTransactionGroups(
bool force )
2499 bool changed =
false;
2500 for ( QMap< QPair< QString, QString>,
QgsTransactionGroup *>::Iterator tg = mTransactionGroups.begin(); tg != mTransactionGroups.end(); )
2502 if ( tg.value()->isEmpty() || force )
2505 tg = mTransactionGroups.erase( tg );
2517void QgsProject::updateTransactionGroups()
2521 mEditBufferGroup.
clear();
2523 switch ( mTransactionMode )
2527 cleanTransactionGroups(
true );
2532 cleanTransactionGroups(
true );
2535 cleanTransactionGroups(
false );
2539 bool tgChanged =
false;
2540 const auto constLayers =
mapLayers().values();
2543 if ( ! layer->isValid() )
2546 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
2550 switch ( mTransactionMode )
2567 mTransactionGroups.insert( qMakePair( key, connString ), tg );
2577 mEditBufferGroup.
addLayer( vlayer );
2593 context.setProjectTranslator(
this );
2595 QList<QDomNode> brokenNodes;
2596 if ( addLayer( layerNode.toElement(), brokenNodes, context ) )
2600 const QVector<QgsVectorLayer *> vectorLayers = layers<QgsVectorLayer *>();
2604 layer->resolveReferences(
this );
2606 if ( layer->isValid() && layer->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2608 layer->startEditing();
2609 layer->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2621 mFile.setFileName( filename );
2622 mCachedHomePath.clear();
2630 mProjectScope.reset();
2636 const QString storageFilePath { storage->filePath( mFile.fileName() ) };
2637 if ( storageFilePath.isEmpty() )
2643 const QString tempPath = QStandardPaths::standardLocations( QStandardPaths::TempLocation ).at( 0 );
2644 const QString tmpZipFilename( tempPath + QDir::separator() + QUuid::createUuid().toString() );
2646 if ( !zip( tmpZipFilename ) )
2649 QFile tmpZipFile( tmpZipFilename );
2650 if ( !tmpZipFile.open( QIODevice::ReadOnly ) )
2652 setError( tr(
"Unable to read file %1" ).arg( tmpZipFilename ) );
2657 if ( !storage->writeProject( mFile.fileName(), &tmpZipFile, context ) )
2659 QString err = tr(
"Unable to save project to storage %1" ).arg( mFile.fileName() );
2660 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
2661 if ( !messages.isEmpty() )
2662 err += QStringLiteral(
"\n\n" ) + messages.last().message();
2668 QFile::remove( tmpZipFilename );
2675 return zip( mFile.fileName() );
2681 const bool asOk = saveAuxiliaryStorage();
2682 const bool writeOk = writeProjectFile( mFile.fileName() );
2683 bool attachmentsOk =
true;
2684 if ( !mArchive->files().isEmpty() )
2686 const QFileInfo finfo( mFile.fileName() );
2687 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
2688 attachmentsOk = mArchive->zip( attachmentsZip );
2692 if ( ( !asOk || !attachmentsOk ) && writeOk )
2694 QStringList errorMessage;
2697 const QString err = mAuxiliaryStorage->errorString();
2698 errorMessage.append( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
2700 if ( !attachmentsOk )
2702 errorMessage.append( tr(
"Unable to save attachments archive" ) );
2704 setError( errorMessage.join(
'\n' ) );
2707 return asOk && writeOk && attachmentsOk;
2711bool QgsProject::writeProjectFile(
const QString &filename )
2715 QFile projectFile( filename );
2721 const QFileInfo myFileInfo( projectFile );
2722 if ( myFileInfo.exists() && !myFileInfo.isWritable() )
2724 setError( tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
2725 .arg( projectFile.fileName() ) );
2733 QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
2735 const QDomDocumentType documentType =
2736 QDomImplementation().createDocumentType( QStringLiteral(
"qgis" ), QStringLiteral(
"http://mrcc.com/qgis.dtd" ),
2737 QStringLiteral(
"SYSTEM" ) );
2738 std::unique_ptr<QDomDocument> doc(
new QDomDocument( documentType ) );
2740 QDomElement qgisNode = doc->createElement( QStringLiteral(
"qgis" ) );
2741 qgisNode.setAttribute( QStringLiteral(
"projectname" ),
title() );
2742 qgisNode.setAttribute( QStringLiteral(
"version" ),
Qgis::version() );
2744 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_saved_projects" ),
false,
QgsSettings::Core ).toBool() )
2748 qgisNode.setAttribute( QStringLiteral(
"saveUser" ), newSaveUser );
2749 qgisNode.setAttribute( QStringLiteral(
"saveUserFull" ), newSaveUserFull );
2750 mSaveUser = newSaveUser;
2751 mSaveUserFull = newSaveUserFull;
2752 mSaveDateTime = QDateTime::currentDateTime();
2753 qgisNode.setAttribute( QStringLiteral(
"saveDateTime" ), mSaveDateTime.toString( Qt::ISODate ) );
2758 mSaveUserFull.clear();
2759 mSaveDateTime = QDateTime();
2761 doc->appendChild( qgisNode );
2764 QDomElement homePathNode = doc->createElement( QStringLiteral(
"homePath" ) );
2765 homePathNode.setAttribute( QStringLiteral(
"path" ), mHomePath );
2766 qgisNode.appendChild( homePathNode );
2769 QDomElement titleNode = doc->createElement( QStringLiteral(
"title" ) );
2770 qgisNode.appendChild( titleNode );
2772 QDomElement transactionNode = doc->createElement( QStringLiteral(
"transaction" ) );
2773 transactionNode.setAttribute( QStringLiteral(
"mode" ),
qgsEnumValueToKey( mTransactionMode ) );
2774 qgisNode.appendChild( transactionNode );
2776 QDomElement flagsNode = doc->createElement( QStringLiteral(
"projectFlags" ) );
2778 qgisNode.appendChild( flagsNode );
2780 const QDomText titleText = doc->createTextNode(
title() );
2781 titleNode.appendChild( titleText );
2784 QDomElement srsNode = doc->createElement( QStringLiteral(
"projectCrs" ) );
2786 qgisNode.appendChild( srsNode );
2788 QDomElement elevationShadingNode = doc->createElement( QStringLiteral(
"elevation-shading-renderer" ) );
2789 mElevationShadingRenderer.
writeXml( elevationShadingNode, context );
2790 qgisNode.appendChild( elevationShadingNode );
2797 clonedRoot->
writeXml( qgisNode, context );
2801 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsMode" ),
static_cast<int>( mAvoidIntersectionsMode ) );
2809 QDomElement annotationLayerNode = doc->createElement( QStringLiteral(
"main-annotation-layer" ) );
2810 mMainAnnotationLayer->
writeLayerXml( annotationLayerNode, *doc, context );
2811 qgisNode.appendChild( annotationLayerNode );
2815 QDomElement projectLayersNode = doc->createElement( QStringLiteral(
"projectlayers" ) );
2817 QMap<QString, QgsMapLayer *>::ConstIterator li =
layers.constBegin();
2818 while ( li !=
layers.end() )
2824 const QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.constFind( ml->
id() );
2825 if ( emIt == mEmbeddedLayers.constEnd() )
2827 QDomElement maplayerElem;
2833 maplayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2837 maplayerElem.setAttribute( QStringLiteral(
"editable" ), QStringLiteral(
"1" ) );
2841 QDomDocument document;
2844 maplayerElem = document.firstChildElement();
2848 QgsDebugMsg( QStringLiteral(
"Could not restore layer properties for layer %1" ).arg( ml->
id() ) );
2854 projectLayersNode.appendChild( maplayerElem );
2860 if ( emIt.value().second )
2862 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2863 mapLayerElem.setAttribute( QStringLiteral(
"embedded" ), 1 );
2864 mapLayerElem.setAttribute( QStringLiteral(
"project" ),
writePath( emIt.value().first ) );
2865 mapLayerElem.setAttribute( QStringLiteral(
"id" ), ml->
id() );
2866 projectLayersNode.appendChild( mapLayerElem );
2873 qgisNode.appendChild( projectLayersNode );
2875 QDomElement layerOrderNode = doc->createElement( QStringLiteral(
"layerorder" ) );
2877 for (
QgsMapLayer *layer : constCustomLayerOrder )
2879 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"layer" ) );
2880 mapLayerElem.setAttribute( QStringLiteral(
"id" ), layer->id() );
2881 layerOrderNode.appendChild( mapLayerElem );
2883 qgisNode.appendChild( layerOrderNode );
2885 mLabelingEngineSettings->writeSettingsToProject(
this );
2887 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorRedPart" ), mBackgroundColor.red() );
2888 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), mBackgroundColor.green() );
2889 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), mBackgroundColor.blue() );
2891 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorRedPart" ), mSelectionColor.red() );
2892 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), mSelectionColor.green() );
2893 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), mSelectionColor.blue() );
2894 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), mSelectionColor.alpha() );
2901 dump_( mProperties );
2904 QgsDebugMsgLevel( QStringLiteral(
"there are %1 property scopes" ).arg(
static_cast<int>( mProperties.
count() ) ), 2 );
2909 mProperties.
writeXml( QStringLiteral(
"properties" ), qgisNode, *doc );
2912 QDomElement ddElem = doc->createElement( QStringLiteral(
"dataDefinedServerProperties" ) );
2913 mDataDefinedServerProperties.
writeXml( ddElem, dataDefinedServerPropertyDefinitions() );
2914 qgisNode.appendChild( ddElem );
2916 mMapThemeCollection->writeXml( *doc );
2918 mTransformContext.
writeXml( qgisNode, context );
2920 QDomElement metadataElem = doc->createElement( QStringLiteral(
"projectMetadata" ) );
2922 qgisNode.appendChild( metadataElem );
2925 const QDomElement annotationsElem = mAnnotationManager->writeXml( *doc, context );
2926 qgisNode.appendChild( annotationsElem );
2930 const QDomElement layoutElem = mLayoutManager->writeXml( *doc );
2931 qgisNode.appendChild( layoutElem );
2935 const QDomElement views3DElem = m3DViewsManager->writeXml( *doc );
2936 qgisNode.appendChild( views3DElem );
2940 const QDomElement bookmarkElem = mBookmarkManager->
writeXml( *doc );
2941 qgisNode.appendChild( bookmarkElem );
2945 const QDomElement viewSettingsElem = mViewSettings->
writeXml( *doc, context );
2946 qgisNode.appendChild( viewSettingsElem );
2950 const QDomElement styleSettingsElem = mStyleSettings->
writeXml( *doc, context );
2951 qgisNode.appendChild( styleSettingsElem );
2955 const QDomElement timeSettingsElement = mTimeSettings->
writeXml( *doc, context );
2956 qgisNode.appendChild( timeSettingsElement );
2960 const QDomElement elevationPropertiesElement = mElevationProperties->
writeXml( *doc, context );
2961 qgisNode.appendChild( elevationPropertiesElement );
2965 const QDomElement displaySettingsElem = mDisplaySettings->
writeXml( *doc, context );
2966 qgisNode.appendChild( displaySettingsElem );
2970 const QDomElement gpsSettingsElem = mGpsSettings->
writeXml( *doc, context );
2971 qgisNode.appendChild( gpsSettingsElem );
2980 QFile backupFile( QStringLiteral(
"%1~" ).arg( filename ) );
2982 ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
2983 ok &= projectFile.open( QIODevice::ReadOnly );
2986 while ( ok && !projectFile.atEnd() )
2988 ba = projectFile.read( 10240 );
2989 ok &= backupFile.write( ba ) == ba.size();
2992 projectFile.close();
2997 setError( tr(
"Unable to create backup file %1" ).arg( backupFile.fileName() ) );
3002 struct utimbuf tb = {
static_cast<time_t
>( fi.lastRead().toSecsSinceEpoch() ),
static_cast<time_t
>( fi.lastModified().toSecsSinceEpoch() ) };
3003 utime( backupFile.fileName().toUtf8().constData(), &tb );
3006 if ( !projectFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3008 projectFile.close();
3011 setError( tr(
"Unable to save to file %1" ).arg( projectFile.fileName() ) );
3015 QTemporaryFile tempFile;
3016 bool ok = tempFile.open();
3019 QTextStream projectFileStream( &tempFile );
3020 doc->save( projectFileStream, 2 );
3021 ok &= projectFileStream.pos() > -1;
3023 ok &= tempFile.seek( 0 );
3026 while ( ok && !tempFile.atEnd() )
3028 ba = tempFile.read( 10240 );
3029 ok &= projectFile.write( ba ) == ba.size();
3032 ok &= projectFile.error() == QFile::NoError;
3034 projectFile.close();
3041 setError( tr(
"Unable to save to file %1. Your project "
3042 "may be corrupted on disk. Try clearing some space on the volume and "
3043 "check file permissions before pressing save again." )
3044 .arg( projectFile.fileName() ) );
3058 bool propertiesModified;
3059 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3061 if ( propertiesModified )
3071 bool propertiesModified;
3072 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3074 if ( propertiesModified )
3084 bool propertiesModified;
3085 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3087 if ( propertiesModified )
3097 bool propertiesModified;
3098 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3100 if ( propertiesModified )
3110 bool propertiesModified;
3111 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3113 if ( propertiesModified )
3121 const QStringList &def,
3133 value =
property->value();
3135 const bool valid = QVariant::StringList == value.type();
3141 return value.toStringList();
3164 value =
property->value();
3166 const bool valid = value.canConvert( QVariant::String );
3171 return value.toString();
3190 value =
property->value();
3193 const bool valid = value.canConvert( QVariant::Int );
3202 return value.toInt();
3217 const QVariant value =
property->value();
3219 const bool valid = value.canConvert( QVariant::Double );
3224 return value.toDouble();
3241 const QVariant value =
property->value();
3243 const bool valid = value.canConvert( QVariant::Bool );
3248 return value.toBool();
3260 if (
findKey_( scope, key, mProperties ) )
3266 return !
findKey_( scope, key, mProperties );
3275 QStringList entries;
3277 if ( foundProperty )
3294 QStringList entries;
3296 if ( foundProperty )
3311 dump_( mProperties );
3331 filePath = storage->filePath( mFile.fileName() );
3358void QgsProject::setError(
const QString &errorMessage )
3362 mErrorMessage = errorMessage;
3369 return mErrorMessage;
3372void QgsProject::clearError()
3376 setError( QString() );
3383 delete mBadLayerHandler;
3384 mBadLayerHandler = handler;
3391 const QHash< QString, QPair< QString, bool > >::const_iterator it = mEmbeddedLayers.find(
id );
3392 if ( it == mEmbeddedLayers.constEnd() )
3396 return it.value().first;
3400 bool saveFlag, Qgis::ProjectReadFlags flags )
3406 static QString sPrevProjectFilePath;
3407 static QDateTime sPrevProjectFileTimestamp;
3408 static QDomDocument sProjectDocument;
3410 QString qgsProjectFile = projectFilePath;
3412 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3414 archive.
unzip( projectFilePath );
3418 const QDateTime projectFileTimestamp = QFileInfo( projectFilePath ).lastModified();
3420 if ( projectFilePath != sPrevProjectFilePath || projectFileTimestamp != sPrevProjectFileTimestamp )
3422 sPrevProjectFilePath.clear();
3424 QFile projectFile( qgsProjectFile );
3425 if ( !projectFile.open( QIODevice::ReadOnly ) )
3430 if ( !sProjectDocument.setContent( &projectFile ) )
3435 sPrevProjectFilePath = projectFilePath;
3436 sPrevProjectFileTimestamp = projectFileTimestamp;
3440 bool useAbsolutePaths =
true;
3442 const QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
3443 if ( !propertiesElem.isNull() )
3445 const QDomElement absElem = propertiesElem.firstChildElement( QStringLiteral(
"Paths" ) ).firstChildElement( QStringLiteral(
"Absolute" ) );
3446 if ( !absElem.isNull() )
3448 useAbsolutePaths = absElem.text().compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0;
3453 if ( !useAbsolutePaths )
3458 const QDomElement projectLayersElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) );
3459 if ( projectLayersElem.isNull() )
3464 QDomElement mapLayerElem = projectLayersElem.firstChildElement( QStringLiteral(
"maplayer" ) );
3465 while ( ! mapLayerElem.isNull() )
3468 const QString
id = mapLayerElem.firstChildElement( QStringLiteral(
"id" ) ).text();
3469 if (
id == layerId )
3472 if ( mapLayerElem.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
3477 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
3479 if ( addLayer( mapLayerElem, brokenNodes, embeddedContext,
flags ) )
3485 mEmbeddedLayers.remove( layerId );
3489 mapLayerElem = mapLayerElem.nextSiblingElement( QStringLiteral(
"maplayer" ) );
3499 QString qgsProjectFile = projectFilePath;
3501 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3503 archive.
unzip( projectFilePath );
3508 QFile projectFile( qgsProjectFile );
3509 if ( !projectFile.open( QIODevice::ReadOnly ) )
3514 QDomDocument projectDocument;
3515 if ( !projectDocument.setContent( &projectFile ) )
3527 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
3528 if ( !layerTreeElem.isNull() )
3538 if ( !group || group->
customProperty( QStringLiteral(
"embedded" ) ).toBool() )
3551 newGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectFilePath );
3554 mLayerTreeRegistryBridge->
setEnabled(
false );
3555 initializeEmbeddedSubtree( projectFilePath, newGroup,
flags );
3556 mLayerTreeRegistryBridge->
setEnabled(
true );
3559 const auto constFindLayerIds = newGroup->
findLayerIds();
3560 for (
const QString &layerId : constFindLayerIds )
3573void QgsProject::initializeEmbeddedSubtree(
const QString &projectFilePath,
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
3577 const auto constChildren = group->
children();
3581 child->setCustomProperty( QStringLiteral(
"embedded" ), 1 );
3590 QList<QDomNode> brokenNodes;
3614 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), ( enabled ? 1 : 0 ) );
3622 return readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), 0 );
3629 if ( mDistanceUnits == unit )
3632 mDistanceUnits = unit;
3641 if ( mAreaUnits == unit )
3654 if ( !mCachedHomePath.isEmpty() )
3655 return mCachedHomePath;
3659 if ( !mHomePath.isEmpty() )
3661 const QFileInfo homeInfo( mHomePath );
3662 if ( !homeInfo.isRelative() )
3664 mCachedHomePath = mHomePath;
3670 mCachedHomePath = pfi.path();
3672 return mCachedHomePath;
3675 if ( !pfi.exists() )
3677 mCachedHomePath = mHomePath;
3681 if ( !mHomePath.isEmpty() )
3684 mCachedHomePath = QDir::cleanPath( pfi.path() +
'/' + mHomePath );
3688 mCachedHomePath = pfi.canonicalPath();
3690 return mCachedHomePath;
3705 return mRelationManager;
3712 return mLayoutManager.get();
3719 return mLayoutManager.get();
3726 return m3DViewsManager.get();
3733 return m3DViewsManager.get();
3740 return mBookmarkManager;
3747 return mBookmarkManager;
3754 return mViewSettings;
3761 return mViewSettings;
3768 return mStyleSettings;
3776 return mStyleSettings;
3783 return mTimeSettings;
3790 return mTimeSettings;
3797 return mElevationProperties;
3804 return mElevationProperties;
3811 return mDisplaySettings;
3818 return mDisplaySettings;
3825 return mGpsSettings;
3832 return mGpsSettings;
3846 return mMapThemeCollection.get();
3853 return mAnnotationManager.get();
3860 return mAnnotationManager.get();
3867 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
3868 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
3873 if (
layers.contains( it.value() ) )
3890 for (
const QString &layerId : layerIds )
3908 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
3942 updateTransactionGroups();
3949 return mTransactionMode;
3960 const auto constLayers =
mapLayers().values();
3963 if ( layer->isEditable() )
3965 QgsLogger::warning( tr(
"Transaction mode can be changed only if all layers are not editable." ) );
3971 updateTransactionGroups();
3979 return mTransactionGroups;
3992 return mLayerStore->count();
3999 return mLayerStore->validCount();
4007 return mLayerStore->mapLayer( layerId );
4014 return mLayerStore->mapLayersByName( layerName );
4021 QList<QgsMapLayer *>
layers;
4022 const auto constMapLayers { mLayerStore->mapLayers() };
4023 for (
const auto &l : constMapLayers )
4025 if ( ! l->shortName().isEmpty() )
4027 if ( l->shortName() == shortName )
4030 else if ( l->name() == shortName )
4038bool QgsProject::unzip(
const QString &filename, Qgis::ProjectReadFlags flags )
4046 if ( !archive->unzip( filename ) )
4048 setError( tr(
"Unable to unzip file '%1'" ).arg( filename ) );
4053 if ( archive->projectFile().isEmpty() )
4055 setError( tr(
"Zip archive does not provide a project file" ) );
4060 mArchive = std::move( archive );
4077 setError( tr(
"Cannot read unzipped qgs project file" ) + QStringLiteral(
": " ) +
error() );
4087bool QgsProject::zip(
const QString &filename )
4095 const QString
baseName = QFileInfo( filename ).baseName();
4096 const QString qgsFileName = QStringLiteral(
"%1.qgs" ).arg(
baseName );
4097 QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
4099 bool writeOk =
false;
4100 if ( qgsFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
4102 writeOk = writeProjectFile( qgsFile.fileName() );
4109 setError( tr(
"Unable to write temporary qgs file" ) );
4114 const QFileInfo info( qgsFile );
4116 const QString asFileName = info.path() + QDir::separator() + info.completeBaseName() + asExt;
4118 bool auxiliaryStorageSavedOk =
true;
4119 if ( ! saveAuxiliaryStorage( asFileName ) )
4121 const QString err = mAuxiliaryStorage->errorString();
4122 setError( tr(
"Unable to save auxiliary storage file ('%1'). The project has been saved but the latest changes to auxiliary data cannot be recovered. It is recommended to reload the project." ).arg( err ) );
4123 auxiliaryStorageSavedOk =
false;
4126 if ( !mArchive->exists() )
4129 mArchive->unzip( mFile.fileName() );
4132 const QString auxiliaryStorageFile =
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile();
4133 if ( ! auxiliaryStorageFile.isEmpty() )
4135 archive->
addFile( auxiliaryStorageFile );
4144 if ( QFile::exists( asFileName ) )
4146 archive->addFile( asFileName );
4151 archive->addFile( qgsFile.fileName() );
4154 const QStringList &files = mArchive->files();
4155 for (
const QString &file : files )
4157 if ( !file.endsWith( QLatin1String(
".qgs" ), Qt::CaseInsensitive ) && !file.endsWith( asExt, Qt::CaseInsensitive ) )
4159 archive->addFile( file );
4165 if ( !archive->zip( filename ) )
4167 setError( tr(
"Unable to perform zip" ) );
4171 return auxiliaryStorageSavedOk && zipOk;
4182 const QList<QgsMapLayer *> &layers,
4184 bool takeOwnership )
4188 const QList<QgsMapLayer *> myResultList { mLayerStore->addMapLayers(
layers, takeOwnership ) };
4189 if ( !myResultList.isEmpty() )
4192 for (
auto &l : myResultList )
4202 if ( mAuxiliaryStorage )
4206 if ( mlayer->type() != Qgis::LayerType::Vector )
4217 mProjectScope.reset();
4219 return myResultList;
4225 bool takeOwnership )
4229 QList<QgsMapLayer *> addedLayers;
4230 addedLayers =
addMapLayers( QList<QgsMapLayer *>() << layer, addToLegend, takeOwnership );
4231 return addedLayers.isEmpty() ? nullptr : addedLayers[0];
4234void QgsProject::removeAuxiliaryLayer(
const QgsMapLayer *ml )
4238 if ( ! ml || ml->
type() != Qgis::LayerType::Vector )
4241 const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( ml );
4253 for (
const auto &layerId : layerIds )
4254 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
4256 mProjectScope.reset();
4257 mLayerStore->removeMapLayers( layerIds );
4264 for (
const auto &layer :
layers )
4265 removeAuxiliaryLayer( layer );
4267 mProjectScope.reset();
4268 mLayerStore->removeMapLayers(
layers );
4275 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
4276 mProjectScope.reset();
4277 mLayerStore->removeMapLayer( layerId );
4284 removeAuxiliaryLayer( layer );
4285 mProjectScope.reset();
4286 mLayerStore->removeMapLayer( layer );
4293 mProjectScope.reset();
4294 return mLayerStore->takeMapLayer( layer );
4301 return mMainAnnotationLayer;
4308 if ( mLayerStore->count() == 0 )
4311 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
4312 mProjectScope.reset();
4313 mLayerStore->removeAllMapLayers();
4315 snapSingleBlocker.release();
4317 if ( !mBlockSnappingUpdates )
4325 const QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
4326 QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin();
4327 for ( ; it !=
layers.constEnd(); ++it )
4329 it.value()->reload();
4338 return validOnly ? mLayerStore->validMapLayers() : mLayerStore->mapLayers();
4345 return mTransactionGroups.value( qMakePair( providerKey, connString ) );
4352 return &mEditBufferGroup;
4363 if ( mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), QStringLiteral(
"NoAction" ),
QgsSettings::App ).toString() == QStringLiteral(
"UseProjectCrs" )
4364 || mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), 0,
QgsSettings::App ).toString() == QLatin1String(
"2" ) )
4372 const QString layerDefaultCrs = mSettings.
value( QStringLiteral(
"/Projections/layerDefaultCrs" ),
geoEpsgCrsAuthId() ).toString();
4393bool QgsProject::saveAuxiliaryStorage(
const QString &filename )
4399 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4401 if ( it.value()->type() != Qgis::LayerType::Vector )
4404 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
4412 if ( !mAuxiliaryStorage->exists( *
this ) && empty )
4416 else if ( !filename.isEmpty() )
4418 return mAuxiliaryStorage->saveAs( filename );
4422 return mAuxiliaryStorage->saveAs( *
this );
4431 QgsProject::DataDefinedServerProperty::WMSOnlineResource,
4435 return sPropertyDefinitions;
4448 return mAuxiliaryStorage.get();
4455 return mAuxiliaryStorage.get();
4462 const QDir archiveDir( mArchive->dir() );
4463 QTemporaryFile tmpFile( archiveDir.filePath(
"XXXXXX_" + nameTemplate ),
this );
4464 tmpFile.setAutoRemove(
false );
4466 mArchive->addFile( tmpFile.fileName() );
4467 return tmpFile.fileName();
4474 QStringList attachments;
4476 const QStringList files = mArchive->files();
4477 attachments.reserve( files.size() );
4478 for (
const QString &file : files )
4482 attachments.append( file );
4492 return mArchive->removeFile( path );
4499 return QStringLiteral(
"attachment:///%1" ).arg( QFileInfo( attachedFile ).
fileName() );
4506 if ( identifier.startsWith( QLatin1String(
"attachment:///" ) ) )
4508 return QDir( mArchive->dir() ).absoluteFilePath( identifier.mid( 14 ) );
4529 mProjectScope.reset();
4543 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4557 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
4558 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
4563 if (
layers.contains( it.value() ) )
4575 QStringList customColors;
4576 QStringList customColorLabels;
4578 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
4579 for ( ; colorIt != colors.constEnd(); ++colorIt )
4582 const QString label = ( *colorIt ).second;
4583 customColors.append( color );
4584 customColorLabels.append( label );
4586 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ), customColors );
4587 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ), customColorLabels );
4588 mProjectScope.reset();
4596 if ( mBackgroundColor == color )
4599 mBackgroundColor = color;
4607 return mBackgroundColor;
4614 if ( mSelectionColor == color )
4617 mSelectionColor = color;
4625 return mSelectionColor;
4662 translationContext.setFileName( QStringLiteral(
"%1/%2.ts" ).arg(
absolutePath(),
baseName() ) );
4666 translationContext.writeTsFile( locale );
4669QString
QgsProject::translate(
const QString &context,
const QString &sourceText,
const char *disambiguation,
int n )
const
4678 QString result = mTranslator->translate( context.toUtf8(), sourceText.toUtf8(), disambiguation, n );
4680 if ( result.isEmpty() )
4694 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4699 if ( !( ( *it )->accept( visitor ) ) )
4708 if ( !mLayoutManager->accept( visitor ) )
4711 if ( !mAnnotationManager->accept( visitor ) )
4719 return mElevationShadingRenderer;
4722void QgsProject::loadProjectFlags(
const QDomDocument *doc )
4726 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectFlags" ) );
4727 Qgis::ProjectFlags
flags;
4728 if ( !element.isNull() )
4735 element = doc->documentElement().firstChildElement( QStringLiteral(
"evaluateDefaultValues" ) );
4736 if ( !element.isNull() )
4738 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
4743 element = doc->documentElement().firstChildElement( QStringLiteral(
"trust" ) );
4744 if ( !element.isNull() )
4746 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
4755GetNamedProjectColor::GetNamedProjectColor(
const QgsProject *project )
4762 QStringList colorStrings = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ) );
4763 const QStringList colorLabels = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ) );
4767 for ( QStringList::iterator it = colorStrings.begin();
4768 it != colorStrings.end(); ++it )
4772 if ( colorLabels.length() > colorIndex )
4774 label = colorLabels.at( colorIndex );
4777 mColors.insert( label.toLower(), color );
4782GetNamedProjectColor::GetNamedProjectColor(
const QHash<QString, QColor> &colors )
4790 const QString colorName = values.at( 0 ).toString().toLower();
4791 if ( mColors.contains( colorName ) )
4793 return QStringLiteral(
"%1,%2,%3" ).arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
4801 return new GetNamedProjectColor( mColors );
@ ForceReadOnlyLayers
Open layers in a read-only mode. (since QGIS 3.28)
static QString version()
Version string.
DistanceUnit
Units of distance.
FilePathType
File path types.
TransactionMode
Transaction mode.
@ AutomaticGroups
Automatic transactional editing means that on supported datasources (postgres and geopackage database...
@ BufferedGroups
Buffered transactional editing means that all editable layers in the buffered transaction group are t...
@ Disabled
Edits are buffered locally and sent to the provider when toggling layer editing mode.
AvoidIntersectionsMode
Flags which control how intersections of pre-existing feature are handled when digitizing new feature...
@ AvoidIntersectionsLayers
Overlap with features from a specified list of layers when digitizing new features not allowed.
@ AllowIntersections
Overlap with any feature allowed when digitizing new features.
ProjectFlag
Flags which control the behavior of QgsProjects.
@ RememberLayerEditStatusBetweenSessions
If set, then any layers set to be editable will be stored in the project and immediately made editabl...
@ EvaluateDefaultValuesOnProviderSide
If set, default values for fields will be evaluated on the provider side when features from the proje...
@ TrustStoredLayerStatistics
If set, then layer statistics (such as the layer extent) will be read from values stored in the proje...
LayerType
Types of layers that can be added to a map.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Represents a map layer containing a set of georeferenced annotations, e.g.
void setTransformContext(const QgsCoordinateTransformContext &context) override
Sets the coordinate transform context to transformContext.
void reset()
Resets the annotation layer to a default state, and clears all items from it.
bool isEmpty() const
Returns true if the annotation layer is empty and contains no annotations.
Manages storage of a set of QgsAnnotation annotation objects.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QgsProjectStorageRegistry * projectStorageRegistry()
Returns registry of available project storage implementations.
static const QgsSettingsEntryString * settingsLocaleUserLocale
Settings entry locale user locale.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
void collectTranslatableObjects(QgsTranslationContext *translationContext)
Emits the signal to collect all the strings of .qgs to be included in ts file.
static QgsPluginLayerRegistry * pluginLayerRegistry()
Returns the application's plugin layer registry, used for managing plugin layer types.
void requestForTranslatableObjects(QgsTranslationContext *translationContext)
Emitted when project strings which require translation are being collected for inclusion in a ....
static QString userFullName()
Returns the user's operating system login account full display name.
static QString userLoginName()
Returns the user's operating system login account name.
Class allowing to manage the zip/unzip actions.
void addFile(const QString &filename)
Add a new file to this archive.
This is a container for attribute editors, used to group them visually in the attribute form if it is...
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
This is an abstract base class for any elements of a drag and drop form.
QString name() const
Returns the name of this element.
@ AeTypeContainer
A container.
QgsFields auxiliaryFields() const
Returns a list of all auxiliary fields currently managed by the layer.
bool save()
Commits changes and starts editing then.
Class providing some utility methods to manage auxiliary storage.
static QString extension()
Returns the extension used for auxiliary databases.
static bool deleteTable(const QgsDataSourceUri &uri)
Removes a table from the auxiliary storage.
Manages storage of a set of bookmarks.
bool readXml(const QDomElement &element, const QDomDocument &doc)
Reads the manager's state from a DOM element, restoring all bookmarks present in the XML document.
void clear()
Removes and deletes all bookmarks from the manager.
QDomElement writeXml(QDomDocument &doc) const
Returns a DOM element representing the state of the manager.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Q_GADGET Qgis::DistanceUnit mapUnits
QString toProj() const
Returns a Proj string representation of this CRS.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
QString projectionAcronym() const
Returns the projection acronym for the projection used by the CRS.
static QgsCoordinateReferenceSystem fromProj(const QString &proj)
Creates a CRS from a proj style formatted string.
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Contains information about the context in which a coordinate transform is executed.
void readSettings()
Reads the context's state from application settings.
void writeXml(QDomElement &element, const QgsReadWriteContext &context) const
Writes the context's state to a DOM element.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context, QStringList &missingTransforms)
Reads the context's state from a DOM element.
@ EvaluateDefaultValues
Evaluate default values on provider side when calling QgsVectorDataProvider::defaultValue( int index ...
Class for storing the component parts of a RDBMS data source URI (e.g.
This class can render elevation shading on an image with different methods (eye dome lighting,...
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const
Writes configuration on a DOM element.
void readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads configuration from a DOM element.
Single scope for storing variables and functions for use within a QgsExpressionContext.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
An expression node for expression functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
Encapsulate a field in an attribute table or data source.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
bool isEmpty() const
Checks whether the container is empty.
Stores global configuration for labeling engine.
Class used to work with layer dependencies stored in a XML project or layer definition file.
Layer tree group node serves as a container for layers and further groups.
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Calls resolveReferences() on child tree nodes.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name.
QList< QgsLayerTreeGroup * > findGroups(bool recursive=false) const
Find group layer nodes.
QString name() const override
Returns the group's name.
QStringList findLayerIds() const
Find layer IDs used in all layer nodes.
void insertChildNodes(int index, const QList< QgsLayerTreeNode * > &nodes)
Insert existing nodes at specified position.
void readChildrenFromXml(QDomElement &element, const QgsReadWriteContext &context)
Read children from XML and append them to the group.
QgsLayerTreeGroup * clone() const override
Returns a clone of the group.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
Layer tree node points to a map layer.
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Resolves reference to layer from stored layer ID (if it has not been resolved already)
This class is a base class for nodes in a layer tree.
QList< QgsLayerTreeNode * > abandonChildren()
Removes the childrens, disconnect all the forwarded and external signals and sets their parent to nul...
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file.
virtual void writeXml(QDomElement &parentElement, const QgsReadWriteContext &context)=0
Write layer tree to XML.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
Listens to the updates in map layer registry and does changes in layer tree.
void setEnabled(bool enabled)
static void replaceChildrenOfEmbeddedGroups(QgsLayerTreeGroup *group)
Remove subtree of embedded groups and replaces it with a custom property embedded-visible-layers.
static void storeOriginalLayersProperties(QgsLayerTreeGroup *group, const QDomDocument *doc)
Stores in a layer's originalXmlProperties the layer properties information.
static void updateEmbeddedGroupsProjectPath(QgsLayerTreeGroup *group, const QgsProject *project)
Updates an embedded group from a project.
static bool readOldLegend(QgsLayerTreeGroup *root, const QDomElement &legendElem)
Try to load layer tree from.
Namespace with helper functions for layer tree operations.
void readLayerOrderFromXml(const QDomElement &doc)
Load the layer order from an XML element.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
void clear()
Clear any information from this layer tree.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
QList< QgsMapLayer * > customLayerOrder() const
The order in which layers will be rendered on the canvas.
QgsLayerTree * clone() const override
Create a copy of the node. Returns new instance.
Manages storage of a set of layouts.
static void warning(const QString &msg)
Goes to qWarning.
static Qgis::LayerType typeFromString(const QString &string, bool &ok)
Returns the map layer type corresponding a string value.
A storage object for map layers, in which the layers are owned by the store and have their lifetime b...
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the store.
void layerWillBeRemoved(const QString &layerId)
Emitted when a layer is about to be removed from the store.
void layersRemoved(const QStringList &layerIds)
Emitted after one or more layers were removed from the store.
void allLayersRemoved()
Emitted when all layers are removed, before layersWillBeRemoved() and layerWillBeRemoved() signals ar...
void layerRemoved(const QString &layerId)
Emitted after a layer was removed from the store.
void layerWasAdded(QgsMapLayer *layer)
Emitted when a layer was added to the store.
QgsMapLayer * mapLayer(const QString &id) const
Retrieve a pointer to a layer by layer id.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the store.
Base class for all map layer types.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
void configChanged()
Emitted whenever the configuration is changed.
QgsCoordinateReferenceSystem crs
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QString originalXmlProperties() const
Returns the XML properties of the original layer as they were when the layer was first read from the ...
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
virtual bool isEditable() const
Returns true if the layer can be edited.
bool writeLayerXml(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores state in DOM node.
bool readLayerXml(const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags=QgsMapLayer::ReadFlags())
Sets state from DOM document.
@ Identifiable
If the layer is identifiable using the identify map tool and as a WMS layer.
@ Removable
If the layer can be removed from the project. The layer will not be removable from the legend menu en...
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
@ FlagForceReadOnly
Force open as read only.
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Container class that allows storage of map themes consisting of visible map layers and layer styles.
Manages storage of a set of views.
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).
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
Class allowing to manage the zip/unzip actions on project file.
QString projectFile() const
Returns the current .qgs project file or an empty string if there's none.
QString auxiliaryStorageFile() const
Returns the current .qgd auxiliary storage file or an empty string if there's none.
bool unzip(const QString &zipFilename) override
Clear the current content of this archive and unzip.
Interface for classes that handle missing layer files when reading project file.
virtual void handleBadLayers(const QList< QDomNode > &layers)
This method will be called whenever the project tries to load layers which cannot be accessed.
Contains settings and properties relating to how a QgsProject should display values such as map coord...
void reset()
Resets the settings to a default state.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
Contains elevation properties for a QgsProject.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the property state from a DOM element.
void reset()
Resets the properties to a default state.
QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Returns a DOM element representing the properties.
void resolveReferences(const QgsProject *project)
Resolves reference to layers from stored layer ID.
Contains settings and properties relating to how a QgsProject should interact with a GPS device.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
void reset()
Resets the settings to a default state.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
void resolveReferences(const QgsProject *project)
Resolves reference to layers from stored layer ID (if it has not been resolved already)
Project property key node.
QString name() const
The name of the property is used as identifier.
QgsProjectProperty * find(const QString &propertyName) const
Attempts to find a property with a matching sub-key name.
void removeKey(const QString &keyName)
Removes the specified key.
void dump(int tabs=0) const override
Dumps out the keys and values.
bool isEmpty() const
Returns true if this property contains no sub-keys.
virtual void clearKeys()
Deletes any sub-nodes from the property.
bool writeXml(const QString &nodeName, QDomElement &element, QDomDocument &document) override
Writes the property hierarchy to a specified DOM element.
void subkeyList(QStringList &entries) const
Returns any sub-keys contained by this property which themselves contain other keys.
void setName(const QString &name)
The name of the property is used as identifier.
QgsProjectPropertyKey * addKey(const QString &keyName)
Adds the specified property key as a sub-key.
QVariant value() const override
If this key has a value, it will be stored by its name in its properties.
QgsProjectPropertyValue * setValue(const QString &name, const QVariant &value)
Sets the value associated with this key.
void entryList(QStringList &entries) const
Returns any sub-keys contained by this property that do not contain other keys.
int count() const
Returns the number of sub-keys contained by this property.
bool readXml(const QDomNode &keyNode) override
Restores the property hierarchy from a specified DOM node.
An Abstract Base Class for QGIS project property hierarchys.
virtual bool isKey() const =0
Returns true if the property is a QgsProjectPropertyKey.
virtual bool isValue() const =0
Returns true if the property is a QgsProjectPropertyValue.
QgsProjectStorage * projectStorageFromUri(const QString &uri)
Returns storage implementation if the URI matches one. Returns nullptr otherwise (it is a normal file...
Abstract interface for project storage - to be implemented by various backends and registered in QgsP...
Contains settings and properties relating to how a QgsProject should handle styling.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
void setDefaultSymbol(Qgis::SymbolType symbolType, QgsSymbol *symbol)
Sets the project default symbol for a given type.
void reset()
Resets the settings to a default state.
void setRandomizeDefaultSymbolColor(bool randomized)
Sets whether the default symbol fill color is randomized.
void setDefaultColorRamp(QgsColorRamp *colorRamp)
Sets the project default color ramp.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context, Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
Reads the settings's state from a DOM element.
void setDefaultSymbolOpacity(double opacity)
Sets the default symbol opacity.
Contains temporal settings and properties for the project, this may be used when animating maps or sh...
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
void reset()
Resets the settings to a default state.
QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
A class to describe the version of a project.
QString text() const
Returns a string representation of the version.
int majorVersion() const
Returns the major version number.
Contains settings and properties relating to how a QgsProject should be displayed inside map canvas,...
bool useProjectScales() const
Returns true if project mapScales() are enabled.
void reset()
Resets the settings to a default state.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
void setMapScales(const QVector< double > &scales)
Sets the list of custom project map scales.
void setUseProjectScales(bool enabled)
Sets whether project mapScales() are enabled.
QVector< double > mapScales() const
Returns the list of custom project map scales.
void mapScalesChanged()
Emitted when the list of custom project map scales changes.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
bool isZipped() const
Returns true if the project comes from a zip archive, false otherwise.
bool removeAttachedFile(const QString &path)
Removes the attached file.
QgsRelationManager * relationManager
bool write()
Writes the project to its current associated file (see fileName() ).
QgsProject(QObject *parent=nullptr, Qgis::ProjectCapabilities capabilities=Qgis::ProjectCapability::ProjectStyles)
Create a new QgsProject.
void removeMapLayer(const QString &layerId)
Remove a layer from the registry by layer ID.
Q_DECL_DEPRECATED bool evaluateDefaultValues() const
Should default values be evaluated on provider side when requested and not when committed.
Qgis::DistanceUnit distanceUnits
void layersRemoved(const QStringList &layerIds)
Emitted after one or more layers were removed from the registry.
void clear()
Clears the project, removing all settings and resetting it back to an empty, default state.
QString error() const
Returns error message from previous read/write.
Q_DECL_DEPRECATED void setUseProjectScales(bool enabled)
Sets whether project mapScales() are enabled.
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
Reads an integer from the specified scope and key.
Q_DECL_DEPRECATED void setNonIdentifiableLayers(const QList< QgsMapLayer * > &layers)
Set a list of layers which should not be taken into account on map identification.
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer * > &mapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
Qgis::ProjectFlags flags() const
Returns the project's flags, which dictate the behavior of the project.
Q_DECL_DEPRECATED QFileInfo fileInfo() const
Returns QFileInfo object for the project's associated file.
QString presetHomePath() const
Returns any manual project home path setting, or an empty string if not set.
void setBackgroundColor(const QColor &color)
Sets the default background color used by default map canvases.
void setCrs(const QgsCoordinateReferenceSystem &crs, bool adjustEllipsoid=false)
Sets the project's native coordinate reference system.
QString title() const
Returns the project's title.
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...
void mapThemeCollectionChanged()
Emitted when the map theme collection changes.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Qgis::FilePathType filePathStorage() const
Returns the type of paths used when storing file paths in a QGS/QGZ project file.
QString createAttachedFile(const QString &nameTemplate)
Attaches a file to the project.
Q_DECL_DEPRECATED void mapScalesChanged()
Emitted when the list of custom project map scales changes.
void readVersionMismatchOccurred(const QString &fileVersion)
Emitted when a project is read and the version of QGIS used to save the project differs from the curr...
void fileNameChanged()
Emitted when the file name of the project changes.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
void writeMapLayer(QgsMapLayer *mapLayer, QDomElement &layerElem, QDomDocument &doc)
Emitted when a layer is being saved.
void setSnappingConfig(const QgsSnappingConfig &snappingConfig)
The snapping configuration for this project.
void areaUnitsChanged()
Emitted when the default area units changes.
QgsPropertyCollection dataDefinedServerProperties() const
Returns the data defined properties used for overrides in user defined server parameters.
Q_DECL_DEPRECATED void nonIdentifiableLayersChanged(QStringList nonIdentifiableLayers)
Emitted when the list of layer which are excluded from map identification changes.
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QString attachmentIdentifier(const QString &attachedFile) const
Returns an identifier for an attachment file path An attachment identifier is a string which does not...
QgsVectorLayerEditBufferGroup * editBufferGroup()
Returns the edit buffer group.
void setSelectionColor(const QColor &color)
Sets the color used to highlight selected features.
bool rollBack(QStringList &rollbackErrors, bool stopEditing=true, QgsVectorLayer *vectorLayer=nullptr)
Stops a current editing operation on vectorLayer and discards any uncommitted edits.
void snappingConfigChanged(const QgsSnappingConfig &config)
Emitted whenever the configuration for snapping has changed.
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
void setBadLayerHandler(QgsProjectBadLayerHandler *handler)
Change handler for missing layers.
Q_DECL_DEPRECATED void setEvaluateDefaultValues(bool evaluateDefaultValues)
Defines if default values should be evaluated on provider side when requested and not when committed.
void crsChanged()
Emitted when the CRS of the project has changed.
QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const override
Translates the project with QTranslator and qm file.
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
QgsSnappingConfig snappingConfig
const QgsProjectGpsSettings * gpsSettings() const
Returns the project's GPS settings, which contains settings and properties relating to how a QgsProje...
void setFileName(const QString &name)
Sets the file name associated with the project.
void avoidIntersectionsLayersChanged()
Emitted whenever avoidIntersectionsLayers has changed.
void setDataDefinedServerProperties(const QgsPropertyCollection &properties)
Sets the data defined properties used for overrides in user defined server parameters to properties.
void registerTranslatableObjects(QgsTranslationContext *translationContext)
Registers the objects that require translation into the translationContext.
void distanceUnitsChanged()
Emitted when the default distance units changes.
QgsAnnotationLayer * mainAnnotationLayer()
Returns the main annotation layer associated with the project.
const QgsBookmarkManager * bookmarkManager() const
Returns the project's bookmark manager, which manages bookmarks within the project.
void readMapLayer(QgsMapLayer *mapLayer, const QDomElement &layerNode)
Emitted after the basic initialization of a layer from the project file is done.
Q_DECL_DEPRECATED void setAutoTransaction(bool autoTransaction)
Transactional editing means that on supported datasources (postgres databases) the edit state of all ...
bool startEditing(QgsVectorLayer *vectorLayer=nullptr)
Makes the layer editable.
Q_DECL_DEPRECATED void setTrustLayerMetadata(bool trust)
Sets the trust option allowing to indicate if the extent has to be read from the XML document when da...
void cleared()
Emitted when the project is cleared (and additionally when an open project is cleared just before a n...
Q_DECL_DEPRECATED void oldProjectVersionWarning(const QString &)
Emitted when an old project file is read.
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets project's global labeling engine settings.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void metadataChanged()
Emitted when the project's metadata is changed.
QString resolveAttachmentIdentifier(const QString &identifier) const
Resolves an attachment identifier to a attachment file path.
const QgsProjectElevationProperties * elevationProperties() const
Returns the project's elevation properties, which contains the project's elevation related settings.
QString absolutePath() const
Returns full absolute path to the project folder if the project is stored in a file system - derived ...
void removeMapLayers(const QStringList &layerIds)
Remove a set of layers from the registry by layer ID.
Q_DECL_DEPRECATED void setRequiredLayers(const QSet< QgsMapLayer * > &layers)
Configures a set of map layers that are required in the project and therefore they should not get rem...
bool createEmbeddedLayer(const QString &layerId, const QString &projectFilePath, QList< QDomNode > &brokenNodes, bool saveFlag=true, Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
Creates a maplayer instance defined in an arbitrary project file.
QList< QgsVectorLayer * > avoidIntersectionsLayers
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Reads a string from the specified scope and key.
QgsExpressionContextScope * createExpressionContextScope() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QString baseName() const
Returns the base name of the project file without the path and without extension - derived from fileN...
void ellipsoidChanged(const QString &ellipsoid)
Emitted when the project ellipsoid is changed.
QgsMapThemeCollection * mapThemeCollection
void generateTsFile(const QString &locale)
Triggers the collection strings of .qgs to be included in ts file and calls writeTsFile()
QStringList entryList(const QString &scope, const QString &key) const
Returns a list of child keys with values which exist within the the specified scope and key.
QgsAnnotationManager * annotationManager()
Returns pointer to the project's annotation manager.
QgsProjectDisplaySettings * displaySettings
Qgis::TransactionMode transactionMode() const
Returns the transaction mode.
QgsProjectMetadata metadata
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
QString saveUser() const
Returns the user name that did the last save.
QVector< T > layers() const
Returns a list of registered map layers with a specified layer type.
void setProjectColors(const QgsNamedColorList &colors)
Sets the colors for the project's color scheme (see QgsProjectColorScheme).
bool setTransactionMode(Qgis::TransactionMode transactionMode)
Set transaction mode.
QgsCoordinateTransformContext transformContext
void labelingEngineSettingsChanged()
Emitted when global configuration of the labeling engine changes.
void customVariablesChanged()
Emitted whenever the expression variables stored in the project have been changed.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
bool readBoolEntry(const QString &scope, const QString &key, bool def=false, bool *ok=nullptr) const
Reads a boolean from the specified scope and key.
QgsMapLayerStore * layerStore()
Returns a pointer to the project's internal layer store.
void readProject(const QDomDocument &)
Emitted when a project is being read.
QString originalPath() const
Returns the original path associated with the project.
void setOriginalPath(const QString &path)
Sets the original path associated with the project.
void dumpProperties() const
Dump out current project properties to stderr.
QgsElevationShadingRenderer elevationShadingRenderer() const
Returns the elevation shading renderer used for map shading.
const QgsMapViewsManager * viewsManager() const
Returns the project's views manager, which manages map views (including 3d maps) in the project.
static void setInstance(QgsProject *project)
Set the current project singleton instance to project.
int validCount() const
Returns the number of registered valid layers.
const QgsLayoutManager * layoutManager() const
Returns the project's layout manager, which manages print layouts, atlases and reports within the pro...
void elevationShadingRendererChanged()
Emitted when the map shading renderer changes.
QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
Q_DECL_DEPRECATED bool autoTransaction() const
Transactional editing means that on supported datasources (postgres databases) the edit state of all ...
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
QStringList attachedFiles() const
Returns a map of all attached files with identifier and real paths.
void setMetadata(const QgsProjectMetadata &metadata)
Sets the project's metadata store.
void missingDatumTransforms(const QStringList &missingTransforms)
Emitted when datum transforms stored in the project are not available locally.
QgsTransactionGroup * transactionGroup(const QString &providerKey, const QString &connString)
Returns the matching transaction group from a provider key and connection string.
QgsCoordinateReferenceSystem crs
void readProjectWithContext(const QDomDocument &, QgsReadWriteContext &context)
Emitted when a project is being read.
QgsMapLayer * addMapLayer(QgsMapLayer *mapLayer, bool addToLegend=true, bool takeOwnership=true)
Add a layer to the map of loaded layers.
QStringList nonIdentifiableLayers
void setAvoidIntersectionsMode(const Qgis::AvoidIntersectionsMode mode)
Sets the avoid intersections mode.
void transactionGroupsChanged()
Emitted whenever a new transaction group has been created or a transaction group has been removed.
const QgsAuxiliaryStorage * auxiliaryStorage() const
Returns the current const auxiliary storage.
void reloadAllLayers()
Reload all registered layer's provider data caches, synchronising the layer with any changes in the d...
int count() const
Returns the number of registered layers.
void loadingLayerMessageReceived(const QString &layerName, const QList< QgsReadWriteContext::ReadWriteMessage > &messages)
Emitted when loading layers has produced some messages.
void setAreaUnits(Qgis::AreaUnit unit)
Sets the default area measurement units for the project.
void setTitle(const QString &title)
Sets the project's title.
QMap< QPair< QString, QString >, QgsTransactionGroup * > transactionGroups()
Map of transaction groups.
void writeProject(QDomDocument &)
Emitted when the project is being written.
void setFlag(Qgis::ProjectFlag flag, bool enabled=true)
Sets whether a project flag is enabled.
QDateTime lastModified() const
Returns last modified time of the project file as returned by the file system (or other project stora...
bool readLayer(const QDomNode &layerNode)
Reads the layer described in the associated DOM node.
double readDoubleEntry(const QString &scope, const QString &key, double def=0, bool *ok=nullptr) const
Reads a double from the specified scope and key.
bool writeEntry(const QString &scope, const QString &key, bool value)
Write a boolean value to the project file.
QString absoluteFilePath() const
Returns full absolute path to the project file if the project is stored in a file system - derived fr...
QDateTime lastSaveDateTime() const
Returns the date and time when the project was last saved.
void projectSaved()
Emitted when the project file has been written and closed.
Q_DECL_DEPRECATED bool trustLayerMetadata() const
Returns true if the trust option is activated, false otherwise.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
void setEllipsoid(const QString &ellipsoid)
Sets the project's ellipsoid from a proj string representation, e.g., "WGS84".
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the project's coordinate transform context, which stores various information regarding which dat...
void layerLoaded(int i, int n)
Emitted when a layer from a projects was read.
QStringList subkeyList(const QString &scope, const QString &key) const
Returns a list of child keys which contain other keys that exist within the the specified scope and k...
bool read(const QString &filename, Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
Reads given project file from the given file.
QStringList readListEntry(const QString &scope, const QString &key, const QStringList &def=QStringList(), bool *ok=nullptr) const
Reads a string list from the specified scope and key.
void selectionColorChanged()
Emitted whenever the project's selection color has been changed.
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns project's global labeling engine settings.
void removeAllMapLayers()
Removes all registered layers.
Q_DECL_DEPRECATED QVector< double > mapScales() const
Returns the list of custom project map scales.
void setDirty(bool b=true)
Flag the project as dirty (modified).
void backgroundColorChanged()
Emitted whenever the project's canvas background color has been changed.
QgsLayerTreeGroup * createEmbeddedGroup(const QString &groupName, const QString &projectFilePath, const QStringList &invisibleLayers, Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
Create layer group instance defined in an arbitrary project file.
const QgsProjectViewSettings * viewSettings() const
Returns the project's view settings, which contains settings and properties relating to how a QgsProj...
QString readPath(const QString &filename) const
Transforms a filename read from the project file to an absolute path.
void registerTranslatableContainers(QgsTranslationContext *translationContext, QgsAttributeEditorContainer *parent, const QString &layerId)
Registers the containers that require translation into the translationContext.
void setElevationShadingRenderer(const QgsElevationShadingRenderer &elevationShadingRenderer)
Sets the elevation shading renderer used for global map shading.
void setFilePathStorage(Qgis::FilePathType type)
Sets the type of paths used when storing file paths in a QGS/QGZ project file.
Q_DECL_DEPRECATED QSet< QgsMapLayer * > requiredLayers() const
Returns a set of map layers that are required in the project and therefore they should not get remove...
void transformContextChanged()
Emitted when the project transformContext() is changed.
void setTopologicalEditing(bool enabled)
Convenience function to set topological editing.
void legendLayersAdded(const QList< QgsMapLayer * > &layers)
Emitted, when a layer was added to the registry and the legend.
QVariantMap customVariables() const
A map of custom project variables.
void setAvoidIntersectionsLayers(const QList< QgsVectorLayer * > &layers)
Sets the list of layers with which intersections should be avoided.
void homePathChanged()
Emitted when the home path of the project changes.
void dirtySet()
Emitted when setDirty(true) is called.
void setCustomVariables(const QVariantMap &customVariables)
A map of custom project variables.
QgsCoordinateReferenceSystem defaultCrsForNewLayers() const
Returns the default CRS for new layers based on the settings and the current project CRS.
QString saveUserFullName() const
Returns the full user name that did the last save.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the registry.
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
bool isDirty() const
Returns true if the project has been modified since the last write()
QgsMapLayer * takeMapLayer(QgsMapLayer *layer)
Takes a layer from the registry.
void isDirtyChanged(bool dirty)
Emitted when the project dirty status changes.
void setDistanceUnits(Qgis::DistanceUnit unit)
Sets the default distance measurement units for the project.
Q_DECL_DEPRECATED bool useProjectScales() const
Returns true if project mapScales() are enabled.
Q_DECL_DEPRECATED void setMapScales(const QVector< double > &scales)
Sets the list of custom project map scales.
void setPresetHomePath(const QString &path)
Sets the project's home path.
void setFlags(Qgis::ProjectFlags flags)
Sets the project's flags, which dictate the behavior of the project.
QList< QgsMapLayer * > mapLayersByShortName(const QString &shortName) const
Retrieves a list of matching registered layers by layer shortName.
QgsProjectStorage * projectStorage() const
Returns pointer to project storage implementation that handles read/write of the project file.
QString layerIsEmbedded(const QString &id) const
Returns the source project file path if the layer with matching id is embedded from other project fil...
const QgsProjectTimeSettings * timeSettings() const
Returns the project's time settings, which contains the project's temporal range and other time based...
void topologicalEditingChanged()
Emitted when the topological editing flag has changed.
bool removeEntry(const QString &scope, const QString &key)
Remove the given key from the specified scope.
QgsProjectVersion lastSaveVersion() const
Returns the QGIS version which the project was last saved using.
void avoidIntersectionsModeChanged()
Emitted whenever the avoid intersections mode has changed.
void loadingLayer(const QString &layerName)
Emitted when a layer is loaded.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
Definition for a property.
@ String
Any string value.
The class is used as a container of context for various read/write operations on other objects.
void setTransformContext(const QgsCoordinateTransformContext &transformContext)
Sets data coordinate transform context to transformContext.
QList< QgsReadWriteContext::ReadWriteMessage > takeMessages()
Returns the stored messages and remove them.
void setProjectTranslator(QgsProjectTranslator *projectTranslator)
Sets the project translator.
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
This class manages a set of relations between layers.
void clear()
Remove any relation managed by this class.
QMap< QString, QgsRelation > relations() const
Gets access to the relations managed by this class.
void clear(const QString &group="startup")
clear Clear all profile data.
Expression function for use within a QgsExpressionContextScope.
Scoped object for logging of the runtime for a single operation or group of operations.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
This is a container for configuration of the snapping of the project.
bool addLayers(const QList< QgsMapLayer * > &layers)
Adds the specified layers as individual layers to the configuration with standard configuration.
void readProject(const QDomDocument &doc)
Reads the configuration from the specified QGIS project document.
void reset()
reset to default values
void writeProject(QDomDocument &doc)
Writes the configuration to the specified QGIS project document.
void clearIndividualLayerSettings()
Removes all individual layer snapping settings.
bool removeLayers(const QList< QgsMapLayer * > &layers)
Removes the specified layers from the individual layer configuration.
An interface for classes which can visit style entity (e.g.
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
static QgsStyle * defaultStyle()
Returns default application-wide style.
void triggerIconRebuild()
Triggers emission of the rebuildIconPreviews() signal.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
bool addLayer(QgsVectorLayer *layer)
Add a layer to this transaction group.
static bool supportsTransaction(const QgsVectorLayer *layer)
Checks if the provider of a given layer supports transactions.
QString connectionString() const
Returns the connection string of the transaction.
Used for the collecting of strings from projects for translation and creation of ts files.
void registerTranslation(const QString &context, const QString &source)
Registers the source to be translated.
void setProject(QgsProject *project)
Sets the project being translated.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
static Q_INVOKABLE Qgis::AreaUnit decodeAreaUnit(const QString &string, bool *ok=nullptr)
Decodes an areal unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE Qgis::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
The edit buffer group manages a group of edit buffers.
bool commitChanges(QStringList &commitErrors, bool stopEditing=true)
Attempts to commit any changes to disk.
bool startEditing()
Start editing.
void clear()
Remove all layers from this edit buffer group.
bool rollBack(QStringList &rollbackErrors, bool stopEditing=true)
Stop editing and discard the edits.
void addLayer(QgsVectorLayer *layer)
Add a layer to this edit buffer group.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE bool startEditing()
Makes the layer editable.
bool loadAuxiliaryLayer(const QgsAuxiliaryStorage &storage, const QString &key=QString())
Loads the auxiliary layer for this vector layer.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
Q_INVOKABLE bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits.
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...
QgsEditFormConfig editFormConfig
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
CORE_EXPORT bool isZipFile(const QString &filename)
Returns true if the file name is a zipped file ( i.e with a '.qgz' extension, false otherwise.
CONSTLATIN1STRING geoNone()
Constant that holds the string representation for "No ellips/No CRS".
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.
#define Q_NOWARN_DEPRECATED_POP
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
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.
#define Q_NOWARN_DEPRECATED_PUSH
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
#define QgsDebugMsgLevel(str, level)
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
void _getProperties(const QDomDocument &doc, QgsProjectPropertyKey &project_properties)
Restores any optional properties found in "doc" to "properties".
QgsPropertyCollection getDataDefinedServerProperties(const QDomDocument &doc, const QgsPropertiesDefinition &dataDefinedServerPropertyDefinitions)
Returns the data defined server properties collection found in "doc" to "dataDefinedServerProperties"...
void removeKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
Removes a given key.
QgsProjectVersion getVersion(const QDomDocument &doc)
Returns the version string found in the given DOM document.
QStringList makeKeyTokens_(const QString &scope, const QString &key)
Takes the given scope and key and convert them to a string list of key tokens that will be used to na...
void dump_(const QgsProjectPropertyKey &topQgsPropertyKey)
QgsProjectProperty * findKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
Returns the property that matches the given key sequence, if any.
QgsProjectProperty * addKey_(const QString &scope, const QString &key, QgsProjectPropertyKey *rootProperty, const QVariant &value, bool &propertiesModified)
Adds the given key and value.
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS_NON_FATAL
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
const QgsCoordinateReferenceSystem & crs
Setting options for loading annotation layers.
Single variable definition for use within a QgsExpressionContextScope.
Setting options for loading group layers.
Contains information relating to a node (i.e.