76#include <QApplication>
81#include <QTemporaryFile>
84#include <QStandardPaths>
86#include <QRegularExpression>
107 QStringList keyTokens = QStringList( scope );
108#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
109 keyTokens += key.split(
'/', QString::SkipEmptyParts );
111 keyTokens += key.split(
'/', Qt::SkipEmptyParts );
115 keyTokens.push_front( QStringLiteral(
"properties" ) );
118 for (
int i = 0; i < keyTokens.size(); ++i )
120 const QString keyToken = keyTokens.at( i );
124 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}])" ) );
125 if ( keyToken.contains( sInvalidRegexp ) )
127 const QString errorString = QObject::tr(
"Entry token invalid : '%1'. The token will not be saved to file." ).arg( keyToken );
155 while ( !keySequence.isEmpty() )
159 if ( keySequence.first() == currentProperty->
name() )
162 keySequence.pop_front();
164 if ( 1 == keySequence.count() )
167 return currentProperty->
find( keySequence.front() );
169 else if ( keySequence.isEmpty() )
174 return currentProperty;
176 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
178 if ( nextProperty->
isKey() )
182 else if ( nextProperty->
isValue() && 1 == keySequence.count() )
188 return currentProperty;
226 const QVariant &value,
227 bool &propertiesModified )
236 propertiesModified =
false;
237 while ( ! keySequence.isEmpty() )
241 if ( keySequence.first() == currentProperty->
name() )
244 keySequence.pop_front();
248 if ( 1 == keySequence.count() )
251 if ( !property || property->value() != value )
253 currentProperty->
setValue( keySequence.front(), value );
254 propertiesModified =
true;
257 return currentProperty;
261 else if ( keySequence.isEmpty() )
263 if ( currentProperty->
value() != value )
266 propertiesModified =
true;
269 return currentProperty;
271 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
275 if ( currentProperty )
286 if ( ( newPropertyKey = currentProperty->
addKey( keySequence.first() ) ) )
288 currentProperty = newPropertyKey;
320 while ( ! keySequence.isEmpty() )
324 if ( keySequence.first() == currentProperty->
name() )
327 keySequence.pop_front();
331 if ( 1 == keySequence.count() )
333 currentProperty->
removeKey( keySequence.front() );
338 else if ( keySequence.isEmpty() )
340 previousQgsPropertyKey->
removeKey( currentProperty->
name() );
342 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
344 previousQgsPropertyKey = currentProperty;
347 if ( currentProperty )
371 , mCapabilities( capabilities )
374 , mSnappingConfig( this )
390 mProperties.
setName( QStringLiteral(
"properties" ) );
393 mMainAnnotationLayer->setParent(
this );
407 this, [ = ](
const QStringList &
layers ) { mProjectScope.reset(); emit layersWillBeRemoved( layers ); } );
409 this, [ = ](
const QList<QgsMapLayer *> &
layers ) { mProjectScope.reset(); emit layersWillBeRemoved( layers ); } );
411 this, [ = ](
const QString & layer ) { mProjectScope.reset(); emit layerWillBeRemoved( layer ); } );
413 this, [ = ](
QgsMapLayer * layer ) { mProjectScope.reset(); emit layerWillBeRemoved( layer ); } );
415 [ = ](
const QStringList &
layers ) { mProjectScope.reset(); emit layersRemoved( layers ); } );
417 [ = ](
const QString & layer ) { mProjectScope.reset(); emit layerRemoved( layer ); } );
419 [ = ]() { mProjectScope.reset(); emit removeAll(); } );
421 [ = ](
const QList< QgsMapLayer * > &
layers ) { mProjectScope.reset(); emit layersAdded( layers ); } );
423 [ = ](
QgsMapLayer * layer ) { mProjectScope.reset(); emit layerWasAdded( layer ); } );
431 [ = ](
const QList<QgsMapLayer *> &
layers )
433 for ( const auto &layer : layers )
435 disconnect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager, &QgsRelationManager::updateRelationsStatus );
440 [ = ](
const QList<QgsMapLayer *> &layers )
442 for ( const auto &layer : layers )
444 connect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager, &QgsRelationManager::updateRelationsStatus );
453#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
454 mStyleSettings->combinedStyleModel()->addDefaultStyle();
461 mIsBeingDeleted =
true;
464 delete mBadLayerHandler;
465 delete mRelationManager;
466 delete mLayerTreeRegistryBridge;
468 if (
this == sProject )
497 mProjectScope.reset();
505 return mMetadata.
title();
512 if ( oldEvaluateDefaultValues != newEvaluateDefaultValues )
515 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
517 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
526 if ( oldTrustLayerMetadata != newTrustLayerMetadata )
529 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
531 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
533 vl->setReadExtentFromXml( newTrustLayerMetadata );
543 Qgis::ProjectFlags newFlags = mFlags;
547 newFlags &= ~(
static_cast< int >( flag ) );
558 return mSaveUserFull;
563 return mSaveDateTime;
578 if ( dirty && mDirtyBlockCount > 0 )
584 if ( mDirty == dirty )
593 if ( path == mHomePath )
597 mCachedHomePath.clear();
598 mProjectScope.reset();
607 const QList<QgsAttributeEditorElement *> elements = parent->
children();
615 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:formcontainers" ).arg( layerId ), container->
name() );
617 if ( !container->
children().empty() )
630 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1" ).arg( layer->layerId() ), layer->name() );
647 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( vlayer->
id() ), fieldName );
662 const QList<QgsLayerTreeGroup *> groupLayers = mRootGroup->
findGroups();
665 translationContext->
registerTranslation( QStringLiteral(
"project:layergroups" ), groupLayer->name() );
669 const QList<QgsRelation> &relations = mRelationManager->
relations().values();
672 translationContext->
registerTranslation( QStringLiteral(
"project:relations" ), relation.name() );
678 mDataDefinedServerProperties = properties;
683 return mDataDefinedServerProperties;
688 switch ( mTransactionMode )
707 switch ( mTransactionMode )
714 commitErrors.append( tr(
"Trying to commit changes without a layer specified. This only works if the transaction mode is buffered" ) );
723 return mEditBufferGroup.
commitChanges( commitErrors, stopEditing );
731 switch ( mTransactionMode )
738 rollbackErrors.append( tr(
"Trying to roll back changes without a layer specified. This only works if the transaction mode is buffered" ) );
741 bool success = vectorLayer->
rollBack( stopEditing );
747 return mEditBufferGroup.
rollBack( rollbackErrors, stopEditing );
755 if ( name == mFile.fileName() )
758 const QString oldHomePath =
homePath();
760 mFile.setFileName( name );
761 mCachedHomePath.clear();
762 mProjectScope.reset();
766 const QString newHomePath =
homePath();
767 if ( newHomePath != oldHomePath )
775 return mFile.fileName();
780 mOriginalPath = path;
785 return mOriginalPath;
790 return QFileInfo( mFile );
803 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
808 return QFileInfo( mFile.fileName() ).lastModified();
817 if ( mFile.fileName().isEmpty() )
820 return QFileInfo( mFile.fileName() ).absolutePath();
828 if ( mFile.fileName().isEmpty() )
831 return QFileInfo( mFile.fileName() ).absoluteFilePath();
839 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
844 return QFileInfo( mFile.fileName() ).completeBaseName();
850 const bool absolutePaths =
readBoolEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
859 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
true );
862 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
877 writeEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ),
crs.
isValid() ? 1 : 0 );
878 mProjectScope.reset();
889 if ( adjustEllipsoid )
895 if ( !
crs().isValid() )
898 return readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ),
geoNone() );
903 if (
ellipsoid ==
readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ) ) )
906 mProjectScope.reset();
913 return mTransformContext;
918 if ( context == mTransformContext )
921 mTransformContext = context;
922 mProjectScope.reset();
925 for (
auto &layer : mLayerStore.get()->mapLayers() )
927 layer->setTransformContext( context );
934 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
936 mProjectScope.reset();
937 mFile.setFileName( QString() );
940 mSaveUserFull.clear();
941 mSaveDateTime = QDateTime();
944 mCachedHomePath.clear();
946 mFlags = Qgis::ProjectFlags();
948 mCustomVariables.clear();
951 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_new_projects" ),
false,
QgsSettings::Core ).toBool() )
962 mEmbeddedLayers.clear();
963 mRelationManager->
clear();
964 mAnnotationManager->clear();
965 mLayoutManager->clear();
966 m3DViewsManager->clear();
967 mBookmarkManager->
clear();
968 mViewSettings->
reset();
969 mTimeSettings->
reset();
970 mElevationProperties->
reset();
971 mDisplaySettings->
reset();
972 mSnappingConfig.
reset();
980 mLabelingEngineSettings->clear();
986 mStyleSettings->
reset();
990 if ( !mIsBeingDeleted )
998 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/Automatic" ),
true );
999 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/DecimalPlaces" ), 2 );
1001 const bool defaultRelativePaths = mSettings.
value( QStringLiteral(
"/qgis/defaultProjectPathsRelative" ),
true ).toBool();
1005 writeEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), mSettings.
value( QStringLiteral(
"/qgis/measure/displayunits" ) ).toString() );
1006 writeEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), mSettings.
value( QStringLiteral(
"/qgis/measure/areaunits" ) ).toString() );
1008 int red = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_red" ), 255 ).toInt();
1009 int green = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_green" ), 255 ).toInt();
1010 int blue = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_blue" ), 255 ).toInt();
1013 red = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_red" ), 255 ).toInt();
1014 green = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_green" ), 255 ).toInt();
1015 blue = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_blue" ), 0 ).toInt();
1016 const int alpha = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_alpha" ), 255 ).toInt();
1022 mRootGroup->
clear();
1023 if ( mMainAnnotationLayer )
1024 mMainAnnotationLayer->
reset();
1026 snapSingleBlocker.release();
1028 if ( !mBlockSnappingUpdates )
1040 topQgsPropertyKey.
dump();
1073 const QDomElement propertiesElem = doc.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
1075 if ( propertiesElem.isNull() )
1080 const QDomNodeList scopes = propertiesElem.childNodes();
1082 if ( propertiesElem.firstChild().isNull() )
1084 QgsDebugMsg( QStringLiteral(
"empty ``properties'' XML tag ... bailing" ) );
1088 if ( ! project_properties.
readXml( propertiesElem ) )
1090 QgsDebugMsg( QStringLiteral(
"Project_properties.readXml() failed" ) );
1104 const QDomElement ddElem = doc.documentElement().firstChildElement( QStringLiteral(
"dataDefinedServerProperties" ) );
1105 if ( !ddElem.isNull() )
1107 if ( !ddServerProperties.
readXml( ddElem, dataDefinedServerPropertyDefinitions ) )
1109 QgsDebugMsg( QStringLiteral(
"dataDefinedServerProperties.readXml() failed" ) );
1112 return ddServerProperties;
1119static void _getTitle(
const QDomDocument &doc, QString &title )
1121 const QDomElement titleNode = doc.documentElement().firstChildElement( QStringLiteral(
"title" ) );
1125 if ( titleNode.isNull() )
1131 if ( !titleNode.hasChildNodes() )
1137 const QDomNode titleTextNode = titleNode.firstChild();
1139 if ( !titleTextNode.isText() )
1145 const QDomText titleText = titleTextNode.toText();
1147 title = titleText.data();
1151static void readProjectFileMetadata(
const QDomDocument &doc, QString &lastUser, QString &lastUserFull, QDateTime &lastSaveDateTime )
1153 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1157 QgsDebugMsg( QStringLiteral(
"unable to find qgis element" ) );
1161 const QDomNode qgisNode = nl.item( 0 );
1163 const QDomElement qgisElement = qgisNode.toElement();
1164 lastUser = qgisElement.attribute( QStringLiteral(
"saveUser" ), QString() );
1165 lastUserFull = qgisElement.attribute( QStringLiteral(
"saveUserFull" ), QString() );
1166 lastSaveDateTime = QDateTime::fromString( qgisElement.attribute( QStringLiteral(
"saveDateTime" ), QString() ), Qt::ISODate );
1172 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1176 QgsDebugMsg( QStringLiteral(
" unable to find qgis element in project file" ) );
1180 const QDomNode qgisNode = nl.item( 0 );
1182 const QDomElement qgisElement = qgisNode.toElement();
1183 QgsProjectVersion projectVersion( qgisElement.attribute( QStringLiteral(
"version" ) ) );
1184 return projectVersion;
1190 return mSnappingConfig;
1205 if ( mAvoidIntersectionsMode == mode )
1208 mAvoidIntersectionsMode = mode;
1212bool QgsProject::_getMapLayers(
const QDomDocument &doc, QList<QDomNode> &brokenNodes, Qgis::ProjectReadFlags flags )
1217 QDomElement layerElement = doc.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
1221 if ( layerElement.isNull() )
1231 bool returnStatus =
true;
1234 while ( ! layerElement.isNull() )
1237 layerElement = layerElement.nextSiblingElement( QStringLiteral(
"maplayer" ) );
1243 if ( depSorter.hasCycle() )
1247 if ( depSorter.hasMissingDependency() )
1248 returnStatus =
false;
1252 const QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
1253 const int totalLayerCount = sortedLayerNodes.count();
1256 for (
const QDomNode &node : sortedLayerNodes )
1258 const QDomElement element = node.toElement();
1260 const QString name =
translate( QStringLiteral(
"project:layers:%1" ).arg( node.namedItem( QStringLiteral(
"id" ) ).toElement().text() ), node.namedItem( QStringLiteral(
"layername" ) ).toElement().text() );
1261 if ( !name.isNull() )
1262 emit
loadingLayer( tr(
"Loading layer %1" ).arg( name ) );
1264 profile.switchTask( name );
1266 if ( element.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
1268 createEmbeddedLayer( element.attribute( QStringLiteral(
"id" ) ),
readPath( element.attribute( QStringLiteral(
"project" ) ) ), brokenNodes,
true,
flags );
1277 if ( !addLayer( element, brokenNodes, context,
flags ) )
1279 returnStatus =
false;
1282 if ( !messages.isEmpty() )
1291 return returnStatus;
1294bool QgsProject::addLayer(
const QDomElement &layerElem, QList<QDomNode> &brokenNodes,
QgsReadWriteContext &context, Qgis::ProjectReadFlags flags )
1296 const QString type = layerElem.attribute( QStringLiteral(
"type" ) );
1298 std::unique_ptr<QgsMapLayer>
mapLayer;
1306 QgsDebugMsg( QStringLiteral(
"Unknown layer type \"%1\"" ).arg( type ) );
1310 switch ( layerType )
1314 mapLayer = std::make_unique<QgsVectorLayer>();
1324 mapLayer = std::make_unique<QgsRasterLayer>();
1328 mapLayer = std::make_unique<QgsMeshLayer>();
1332 mapLayer = std::make_unique<QgsVectorTileLayer>();
1336 mapLayer = std::make_unique<QgsPointCloudLayer>();
1341 const QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
1349 mapLayer = std::make_unique<QgsAnnotationLayer>( QString(), options );
1356 mapLayer = std::make_unique<QgsGroupLayer>( QString(), options );
1363 QgsDebugMsg( QStringLiteral(
"Unable to create layer" ) );
1371 const QString layerId { layerElem.namedItem( QStringLiteral(
"id" ) ).toElement().text() };
1372 Q_ASSERT( ! layerId.isEmpty() );
1376 QgsMapLayer::ReadFlags layerFlags = QgsMapLayer::ReadFlags();
1377 if (
flags & Qgis::ProjectReadFlag::DontResolveLayers )
1383 profile.switchTask( tr(
"Load layer source" ) );
1386 profile.switchTask( tr(
"Add layer to project" ) );
1387 QList<QgsMapLayer *> newLayers;
1389 if ( layerIsValid ||
flags & Qgis::ProjectReadFlag::DontResolveLayers )
1399 vLayer->joinBuffer()->resolveReferences(
this );
1407 QgsDebugMsg(
"Unable to load " + type +
" layer" );
1408 brokenNodes.push_back( layerElem );
1411 const bool wasEditable = layerElem.attribute( QStringLiteral(
"editable" ), QStringLiteral(
"0" ) ).toInt();
1423 if ( ! layerWasStored )
1428 return layerIsValid;
1433 mFile.setFileName( filename );
1434 mCachedHomePath.clear();
1435 mProjectScope.reset();
1442 const QString filename = mFile.fileName();
1447 QTemporaryFile inDevice;
1448 if ( !inDevice.open() )
1450 setError( tr(
"Unable to open %1" ).arg( inDevice.fileName() ) );
1456 if ( !storage->readProject( filename, &inDevice, context ) )
1458 QString err = tr(
"Unable to open %1" ).arg( filename );
1459 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
1460 if ( !messages.isEmpty() )
1461 err += QStringLiteral(
"\n\n" ) + messages.last().message();
1465 returnValue = unzip( inDevice.fileName(),
flags );
1471 returnValue = unzip( mFile.fileName(),
flags );
1476 const QFileInfo finfo( mFile.fileName() );
1477 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
1478 if ( QFile( attachmentsZip ).exists() )
1480 std::unique_ptr<QgsArchive> archive(
new QgsArchive() );
1481 if ( archive->unzip( attachmentsZip ) )
1483 mArchive = std::move( archive );
1486 returnValue = readProjectFile( mFile.fileName(),
flags );
1492 mFile.setFileName( filename );
1493 mCachedHomePath.clear();
1494 mProjectScope.reset();
1499 mTranslator.reset(
nullptr );
1506bool QgsProject::readProjectFile(
const QString &filename, Qgis::ProjectReadFlags flags )
1509 ScopedIntIncrementor snapSignalBlock( &mBlockSnappingUpdates );
1511 QFile projectFile( filename );
1519 if ( QFile( QStringLiteral(
"%1/%2.qm" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) ).exists() )
1521 mTranslator.reset(
new QTranslator() );
1522 ( void )mTranslator->load( localeFileName, QFileInfo( projectFile.fileName() ).absolutePath() );
1525 profile.switchTask( tr(
"Reading project file" ) );
1526 std::unique_ptr<QDomDocument> doc(
new QDomDocument( QStringLiteral(
"qgis" ) ) );
1528 if ( !projectFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
1530 projectFile.close();
1532 setError( tr(
"Unable to open %1" ).arg( projectFile.fileName() ) );
1541 if ( !doc->setContent( &projectFile, &errorMsg, &line, &column ) )
1543 const QString errorString = tr(
"Project file read error in file %1: %2 at line %3 column %4" )
1544 .arg( projectFile.fileName(), errorMsg ).arg( line ).arg( column );
1548 projectFile.close();
1550 setError( tr(
"%1 for file %2" ).arg( errorString, projectFile.fileName() ) );
1555 projectFile.close();
1563 profile.switchTask( tr(
"Updating project file" ) );
1564 if ( thisVersion > fileVersion )
1566 const bool isOlderMajorVersion = fileVersion.
majorVersion() < thisVersion.majorVersion();
1568 if ( isOlderMajorVersion )
1571 "version of qgis (saved in " + fileVersion.
text() +
1573 "). Problems may occur." );
1584 projectFile.updateRevision( thisVersion );
1586 else if ( fileVersion > thisVersion )
1589 "version of qgis (saved in " + fileVersion.
text() +
1591 "). Problems may occur." );
1597 profile.switchTask( tr(
"Creating auxiliary storage" ) );
1598 const QString
fileName = mFile.fileName();
1599 std::unique_ptr<QgsAuxiliaryStorage> aStorage = std::move( mAuxiliaryStorage );
1600 std::unique_ptr<QgsArchive> archive = std::move( mArchive );
1602 mAuxiliaryStorage = std::move( aStorage );
1603 mArchive = std::move( archive );
1605 mCachedHomePath.clear();
1606 mProjectScope.reset();
1607 mSaveVersion = fileVersion;
1610 profile.switchTask( tr(
"Reading properties" ) );
1619 dump_( mProperties );
1624 _getTitle( *doc, oldTitle );
1626 readProjectFileMetadata( *doc, mSaveUser, mSaveUserFull, mSaveDateTime );
1628 const QDomNodeList homePathNl = doc->elementsByTagName( QStringLiteral(
"homePath" ) );
1629 if ( homePathNl.count() > 0 )
1631 const QDomElement homePathElement = homePathNl.at( 0 ).toElement();
1632 const QString
homePath = homePathElement.attribute( QStringLiteral(
"path" ) );
1642 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), 255 ),
1643 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), 255 ) );
1646 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), 255 ),
1647 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), 255 ),
1648 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), 255 ) );
1657 if (
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ), 0 ) )
1660 const QDomNode srsNode = doc->documentElement().namedItem( QStringLiteral(
"projectCrs" ) );
1661 if ( !srsNode.isNull() )
1663 projectCrs.
readXml( srsNode );
1668 const QString projCrsString =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSProj4String" ) );
1669 const long currentCRS =
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSID" ), -1 );
1670 const QString authid =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCrs" ) );
1673 const bool isUserAuthId = authid.startsWith( QLatin1String(
"USER:" ), Qt::CaseInsensitive );
1674 if ( !authid.isEmpty() && !isUserAuthId )
1678 if ( !projectCrs.
isValid() && currentCRS >= 0 )
1684 if ( !projCrsString.isEmpty() && ( authid.isEmpty() || isUserAuthId ) && ( !projectCrs.
isValid() || projectCrs.
toProj() != projCrsString ) )
1698 QStringList datumErrors;
1699 if ( !mTransformContext.
readXml( doc->documentElement(), context, datumErrors ) && !datumErrors.empty() )
1707 const QStringList variableNames =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ) );
1708 const QStringList variableValues =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ) );
1710 mCustomVariables.clear();
1711 if ( variableNames.length() == variableValues.length() )
1713 for (
int i = 0; i < variableNames.length(); ++i )
1715 mCustomVariables.insert( variableNames.at( i ), variableValues.at( i ) );
1720 QgsMessageLog::logMessage( tr(
"Project Variables Invalid" ), tr(
"The project contains invalid variable settings." ) );
1723 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectMetadata" ) );
1725 if ( !element.isNull() )
1734 if ( mMetadata.
title().isEmpty() && !oldTitle.isEmpty() )
1742 element = doc->documentElement().firstChildElement( QStringLiteral(
"transaction" ) );
1743 if ( !element.isNull() )
1750 element = doc->documentElement().firstChildElement( QStringLiteral(
"autotransaction" ) );
1751 if ( ! element.isNull() )
1753 mTransactionMode =
static_cast<Qgis::TransactionMode>( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() );
1757 element = doc->documentElement().firstChildElement( QStringLiteral(
"projectFlags" ) );
1758 if ( !element.isNull() )
1760 mFlags =
qgsFlagKeysToValue( element.attribute( QStringLiteral(
"set" ) ), Qgis::ProjectFlags() );
1765 element = doc->documentElement().firstChildElement( QStringLiteral(
"evaluateDefaultValues" ) );
1766 if ( !element.isNull() )
1768 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
1773 element = doc->documentElement().firstChildElement( QStringLiteral(
"trust" ) );
1774 if ( !element.isNull() )
1776 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
1782 profile.switchTask( tr(
"Loading layer tree" ) );
1785 QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
1786 if ( !layerTreeElem.isNull() )
1798 mLayerTreeRegistryBridge->
setEnabled(
false );
1801 profile.switchTask( tr(
"Reading map layers" ) );
1803 QList<QDomNode> brokenNodes;
1804 const bool clean = _getMapLayers( *doc, brokenNodes,
flags );
1807 if ( !clean && !(
flags & Qgis::ProjectReadFlag::DontResolveLayers ) )
1809 QgsDebugMsg( QStringLiteral(
"Unable to get map layers from project file." ) );
1811 if ( !brokenNodes.isEmpty() )
1813 QgsDebugMsg(
"there are " + QString::number( brokenNodes.size() ) +
" broken layers" );
1821 mMainAnnotationLayer->
readLayerXml( doc->documentElement().firstChildElement( QStringLiteral(
"main-annotation-layer" ) ), context );
1825 profile.switchTask( tr(
"Loading embedded layers" ) );
1826 loadEmbeddedNodes( mRootGroup,
flags );
1830 profile.switchTask( tr(
"Resolving layer references" ) );
1831 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
1832 for ( QMap<QString, QgsMapLayer *>::iterator it =
layers.begin(); it !=
layers.end(); ++it )
1834 it.value()->resolveReferences(
this );
1837 mLayerTreeRegistryBridge->
setEnabled(
true );
1840 profile.switchTask( tr(
"Resolving references" ) );
1843 if ( !layerTreeElem.isNull() )
1849 const QDomElement layerTreeCanvasElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-canvas" ) );
1850 if ( !layerTreeCanvasElem.isNull( ) )
1858 const QStringList requiredLayerIds =
readListEntry( QStringLiteral(
"RequiredLayers" ), QStringLiteral(
"Layers" ) );
1859 for (
const QString &layerId : requiredLayerIds )
1866 const QStringList disabledLayerIds =
readListEntry( QStringLiteral(
"Identify" ), QStringLiteral(
"/disabledLayers" ) );
1867 for (
const QString &layerId : disabledLayerIds )
1880 QString styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1881 if ( !styleName.isEmpty() )
1886 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
1887 if ( !styleName.isEmpty() )
1892 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
1893 if ( !styleName.isEmpty() )
1898 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
1899 if ( !styleName.isEmpty() )
1909 double opacity = 1.0;
1912 double alpha =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ), 255, &ok );
1914 opacity = alpha / 255.0;
1915 double newOpacity =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ), 1.0, &ok );
1917 opacity = newOpacity;
1921 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1922 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
1923 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
1924 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
1925 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/RandomColors" ) );
1926 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ) );
1927 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ) );
1933 if ( !(
flags & Qgis::ProjectReadFlag::DontStoreOriginalStyles ) )
1935 profile.switchTask( tr(
"Storing original layer properties" ) );
1941 profile.switchTask( tr(
"Loading map themes" ) );
1944 mMapThemeCollection->readXml( *doc );
1946 profile.switchTask( tr(
"Loading label settings" ) );
1947 mLabelingEngineSettings->readSettingsFromProject(
this );
1950 profile.switchTask( tr(
"Loading annotations" ) );
1951 mAnnotationManager->readXml( doc->documentElement(), context );
1952 if ( !(
flags & Qgis::ProjectReadFlag::DontLoadLayouts ) )
1954 profile.switchTask( tr(
"Loading layouts" ) );
1955 mLayoutManager->readXml( doc->documentElement(), *doc );
1958 if ( !(
flags & Qgis::ProjectReadFlag::DontLoad3DViews ) )
1960 profile.switchTask( tr(
"Loading 3D Views" ) );
1961 m3DViewsManager->readXml( doc->documentElement(), *doc );
1964 profile.switchTask( tr(
"Loading bookmarks" ) );
1965 mBookmarkManager->
readXml( doc->documentElement(), *doc );
1968 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
1969 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); ++it )
1971 it.value()->setDependencies( it.value()->dependencies() );
1974 profile.switchTask( tr(
"Loading snapping settings" ) );
1978 profile.switchTask( tr(
"Loading view settings" ) );
1981 const QStringList scales =
readListEntry( QStringLiteral(
"Scales" ), QStringLiteral(
"/ScalesList" ) );
1982 QVector<double> res;
1983 for (
const QString &scale : scales )
1985 const QStringList parts = scale.split(
':' );
1986 if ( parts.size() != 2 )
1990 const double denominator = QLocale().toDouble( parts[1], &ok );
1997 const QDomElement viewSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectViewSettings" ) );
1998 if ( !viewSettingsElement.isNull() )
1999 mViewSettings->
readXml( viewSettingsElement, context );
2002 profile.switchTask( tr(
"Loading style properties" ) );
2003 const QDomElement styleSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectStyleSettings" ) );
2004 if ( !styleSettingsElement.isNull() )
2005 mStyleSettings->
readXml( styleSettingsElement, context,
flags );
2008 profile.switchTask( tr(
"Loading temporal settings" ) );
2009 const QDomElement timeSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectTimeSettings" ) );
2010 if ( !timeSettingsElement.isNull() )
2011 mTimeSettings->
readXml( timeSettingsElement, context );
2014 profile.switchTask( tr(
"Loading elevation properties" ) );
2015 const QDomElement elevationPropertiesElement = doc->documentElement().firstChildElement( QStringLiteral(
"ElevationProperties" ) );
2016 if ( !elevationPropertiesElement.isNull() )
2017 mElevationProperties->
readXml( elevationPropertiesElement, context );
2020 profile.switchTask( tr(
"Loading display settings" ) );
2021 const QDomElement displaySettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectDisplaySettings" ) );
2022 if ( !displaySettingsElement.isNull() )
2023 mDisplaySettings->
readXml( displaySettingsElement, context );
2025 profile.switchTask( tr(
"Updating variables" ) );
2027 profile.switchTask( tr(
"Updating CRS" ) );
2032 profile.switchTask( tr(
"Reading external settings" ) );
2036 profile.switchTask( tr(
"Updating interface" ) );
2038 snapSignalBlock.release();
2039 if ( !mBlockSnappingUpdates )
2050 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUser ), 2 );
2051 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUserFull ), 2 );
2060 const QString newFileName( QStringLiteral(
"%1/%2.qgs" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) );
2066 QgsMessageLog::logMessage( tr(
"Translated project saved with locale prefix %1" ).arg( newFileName ), QObject::tr(
"Project translation" ), Qgis::MessageLevel::Success );
2070 QgsMessageLog::logMessage( tr(
"Error saving translated project with locale prefix %1" ).arg( newFileName ), QObject::tr(
"Project translation" ), Qgis::MessageLevel::Critical );
2075 const QMap<QString, QgsMapLayer *> loadedLayers =
mapLayers();
2076 for (
auto it = loadedLayers.constBegin(); it != loadedLayers.constEnd(); ++it )
2078 if ( it.value()->isValid() && it.value()->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2080 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( it.value() ) )
2082 it.value()->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2090bool QgsProject::loadEmbeddedNodes(
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
2093 const auto constChildren = group->
children();
2099 if ( childGroup->
customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2102 const QString projectPath =
readPath( childGroup->
customProperty( QStringLiteral(
"embedded_project" ) ).toString() );
2103 childGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectPath );
2107 QList<QgsLayerTreeNode *> clonedChildren;
2108 const QList<QgsLayerTreeNode *> constChildren = newGroup->
children();
2109 clonedChildren.reserve( constChildren.size() );
2111 clonedChildren << newGroupChild->clone();
2119 loadEmbeddedNodes( childGroup,
flags );
2124 if ( child->customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2126 QList<QDomNode> brokenNodes;
2129 valid = valid &&
false;
2141 return mCustomVariables;
2146 if ( variables == mCustomVariables )
2150 QStringList variableNames;
2151 QStringList variableValues;
2153 QVariantMap::const_iterator it = variables.constBegin();
2154 for ( ; it != variables.constEnd(); ++it )
2156 variableNames << it.key();
2157 variableValues << it.value().toString();
2160 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ), variableNames );
2161 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ), variableValues );
2163 mCustomVariables = variables;
2164 mProjectScope.reset();
2171 *mLabelingEngineSettings = settings;
2177 return *mLabelingEngineSettings;
2182 mProjectScope.reset();
2183 return mLayerStore.get();
2188 return mLayerStore.get();
2193 QList<QgsVectorLayer *>
layers;
2194 const QStringList layerIds =
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), QStringList() );
2195 const auto constLayerIds = layerIds;
2196 for (
const QString &layerId : constLayerIds )
2207 list.reserve(
layers.size() );
2209 list << layer->id();
2210 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), list );
2227 if ( mProjectScope )
2229 std::unique_ptr< QgsExpressionContextScope > projectScope = std::make_unique< QgsExpressionContextScope >( *mProjectScope );
2233 return projectScope.release();
2236 mProjectScope = std::make_unique< QgsExpressionContextScope >( QObject::tr(
"Project" ) );
2240 QVariantMap::const_iterator it = vars.constBegin();
2242 for ( ; it != vars.constEnd(); ++it )
2244 mProjectScope->setVariable( it.key(), it.value(),
true );
2248 if ( projectPath.isEmpty() )
2249 projectPath = mOriginalPath;
2250 const QString projectFolder = QFileInfo( projectPath ).path();
2251 const QString projectFilename = QFileInfo( projectPath ).fileName();
2252 const QString projectBasename =
baseName();
2281 QVariantMap keywords;
2283 for (
auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
2285 keywords.insert( it.key(), it.value() );
2290 QVariantList layersIds;
2292 const QMap<QString, QgsMapLayer *> layersInProject = mLayerStore->mapLayers();
2293 layersIds.reserve( layersInProject.count() );
2294 layers.reserve( layersInProject.count() );
2295 for (
auto it = layersInProject.constBegin(); it != layersInProject.constEnd(); ++it )
2297 layersIds << it.value()->id();
2303 mProjectScope->addFunction( QStringLiteral(
"project_color" ),
new GetNamedProjectColor(
this ) );
2308void QgsProject::onMapLayersAdded(
const QList<QgsMapLayer *> &layers )
2310 const QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2312 const auto constLayers =
layers;
2315 if ( ! layer->isValid() )
2321 for ( QMap<QString, QgsMapLayer *>::const_iterator it = existingMaps.cbegin(); it != existingMaps.cend(); ++it )
2323 const QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
2324 if ( deps.contains( layer->id() ) )
2327 it.value()->setDependencies( deps );
2332 updateTransactionGroups();
2338void QgsProject::onMapLayersRemoved(
const QList<QgsMapLayer *> &layers )
2344void QgsProject::cleanTransactionGroups(
bool force )
2346 bool changed =
false;
2347 for ( QMap< QPair< QString, QString>,
QgsTransactionGroup *>::Iterator tg = mTransactionGroups.begin(); tg != mTransactionGroups.end(); )
2349 if ( tg.value()->isEmpty() || force )
2352 tg = mTransactionGroups.erase( tg );
2364void QgsProject::updateTransactionGroups()
2366 mEditBufferGroup.
clear();
2368 switch ( mTransactionMode )
2372 cleanTransactionGroups(
true );
2377 cleanTransactionGroups(
true );
2380 cleanTransactionGroups(
false );
2384 bool tgChanged =
false;
2385 const auto constLayers =
mapLayers().values();
2388 if ( ! layer->isValid() )
2391 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
2395 switch ( mTransactionMode )
2412 mTransactionGroups.insert( qMakePair( key, connString ), tg );
2422 mEditBufferGroup.
addLayer( vlayer );
2438 QList<QDomNode> brokenNodes;
2439 if ( addLayer( layerNode.toElement(), brokenNodes, context ) )
2443 const QVector<QgsVectorLayer *> vectorLayers = layers<QgsVectorLayer *>();
2447 layer->resolveReferences(
this );
2449 if ( layer->isValid() && layer->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2451 layer->startEditing();
2452 layer->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2462 mFile.setFileName( filename );
2463 mCachedHomePath.clear();
2469 mProjectScope.reset();
2475 const QString storageFilePath { storage->filePath( mFile.fileName() ) };
2476 if ( storageFilePath.isEmpty() )
2482 const QString tempPath = QStandardPaths::standardLocations( QStandardPaths::TempLocation ).at( 0 );
2483 const QString tmpZipFilename( tempPath + QDir::separator() + QUuid::createUuid().toString() );
2485 if ( !zip( tmpZipFilename ) )
2488 QFile tmpZipFile( tmpZipFilename );
2489 if ( !tmpZipFile.open( QIODevice::ReadOnly ) )
2491 setError( tr(
"Unable to read file %1" ).arg( tmpZipFilename ) );
2496 if ( !storage->writeProject( mFile.fileName(), &tmpZipFile, context ) )
2498 QString err = tr(
"Unable to save project to storage %1" ).arg( mFile.fileName() );
2499 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
2500 if ( !messages.isEmpty() )
2501 err += QStringLiteral(
"\n\n" ) + messages.last().message();
2507 QFile::remove( tmpZipFilename );
2514 return zip( mFile.fileName() );
2520 const bool asOk = saveAuxiliaryStorage();
2521 const bool writeOk = writeProjectFile( mFile.fileName() );
2522 bool attachmentsOk =
true;
2523 if ( !mArchive->files().isEmpty() )
2525 const QFileInfo finfo( mFile.fileName() );
2526 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
2527 attachmentsOk = mArchive->zip( attachmentsZip );
2531 if ( ( !asOk || !attachmentsOk ) && writeOk )
2533 QStringList errorMessage;
2536 const QString err = mAuxiliaryStorage->errorString();
2537 errorMessage.append( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
2539 if ( !attachmentsOk )
2541 errorMessage.append( tr(
"Unable to save attachments archive" ) );
2543 setError( errorMessage.join(
'\n' ) );
2546 return asOk && writeOk && attachmentsOk;
2550bool QgsProject::writeProjectFile(
const QString &filename )
2552 QFile projectFile( filename );
2558 const QFileInfo myFileInfo( projectFile );
2559 if ( myFileInfo.exists() && !myFileInfo.isWritable() )
2561 setError( tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
2562 .arg( projectFile.fileName() ) );
2570 QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
2572 const QDomDocumentType documentType =
2573 QDomImplementation().createDocumentType( QStringLiteral(
"qgis" ), QStringLiteral(
"http://mrcc.com/qgis.dtd" ),
2574 QStringLiteral(
"SYSTEM" ) );
2575 std::unique_ptr<QDomDocument> doc(
new QDomDocument( documentType ) );
2577 QDomElement qgisNode = doc->createElement( QStringLiteral(
"qgis" ) );
2578 qgisNode.setAttribute( QStringLiteral(
"projectname" ),
title() );
2579 qgisNode.setAttribute( QStringLiteral(
"version" ),
Qgis::version() );
2581 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_saved_projects" ),
false,
QgsSettings::Core ).toBool() )
2585 qgisNode.setAttribute( QStringLiteral(
"saveUser" ), newSaveUser );
2586 qgisNode.setAttribute( QStringLiteral(
"saveUserFull" ), newSaveUserFull );
2587 mSaveUser = newSaveUser;
2588 mSaveUserFull = newSaveUserFull;
2589 mSaveDateTime = QDateTime::currentDateTime();
2590 qgisNode.setAttribute( QStringLiteral(
"saveDateTime" ), mSaveDateTime.toString( Qt::ISODate ) );
2595 mSaveUserFull.clear();
2596 mSaveDateTime = QDateTime();
2598 doc->appendChild( qgisNode );
2601 QDomElement homePathNode = doc->createElement( QStringLiteral(
"homePath" ) );
2602 homePathNode.setAttribute( QStringLiteral(
"path" ), mHomePath );
2603 qgisNode.appendChild( homePathNode );
2606 QDomElement titleNode = doc->createElement( QStringLiteral(
"title" ) );
2607 qgisNode.appendChild( titleNode );
2609 QDomElement transactionNode = doc->createElement( QStringLiteral(
"transaction" ) );
2610 transactionNode.setAttribute( QStringLiteral(
"mode" ),
qgsEnumValueToKey( mTransactionMode ) );
2611 qgisNode.appendChild( transactionNode );
2613 QDomElement flagsNode = doc->createElement( QStringLiteral(
"projectFlags" ) );
2615 qgisNode.appendChild( flagsNode );
2617 const QDomText titleText = doc->createTextNode(
title() );
2618 titleNode.appendChild( titleText );
2621 QDomElement srsNode = doc->createElement( QStringLiteral(
"projectCrs" ) );
2623 qgisNode.appendChild( srsNode );
2630 clonedRoot->
writeXml( qgisNode, context );
2634 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsMode" ),
static_cast<int>( mAvoidIntersectionsMode ) );
2642 QDomElement annotationLayerNode = doc->createElement( QStringLiteral(
"main-annotation-layer" ) );
2643 mMainAnnotationLayer->
writeLayerXml( annotationLayerNode, *doc, context );
2644 qgisNode.appendChild( annotationLayerNode );
2648 QDomElement projectLayersNode = doc->createElement( QStringLiteral(
"projectlayers" ) );
2650 QMap<QString, QgsMapLayer *>::ConstIterator li =
layers.constBegin();
2651 while ( li !=
layers.end() )
2657 const QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.constFind( ml->
id() );
2658 if ( emIt == mEmbeddedLayers.constEnd() )
2660 QDomElement maplayerElem;
2666 maplayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2670 maplayerElem.setAttribute( QStringLiteral(
"editable" ), QStringLiteral(
"1" ) );
2674 QDomDocument document;
2677 maplayerElem = document.firstChildElement();
2681 QgsDebugMsg( QStringLiteral(
"Could not restore layer properties for layer %1" ).arg( ml->
id() ) );
2687 projectLayersNode.appendChild( maplayerElem );
2693 if ( emIt.value().second )
2695 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2696 mapLayerElem.setAttribute( QStringLiteral(
"embedded" ), 1 );
2697 mapLayerElem.setAttribute( QStringLiteral(
"project" ),
writePath( emIt.value().first ) );
2698 mapLayerElem.setAttribute( QStringLiteral(
"id" ), ml->
id() );
2699 projectLayersNode.appendChild( mapLayerElem );
2706 qgisNode.appendChild( projectLayersNode );
2708 QDomElement layerOrderNode = doc->createElement( QStringLiteral(
"layerorder" ) );
2710 for (
QgsMapLayer *layer : constCustomLayerOrder )
2712 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"layer" ) );
2713 mapLayerElem.setAttribute( QStringLiteral(
"id" ), layer->id() );
2714 layerOrderNode.appendChild( mapLayerElem );
2716 qgisNode.appendChild( layerOrderNode );
2718 mLabelingEngineSettings->writeSettingsToProject(
this );
2720 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorRedPart" ), mBackgroundColor.red() );
2721 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), mBackgroundColor.green() );
2722 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), mBackgroundColor.blue() );
2724 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorRedPart" ), mSelectionColor.red() );
2725 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), mSelectionColor.green() );
2726 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), mSelectionColor.blue() );
2727 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), mSelectionColor.alpha() );
2731 dump_( mProperties );
2734 QgsDebugMsgLevel( QStringLiteral(
"there are %1 property scopes" ).arg(
static_cast<int>( mProperties.
count() ) ), 2 );
2739 mProperties.
writeXml( QStringLiteral(
"properties" ), qgisNode, *doc );
2742 QDomElement ddElem = doc->createElement( QStringLiteral(
"dataDefinedServerProperties" ) );
2743 mDataDefinedServerProperties.
writeXml( ddElem, dataDefinedServerPropertyDefinitions() );
2744 qgisNode.appendChild( ddElem );
2746 mMapThemeCollection->writeXml( *doc );
2748 mTransformContext.
writeXml( qgisNode, context );
2750 QDomElement metadataElem = doc->createElement( QStringLiteral(
"projectMetadata" ) );
2752 qgisNode.appendChild( metadataElem );
2754 const QDomElement annotationsElem = mAnnotationManager->writeXml( *doc, context );
2755 qgisNode.appendChild( annotationsElem );
2757 const QDomElement layoutElem = mLayoutManager->writeXml( *doc );
2758 qgisNode.appendChild( layoutElem );
2760 const QDomElement views3DElem = m3DViewsManager->writeXml( *doc );
2761 qgisNode.appendChild( views3DElem );
2763 const QDomElement bookmarkElem = mBookmarkManager->
writeXml( *doc );
2764 qgisNode.appendChild( bookmarkElem );
2766 const QDomElement viewSettingsElem = mViewSettings->
writeXml( *doc, context );
2767 qgisNode.appendChild( viewSettingsElem );
2769 const QDomElement styleSettingsElem = mStyleSettings->
writeXml( *doc, context );
2770 qgisNode.appendChild( styleSettingsElem );
2772 const QDomElement timeSettingsElement = mTimeSettings->
writeXml( *doc, context );
2773 qgisNode.appendChild( timeSettingsElement );
2775 const QDomElement elevationPropertiesElement = mElevationProperties->
writeXml( *doc, context );
2776 qgisNode.appendChild( elevationPropertiesElement );
2778 const QDomElement displaySettingsElem = mDisplaySettings->
writeXml( *doc, context );
2779 qgisNode.appendChild( displaySettingsElem );
2787 QFile backupFile( QStringLiteral(
"%1~" ).arg( filename ) );
2789 ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
2790 ok &= projectFile.open( QIODevice::ReadOnly );
2793 while ( ok && !projectFile.atEnd() )
2795 ba = projectFile.read( 10240 );
2796 ok &= backupFile.write( ba ) == ba.size();
2799 projectFile.close();
2804 setError( tr(
"Unable to create backup file %1" ).arg( backupFile.fileName() ) );
2809 struct utimbuf tb = {
static_cast<time_t
>( fi.lastRead().toSecsSinceEpoch() ),
static_cast<time_t
>( fi.lastModified().toSecsSinceEpoch() ) };
2810 utime( backupFile.fileName().toUtf8().constData(), &tb );
2813 if ( !projectFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
2815 projectFile.close();
2818 setError( tr(
"Unable to save to file %1" ).arg( projectFile.fileName() ) );
2822 QTemporaryFile tempFile;
2823 bool ok = tempFile.open();
2826 QTextStream projectFileStream( &tempFile );
2827 doc->save( projectFileStream, 2 );
2828 ok &= projectFileStream.pos() > -1;
2830 ok &= tempFile.seek( 0 );
2833 while ( ok && !tempFile.atEnd() )
2835 ba = tempFile.read( 10240 );
2836 ok &= projectFile.write( ba ) == ba.size();
2839 ok &= projectFile.error() == QFile::NoError;
2841 projectFile.close();
2848 setError( tr(
"Unable to save to file %1. Your project "
2849 "may be corrupted on disk. Try clearing some space on the volume and "
2850 "check file permissions before pressing save again." )
2851 .arg( projectFile.fileName() ) );
2863 bool propertiesModified;
2864 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2866 if ( propertiesModified )
2874 bool propertiesModified;
2875 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2877 if ( propertiesModified )
2885 bool propertiesModified;
2886 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2888 if ( propertiesModified )
2896 bool propertiesModified;
2897 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2899 if ( propertiesModified )
2907 bool propertiesModified;
2908 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2910 if ( propertiesModified )
2918 const QStringList &def,
2927 value =
property->value();
2929 const bool valid = QVariant::StringList == value.type();
2935 return value.toStringList();
2957 value =
property->value();
2959 const bool valid = value.canConvert( QVariant::String );
2964 return value.toString();
2981 value =
property->value();
2984 const bool valid = value.canConvert( QVariant::Int );
2993 return value.toInt();
3006 const QVariant value =
property->value();
3008 const bool valid = value.canConvert( QVariant::Double );
3013 return value.toDouble();
3028 const QVariant value =
property->value();
3030 const bool valid = value.canConvert( QVariant::Bool );
3035 return value.toBool();
3045 if (
findKey_( scope, key, mProperties ) )
3051 return !
findKey_( scope, key, mProperties );
3059 QStringList entries;
3061 if ( foundProperty )
3076 QStringList entries;
3078 if ( foundProperty )
3091 dump_( mProperties );
3109 filePath = storage->filePath( mFile.fileName() );
3132void QgsProject::setError(
const QString &errorMessage )
3134 mErrorMessage = errorMessage;
3139 return mErrorMessage;
3142void QgsProject::clearError()
3144 setError( QString() );
3149 delete mBadLayerHandler;
3150 mBadLayerHandler = handler;
3155 const QHash< QString, QPair< QString, bool > >::const_iterator it = mEmbeddedLayers.find(
id );
3156 if ( it == mEmbeddedLayers.constEnd() )
3160 return it.value().first;
3164 bool saveFlag, Qgis::ProjectReadFlags flags )
3168 static QString sPrevProjectFilePath;
3169 static QDateTime sPrevProjectFileTimestamp;
3170 static QDomDocument sProjectDocument;
3172 QString qgsProjectFile = projectFilePath;
3174 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3176 archive.
unzip( projectFilePath );
3180 const QDateTime projectFileTimestamp = QFileInfo( projectFilePath ).lastModified();
3182 if ( projectFilePath != sPrevProjectFilePath || projectFileTimestamp != sPrevProjectFileTimestamp )
3184 sPrevProjectFilePath.clear();
3186 QFile projectFile( qgsProjectFile );
3187 if ( !projectFile.open( QIODevice::ReadOnly ) )
3192 if ( !sProjectDocument.setContent( &projectFile ) )
3197 sPrevProjectFilePath = projectFilePath;
3198 sPrevProjectFileTimestamp = projectFileTimestamp;
3202 bool useAbsolutePaths =
true;
3204 const QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
3205 if ( !propertiesElem.isNull() )
3207 const QDomElement absElem = propertiesElem.firstChildElement( QStringLiteral(
"Paths" ) ).firstChildElement( QStringLiteral(
"Absolute" ) );
3208 if ( !absElem.isNull() )
3210 useAbsolutePaths = absElem.text().compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0;
3215 if ( !useAbsolutePaths )
3220 const QDomElement projectLayersElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) );
3221 if ( projectLayersElem.isNull() )
3226 QDomElement mapLayerElem = projectLayersElem.firstChildElement( QStringLiteral(
"maplayer" ) );
3227 while ( ! mapLayerElem.isNull() )
3230 const QString
id = mapLayerElem.firstChildElement( QStringLiteral(
"id" ) ).text();
3231 if (
id == layerId )
3234 if ( mapLayerElem.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
3239 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
3241 if ( addLayer( mapLayerElem, brokenNodes, embeddedContext,
flags ) )
3247 mEmbeddedLayers.remove( layerId );
3251 mapLayerElem = mapLayerElem.nextSiblingElement( QStringLiteral(
"maplayer" ) );
3260 QString qgsProjectFile = projectFilePath;
3262 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3264 archive.
unzip( projectFilePath );
3269 QFile projectFile( qgsProjectFile );
3270 if ( !projectFile.open( QIODevice::ReadOnly ) )
3275 QDomDocument projectDocument;
3276 if ( !projectDocument.setContent( &projectFile ) )
3288 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
3289 if ( !layerTreeElem.isNull() )
3299 if ( !group || group->
customProperty( QStringLiteral(
"embedded" ) ).toBool() )
3312 newGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectFilePath );
3315 mLayerTreeRegistryBridge->
setEnabled(
false );
3316 initializeEmbeddedSubtree( projectFilePath, newGroup,
flags );
3317 mLayerTreeRegistryBridge->
setEnabled(
true );
3320 const auto constFindLayerIds = newGroup->
findLayerIds();
3321 for (
const QString &layerId : constFindLayerIds )
3334void QgsProject::initializeEmbeddedSubtree(
const QString &projectFilePath,
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
3336 const auto constChildren = group->
children();
3340 child->setCustomProperty( QStringLiteral(
"embedded" ), 1 );
3349 QList<QDomNode> brokenNodes;
3367 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), ( enabled ? 1 : 0 ) );
3373 return readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), 0 );
3378 const QString distanceUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), QString() );
3379 if ( !distanceUnitString.isEmpty() )
3395 const QString areaUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), QString() );
3396 if ( !areaUnitString.isEmpty() )
3412 if ( !mCachedHomePath.isEmpty() )
3413 return mCachedHomePath;
3417 if ( !mHomePath.isEmpty() )
3419 const QFileInfo homeInfo( mHomePath );
3420 if ( !homeInfo.isRelative() )
3422 mCachedHomePath = mHomePath;
3428 mCachedHomePath = pfi.path();
3430 return mCachedHomePath;
3433 if ( !pfi.exists() )
3435 mCachedHomePath = mHomePath;
3439 if ( !mHomePath.isEmpty() )
3442 mCachedHomePath = QDir::cleanPath( pfi.path() +
'/' + mHomePath );
3446 mCachedHomePath = pfi.canonicalPath();
3448 return mCachedHomePath;
3458 return mRelationManager;
3463 return mLayoutManager.get();
3468 return mLayoutManager.get();
3473 return m3DViewsManager.get();
3478 return m3DViewsManager.get();
3483 return mBookmarkManager;
3488 return mBookmarkManager;
3493 return mViewSettings;
3498 return mViewSettings;
3503 return mStyleSettings;
3508 return mStyleSettings;
3513 return mTimeSettings;
3518 return mTimeSettings;
3523 return mElevationProperties;
3528 return mElevationProperties;
3533 return mDisplaySettings;
3538 return mDisplaySettings;
3548 return mMapThemeCollection.get();
3553 return mAnnotationManager.get();
3558 return mAnnotationManager.get();
3563 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
3564 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
3569 if (
layers.contains( it.value() ) )
3584 for (
const QString &layerId : layerIds )
3600 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
3630 updateTransactionGroups();
3635 return mTransactionMode;
3644 const auto constLayers =
mapLayers().values();
3647 if ( layer->isEditable() )
3649 QgsLogger::warning( tr(
"Transaction mode can be changed only if all layers are not editable." ) );
3655 updateTransactionGroups();
3661 return mTransactionGroups;
3672 return mLayerStore->count();
3677 return mLayerStore->validCount();
3682 return mLayerStore->mapLayer( layerId );
3687 return mLayerStore->mapLayersByName( layerName );
3692 QList<QgsMapLayer *>
layers;
3693 const auto constMapLayers { mLayerStore->mapLayers() };
3694 for (
const auto &l : constMapLayers )
3696 if ( ! l->shortName().isEmpty() )
3698 if ( l->shortName() == shortName )
3701 else if ( l->name() == shortName )
3709bool QgsProject::unzip(
const QString &filename, Qgis::ProjectReadFlags flags )
3715 if ( !archive->unzip( filename ) )
3717 setError( tr(
"Unable to unzip file '%1'" ).arg( filename ) );
3722 if ( archive->projectFile().isEmpty() )
3724 setError( tr(
"Zip archive does not provide a project file" ) );
3729 mArchive = std::move( archive );
3746 setError( tr(
"Cannot read unzipped qgs project file" ) );
3756bool QgsProject::zip(
const QString &filename )
3762 const QString
baseName = QFileInfo( filename ).baseName();
3763 const QString qgsFileName = QStringLiteral(
"%1.qgs" ).arg(
baseName );
3764 QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
3766 bool writeOk =
false;
3767 if ( qgsFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3769 writeOk = writeProjectFile( qgsFile.fileName() );
3776 setError( tr(
"Unable to write temporary qgs file" ) );
3781 const QFileInfo info( qgsFile );
3783 const QString asFileName = info.path() + QDir::separator() + info.completeBaseName() + asExt;
3785 bool auxiliaryStorageSavedOk =
true;
3786 if ( ! saveAuxiliaryStorage( asFileName ) )
3788 const QString err = mAuxiliaryStorage->errorString();
3789 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 ) );
3790 auxiliaryStorageSavedOk =
false;
3793 if ( !mArchive->exists() )
3796 mArchive->unzip( mFile.fileName() );
3799 const QString auxiliaryStorageFile =
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile();
3800 if ( ! auxiliaryStorageFile.isEmpty() )
3802 archive->
addFile( auxiliaryStorageFile );
3811 if ( QFile::exists( asFileName ) )
3813 archive->addFile( asFileName );
3818 archive->addFile( qgsFile.fileName() );
3821 const QStringList &files = mArchive->files();
3822 for (
const QString &file : files )
3824 if ( !file.endsWith( QLatin1String(
".qgs" ), Qt::CaseInsensitive ) && !file.endsWith( asExt, Qt::CaseInsensitive ) )
3826 archive->addFile( file );
3832 if ( !archive->zip( filename ) )
3834 setError( tr(
"Unable to perform zip" ) );
3838 return auxiliaryStorageSavedOk && zipOk;
3847 const QList<QgsMapLayer *> &layers,
3849 bool takeOwnership )
3851 const QList<QgsMapLayer *> myResultList { mLayerStore->addMapLayers(
layers, takeOwnership ) };
3852 if ( !myResultList.isEmpty() )
3855 for (
auto &l : myResultList )
3865 if ( mAuxiliaryStorage )
3880 mProjectScope.reset();
3882 return myResultList;
3888 bool takeOwnership )
3890 QList<QgsMapLayer *> addedLayers;
3891 addedLayers =
addMapLayers( QList<QgsMapLayer *>() << layer, addToLegend, takeOwnership );
3892 return addedLayers.isEmpty() ? nullptr : addedLayers[0];
3897 mProjectScope.reset();
3898 mLayerStore->removeMapLayers( layerIds );
3903 mProjectScope.reset();
3904 mLayerStore->removeMapLayers(
layers );
3909 mProjectScope.reset();
3910 mLayerStore->removeMapLayer( layerId );
3915 mProjectScope.reset();
3916 mLayerStore->removeMapLayer( layer );
3921 mProjectScope.reset();
3922 return mLayerStore->takeMapLayer( layer );
3927 return mMainAnnotationLayer;
3932 if ( mLayerStore->count() == 0 )
3935 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
3936 mProjectScope.reset();
3937 mLayerStore->removeAllMapLayers();
3939 snapSingleBlocker.release();
3941 if ( !mBlockSnappingUpdates )
3947 const QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
3948 QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin();
3949 for ( ; it !=
layers.constEnd(); ++it )
3951 it.value()->reload();
3957 return validOnly ? mLayerStore->validMapLayers() : mLayerStore->mapLayers();
3962 return mTransactionGroups.value( qMakePair( providerKey, connString ) );
3967 return &mEditBufferGroup;
3976 if ( mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), QStringLiteral(
"NoAction" ),
QgsSettings::App ).toString() == QStringLiteral(
"UseProjectCrs" )
3977 || mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), 0,
QgsSettings::App ).toString() == QLatin1String(
"2" ) )
3985 const QString layerDefaultCrs = mSettings.
value( QStringLiteral(
"/Projections/layerDefaultCrs" ),
geoEpsgCrsAuthId() ).toString();
4002bool QgsProject::saveAuxiliaryStorage(
const QString &filename )
4006 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4011 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
4019 if ( !mAuxiliaryStorage->exists( *
this ) && empty )
4023 else if ( !filename.isEmpty() )
4025 return mAuxiliaryStorage->saveAs( filename );
4029 return mAuxiliaryStorage->saveAs( *
this );
4038 QgsProject::DataDefinedServerProperty::WMSOnlineResource,
4042 return sPropertyDefinitions;
4047 return mAuxiliaryStorage.get();
4052 return mAuxiliaryStorage.get();
4057 const QDir archiveDir( mArchive->dir() );
4058 QTemporaryFile tmpFile( archiveDir.filePath(
"XXXXXX_" + nameTemplate ),
this );
4059 tmpFile.setAutoRemove(
false );
4061 mArchive->addFile( tmpFile.fileName() );
4062 return tmpFile.fileName();
4067 QStringList attachments;
4069 const QStringList files = mArchive->files();
4070 attachments.reserve( files.size() );
4071 for (
const QString &file : files )
4075 attachments.append( file );
4083 return mArchive->removeFile( path );
4088 return QStringLiteral(
"attachment:///%1" ).arg( QFileInfo( attachedFile ).
fileName() );
4093 if ( identifier.startsWith( QLatin1String(
"attachment:///" ) ) )
4095 return QDir( mArchive->dir() ).absoluteFilePath( identifier.mid( 14 ) );
4111 mProjectScope.reset();
4123 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4135 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
4136 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
4141 if (
layers.contains( it.value() ) )
4151 QStringList customColors;
4152 QStringList customColorLabels;
4154 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
4155 for ( ; colorIt != colors.constEnd(); ++colorIt )
4158 const QString label = ( *colorIt ).second;
4159 customColors.append( color );
4160 customColorLabels.append( label );
4162 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ), customColors );
4163 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ), customColorLabels );
4164 mProjectScope.reset();
4170 if ( mBackgroundColor == color )
4173 mBackgroundColor = color;
4179 return mBackgroundColor;
4184 if ( mSelectionColor == color )
4187 mSelectionColor = color;
4193 return mSelectionColor;
4227QString
QgsProject::translate(
const QString &context,
const QString &sourceText,
const char *disambiguation,
int n )
const
4234 QString result = mTranslator->translate( context.toUtf8(), sourceText.toUtf8(), disambiguation, n );
4236 if ( result.isEmpty() )
4248 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4253 if ( !( ( *it )->accept( visitor ) ) )
4262 if ( !mLayoutManager->accept( visitor ) )
4265 if ( !mAnnotationManager->accept( visitor ) )
4272GetNamedProjectColor::GetNamedProjectColor(
const QgsProject *project )
4279 QStringList colorStrings = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ) );
4280 const QStringList colorLabels = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ) );
4284 for ( QStringList::iterator it = colorStrings.begin();
4285 it != colorStrings.end(); ++it )
4289 if ( colorLabels.length() > colorIndex )
4291 label = colorLabels.at( colorIndex );
4294 mColors.insert( label.toLower(), color );
4299GetNamedProjectColor::GetNamedProjectColor(
const QHash<QString, QColor> &colors )
4307 const QString colorName = values.at( 0 ).toString().toLower();
4308 if ( mColors.contains( colorName ) )
4310 return QStringLiteral(
"%1,%2,%3" ).arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
4318 return new GetNamedProjectColor( mColors );
static QString version()
Version string.
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...
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 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.
static const QgsSettingsEntryString settingsLocaleUserLocale
Settings entry locale user locale.
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.
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.
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.
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
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 ...
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 QgsMapLayerType 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,...
@ 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.
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.
void setAreaUnits(QgsUnitTypes::AreaUnit unit)
Sets the default area measurement units for the project.
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 setDistanceUnits(QgsUnitTypes::DistanceUnit unit)
Sets the default distance measurement units for the project.
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
void setFileName(const QString &name)
Sets the file name associated with the project.
QgsUnitTypes::AreaUnit areaUnits() const
Convenience function to query default area measurement units for 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.
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.
Qgis::TransactionMode transactionMode() const
Returns the transaction mode.
QgsProjectMetadata metadata
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
QgsUnitTypes::DistanceUnit distanceUnits() const
Convenience function to query default distance measurement units for project.
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.
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...
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 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 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.
const QgsProjectDisplaySettings * displaySettings() const
Returns the project's display settings, which settings and properties relating to how a QgsProject sh...
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.
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 setFileName(const QString &fileName)
Sets the fileName of the TS file.
void writeTsFile(const QString &locale) const
Writes the Ts-file.
void setProject(QgsProject *project)
Sets the project being translated.
DistanceUnit
Units of distance.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
static Q_INVOKABLE QgsUnitTypes::AreaUnit decodeAreaUnit(const QString &string, bool *ok=nullptr)
Decodes an areal unit from a string.
@ AreaSquareMeters
Square meters.
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.
QgsMapLayerType
Types of layers that can be added to a map.
@ PointCloudLayer
Point cloud layer. Added in QGIS 3.18.
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
@ VectorLayer
Vector layer.
@ RasterLayer
Raster layer.
@ GroupLayer
Composite group layer. Added in QGIS 3.24.
@ VectorTileLayer
Vector tile layer. Added in QGIS 3.14.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ PluginLayer
Plugin based layer.
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.
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.