76 #include <QApplication>
80 #include <QTextStream>
81 #include <QTemporaryFile>
84 #include <QStandardPaths>
86 #include <QRegularExpression>
89 #include <sys/utime.h>
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 )
373 , mSnappingConfig( this )
389 mProperties.
setName( QStringLiteral(
"properties" ) );
392 mMainAnnotationLayer->setParent(
this );
406 this, [ = ](
const QStringList &
layers ) { mProjectScope.reset(); emit layersWillBeRemoved( layers ); } );
408 this, [ = ](
const QList<QgsMapLayer *> &
layers ) { mProjectScope.reset(); emit layersWillBeRemoved( layers ); } );
410 this, [ = ](
const QString & layer ) { mProjectScope.reset(); emit layerWillBeRemoved( layer ); } );
412 this, [ = ](
QgsMapLayer * layer ) { mProjectScope.reset(); emit layerWillBeRemoved( layer ); } );
414 [ = ](
const QStringList &
layers ) { mProjectScope.reset(); emit layersRemoved( layers ); } );
416 [ = ](
const QString & layer ) { mProjectScope.reset(); emit layerRemoved( layer ); } );
418 [ = ]() { mProjectScope.reset(); emit removeAll(); } );
420 [ = ](
const QList< QgsMapLayer * > &
layers ) { mProjectScope.reset(); emit layersAdded( layers ); } );
422 [ = ](
QgsMapLayer * layer ) { mProjectScope.reset(); emit layerWasAdded( layer ); } );
430 [ = ](
const QList<QgsMapLayer *> &
layers )
432 for ( const auto &layer : layers )
434 disconnect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager, &QgsRelationManager::updateRelationsStatus );
439 [ = ](
const QList<QgsMapLayer *> &layers )
441 for ( const auto &layer : layers )
443 connect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager, &QgsRelationManager::updateRelationsStatus );
452 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
453 mStyleSettings->combinedStyleModel()->addDefaultStyle();
460 mIsBeingDeleted =
true;
463 delete mBadLayerHandler;
464 delete mRelationManager;
465 delete mLayerTreeRegistryBridge;
467 if (
this == sProject )
496 mProjectScope.reset();
504 return mMetadata.
title();
511 if ( oldEvaluateDefaultValues != newEvaluateDefaultValues )
514 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
516 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
525 if ( oldTrustLayerMetadata != newTrustLayerMetadata )
528 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
530 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
532 vl->setReadExtentFromXml( newTrustLayerMetadata );
542 Qgis::ProjectFlags newFlags = mFlags;
546 newFlags &= ~(
static_cast< int >( flag ) );
557 return mSaveUserFull;
562 return mSaveDateTime;
577 if ( dirty && mDirtyBlockCount > 0 )
583 if ( mDirty == dirty )
592 if ( path == mHomePath )
596 mCachedHomePath.clear();
597 mProjectScope.reset();
606 const QList<QgsAttributeEditorElement *> elements = parent->
children();
614 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:formcontainers" ).arg( layerId ), container->
name() );
616 if ( !container->
children().empty() )
629 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1" ).arg( layer->layerId() ), layer->name() );
646 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( vlayer->
id() ), fieldName );
661 const QList<QgsLayerTreeGroup *> groupLayers = mRootGroup->
findGroups();
664 translationContext->
registerTranslation( QStringLiteral(
"project:layergroups" ), groupLayer->name() );
668 const QList<QgsRelation> &relations = mRelationManager->
relations().values();
671 translationContext->
registerTranslation( QStringLiteral(
"project:relations" ), relation.name() );
677 mDataDefinedServerProperties = properties;
682 return mDataDefinedServerProperties;
687 switch ( mTransactionMode )
706 switch ( mTransactionMode )
713 commitErrors.append( tr(
"Trying to commit changes without a layer specified. This only works if the transaction mode is buffered" ) );
722 return mEditBufferGroup.
commitChanges( commitErrors, stopEditing );
730 switch ( mTransactionMode )
737 rollbackErrors.append( tr(
"Trying to roll back changes without a layer specified. This only works if the transaction mode is buffered" ) );
740 bool success = vectorLayer->
rollBack( stopEditing );
746 return mEditBufferGroup.
rollBack( rollbackErrors, stopEditing );
754 if ( name == mFile.fileName() )
757 const QString oldHomePath =
homePath();
759 mFile.setFileName( name );
760 mCachedHomePath.clear();
761 mProjectScope.reset();
765 const QString newHomePath =
homePath();
766 if ( newHomePath != oldHomePath )
774 return mFile.fileName();
779 mOriginalPath = path;
784 return mOriginalPath;
789 return QFileInfo( mFile );
802 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
807 return QFileInfo( mFile.fileName() ).lastModified();
816 if ( mFile.fileName().isEmpty() )
819 return QFileInfo( mFile.fileName() ).absolutePath();
827 if ( mFile.fileName().isEmpty() )
830 return QFileInfo( mFile.fileName() ).absoluteFilePath();
838 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
843 return QFileInfo( mFile.fileName() ).completeBaseName();
849 const bool absolutePaths =
readBoolEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
858 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
true );
861 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
876 writeEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ),
crs.
isValid() ? 1 : 0 );
877 mProjectScope.reset();
888 if ( adjustEllipsoid )
894 if ( !
crs().isValid() )
897 return readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ),
geoNone() );
902 if (
ellipsoid ==
readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ) ) )
905 mProjectScope.reset();
912 return mTransformContext;
917 if ( context == mTransformContext )
920 mTransformContext = context;
921 mProjectScope.reset();
924 for (
auto &layer : mLayerStore.get()->mapLayers() )
926 layer->setTransformContext( context );
933 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
935 mProjectScope.reset();
936 mFile.setFileName( QString() );
939 mSaveUserFull.clear();
940 mSaveDateTime = QDateTime();
943 mCachedHomePath.clear();
945 mFlags = Qgis::ProjectFlags();
947 mCustomVariables.clear();
950 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_new_projects" ),
false,
QgsSettings::Core ).toBool() )
961 mEmbeddedLayers.clear();
962 mRelationManager->
clear();
963 mAnnotationManager->clear();
964 mLayoutManager->clear();
965 m3DViewsManager->clear();
966 mBookmarkManager->
clear();
967 mViewSettings->
reset();
968 mTimeSettings->
reset();
969 mElevationProperties->
reset();
970 mDisplaySettings->
reset();
971 mSnappingConfig.
reset();
979 mLabelingEngineSettings->clear();
985 mStyleSettings->
reset();
989 if ( !mIsBeingDeleted )
997 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/Automatic" ),
true );
998 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/DecimalPlaces" ), 2 );
1000 const bool defaultRelativePaths = mSettings.
value( QStringLiteral(
"/qgis/defaultProjectPathsRelative" ),
true ).toBool();
1004 writeEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), mSettings.
value( QStringLiteral(
"/qgis/measure/displayunits" ) ).toString() );
1005 writeEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), mSettings.
value( QStringLiteral(
"/qgis/measure/areaunits" ) ).toString() );
1007 int red = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_red" ), 255 ).toInt();
1008 int green = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_green" ), 255 ).toInt();
1009 int blue = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_blue" ), 255 ).toInt();
1012 red = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_red" ), 255 ).toInt();
1013 green = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_green" ), 255 ).toInt();
1014 blue = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_blue" ), 0 ).toInt();
1015 const int alpha = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_alpha" ), 255 ).toInt();
1021 mRootGroup->
clear();
1022 if ( mMainAnnotationLayer )
1023 mMainAnnotationLayer->
reset();
1025 snapSingleBlocker.release();
1027 if ( !mBlockSnappingUpdates )
1039 topQgsPropertyKey.
dump();
1072 const QDomElement propertiesElem = doc.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
1074 if ( propertiesElem.isNull() )
1079 const QDomNodeList scopes = propertiesElem.childNodes();
1081 if ( propertiesElem.firstChild().isNull() )
1083 QgsDebugMsg( QStringLiteral(
"empty ``properties'' XML tag ... bailing" ) );
1087 if ( ! project_properties.
readXml( propertiesElem ) )
1089 QgsDebugMsg( QStringLiteral(
"Project_properties.readXml() failed" ) );
1103 const QDomElement ddElem = doc.documentElement().firstChildElement( QStringLiteral(
"dataDefinedServerProperties" ) );
1104 if ( !ddElem.isNull() )
1106 if ( !ddServerProperties.
readXml( ddElem, dataDefinedServerPropertyDefinitions ) )
1108 QgsDebugMsg( QStringLiteral(
"dataDefinedServerProperties.readXml() failed" ) );
1111 return ddServerProperties;
1118 static void _getTitle(
const QDomDocument &doc, QString &title )
1120 const QDomElement titleNode = doc.documentElement().firstChildElement( QStringLiteral(
"title" ) );
1124 if ( titleNode.isNull() )
1130 if ( !titleNode.hasChildNodes() )
1136 const QDomNode titleTextNode = titleNode.firstChild();
1138 if ( !titleTextNode.isText() )
1144 const QDomText titleText = titleTextNode.toText();
1146 title = titleText.data();
1150 static void readProjectFileMetadata(
const QDomDocument &doc, QString &lastUser, QString &lastUserFull, QDateTime &lastSaveDateTime )
1152 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1156 QgsDebugMsg( QStringLiteral(
"unable to find qgis element" ) );
1160 const QDomNode qgisNode = nl.item( 0 );
1162 const QDomElement qgisElement = qgisNode.toElement();
1163 lastUser = qgisElement.attribute( QStringLiteral(
"saveUser" ), QString() );
1164 lastUserFull = qgisElement.attribute( QStringLiteral(
"saveUserFull" ), QString() );
1165 lastSaveDateTime = QDateTime::fromString( qgisElement.attribute( QStringLiteral(
"saveDateTime" ), QString() ), Qt::ISODate );
1171 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1175 QgsDebugMsg( QStringLiteral(
" unable to find qgis element in project file" ) );
1179 const QDomNode qgisNode = nl.item( 0 );
1181 const QDomElement qgisElement = qgisNode.toElement();
1182 QgsProjectVersion projectVersion( qgisElement.attribute( QStringLiteral(
"version" ) ) );
1183 return projectVersion;
1189 return mSnappingConfig;
1204 if ( mAvoidIntersectionsMode == mode )
1207 mAvoidIntersectionsMode = mode;
1211 bool QgsProject::_getMapLayers(
const QDomDocument &doc, QList<QDomNode> &brokenNodes, Qgis::ProjectReadFlags flags )
1216 QDomElement layerElement = doc.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
1220 if ( layerElement.isNull() )
1230 bool returnStatus =
true;
1233 while ( ! layerElement.isNull() )
1236 layerElement = layerElement.nextSiblingElement( QStringLiteral(
"maplayer" ) );
1242 if ( depSorter.hasCycle() )
1246 if ( depSorter.hasMissingDependency() )
1247 returnStatus =
false;
1251 const QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
1252 const int totalLayerCount = sortedLayerNodes.count();
1255 for (
const QDomNode &node : sortedLayerNodes )
1257 const QDomElement element = node.toElement();
1259 const QString name =
translate( QStringLiteral(
"project:layers:%1" ).arg( node.namedItem( QStringLiteral(
"id" ) ).toElement().text() ), node.namedItem( QStringLiteral(
"layername" ) ).toElement().text() );
1260 if ( !name.isNull() )
1261 emit
loadingLayer( tr(
"Loading layer %1" ).arg( name ) );
1263 profile.switchTask( name );
1265 if ( element.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
1267 createEmbeddedLayer( element.attribute( QStringLiteral(
"id" ) ),
readPath( element.attribute( QStringLiteral(
"project" ) ) ), brokenNodes,
true,
flags );
1276 if ( !addLayer( element, brokenNodes, context,
flags ) )
1278 returnStatus =
false;
1281 if ( !messages.isEmpty() )
1290 return returnStatus;
1293 bool QgsProject::addLayer(
const QDomElement &layerElem, QList<QDomNode> &brokenNodes,
QgsReadWriteContext &context, Qgis::ProjectReadFlags flags )
1295 const QString type = layerElem.attribute( QStringLiteral(
"type" ) );
1297 std::unique_ptr<QgsMapLayer>
mapLayer;
1305 QgsDebugMsg( QStringLiteral(
"Unknown layer type \"%1\"" ).arg( type ) );
1309 switch ( layerType )
1313 mapLayer = std::make_unique<QgsVectorLayer>();
1323 mapLayer = std::make_unique<QgsRasterLayer>();
1327 mapLayer = std::make_unique<QgsMeshLayer>();
1331 mapLayer = std::make_unique<QgsVectorTileLayer>();
1335 mapLayer = std::make_unique<QgsPointCloudLayer>();
1340 const QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
1348 mapLayer = std::make_unique<QgsAnnotationLayer>( QString(), options );
1355 mapLayer = std::make_unique<QgsGroupLayer>( QString(), options );
1362 QgsDebugMsg( QStringLiteral(
"Unable to create layer" ) );
1370 const QString layerId { layerElem.namedItem( QStringLiteral(
"id" ) ).toElement().text() };
1371 Q_ASSERT( ! layerId.isEmpty() );
1375 QgsMapLayer::ReadFlags layerFlags = QgsMapLayer::ReadFlags();
1376 if (
flags & Qgis::ProjectReadFlag::DontResolveLayers )
1382 profile.switchTask( tr(
"Load layer source" ) );
1385 profile.switchTask( tr(
"Add layer to project" ) );
1386 QList<QgsMapLayer *> newLayers;
1388 if ( layerIsValid ||
flags & Qgis::ProjectReadFlag::DontResolveLayers )
1398 vLayer->joinBuffer()->resolveReferences(
this );
1406 QgsDebugMsg(
"Unable to load " + type +
" layer" );
1407 brokenNodes.push_back( layerElem );
1410 const bool wasEditable = layerElem.attribute( QStringLiteral(
"editable" ), QStringLiteral(
"0" ) ).toInt();
1422 if ( ! layerWasStored )
1427 return layerIsValid;
1432 mFile.setFileName( filename );
1433 mCachedHomePath.clear();
1434 mProjectScope.reset();
1441 const QString filename = mFile.fileName();
1446 QTemporaryFile inDevice;
1447 if ( !inDevice.open() )
1449 setError( tr(
"Unable to open %1" ).arg( inDevice.fileName() ) );
1455 if ( !storage->readProject( filename, &inDevice, context ) )
1457 QString err = tr(
"Unable to open %1" ).arg( filename );
1458 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
1459 if ( !messages.isEmpty() )
1460 err += QStringLiteral(
"\n\n" ) + messages.last().message();
1464 returnValue = unzip( inDevice.fileName(),
flags );
1470 returnValue = unzip( mFile.fileName(),
flags );
1475 const QFileInfo finfo( mFile.fileName() );
1476 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
1477 if ( QFile( attachmentsZip ).exists() )
1479 std::unique_ptr<QgsArchive> archive(
new QgsArchive() );
1480 if ( archive->unzip( attachmentsZip ) )
1482 mArchive = std::move( archive );
1485 returnValue = readProjectFile( mFile.fileName(),
flags );
1491 mFile.setFileName( filename );
1492 mCachedHomePath.clear();
1493 mProjectScope.reset();
1498 mTranslator.reset(
nullptr );
1505 bool QgsProject::readProjectFile(
const QString &filename, Qgis::ProjectReadFlags flags )
1508 ScopedIntIncrementor snapSignalBlock( &mBlockSnappingUpdates );
1510 QFile projectFile( filename );
1518 if ( QFile( QStringLiteral(
"%1/%2.qm" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) ).exists() )
1520 mTranslator.reset(
new QTranslator() );
1521 ( void )mTranslator->load( localeFileName, QFileInfo( projectFile.fileName() ).absolutePath() );
1524 profile.switchTask( tr(
"Reading project file" ) );
1525 std::unique_ptr<QDomDocument> doc(
new QDomDocument( QStringLiteral(
"qgis" ) ) );
1527 if ( !projectFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
1529 projectFile.close();
1531 setError( tr(
"Unable to open %1" ).arg( projectFile.fileName() ) );
1540 if ( !doc->setContent( &projectFile, &errorMsg, &line, &column ) )
1542 const QString errorString = tr(
"Project file read error in file %1: %2 at line %3 column %4" )
1543 .arg( projectFile.fileName(), errorMsg ).arg( line ).arg( column );
1547 projectFile.close();
1549 setError( tr(
"%1 for file %2" ).arg( errorString, projectFile.fileName() ) );
1554 projectFile.close();
1562 profile.switchTask( tr(
"Updating project file" ) );
1563 if ( thisVersion > fileVersion )
1565 const bool isOlderMajorVersion = fileVersion.
majorVersion() < thisVersion.majorVersion();
1567 if ( isOlderMajorVersion )
1570 "version of qgis (saved in " + fileVersion.
text() +
1572 "). Problems may occur." );
1583 projectFile.updateRevision( thisVersion );
1585 else if ( fileVersion > thisVersion )
1588 "version of qgis (saved in " + fileVersion.
text() +
1590 "). Problems may occur." );
1596 profile.switchTask( tr(
"Creating auxiliary storage" ) );
1597 const QString
fileName = mFile.fileName();
1598 std::unique_ptr<QgsAuxiliaryStorage> aStorage = std::move( mAuxiliaryStorage );
1599 std::unique_ptr<QgsArchive> archive = std::move( mArchive );
1601 mAuxiliaryStorage = std::move( aStorage );
1602 mArchive = std::move( archive );
1604 mCachedHomePath.clear();
1605 mProjectScope.reset();
1606 mSaveVersion = fileVersion;
1609 profile.switchTask( tr(
"Reading properties" ) );
1618 dump_( mProperties );
1623 _getTitle( *doc, oldTitle );
1625 readProjectFileMetadata( *doc, mSaveUser, mSaveUserFull, mSaveDateTime );
1627 const QDomNodeList homePathNl = doc->elementsByTagName( QStringLiteral(
"homePath" ) );
1628 if ( homePathNl.count() > 0 )
1630 const QDomElement homePathElement = homePathNl.at( 0 ).toElement();
1631 const QString
homePath = homePathElement.attribute( QStringLiteral(
"path" ) );
1641 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), 255 ),
1642 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), 255 ) );
1645 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), 255 ),
1646 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), 255 ),
1647 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), 255 ) );
1656 if (
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ), 0 ) )
1659 const QDomNode srsNode = doc->documentElement().namedItem( QStringLiteral(
"projectCrs" ) );
1660 if ( !srsNode.isNull() )
1662 projectCrs.
readXml( srsNode );
1667 const QString projCrsString =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSProj4String" ) );
1668 const long currentCRS =
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSID" ), -1 );
1669 const QString authid =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCrs" ) );
1672 const bool isUserAuthId = authid.startsWith( QLatin1String(
"USER:" ), Qt::CaseInsensitive );
1673 if ( !authid.isEmpty() && !isUserAuthId )
1677 if ( !projectCrs.
isValid() && currentCRS >= 0 )
1683 if ( !projCrsString.isEmpty() && ( authid.isEmpty() || isUserAuthId ) && ( !projectCrs.
isValid() || projectCrs.
toProj() != projCrsString ) )
1697 QStringList datumErrors;
1698 if ( !mTransformContext.
readXml( doc->documentElement(), context, datumErrors ) && !datumErrors.empty() )
1706 const QStringList variableNames =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ) );
1707 const QStringList variableValues =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ) );
1709 mCustomVariables.clear();
1710 if ( variableNames.length() == variableValues.length() )
1712 for (
int i = 0; i < variableNames.length(); ++i )
1714 mCustomVariables.insert( variableNames.at( i ), variableValues.at( i ) );
1719 QgsMessageLog::logMessage( tr(
"Project Variables Invalid" ), tr(
"The project contains invalid variable settings." ) );
1722 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectMetadata" ) );
1724 if ( !element.isNull() )
1733 if ( mMetadata.
title().isEmpty() && !oldTitle.isEmpty() )
1741 element = doc->documentElement().firstChildElement( QStringLiteral(
"transaction" ) );
1742 if ( !element.isNull() )
1749 element = doc->documentElement().firstChildElement( QStringLiteral(
"autotransaction" ) );
1750 if ( ! element.isNull() )
1752 mTransactionMode =
static_cast<Qgis::TransactionMode>( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() );
1756 element = doc->documentElement().firstChildElement( QStringLiteral(
"projectFlags" ) );
1757 if ( !element.isNull() )
1759 mFlags =
qgsFlagKeysToValue( element.attribute( QStringLiteral(
"set" ) ), Qgis::ProjectFlags() );
1764 element = doc->documentElement().firstChildElement( QStringLiteral(
"evaluateDefaultValues" ) );
1765 if ( !element.isNull() )
1767 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
1772 element = doc->documentElement().firstChildElement( QStringLiteral(
"trust" ) );
1773 if ( !element.isNull() )
1775 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
1781 profile.switchTask( tr(
"Loading layer tree" ) );
1784 QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
1785 if ( !layerTreeElem.isNull() )
1797 mLayerTreeRegistryBridge->
setEnabled(
false );
1800 profile.switchTask( tr(
"Reading map layers" ) );
1802 QList<QDomNode> brokenNodes;
1803 const bool clean = _getMapLayers( *doc, brokenNodes,
flags );
1808 QgsDebugMsg( QStringLiteral(
"Unable to get map layers from project file." ) );
1810 if ( !brokenNodes.isEmpty() )
1812 QgsDebugMsg(
"there are " + QString::number( brokenNodes.size() ) +
" broken layers" );
1820 mMainAnnotationLayer->
readLayerXml( doc->documentElement().firstChildElement( QStringLiteral(
"main-annotation-layer" ) ), context );
1824 profile.switchTask( tr(
"Loading embedded layers" ) );
1825 loadEmbeddedNodes( mRootGroup,
flags );
1829 profile.switchTask( tr(
"Resolving layer references" ) );
1830 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
1831 for ( QMap<QString, QgsMapLayer *>::iterator it =
layers.begin(); it !=
layers.end(); ++it )
1833 it.value()->resolveReferences(
this );
1836 mLayerTreeRegistryBridge->
setEnabled(
true );
1839 profile.switchTask( tr(
"Resolving references" ) );
1842 if ( !layerTreeElem.isNull() )
1848 const QDomElement layerTreeCanvasElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-canvas" ) );
1849 if ( !layerTreeCanvasElem.isNull( ) )
1857 const QStringList requiredLayerIds =
readListEntry( QStringLiteral(
"RequiredLayers" ), QStringLiteral(
"Layers" ) );
1858 for (
const QString &layerId : requiredLayerIds )
1865 const QStringList disabledLayerIds =
readListEntry( QStringLiteral(
"Identify" ), QStringLiteral(
"/disabledLayers" ) );
1866 for (
const QString &layerId : disabledLayerIds )
1879 QString styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1880 if ( !styleName.isEmpty() )
1885 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
1886 if ( !styleName.isEmpty() )
1891 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
1892 if ( !styleName.isEmpty() )
1897 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
1898 if ( !styleName.isEmpty() )
1908 double opacity = 1.0;
1911 double alpha =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ), 255, &ok );
1913 opacity = alpha / 255.0;
1914 double newOpacity =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ), 1.0, &ok );
1916 opacity = newOpacity;
1920 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1921 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
1922 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
1923 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
1924 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/RandomColors" ) );
1925 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ) );
1926 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ) );
1932 if ( !(
flags & Qgis::ProjectReadFlag::DontStoreOriginalStyles ) )
1934 profile.switchTask( tr(
"Storing original layer properties" ) );
1940 profile.switchTask( tr(
"Loading map themes" ) );
1943 mMapThemeCollection->readXml( *doc );
1945 profile.switchTask( tr(
"Loading label settings" ) );
1946 mLabelingEngineSettings->readSettingsFromProject(
this );
1949 profile.switchTask( tr(
"Loading annotations" ) );
1950 mAnnotationManager->readXml( doc->documentElement(), context );
1951 if ( !(
flags & Qgis::ProjectReadFlag::DontLoadLayouts ) )
1953 profile.switchTask( tr(
"Loading layouts" ) );
1954 mLayoutManager->readXml( doc->documentElement(), *doc );
1957 if ( !(
flags & Qgis::ProjectReadFlag::DontLoad3DViews ) )
1959 profile.switchTask( tr(
"Loading 3D Views" ) );
1960 m3DViewsManager->readXml( doc->documentElement(), *doc );
1963 profile.switchTask( tr(
"Loading bookmarks" ) );
1964 mBookmarkManager->
readXml( doc->documentElement(), *doc );
1967 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
1968 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); ++it )
1970 it.value()->setDependencies( it.value()->dependencies() );
1973 profile.switchTask( tr(
"Loading snapping settings" ) );
1977 profile.switchTask( tr(
"Loading view settings" ) );
1980 const QStringList scales =
readListEntry( QStringLiteral(
"Scales" ), QStringLiteral(
"/ScalesList" ) );
1981 QVector<double> res;
1982 for (
const QString &scale : scales )
1984 const QStringList parts = scale.split(
':' );
1985 if ( parts.size() != 2 )
1989 const double denominator = QLocale().toDouble( parts[1], &ok );
1996 const QDomElement viewSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectViewSettings" ) );
1997 if ( !viewSettingsElement.isNull() )
1998 mViewSettings->
readXml( viewSettingsElement, context );
2001 profile.switchTask( tr(
"Loading style properties" ) );
2002 const QDomElement styleSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectStyleSettings" ) );
2003 if ( !styleSettingsElement.isNull() )
2004 mStyleSettings->
readXml( styleSettingsElement, context,
flags );
2007 profile.switchTask( tr(
"Loading temporal settings" ) );
2008 const QDomElement timeSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectTimeSettings" ) );
2009 if ( !timeSettingsElement.isNull() )
2010 mTimeSettings->
readXml( timeSettingsElement, context );
2013 profile.switchTask( tr(
"Loading elevation properties" ) );
2014 const QDomElement elevationPropertiesElement = doc->documentElement().firstChildElement( QStringLiteral(
"ElevationProperties" ) );
2015 if ( !elevationPropertiesElement.isNull() )
2016 mElevationProperties->
readXml( elevationPropertiesElement, context );
2019 profile.switchTask( tr(
"Loading display settings" ) );
2020 const QDomElement displaySettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectDisplaySettings" ) );
2021 if ( !displaySettingsElement.isNull() )
2022 mDisplaySettings->
readXml( displaySettingsElement, context );
2024 profile.switchTask( tr(
"Updating variables" ) );
2026 profile.switchTask( tr(
"Updating CRS" ) );
2031 profile.switchTask( tr(
"Reading external settings" ) );
2035 profile.switchTask( tr(
"Updating interface" ) );
2037 snapSignalBlock.release();
2038 if ( !mBlockSnappingUpdates )
2049 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUser ), 2 );
2050 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUserFull ), 2 );
2059 const QString newFileName( QStringLiteral(
"%1/%2.qgs" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) );
2065 QgsMessageLog::logMessage( tr(
"Translated project saved with locale prefix %1" ).arg( newFileName ), QObject::tr(
"Project translation" ), Qgis::MessageLevel::Success );
2069 QgsMessageLog::logMessage( tr(
"Error saving translated project with locale prefix %1" ).arg( newFileName ), QObject::tr(
"Project translation" ), Qgis::MessageLevel::Critical );
2074 const QMap<QString, QgsMapLayer *> loadedLayers =
mapLayers();
2075 for (
auto it = loadedLayers.constBegin(); it != loadedLayers.constEnd(); ++it )
2077 if ( it.value()->isValid() && it.value()->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2079 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( it.value() ) )
2081 it.value()->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2089 bool QgsProject::loadEmbeddedNodes(
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
2092 const auto constChildren = group->
children();
2098 if ( childGroup->
customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2101 const QString projectPath =
readPath( childGroup->
customProperty( QStringLiteral(
"embedded_project" ) ).toString() );
2102 childGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectPath );
2106 QList<QgsLayerTreeNode *> clonedChildren;
2107 const QList<QgsLayerTreeNode *> constChildren = newGroup->
children();
2108 clonedChildren.reserve( constChildren.size() );
2110 clonedChildren << newGroupChild->clone();
2118 loadEmbeddedNodes( childGroup,
flags );
2123 if ( child->customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2125 QList<QDomNode> brokenNodes;
2128 valid = valid &&
false;
2140 return mCustomVariables;
2145 if ( variables == mCustomVariables )
2149 QStringList variableNames;
2150 QStringList variableValues;
2152 QVariantMap::const_iterator it = variables.constBegin();
2153 for ( ; it != variables.constEnd(); ++it )
2155 variableNames << it.key();
2156 variableValues << it.value().toString();
2159 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ), variableNames );
2160 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ), variableValues );
2162 mCustomVariables = variables;
2163 mProjectScope.reset();
2170 *mLabelingEngineSettings = settings;
2176 return *mLabelingEngineSettings;
2181 mProjectScope.reset();
2182 return mLayerStore.get();
2187 return mLayerStore.get();
2192 QList<QgsVectorLayer *>
layers;
2193 const QStringList layerIds =
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), QStringList() );
2194 const auto constLayerIds = layerIds;
2195 for (
const QString &layerId : constLayerIds )
2206 list.reserve(
layers.size() );
2208 list << layer->id();
2209 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), list );
2226 if ( mProjectScope )
2228 std::unique_ptr< QgsExpressionContextScope > projectScope = std::make_unique< QgsExpressionContextScope >( *mProjectScope );
2232 return projectScope.release();
2235 mProjectScope = std::make_unique< QgsExpressionContextScope >( QObject::tr(
"Project" ) );
2239 QVariantMap::const_iterator it = vars.constBegin();
2241 for ( ; it != vars.constEnd(); ++it )
2243 mProjectScope->setVariable( it.key(), it.value(),
true );
2247 if ( projectPath.isEmpty() )
2248 projectPath = mOriginalPath;
2249 const QString projectFolder = QFileInfo( projectPath ).path();
2250 const QString projectFilename = QFileInfo( projectPath ).fileName();
2251 const QString projectBasename =
baseName();
2280 QVariantMap keywords;
2282 for (
auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
2284 keywords.insert( it.key(), it.value() );
2289 QVariantList layersIds;
2291 const QMap<QString, QgsMapLayer *> layersInProject = mLayerStore->mapLayers();
2292 layersIds.reserve( layersInProject.count() );
2293 layers.reserve( layersInProject.count() );
2294 for (
auto it = layersInProject.constBegin(); it != layersInProject.constEnd(); ++it )
2296 layersIds << it.value()->id();
2302 mProjectScope->addFunction( QStringLiteral(
"project_color" ),
new GetNamedProjectColor(
this ) );
2307 void QgsProject::onMapLayersAdded(
const QList<QgsMapLayer *> &layers )
2309 const QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2311 const auto constLayers =
layers;
2314 if ( ! layer->isValid() )
2320 for ( QMap<QString, QgsMapLayer *>::const_iterator it = existingMaps.cbegin(); it != existingMaps.cend(); ++it )
2322 const QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
2323 if ( deps.contains( layer->id() ) )
2326 it.value()->setDependencies( deps );
2331 updateTransactionGroups();
2337 void QgsProject::onMapLayersRemoved(
const QList<QgsMapLayer *> &layers )
2343 void QgsProject::cleanTransactionGroups(
bool force )
2345 bool changed =
false;
2346 for ( QMap< QPair< QString, QString>,
QgsTransactionGroup *>::Iterator tg = mTransactionGroups.begin(); tg != mTransactionGroups.end(); )
2348 if ( tg.value()->isEmpty() || force )
2351 tg = mTransactionGroups.erase( tg );
2363 void QgsProject::updateTransactionGroups()
2365 mEditBufferGroup.
clear();
2367 switch ( mTransactionMode )
2371 cleanTransactionGroups(
true );
2376 cleanTransactionGroups(
true );
2379 cleanTransactionGroups(
false );
2383 bool tgChanged =
false;
2384 const auto constLayers =
mapLayers().values();
2387 if ( ! layer->isValid() )
2390 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
2394 switch ( mTransactionMode )
2411 mTransactionGroups.insert( qMakePair( key, connString ), tg );
2421 mEditBufferGroup.
addLayer( vlayer );
2437 QList<QDomNode> brokenNodes;
2438 if ( addLayer( layerNode.toElement(), brokenNodes, context ) )
2442 const QVector<QgsVectorLayer *> vectorLayers = layers<QgsVectorLayer *>();
2446 layer->resolveReferences(
this );
2448 if ( layer->isValid() && layer->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2450 layer->startEditing();
2451 layer->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2461 mFile.setFileName( filename );
2462 mCachedHomePath.clear();
2468 mProjectScope.reset();
2474 const QString storageFilePath { storage->filePath( mFile.fileName() ) };
2475 if ( storageFilePath.isEmpty() )
2481 const QString tempPath = QStandardPaths::standardLocations( QStandardPaths::TempLocation ).at( 0 );
2482 const QString tmpZipFilename( tempPath + QDir::separator() + QUuid::createUuid().toString() );
2484 if ( !zip( tmpZipFilename ) )
2487 QFile tmpZipFile( tmpZipFilename );
2488 if ( !tmpZipFile.open( QIODevice::ReadOnly ) )
2490 setError( tr(
"Unable to read file %1" ).arg( tmpZipFilename ) );
2495 if ( !storage->writeProject( mFile.fileName(), &tmpZipFile, context ) )
2497 QString err = tr(
"Unable to save project to storage %1" ).arg( mFile.fileName() );
2498 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
2499 if ( !messages.isEmpty() )
2500 err += QStringLiteral(
"\n\n" ) + messages.last().message();
2506 QFile::remove( tmpZipFilename );
2513 return zip( mFile.fileName() );
2519 const bool asOk = saveAuxiliaryStorage();
2520 const bool writeOk = writeProjectFile( mFile.fileName() );
2521 bool attachmentsOk =
true;
2522 if ( !mArchive->files().isEmpty() )
2524 const QFileInfo finfo( mFile.fileName() );
2525 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
2526 attachmentsOk = mArchive->zip( attachmentsZip );
2530 if ( ( !asOk || !attachmentsOk ) && writeOk )
2532 QStringList errorMessage;
2535 const QString err = mAuxiliaryStorage->errorString();
2536 errorMessage.append( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
2538 if ( !attachmentsOk )
2540 errorMessage.append( tr(
"Unable to save attachments archive" ) );
2542 setError( errorMessage.join(
'\n' ) );
2545 return asOk && writeOk && attachmentsOk;
2549 bool QgsProject::writeProjectFile(
const QString &filename )
2551 QFile projectFile( filename );
2557 const QFileInfo myFileInfo( projectFile );
2558 if ( myFileInfo.exists() && !myFileInfo.isWritable() )
2560 setError( tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
2561 .arg( projectFile.fileName() ) );
2569 QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
2571 const QDomDocumentType documentType =
2572 QDomImplementation().createDocumentType( QStringLiteral(
"qgis" ), QStringLiteral(
"http://mrcc.com/qgis.dtd" ),
2573 QStringLiteral(
"SYSTEM" ) );
2574 std::unique_ptr<QDomDocument> doc(
new QDomDocument( documentType ) );
2576 QDomElement qgisNode = doc->createElement( QStringLiteral(
"qgis" ) );
2577 qgisNode.setAttribute( QStringLiteral(
"projectname" ),
title() );
2578 qgisNode.setAttribute( QStringLiteral(
"version" ),
Qgis::version() );
2580 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_saved_projects" ),
false,
QgsSettings::Core ).toBool() )
2584 qgisNode.setAttribute( QStringLiteral(
"saveUser" ), newSaveUser );
2585 qgisNode.setAttribute( QStringLiteral(
"saveUserFull" ), newSaveUserFull );
2586 mSaveUser = newSaveUser;
2587 mSaveUserFull = newSaveUserFull;
2588 mSaveDateTime = QDateTime::currentDateTime();
2589 qgisNode.setAttribute( QStringLiteral(
"saveDateTime" ), mSaveDateTime.toString( Qt::ISODate ) );
2594 mSaveUserFull.clear();
2595 mSaveDateTime = QDateTime();
2597 doc->appendChild( qgisNode );
2600 QDomElement homePathNode = doc->createElement( QStringLiteral(
"homePath" ) );
2601 homePathNode.setAttribute( QStringLiteral(
"path" ), mHomePath );
2602 qgisNode.appendChild( homePathNode );
2605 QDomElement titleNode = doc->createElement( QStringLiteral(
"title" ) );
2606 qgisNode.appendChild( titleNode );
2608 QDomElement transactionNode = doc->createElement( QStringLiteral(
"transaction" ) );
2609 transactionNode.setAttribute( QStringLiteral(
"mode" ),
qgsEnumValueToKey( mTransactionMode ) );
2610 qgisNode.appendChild( transactionNode );
2612 QDomElement flagsNode = doc->createElement( QStringLiteral(
"projectFlags" ) );
2614 qgisNode.appendChild( flagsNode );
2616 const QDomText titleText = doc->createTextNode(
title() );
2617 titleNode.appendChild( titleText );
2620 QDomElement srsNode = doc->createElement( QStringLiteral(
"projectCrs" ) );
2622 qgisNode.appendChild( srsNode );
2629 clonedRoot->
writeXml( qgisNode, context );
2633 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsMode" ),
static_cast<int>( mAvoidIntersectionsMode ) );
2641 QDomElement annotationLayerNode = doc->createElement( QStringLiteral(
"main-annotation-layer" ) );
2642 mMainAnnotationLayer->
writeLayerXml( annotationLayerNode, *doc, context );
2643 qgisNode.appendChild( annotationLayerNode );
2647 QDomElement projectLayersNode = doc->createElement( QStringLiteral(
"projectlayers" ) );
2649 QMap<QString, QgsMapLayer *>::ConstIterator li =
layers.constBegin();
2650 while ( li !=
layers.end() )
2656 const QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.constFind( ml->
id() );
2657 if ( emIt == mEmbeddedLayers.constEnd() )
2659 QDomElement maplayerElem;
2665 maplayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2669 maplayerElem.setAttribute( QStringLiteral(
"editable" ), QStringLiteral(
"1" ) );
2673 QDomDocument document;
2676 maplayerElem = document.firstChildElement();
2680 QgsDebugMsg( QStringLiteral(
"Could not restore layer properties for layer %1" ).arg( ml->
id() ) );
2686 projectLayersNode.appendChild( maplayerElem );
2692 if ( emIt.value().second )
2694 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2695 mapLayerElem.setAttribute( QStringLiteral(
"embedded" ), 1 );
2696 mapLayerElem.setAttribute( QStringLiteral(
"project" ),
writePath( emIt.value().first ) );
2697 mapLayerElem.setAttribute( QStringLiteral(
"id" ), ml->
id() );
2698 projectLayersNode.appendChild( mapLayerElem );
2705 qgisNode.appendChild( projectLayersNode );
2707 QDomElement layerOrderNode = doc->createElement( QStringLiteral(
"layerorder" ) );
2709 for (
QgsMapLayer *layer : constCustomLayerOrder )
2711 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"layer" ) );
2712 mapLayerElem.setAttribute( QStringLiteral(
"id" ), layer->id() );
2713 layerOrderNode.appendChild( mapLayerElem );
2715 qgisNode.appendChild( layerOrderNode );
2717 mLabelingEngineSettings->writeSettingsToProject(
this );
2719 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorRedPart" ), mBackgroundColor.red() );
2720 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), mBackgroundColor.green() );
2721 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), mBackgroundColor.blue() );
2723 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorRedPart" ), mSelectionColor.red() );
2724 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), mSelectionColor.green() );
2725 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), mSelectionColor.blue() );
2726 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), mSelectionColor.alpha() );
2730 dump_( mProperties );
2733 QgsDebugMsgLevel( QStringLiteral(
"there are %1 property scopes" ).arg(
static_cast<int>( mProperties.
count() ) ), 2 );
2738 mProperties.
writeXml( QStringLiteral(
"properties" ), qgisNode, *doc );
2741 QDomElement ddElem = doc->createElement( QStringLiteral(
"dataDefinedServerProperties" ) );
2742 mDataDefinedServerProperties.
writeXml( ddElem, dataDefinedServerPropertyDefinitions() );
2743 qgisNode.appendChild( ddElem );
2745 mMapThemeCollection->writeXml( *doc );
2747 mTransformContext.
writeXml( qgisNode, context );
2749 QDomElement metadataElem = doc->createElement( QStringLiteral(
"projectMetadata" ) );
2751 qgisNode.appendChild( metadataElem );
2753 const QDomElement annotationsElem = mAnnotationManager->writeXml( *doc, context );
2754 qgisNode.appendChild( annotationsElem );
2756 const QDomElement layoutElem = mLayoutManager->writeXml( *doc );
2757 qgisNode.appendChild( layoutElem );
2759 const QDomElement views3DElem = m3DViewsManager->writeXml( *doc );
2760 qgisNode.appendChild( views3DElem );
2762 const QDomElement bookmarkElem = mBookmarkManager->
writeXml( *doc );
2763 qgisNode.appendChild( bookmarkElem );
2765 const QDomElement viewSettingsElem = mViewSettings->
writeXml( *doc, context );
2766 qgisNode.appendChild( viewSettingsElem );
2768 const QDomElement styleSettingsElem = mStyleSettings->
writeXml( *doc, context );
2769 qgisNode.appendChild( styleSettingsElem );
2771 const QDomElement timeSettingsElement = mTimeSettings->
writeXml( *doc, context );
2772 qgisNode.appendChild( timeSettingsElement );
2774 const QDomElement elevationPropertiesElement = mElevationProperties->
writeXml( *doc, context );
2775 qgisNode.appendChild( elevationPropertiesElement );
2777 const QDomElement displaySettingsElem = mDisplaySettings->
writeXml( *doc, context );
2778 qgisNode.appendChild( displaySettingsElem );
2786 QFile backupFile( QStringLiteral(
"%1~" ).arg( filename ) );
2788 ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
2789 ok &= projectFile.open( QIODevice::ReadOnly );
2792 while ( ok && !projectFile.atEnd() )
2794 ba = projectFile.read( 10240 );
2795 ok &= backupFile.write( ba ) == ba.size();
2798 projectFile.close();
2803 setError( tr(
"Unable to create backup file %1" ).arg( backupFile.fileName() ) );
2808 struct utimbuf tb = {
static_cast<time_t
>( fi.lastRead().toSecsSinceEpoch() ),
static_cast<time_t
>( fi.lastModified().toSecsSinceEpoch() ) };
2809 utime( backupFile.fileName().toUtf8().constData(), &tb );
2812 if ( !projectFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
2814 projectFile.close();
2817 setError( tr(
"Unable to save to file %1" ).arg( projectFile.fileName() ) );
2821 QTemporaryFile tempFile;
2822 bool ok = tempFile.open();
2825 QTextStream projectFileStream( &tempFile );
2826 doc->save( projectFileStream, 2 );
2827 ok &= projectFileStream.pos() > -1;
2829 ok &= tempFile.seek( 0 );
2832 while ( ok && !tempFile.atEnd() )
2834 ba = tempFile.read( 10240 );
2835 ok &= projectFile.write( ba ) == ba.size();
2838 ok &= projectFile.error() == QFile::NoError;
2840 projectFile.close();
2847 setError( tr(
"Unable to save to file %1. Your project "
2848 "may be corrupted on disk. Try clearing some space on the volume and "
2849 "check file permissions before pressing save again." )
2850 .arg( projectFile.fileName() ) );
2862 bool propertiesModified;
2863 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2865 if ( propertiesModified )
2873 bool propertiesModified;
2874 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2876 if ( propertiesModified )
2884 bool propertiesModified;
2885 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2887 if ( propertiesModified )
2895 bool propertiesModified;
2896 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2898 if ( propertiesModified )
2906 bool propertiesModified;
2907 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2909 if ( propertiesModified )
2917 const QStringList &def,
2926 value =
property->value();
2928 const bool valid = QVariant::StringList == value.type();
2934 return value.toStringList();
2956 value =
property->value();
2958 const bool valid = value.canConvert( QVariant::String );
2963 return value.toString();
2980 value =
property->value();
2983 const bool valid = value.canConvert( QVariant::Int );
2992 return value.toInt();
3005 const QVariant value =
property->value();
3007 const bool valid = value.canConvert( QVariant::Double );
3012 return value.toDouble();
3027 const QVariant value =
property->value();
3029 const bool valid = value.canConvert( QVariant::Bool );
3034 return value.toBool();
3044 if (
findKey_( scope, key, mProperties ) )
3050 return !
findKey_( scope, key, mProperties );
3058 QStringList entries;
3060 if ( foundProperty )
3075 QStringList entries;
3077 if ( foundProperty )
3090 dump_( mProperties );
3108 filePath = storage->filePath( mFile.fileName() );
3131 void QgsProject::setError(
const QString &errorMessage )
3133 mErrorMessage = errorMessage;
3138 return mErrorMessage;
3141 void QgsProject::clearError()
3143 setError( QString() );
3148 delete mBadLayerHandler;
3149 mBadLayerHandler = handler;
3154 const QHash< QString, QPair< QString, bool > >::const_iterator it = mEmbeddedLayers.find(
id );
3155 if ( it == mEmbeddedLayers.constEnd() )
3159 return it.value().first;
3163 bool saveFlag, Qgis::ProjectReadFlags flags )
3167 static QString sPrevProjectFilePath;
3168 static QDateTime sPrevProjectFileTimestamp;
3169 static QDomDocument sProjectDocument;
3171 QString qgsProjectFile = projectFilePath;
3173 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3175 archive.
unzip( projectFilePath );
3179 const QDateTime projectFileTimestamp = QFileInfo( projectFilePath ).lastModified();
3181 if ( projectFilePath != sPrevProjectFilePath || projectFileTimestamp != sPrevProjectFileTimestamp )
3183 sPrevProjectFilePath.clear();
3185 QFile projectFile( qgsProjectFile );
3186 if ( !projectFile.open( QIODevice::ReadOnly ) )
3191 if ( !sProjectDocument.setContent( &projectFile ) )
3196 sPrevProjectFilePath = projectFilePath;
3197 sPrevProjectFileTimestamp = projectFileTimestamp;
3201 bool useAbsolutePaths =
true;
3203 const QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
3204 if ( !propertiesElem.isNull() )
3206 const QDomElement absElem = propertiesElem.firstChildElement( QStringLiteral(
"Paths" ) ).firstChildElement( QStringLiteral(
"Absolute" ) );
3207 if ( !absElem.isNull() )
3209 useAbsolutePaths = absElem.text().compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0;
3214 if ( !useAbsolutePaths )
3219 const QDomElement projectLayersElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) );
3220 if ( projectLayersElem.isNull() )
3225 QDomElement mapLayerElem = projectLayersElem.firstChildElement( QStringLiteral(
"maplayer" ) );
3226 while ( ! mapLayerElem.isNull() )
3229 const QString
id = mapLayerElem.firstChildElement( QStringLiteral(
"id" ) ).text();
3230 if (
id == layerId )
3233 if ( mapLayerElem.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
3238 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
3240 if ( addLayer( mapLayerElem, brokenNodes, embeddedContext,
flags ) )
3246 mEmbeddedLayers.remove( layerId );
3250 mapLayerElem = mapLayerElem.nextSiblingElement( QStringLiteral(
"maplayer" ) );
3259 QString qgsProjectFile = projectFilePath;
3261 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3263 archive.
unzip( projectFilePath );
3268 QFile projectFile( qgsProjectFile );
3269 if ( !projectFile.open( QIODevice::ReadOnly ) )
3274 QDomDocument projectDocument;
3275 if ( !projectDocument.setContent( &projectFile ) )
3287 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
3288 if ( !layerTreeElem.isNull() )
3298 if ( !group || group->
customProperty( QStringLiteral(
"embedded" ) ).toBool() )
3311 newGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectFilePath );
3314 mLayerTreeRegistryBridge->
setEnabled(
false );
3315 initializeEmbeddedSubtree( projectFilePath, newGroup,
flags );
3316 mLayerTreeRegistryBridge->
setEnabled(
true );
3319 const auto constFindLayerIds = newGroup->
findLayerIds();
3320 for (
const QString &layerId : constFindLayerIds )
3333 void QgsProject::initializeEmbeddedSubtree(
const QString &projectFilePath,
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
3335 const auto constChildren = group->
children();
3339 child->setCustomProperty( QStringLiteral(
"embedded" ), 1 );
3348 QList<QDomNode> brokenNodes;
3366 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), ( enabled ? 1 : 0 ) );
3372 return readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), 0 );
3377 const QString distanceUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), QString() );
3378 if ( !distanceUnitString.isEmpty() )
3394 const QString areaUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), QString() );
3395 if ( !areaUnitString.isEmpty() )
3411 if ( !mCachedHomePath.isEmpty() )
3412 return mCachedHomePath;
3416 if ( !mHomePath.isEmpty() )
3418 const QFileInfo homeInfo( mHomePath );
3419 if ( !homeInfo.isRelative() )
3421 mCachedHomePath = mHomePath;
3427 mCachedHomePath = pfi.path();
3429 return mCachedHomePath;
3432 if ( !pfi.exists() )
3434 mCachedHomePath = mHomePath;
3438 if ( !mHomePath.isEmpty() )
3441 mCachedHomePath = QDir::cleanPath( pfi.path() +
'/' + mHomePath );
3445 mCachedHomePath = pfi.canonicalPath();
3447 return mCachedHomePath;
3457 return mRelationManager;
3462 return mLayoutManager.get();
3467 return mLayoutManager.get();
3472 return m3DViewsManager.get();
3477 return m3DViewsManager.get();
3482 return mBookmarkManager;
3487 return mBookmarkManager;
3492 return mViewSettings;
3497 return mViewSettings;
3502 return mStyleSettings;
3507 return mStyleSettings;
3512 return mTimeSettings;
3517 return mTimeSettings;
3522 return mElevationProperties;
3527 return mElevationProperties;
3532 return mDisplaySettings;
3537 return mDisplaySettings;
3547 return mMapThemeCollection.get();
3552 return mAnnotationManager.get();
3557 return mAnnotationManager.get();
3562 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
3563 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
3568 if (
layers.contains( it.value() ) )
3583 for (
const QString &layerId : layerIds )
3599 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
3629 updateTransactionGroups();
3634 return mTransactionMode;
3643 const auto constLayers =
mapLayers().values();
3646 if ( layer->isEditable() )
3648 QgsLogger::warning( tr(
"Transaction mode can be changed only if all layers are not editable." ) );
3654 updateTransactionGroups();
3660 return mTransactionGroups;
3671 return mLayerStore->count();
3676 return mLayerStore->validCount();
3681 return mLayerStore->mapLayer( layerId );
3686 return mLayerStore->mapLayersByName( layerName );
3691 QList<QgsMapLayer *>
layers;
3692 const auto constMapLayers { mLayerStore->mapLayers() };
3693 for (
const auto &l : constMapLayers )
3695 if ( ! l->shortName().isEmpty() )
3697 if ( l->shortName() == shortName )
3700 else if ( l->name() == shortName )
3708 bool QgsProject::unzip(
const QString &filename, Qgis::ProjectReadFlags flags )
3714 if ( !archive->unzip( filename ) )
3716 setError( tr(
"Unable to unzip file '%1'" ).arg( filename ) );
3721 if ( archive->projectFile().isEmpty() )
3723 setError( tr(
"Zip archive does not provide a project file" ) );
3728 mArchive = std::move( archive );
3745 setError( tr(
"Cannot read unzipped qgs project file" ) );
3755 bool QgsProject::zip(
const QString &filename )
3761 const QString
baseName = QFileInfo( filename ).baseName();
3762 const QString qgsFileName = QStringLiteral(
"%1.qgs" ).arg(
baseName );
3763 QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
3765 bool writeOk =
false;
3766 if ( qgsFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3768 writeOk = writeProjectFile( qgsFile.fileName() );
3775 setError( tr(
"Unable to write temporary qgs file" ) );
3780 const QFileInfo info( qgsFile );
3782 const QString asFileName = info.path() + QDir::separator() + info.completeBaseName() + asExt;
3784 bool auxiliaryStorageSavedOk =
true;
3785 if ( ! saveAuxiliaryStorage( asFileName ) )
3787 const QString err = mAuxiliaryStorage->errorString();
3788 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 ) );
3789 auxiliaryStorageSavedOk =
false;
3792 if ( !mArchive->exists() )
3795 mArchive->unzip( mFile.fileName() );
3798 const QString auxiliaryStorageFile =
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile();
3799 if ( ! auxiliaryStorageFile.isEmpty() )
3801 archive->
addFile( auxiliaryStorageFile );
3810 if ( QFile::exists( asFileName ) )
3812 archive->addFile( asFileName );
3817 archive->addFile( qgsFile.fileName() );
3820 const QStringList &files = mArchive->files();
3821 for (
const QString &file : files )
3823 if ( !file.endsWith( QLatin1String(
".qgs" ), Qt::CaseInsensitive ) && !file.endsWith( asExt, Qt::CaseInsensitive ) )
3825 archive->addFile( file );
3831 if ( !archive->zip( filename ) )
3833 setError( tr(
"Unable to perform zip" ) );
3837 return auxiliaryStorageSavedOk && zipOk;
3846 const QList<QgsMapLayer *> &layers,
3848 bool takeOwnership )
3850 const QList<QgsMapLayer *> myResultList { mLayerStore->addMapLayers(
layers, takeOwnership ) };
3851 if ( !myResultList.isEmpty() )
3854 for (
auto &l : myResultList )
3864 if ( mAuxiliaryStorage )
3879 mProjectScope.reset();
3881 return myResultList;
3887 bool takeOwnership )
3889 QList<QgsMapLayer *> addedLayers;
3890 addedLayers =
addMapLayers( QList<QgsMapLayer *>() << layer, addToLegend, takeOwnership );
3891 return addedLayers.isEmpty() ? nullptr : addedLayers[0];
3896 mProjectScope.reset();
3897 mLayerStore->removeMapLayers( layerIds );
3902 mProjectScope.reset();
3903 mLayerStore->removeMapLayers(
layers );
3908 mProjectScope.reset();
3909 mLayerStore->removeMapLayer( layerId );
3914 mProjectScope.reset();
3915 mLayerStore->removeMapLayer( layer );
3920 mProjectScope.reset();
3921 return mLayerStore->takeMapLayer( layer );
3926 return mMainAnnotationLayer;
3931 if ( mLayerStore->count() == 0 )
3934 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
3935 mProjectScope.reset();
3936 mLayerStore->removeAllMapLayers();
3938 snapSingleBlocker.release();
3940 if ( !mBlockSnappingUpdates )
3946 const QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
3947 QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin();
3948 for ( ; it !=
layers.constEnd(); ++it )
3950 it.value()->reload();
3956 return validOnly ? mLayerStore->validMapLayers() : mLayerStore->mapLayers();
3961 return mTransactionGroups.value( qMakePair( providerKey, connString ) );
3966 return &mEditBufferGroup;
3975 if ( mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), QStringLiteral(
"NoAction" ),
QgsSettings::App ).toString() == QStringLiteral(
"UseProjectCrs" )
3976 || mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), 0,
QgsSettings::App ).toString() == QLatin1String(
"2" ) )
3984 const QString layerDefaultCrs = mSettings.
value( QStringLiteral(
"/Projections/layerDefaultCrs" ),
geoEpsgCrsAuthId() ).toString();
4001 bool QgsProject::saveAuxiliaryStorage(
const QString &filename )
4005 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4010 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
4018 if ( !mAuxiliaryStorage->exists( *
this ) && empty )
4022 else if ( !filename.isEmpty() )
4024 return mAuxiliaryStorage->saveAs( filename );
4028 return mAuxiliaryStorage->saveAs( *
this );
4037 QgsProject::DataDefinedServerProperty::WMSOnlineResource,
4041 return sPropertyDefinitions;
4046 return mAuxiliaryStorage.get();
4051 return mAuxiliaryStorage.get();
4056 const QDir archiveDir( mArchive->dir() );
4057 QTemporaryFile tmpFile( archiveDir.filePath(
"XXXXXX_" + nameTemplate ),
this );
4058 tmpFile.setAutoRemove(
false );
4060 mArchive->addFile( tmpFile.fileName() );
4061 return tmpFile.fileName();
4066 QStringList attachments;
4068 const QStringList files = mArchive->files();
4069 attachments.reserve( files.size() );
4070 for (
const QString &file : files )
4074 attachments.append( file );
4082 return mArchive->removeFile( path );
4087 return QStringLiteral(
"attachment:///%1" ).arg( QFileInfo( attachedFile ).
fileName() );
4092 if ( identifier.startsWith( QLatin1String(
"attachment:///" ) ) )
4094 return QDir( mArchive->dir() ).absoluteFilePath( identifier.mid( 14 ) );
4110 mProjectScope.reset();
4122 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4134 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
4135 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
4140 if (
layers.contains( it.value() ) )
4150 QStringList customColors;
4151 QStringList customColorLabels;
4153 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
4154 for ( ; colorIt != colors.constEnd(); ++colorIt )
4157 const QString label = ( *colorIt ).second;
4158 customColors.append( color );
4159 customColorLabels.append( label );
4161 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ), customColors );
4162 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ), customColorLabels );
4163 mProjectScope.reset();
4169 if ( mBackgroundColor == color )
4172 mBackgroundColor = color;
4178 return mBackgroundColor;
4183 if ( mSelectionColor == color )
4186 mSelectionColor = color;
4192 return mSelectionColor;
4226 QString
QgsProject::translate(
const QString &context,
const QString &sourceText,
const char *disambiguation,
int n )
const
4233 QString result = mTranslator->translate( context.toUtf8(), sourceText.toUtf8(), disambiguation, n );
4235 if ( result.isEmpty() )
4247 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4252 if ( !( ( *it )->accept( visitor ) ) )
4261 if ( !mLayoutManager->accept( visitor ) )
4264 if ( !mAnnotationManager->accept( visitor ) )
4271 GetNamedProjectColor::GetNamedProjectColor(
const QgsProject *project )
4278 QStringList colorStrings = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ) );
4279 const QStringList colorLabels = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ) );
4283 for ( QStringList::iterator it = colorStrings.begin();
4284 it != colorStrings.end(); ++it )
4288 if ( colorLabels.length() > colorIndex )
4290 label = colorLabels.at( colorIndex );
4293 mColors.insert( label.toLower(), color );
4298 GetNamedProjectColor::GetNamedProjectColor(
const QHash<QString, QColor> &colors )
4306 const QString colorName = values.at( 0 ).toString().toLower();
4307 if ( mColors.contains( colorName ) )
4309 return QStringLiteral(
"%1,%2,%3" ).arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
4317 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.
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.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
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.
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 QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
QList< QgsMapLayer * > customLayerOrder() const
The order in which layers will be rendered on the canvas.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
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.
QgsProjectPropertyKey * addKey(const QString &keyName)
Adds the specified property key as a sub-key.
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.
QgsProjectProperty * find(const QString &propertyName) const
Attempts to find a property with a matching sub-key name.
void setName(const QString &name)
The name of the property is used as identifier.
QVariant value() const override
If this key has a value, it will be stored by its name in its properties.
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.
QgsProjectPropertyValue * setValue(const QString &name, const QVariant &value)
Sets the value associated with this key.
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.
QgsProject(QObject *parent=nullptr)
Create a new QgsProject.
bool removeAttachedFile(const QString &path)
Removes the attached file.
QgsRelationManager * relationManager
bool write()
Writes the project to its current associated file (see fileName() ).
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.
QVector< T > layers() const
Returns a list of registered map layers with a specified layer type.
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.
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"...
QgsProjectProperty * findKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
Returns the property that matches the given key sequence, if any.
void removeKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
Removes a given key.
QgsProjectProperty * addKey_(const QString &scope, const QString &key, QgsProjectPropertyKey *rootProperty, const QVariant &value, bool &propertiesModified)
Adds the given key and value.
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)
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.