75#include <QApplication>
80#include <QTemporaryFile>
83#include <QStandardPaths>
85#include <QRegularExpression>
106 QStringList keyTokens = QStringList( scope );
107#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
108 keyTokens += key.split(
'/', QString::SkipEmptyParts );
110 keyTokens += key.split(
'/', Qt::SkipEmptyParts );
114 keyTokens.push_front( QStringLiteral(
"properties" ) );
117 for (
int i = 0; i < keyTokens.size(); ++i )
119 const QString keyToken = keyTokens.at( i );
123 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}])" ) );
124 if ( keyToken.contains( sInvalidRegexp ) )
126 const QString errorString = QObject::tr(
"Entry token invalid : '%1'. The token will not be saved to file." ).arg( keyToken );
154 while ( !keySequence.isEmpty() )
158 if ( keySequence.first() == currentProperty->
name() )
161 keySequence.pop_front();
163 if ( 1 == keySequence.count() )
166 return currentProperty->
find( keySequence.front() );
168 else if ( keySequence.isEmpty() )
173 return currentProperty;
175 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
177 if ( nextProperty->
isKey() )
181 else if ( nextProperty->
isValue() && 1 == keySequence.count() )
187 return currentProperty;
225 const QVariant &value,
226 bool &propertiesModified )
235 propertiesModified =
false;
236 while ( ! keySequence.isEmpty() )
240 if ( keySequence.first() == currentProperty->
name() )
243 keySequence.pop_front();
247 if ( 1 == keySequence.count() )
250 if ( !property || property->value() != value )
252 currentProperty->
setValue( keySequence.front(), value );
253 propertiesModified =
true;
256 return currentProperty;
260 else if ( keySequence.isEmpty() )
262 if ( currentProperty->
value() != value )
265 propertiesModified =
true;
268 return currentProperty;
270 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
274 if ( currentProperty )
285 if ( ( newPropertyKey = currentProperty->
addKey( keySequence.first() ) ) )
287 currentProperty = newPropertyKey;
319 while ( ! keySequence.isEmpty() )
323 if ( keySequence.first() == currentProperty->
name() )
326 keySequence.pop_front();
330 if ( 1 == keySequence.count() )
332 currentProperty->
removeKey( keySequence.front() );
337 else if ( keySequence.isEmpty() )
339 previousQgsPropertyKey->
removeKey( currentProperty->
name() );
341 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
343 previousQgsPropertyKey = currentProperty;
346 if ( currentProperty )
370 , mCapabilities( capabilities )
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 mStyleSettings->combinedStyleModel()->addDefaultStyle();
458 mIsBeingDeleted =
true;
461 delete mBadLayerHandler;
462 delete mRelationManager;
463 delete mLayerTreeRegistryBridge;
465 if (
this == sProject )
494 mProjectScope.reset();
502 return mMetadata.
title();
509 if ( oldEvaluateDefaultValues != newEvaluateDefaultValues )
512 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
514 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
523 if ( oldTrustLayerMetadata != newTrustLayerMetadata )
526 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
528 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
530 vl->setReadExtentFromXml( newTrustLayerMetadata );
540 Qgis::ProjectFlags newFlags = mFlags;
544 newFlags &= ~(
static_cast< int >( flag ) );
555 return mSaveUserFull;
560 return mSaveDateTime;
575 if ( dirty && mDirtyBlockCount > 0 )
581 if ( mDirty == dirty )
590 if ( path == mHomePath )
594 mCachedHomePath.clear();
595 mProjectScope.reset();
604 const QList<QgsAttributeEditorElement *> elements = parent->
children();
612 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:formcontainers" ).arg( layerId ), container->
name() );
614 if ( !container->
children().empty() )
627 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1" ).arg( layer->layerId() ), layer->name() );
644 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( vlayer->
id() ), fieldName );
659 const QList<QgsLayerTreeGroup *> groupLayers = mRootGroup->
findGroups();
662 translationContext->
registerTranslation( QStringLiteral(
"project:layergroups" ), groupLayer->name() );
666 const QList<QgsRelation> &relations = mRelationManager->
relations().values();
669 translationContext->
registerTranslation( QStringLiteral(
"project:relations" ), relation.name() );
675 mDataDefinedServerProperties = properties;
680 return mDataDefinedServerProperties;
685 switch ( mTransactionMode )
704 switch ( mTransactionMode )
711 commitErrors.append( tr(
"Trying to commit changes without a layer specified. This only works if the transaction mode is buffered" ) );
720 return mEditBufferGroup.
commitChanges( commitErrors, stopEditing );
728 switch ( mTransactionMode )
735 rollbackErrors.append( tr(
"Trying to roll back changes without a layer specified. This only works if the transaction mode is buffered" ) );
738 bool success = vectorLayer->
rollBack( stopEditing );
744 return mEditBufferGroup.
rollBack( rollbackErrors, stopEditing );
752 if ( name == mFile.fileName() )
755 const QString oldHomePath =
homePath();
757 mFile.setFileName( name );
758 mCachedHomePath.clear();
759 mProjectScope.reset();
763 const QString newHomePath =
homePath();
764 if ( newHomePath != oldHomePath )
772 return mFile.fileName();
777 mOriginalPath = path;
782 return mOriginalPath;
787 return QFileInfo( mFile );
800 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
805 return QFileInfo( mFile.fileName() ).lastModified();
814 if ( mFile.fileName().isEmpty() )
817 return QFileInfo( mFile.fileName() ).absolutePath();
825 if ( mFile.fileName().isEmpty() )
828 return QFileInfo( mFile.fileName() ).absoluteFilePath();
836 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
841 return QFileInfo( mFile.fileName() ).completeBaseName();
847 const bool absolutePaths =
readBoolEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
856 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
true );
859 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
874 writeEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ),
crs.
isValid() ? 1 : 0 );
875 mProjectScope.reset();
886 if ( adjustEllipsoid )
892 if ( !
crs().isValid() )
895 return readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ),
geoNone() );
900 if (
ellipsoid ==
readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ) ) )
903 mProjectScope.reset();
910 return mTransformContext;
915 if ( context == mTransformContext )
918 mTransformContext = context;
919 mProjectScope.reset();
922 for (
auto &layer : mLayerStore.get()->mapLayers() )
924 layer->setTransformContext( context );
931 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
933 mProjectScope.reset();
934 mFile.setFileName( QString() );
937 mSaveUserFull.clear();
938 mSaveDateTime = QDateTime();
941 mCachedHomePath.clear();
943 mFlags = Qgis::ProjectFlags();
945 mCustomVariables.clear();
948 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_new_projects" ),
false,
QgsSettings::Core ).toBool() )
967 mEmbeddedLayers.clear();
968 mRelationManager->
clear();
969 mAnnotationManager->clear();
970 mLayoutManager->clear();
971 m3DViewsManager->clear();
972 mBookmarkManager->
clear();
973 mViewSettings->
reset();
974 mTimeSettings->
reset();
975 mElevationProperties->
reset();
976 mDisplaySettings->
reset();
977 mSnappingConfig.
reset();
985 mLabelingEngineSettings->clear();
991 mStyleSettings->
reset();
995 if ( !mIsBeingDeleted )
1003 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/Automatic" ),
true );
1004 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/DecimalPlaces" ), 2 );
1006 const bool defaultRelativePaths = mSettings.
value( QStringLiteral(
"/qgis/defaultProjectPathsRelative" ),
true ).toBool();
1009 int red = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_red" ), 255 ).toInt();
1010 int green = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_green" ), 255 ).toInt();
1011 int blue = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_blue" ), 255 ).toInt();
1014 red = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_red" ), 255 ).toInt();
1015 green = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_green" ), 255 ).toInt();
1016 blue = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_blue" ), 0 ).toInt();
1017 const int alpha = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_alpha" ), 255 ).toInt();
1023 mRootGroup->
clear();
1024 if ( mMainAnnotationLayer )
1025 mMainAnnotationLayer->
reset();
1027 snapSingleBlocker.release();
1029 if ( !mBlockSnappingUpdates )
1041 topQgsPropertyKey.
dump();
1074 const QDomElement propertiesElem = doc.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
1076 if ( propertiesElem.isNull() )
1081 const QDomNodeList scopes = propertiesElem.childNodes();
1083 if ( propertiesElem.firstChild().isNull() )
1085 QgsDebugMsg( QStringLiteral(
"empty ``properties'' XML tag ... bailing" ) );
1089 if ( ! project_properties.
readXml( propertiesElem ) )
1091 QgsDebugMsg( QStringLiteral(
"Project_properties.readXml() failed" ) );
1105 const QDomElement ddElem = doc.documentElement().firstChildElement( QStringLiteral(
"dataDefinedServerProperties" ) );
1106 if ( !ddElem.isNull() )
1108 if ( !ddServerProperties.
readXml( ddElem, dataDefinedServerPropertyDefinitions ) )
1110 QgsDebugMsg( QStringLiteral(
"dataDefinedServerProperties.readXml() failed" ) );
1113 return ddServerProperties;
1120static void _getTitle(
const QDomDocument &doc, QString &title )
1122 const QDomElement titleNode = doc.documentElement().firstChildElement( QStringLiteral(
"title" ) );
1126 if ( titleNode.isNull() )
1132 if ( !titleNode.hasChildNodes() )
1138 const QDomNode titleTextNode = titleNode.firstChild();
1140 if ( !titleTextNode.isText() )
1146 const QDomText titleText = titleTextNode.toText();
1148 title = titleText.data();
1152static void readProjectFileMetadata(
const QDomDocument &doc, QString &lastUser, QString &lastUserFull, QDateTime &lastSaveDateTime )
1154 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1158 QgsDebugMsg( QStringLiteral(
"unable to find qgis element" ) );
1162 const QDomNode qgisNode = nl.item( 0 );
1164 const QDomElement qgisElement = qgisNode.toElement();
1165 lastUser = qgisElement.attribute( QStringLiteral(
"saveUser" ), QString() );
1166 lastUserFull = qgisElement.attribute( QStringLiteral(
"saveUserFull" ), QString() );
1167 lastSaveDateTime = QDateTime::fromString( qgisElement.attribute( QStringLiteral(
"saveDateTime" ), QString() ), Qt::ISODate );
1173 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1177 QgsDebugMsg( QStringLiteral(
" unable to find qgis element in project file" ) );
1181 const QDomNode qgisNode = nl.item( 0 );
1183 const QDomElement qgisElement = qgisNode.toElement();
1184 QgsProjectVersion projectVersion( qgisElement.attribute( QStringLiteral(
"version" ) ) );
1185 return projectVersion;
1191 return mSnappingConfig;
1206 if ( mAvoidIntersectionsMode == mode )
1209 mAvoidIntersectionsMode = mode;
1213bool QgsProject::_getMapLayers(
const QDomDocument &doc, QList<QDomNode> &brokenNodes, Qgis::ProjectReadFlags flags )
1218 QDomElement layerElement = doc.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
1222 if ( layerElement.isNull() )
1232 bool returnStatus =
true;
1235 while ( ! layerElement.isNull() )
1238 layerElement = layerElement.nextSiblingElement( QStringLiteral(
"maplayer" ) );
1244 if ( depSorter.hasCycle() )
1248 if ( depSorter.hasMissingDependency() )
1249 returnStatus =
false;
1253 const QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
1254 const int totalLayerCount = sortedLayerNodes.count();
1257 for (
const QDomNode &node : sortedLayerNodes )
1259 const QDomElement element = node.toElement();
1261 const QString name =
translate( QStringLiteral(
"project:layers:%1" ).arg( node.namedItem( QStringLiteral(
"id" ) ).toElement().text() ), node.namedItem( QStringLiteral(
"layername" ) ).toElement().text() );
1262 if ( !name.isNull() )
1263 emit
loadingLayer( tr(
"Loading layer %1" ).arg( name ) );
1265 profile.switchTask( name );
1267 if ( element.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
1269 createEmbeddedLayer( element.attribute( QStringLiteral(
"id" ) ),
readPath( element.attribute( QStringLiteral(
"project" ) ) ), brokenNodes,
true,
flags );
1278 if ( !addLayer( element, brokenNodes, context,
flags ) )
1280 returnStatus =
false;
1283 if ( !messages.isEmpty() )
1292 return returnStatus;
1295bool QgsProject::addLayer(
const QDomElement &layerElem, QList<QDomNode> &brokenNodes,
QgsReadWriteContext &context, Qgis::ProjectReadFlags flags )
1297 const QString type = layerElem.attribute( QStringLiteral(
"type" ) );
1299 std::unique_ptr<QgsMapLayer>
mapLayer;
1307 QgsDebugMsg( QStringLiteral(
"Unknown layer type \"%1\"" ).arg( type ) );
1311 switch ( layerType )
1315 mapLayer = std::make_unique<QgsVectorLayer>();
1325 mapLayer = std::make_unique<QgsRasterLayer>();
1329 mapLayer = std::make_unique<QgsMeshLayer>();
1333 mapLayer = std::make_unique<QgsVectorTileLayer>();
1337 mapLayer = std::make_unique<QgsPointCloudLayer>();
1342 const QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
1350 mapLayer = std::make_unique<QgsAnnotationLayer>( QString(), options );
1357 mapLayer = std::make_unique<QgsGroupLayer>( QString(), options );
1364 QgsDebugMsg( QStringLiteral(
"Unable to create layer" ) );
1372 const QString layerId { layerElem.namedItem( QStringLiteral(
"id" ) ).toElement().text() };
1373 Q_ASSERT( ! layerId.isEmpty() );
1377 QgsMapLayer::ReadFlags layerFlags = QgsMapLayer::ReadFlags();
1378 if (
flags & Qgis::ProjectReadFlag::DontResolveLayers )
1387 profile.switchTask( tr(
"Load layer source" ) );
1390 profile.switchTask( tr(
"Add layer to project" ) );
1391 QList<QgsMapLayer *> newLayers;
1393 if ( layerIsValid ||
flags & Qgis::ProjectReadFlag::DontResolveLayers )
1403 vLayer->joinBuffer()->resolveReferences(
this );
1411 QgsDebugMsg(
"Unable to load " + type +
" layer" );
1412 brokenNodes.push_back( layerElem );
1415 const bool wasEditable = layerElem.attribute( QStringLiteral(
"editable" ), QStringLiteral(
"0" ) ).toInt();
1427 if ( ! layerWasStored )
1432 return layerIsValid;
1437 mFile.setFileName( filename );
1438 mCachedHomePath.clear();
1439 mProjectScope.reset();
1446 const QString filename = mFile.fileName();
1451 QTemporaryFile inDevice;
1452 if ( !inDevice.open() )
1454 setError( tr(
"Unable to open %1" ).arg( inDevice.fileName() ) );
1460 if ( !storage->readProject( filename, &inDevice, context ) )
1462 QString err = tr(
"Unable to open %1" ).arg( filename );
1463 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
1464 if ( !messages.isEmpty() )
1465 err += QStringLiteral(
"\n\n" ) + messages.last().message();
1469 returnValue = unzip( inDevice.fileName(),
flags );
1475 returnValue = unzip( mFile.fileName(),
flags );
1480 const QFileInfo finfo( mFile.fileName() );
1481 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
1482 if ( QFile( attachmentsZip ).exists() )
1484 std::unique_ptr<QgsArchive> archive(
new QgsArchive() );
1485 if ( archive->unzip( attachmentsZip ) )
1487 mArchive = std::move( archive );
1490 returnValue = readProjectFile( mFile.fileName(),
flags );
1496 mFile.setFileName( filename );
1497 mCachedHomePath.clear();
1498 mProjectScope.reset();
1503 mTranslator.reset(
nullptr );
1510bool QgsProject::readProjectFile(
const QString &filename, Qgis::ProjectReadFlags flags )
1513 ScopedIntIncrementor snapSignalBlock( &mBlockSnappingUpdates );
1515 QFile projectFile( filename );
1523 if ( QFile( QStringLiteral(
"%1/%2.qm" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) ).exists() )
1525 mTranslator.reset(
new QTranslator() );
1526 ( void )mTranslator->load( localeFileName, QFileInfo( projectFile.fileName() ).absolutePath() );
1529 profile.switchTask( tr(
"Reading project file" ) );
1530 std::unique_ptr<QDomDocument> doc(
new QDomDocument( QStringLiteral(
"qgis" ) ) );
1532 if ( !projectFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
1534 projectFile.close();
1536 setError( tr(
"Unable to open %1" ).arg( projectFile.fileName() ) );
1545 if ( !doc->setContent( &projectFile, &errorMsg, &line, &column ) )
1547 const QString errorString = tr(
"Project file read error in file %1: %2 at line %3 column %4" )
1548 .arg( projectFile.fileName(), errorMsg ).arg( line ).arg( column );
1552 projectFile.close();
1554 setError( tr(
"%1 for file %2" ).arg( errorString, projectFile.fileName() ) );
1559 projectFile.close();
1567 profile.switchTask( tr(
"Updating project file" ) );
1568 if ( thisVersion > fileVersion )
1570 const bool isOlderMajorVersion = fileVersion.
majorVersion() < thisVersion.majorVersion();
1572 if ( isOlderMajorVersion )
1575 "version of qgis (saved in " + fileVersion.
text() +
1577 "). Problems may occur." );
1588 projectFile.updateRevision( thisVersion );
1590 else if ( fileVersion > thisVersion )
1593 "version of qgis (saved in " + fileVersion.
text() +
1595 "). Problems may occur." );
1601 profile.switchTask( tr(
"Creating auxiliary storage" ) );
1602 const QString
fileName = mFile.fileName();
1603 std::unique_ptr<QgsAuxiliaryStorage> aStorage = std::move( mAuxiliaryStorage );
1604 std::unique_ptr<QgsArchive> archive = std::move( mArchive );
1606 mAuxiliaryStorage = std::move( aStorage );
1607 mArchive = std::move( archive );
1609 mCachedHomePath.clear();
1610 mProjectScope.reset();
1611 mSaveVersion = fileVersion;
1614 profile.switchTask( tr(
"Reading properties" ) );
1623 dump_( mProperties );
1628 _getTitle( *doc, oldTitle );
1630 readProjectFileMetadata( *doc, mSaveUser, mSaveUserFull, mSaveDateTime );
1632 const QDomNodeList homePathNl = doc->elementsByTagName( QStringLiteral(
"homePath" ) );
1633 if ( homePathNl.count() > 0 )
1635 const QDomElement homePathElement = homePathNl.at( 0 ).toElement();
1636 const QString
homePath = homePathElement.attribute( QStringLiteral(
"path" ) );
1646 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), 255 ),
1647 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), 255 ) );
1650 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), 255 ),
1651 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), 255 ),
1652 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), 255 ) );
1656 const QString distanceUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), QString() );
1657 if ( !distanceUnitString.isEmpty() )
1660 const QString areaUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), QString() );
1661 if ( !areaUnitString.isEmpty() )
1670 if (
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ), 0 ) )
1673 const QDomNode srsNode = doc->documentElement().namedItem( QStringLiteral(
"projectCrs" ) );
1674 if ( !srsNode.isNull() )
1676 projectCrs.
readXml( srsNode );
1681 const QString projCrsString =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSProj4String" ) );
1682 const long currentCRS =
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSID" ), -1 );
1683 const QString authid =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCrs" ) );
1686 const bool isUserAuthId = authid.startsWith( QLatin1String(
"USER:" ), Qt::CaseInsensitive );
1687 if ( !authid.isEmpty() && !isUserAuthId )
1691 if ( !projectCrs.
isValid() && currentCRS >= 0 )
1697 if ( !projCrsString.isEmpty() && ( authid.isEmpty() || isUserAuthId ) && ( !projectCrs.
isValid() || projectCrs.
toProj() != projCrsString ) )
1711 QStringList datumErrors;
1712 if ( !mTransformContext.
readXml( doc->documentElement(), context, datumErrors ) && !datumErrors.empty() )
1720 const QStringList variableNames =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ) );
1721 const QStringList variableValues =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ) );
1723 mCustomVariables.clear();
1724 if ( variableNames.length() == variableValues.length() )
1726 for (
int i = 0; i < variableNames.length(); ++i )
1728 mCustomVariables.insert( variableNames.at( i ), variableValues.at( i ) );
1733 QgsMessageLog::logMessage( tr(
"Project Variables Invalid" ), tr(
"The project contains invalid variable settings." ) );
1736 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectMetadata" ) );
1738 if ( !element.isNull() )
1747 if ( mMetadata.
title().isEmpty() && !oldTitle.isEmpty() )
1755 element = doc->documentElement().firstChildElement( QStringLiteral(
"transaction" ) );
1756 if ( !element.isNull() )
1763 element = doc->documentElement().firstChildElement( QStringLiteral(
"autotransaction" ) );
1764 if ( ! element.isNull() )
1766 mTransactionMode =
static_cast<Qgis::TransactionMode>( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() );
1771 profile.switchTask( tr(
"Loading layer tree" ) );
1774 QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
1775 if ( !layerTreeElem.isNull() )
1787 mLayerTreeRegistryBridge->
setEnabled(
false );
1790 profile.switchTask( tr(
"Reading map layers" ) );
1792 QList<QDomNode> brokenNodes;
1793 const bool clean = _getMapLayers( *doc, brokenNodes,
flags );
1796 if ( !clean && !(
flags & Qgis::ProjectReadFlag::DontResolveLayers ) )
1798 QgsDebugMsg( QStringLiteral(
"Unable to get map layers from project file." ) );
1800 if ( !brokenNodes.isEmpty() )
1802 QgsDebugMsg(
"there are " + QString::number( brokenNodes.size() ) +
" broken layers" );
1810 mMainAnnotationLayer->
readLayerXml( doc->documentElement().firstChildElement( QStringLiteral(
"main-annotation-layer" ) ), context );
1814 profile.switchTask( tr(
"Loading embedded layers" ) );
1815 loadEmbeddedNodes( mRootGroup,
flags );
1819 profile.switchTask( tr(
"Resolving layer references" ) );
1820 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
1821 for ( QMap<QString, QgsMapLayer *>::iterator it =
layers.begin(); it !=
layers.end(); ++it )
1823 it.value()->resolveReferences(
this );
1826 mLayerTreeRegistryBridge->
setEnabled(
true );
1829 profile.switchTask( tr(
"Resolving references" ) );
1832 loadProjectFlags( doc.get() );
1834 if ( !layerTreeElem.isNull() )
1840 const QDomElement layerTreeCanvasElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-canvas" ) );
1841 if ( !layerTreeCanvasElem.isNull( ) )
1849 const QStringList requiredLayerIds =
readListEntry( QStringLiteral(
"RequiredLayers" ), QStringLiteral(
"Layers" ) );
1850 for (
const QString &layerId : requiredLayerIds )
1857 const QStringList disabledLayerIds =
readListEntry( QStringLiteral(
"Identify" ), QStringLiteral(
"/disabledLayers" ) );
1858 for (
const QString &layerId : disabledLayerIds )
1871 QString styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1872 if ( !styleName.isEmpty() )
1877 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
1878 if ( !styleName.isEmpty() )
1883 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
1884 if ( !styleName.isEmpty() )
1889 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
1890 if ( !styleName.isEmpty() )
1900 double opacity = 1.0;
1903 double alpha =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ), 255, &ok );
1905 opacity = alpha / 255.0;
1906 double newOpacity =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ), 1.0, &ok );
1908 opacity = newOpacity;
1912 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1913 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
1914 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
1915 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
1916 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/RandomColors" ) );
1917 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ) );
1918 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ) );
1924 if ( !(
flags & Qgis::ProjectReadFlag::DontStoreOriginalStyles ) )
1926 profile.switchTask( tr(
"Storing original layer properties" ) );
1932 profile.switchTask( tr(
"Loading map themes" ) );
1935 mMapThemeCollection->readXml( *doc );
1937 profile.switchTask( tr(
"Loading label settings" ) );
1938 mLabelingEngineSettings->readSettingsFromProject(
this );
1941 profile.switchTask( tr(
"Loading annotations" ) );
1942 mAnnotationManager->readXml( doc->documentElement(), context );
1943 if ( !(
flags & Qgis::ProjectReadFlag::DontLoadLayouts ) )
1945 profile.switchTask( tr(
"Loading layouts" ) );
1946 mLayoutManager->readXml( doc->documentElement(), *doc );
1949 if ( !(
flags & Qgis::ProjectReadFlag::DontLoad3DViews ) )
1951 profile.switchTask( tr(
"Loading 3D Views" ) );
1952 m3DViewsManager->readXml( doc->documentElement(), *doc );
1955 profile.switchTask( tr(
"Loading bookmarks" ) );
1956 mBookmarkManager->
readXml( doc->documentElement(), *doc );
1959 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
1960 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); ++it )
1962 it.value()->setDependencies( it.value()->dependencies() );
1965 profile.switchTask( tr(
"Loading snapping settings" ) );
1969 profile.switchTask( tr(
"Loading view settings" ) );
1972 const QStringList scales =
readListEntry( QStringLiteral(
"Scales" ), QStringLiteral(
"/ScalesList" ) );
1973 QVector<double> res;
1974 for (
const QString &scale : scales )
1976 const QStringList parts = scale.split(
':' );
1977 if ( parts.size() != 2 )
1981 const double denominator = QLocale().toDouble( parts[1], &ok );
1988 const QDomElement viewSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectViewSettings" ) );
1989 if ( !viewSettingsElement.isNull() )
1990 mViewSettings->
readXml( viewSettingsElement, context );
1993 profile.switchTask( tr(
"Loading style properties" ) );
1994 const QDomElement styleSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectStyleSettings" ) );
1995 if ( !styleSettingsElement.isNull() )
1996 mStyleSettings->
readXml( styleSettingsElement, context,
flags );
1999 profile.switchTask( tr(
"Loading temporal settings" ) );
2000 const QDomElement timeSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectTimeSettings" ) );
2001 if ( !timeSettingsElement.isNull() )
2002 mTimeSettings->
readXml( timeSettingsElement, context );
2005 profile.switchTask( tr(
"Loading elevation properties" ) );
2006 const QDomElement elevationPropertiesElement = doc->documentElement().firstChildElement( QStringLiteral(
"ElevationProperties" ) );
2007 if ( !elevationPropertiesElement.isNull() )
2008 mElevationProperties->
readXml( elevationPropertiesElement, context );
2011 profile.switchTask( tr(
"Loading display settings" ) );
2012 const QDomElement displaySettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectDisplaySettings" ) );
2013 if ( !displaySettingsElement.isNull() )
2014 mDisplaySettings->
readXml( displaySettingsElement, context );
2016 profile.switchTask( tr(
"Updating variables" ) );
2018 profile.switchTask( tr(
"Updating CRS" ) );
2023 profile.switchTask( tr(
"Reading external settings" ) );
2027 profile.switchTask( tr(
"Updating interface" ) );
2029 snapSignalBlock.release();
2030 if ( !mBlockSnappingUpdates )
2041 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUser ), 2 );
2042 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUserFull ), 2 );
2051 const QString newFileName( QStringLiteral(
"%1/%2.qgs" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) );
2057 QgsMessageLog::logMessage( tr(
"Translated project saved with locale prefix %1" ).arg( newFileName ), QObject::tr(
"Project translation" ), Qgis::MessageLevel::Success );
2061 QgsMessageLog::logMessage( tr(
"Error saving translated project with locale prefix %1" ).arg( newFileName ), QObject::tr(
"Project translation" ), Qgis::MessageLevel::Critical );
2066 const QMap<QString, QgsMapLayer *> loadedLayers =
mapLayers();
2067 for (
auto it = loadedLayers.constBegin(); it != loadedLayers.constEnd(); ++it )
2069 if ( it.value()->isValid() && it.value()->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2071 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( it.value() ) )
2073 it.value()->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2081bool QgsProject::loadEmbeddedNodes(
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
2084 const auto constChildren = group->
children();
2090 if ( childGroup->
customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2093 const QString projectPath =
readPath( childGroup->
customProperty( QStringLiteral(
"embedded_project" ) ).toString() );
2094 childGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectPath );
2098 QList<QgsLayerTreeNode *> clonedChildren;
2099 const QList<QgsLayerTreeNode *> constChildren = newGroup->
children();
2100 clonedChildren.reserve( constChildren.size() );
2102 clonedChildren << newGroupChild->clone();
2110 loadEmbeddedNodes( childGroup,
flags );
2115 if ( child->customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2117 QList<QDomNode> brokenNodes;
2120 valid = valid &&
false;
2132 return mCustomVariables;
2137 if ( variables == mCustomVariables )
2141 QStringList variableNames;
2142 QStringList variableValues;
2144 QVariantMap::const_iterator it = variables.constBegin();
2145 for ( ; it != variables.constEnd(); ++it )
2147 variableNames << it.key();
2148 variableValues << it.value().toString();
2151 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ), variableNames );
2152 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ), variableValues );
2154 mCustomVariables = variables;
2155 mProjectScope.reset();
2162 *mLabelingEngineSettings = settings;
2168 return *mLabelingEngineSettings;
2173 mProjectScope.reset();
2174 return mLayerStore.get();
2179 return mLayerStore.get();
2184 QList<QgsVectorLayer *>
layers;
2185 const QStringList layerIds =
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), QStringList() );
2186 const auto constLayerIds = layerIds;
2187 for (
const QString &layerId : constLayerIds )
2198 list.reserve(
layers.size() );
2200 list << layer->id();
2201 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), list );
2218 if ( mProjectScope )
2220 std::unique_ptr< QgsExpressionContextScope > projectScope = std::make_unique< QgsExpressionContextScope >( *mProjectScope );
2224 return projectScope.release();
2227 mProjectScope = std::make_unique< QgsExpressionContextScope >( QObject::tr(
"Project" ) );
2231 QVariantMap::const_iterator it = vars.constBegin();
2233 for ( ; it != vars.constEnd(); ++it )
2235 mProjectScope->setVariable( it.key(), it.value(),
true );
2239 if ( projectPath.isEmpty() )
2240 projectPath = mOriginalPath;
2241 const QString projectFolder = QFileInfo( projectPath ).path();
2242 const QString projectFilename = QFileInfo( projectPath ).fileName();
2243 const QString projectBasename =
baseName();
2272 QVariantMap keywords;
2274 for (
auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
2276 keywords.insert( it.key(), it.value() );
2281 QVariantList layersIds;
2283 const QMap<QString, QgsMapLayer *> layersInProject = mLayerStore->mapLayers();
2284 layersIds.reserve( layersInProject.count() );
2285 layers.reserve( layersInProject.count() );
2286 for (
auto it = layersInProject.constBegin(); it != layersInProject.constEnd(); ++it )
2288 layersIds << it.value()->id();
2294 mProjectScope->addFunction( QStringLiteral(
"project_color" ),
new GetNamedProjectColor(
this ) );
2299void QgsProject::onMapLayersAdded(
const QList<QgsMapLayer *> &layers )
2301 const QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2303 const auto constLayers =
layers;
2306 if ( ! layer->isValid() )
2312 for ( QMap<QString, QgsMapLayer *>::const_iterator it = existingMaps.cbegin(); it != existingMaps.cend(); ++it )
2314 const QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
2315 if ( deps.contains( layer->id() ) )
2318 it.value()->setDependencies( deps );
2323 updateTransactionGroups();
2329void QgsProject::onMapLayersRemoved(
const QList<QgsMapLayer *> &layers )
2335void QgsProject::cleanTransactionGroups(
bool force )
2337 bool changed =
false;
2338 for ( QMap< QPair< QString, QString>,
QgsTransactionGroup *>::Iterator tg = mTransactionGroups.begin(); tg != mTransactionGroups.end(); )
2340 if ( tg.value()->isEmpty() || force )
2343 tg = mTransactionGroups.erase( tg );
2355void QgsProject::updateTransactionGroups()
2357 mEditBufferGroup.
clear();
2359 switch ( mTransactionMode )
2363 cleanTransactionGroups(
true );
2368 cleanTransactionGroups(
true );
2371 cleanTransactionGroups(
false );
2375 bool tgChanged =
false;
2376 const auto constLayers =
mapLayers().values();
2379 if ( ! layer->isValid() )
2382 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
2386 switch ( mTransactionMode )
2403 mTransactionGroups.insert( qMakePair( key, connString ), tg );
2413 mEditBufferGroup.
addLayer( vlayer );
2429 QList<QDomNode> brokenNodes;
2430 if ( addLayer( layerNode.toElement(), brokenNodes, context ) )
2434 const QVector<QgsVectorLayer *> vectorLayers = layers<QgsVectorLayer *>();
2438 layer->resolveReferences(
this );
2440 if ( layer->isValid() && layer->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2442 layer->startEditing();
2443 layer->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2453 mFile.setFileName( filename );
2454 mCachedHomePath.clear();
2460 mProjectScope.reset();
2466 const QString storageFilePath { storage->filePath( mFile.fileName() ) };
2467 if ( storageFilePath.isEmpty() )
2473 const QString tempPath = QStandardPaths::standardLocations( QStandardPaths::TempLocation ).at( 0 );
2474 const QString tmpZipFilename( tempPath + QDir::separator() + QUuid::createUuid().toString() );
2476 if ( !zip( tmpZipFilename ) )
2479 QFile tmpZipFile( tmpZipFilename );
2480 if ( !tmpZipFile.open( QIODevice::ReadOnly ) )
2482 setError( tr(
"Unable to read file %1" ).arg( tmpZipFilename ) );
2487 if ( !storage->writeProject( mFile.fileName(), &tmpZipFile, context ) )
2489 QString err = tr(
"Unable to save project to storage %1" ).arg( mFile.fileName() );
2490 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
2491 if ( !messages.isEmpty() )
2492 err += QStringLiteral(
"\n\n" ) + messages.last().message();
2498 QFile::remove( tmpZipFilename );
2505 return zip( mFile.fileName() );
2511 const bool asOk = saveAuxiliaryStorage();
2512 const bool writeOk = writeProjectFile( mFile.fileName() );
2513 bool attachmentsOk =
true;
2514 if ( !mArchive->files().isEmpty() )
2516 const QFileInfo finfo( mFile.fileName() );
2517 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
2518 attachmentsOk = mArchive->zip( attachmentsZip );
2522 if ( ( !asOk || !attachmentsOk ) && writeOk )
2524 QStringList errorMessage;
2527 const QString err = mAuxiliaryStorage->errorString();
2528 errorMessage.append( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
2530 if ( !attachmentsOk )
2532 errorMessage.append( tr(
"Unable to save attachments archive" ) );
2534 setError( errorMessage.join(
'\n' ) );
2537 return asOk && writeOk && attachmentsOk;
2541bool QgsProject::writeProjectFile(
const QString &filename )
2543 QFile projectFile( filename );
2549 const QFileInfo myFileInfo( projectFile );
2550 if ( myFileInfo.exists() && !myFileInfo.isWritable() )
2552 setError( tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
2553 .arg( projectFile.fileName() ) );
2561 QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
2563 const QDomDocumentType documentType =
2564 QDomImplementation().createDocumentType( QStringLiteral(
"qgis" ), QStringLiteral(
"http://mrcc.com/qgis.dtd" ),
2565 QStringLiteral(
"SYSTEM" ) );
2566 std::unique_ptr<QDomDocument> doc(
new QDomDocument( documentType ) );
2568 QDomElement qgisNode = doc->createElement( QStringLiteral(
"qgis" ) );
2569 qgisNode.setAttribute( QStringLiteral(
"projectname" ),
title() );
2570 qgisNode.setAttribute( QStringLiteral(
"version" ),
Qgis::version() );
2572 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_saved_projects" ),
false,
QgsSettings::Core ).toBool() )
2576 qgisNode.setAttribute( QStringLiteral(
"saveUser" ), newSaveUser );
2577 qgisNode.setAttribute( QStringLiteral(
"saveUserFull" ), newSaveUserFull );
2578 mSaveUser = newSaveUser;
2579 mSaveUserFull = newSaveUserFull;
2580 mSaveDateTime = QDateTime::currentDateTime();
2581 qgisNode.setAttribute( QStringLiteral(
"saveDateTime" ), mSaveDateTime.toString( Qt::ISODate ) );
2586 mSaveUserFull.clear();
2587 mSaveDateTime = QDateTime();
2589 doc->appendChild( qgisNode );
2592 QDomElement homePathNode = doc->createElement( QStringLiteral(
"homePath" ) );
2593 homePathNode.setAttribute( QStringLiteral(
"path" ), mHomePath );
2594 qgisNode.appendChild( homePathNode );
2597 QDomElement titleNode = doc->createElement( QStringLiteral(
"title" ) );
2598 qgisNode.appendChild( titleNode );
2600 QDomElement transactionNode = doc->createElement( QStringLiteral(
"transaction" ) );
2601 transactionNode.setAttribute( QStringLiteral(
"mode" ),
qgsEnumValueToKey( mTransactionMode ) );
2602 qgisNode.appendChild( transactionNode );
2604 QDomElement flagsNode = doc->createElement( QStringLiteral(
"projectFlags" ) );
2606 qgisNode.appendChild( flagsNode );
2608 const QDomText titleText = doc->createTextNode(
title() );
2609 titleNode.appendChild( titleText );
2612 QDomElement srsNode = doc->createElement( QStringLiteral(
"projectCrs" ) );
2614 qgisNode.appendChild( srsNode );
2621 clonedRoot->
writeXml( qgisNode, context );
2625 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsMode" ),
static_cast<int>( mAvoidIntersectionsMode ) );
2633 QDomElement annotationLayerNode = doc->createElement( QStringLiteral(
"main-annotation-layer" ) );
2634 mMainAnnotationLayer->
writeLayerXml( annotationLayerNode, *doc, context );
2635 qgisNode.appendChild( annotationLayerNode );
2639 QDomElement projectLayersNode = doc->createElement( QStringLiteral(
"projectlayers" ) );
2641 QMap<QString, QgsMapLayer *>::ConstIterator li =
layers.constBegin();
2642 while ( li !=
layers.end() )
2648 const QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.constFind( ml->
id() );
2649 if ( emIt == mEmbeddedLayers.constEnd() )
2651 QDomElement maplayerElem;
2657 maplayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2661 maplayerElem.setAttribute( QStringLiteral(
"editable" ), QStringLiteral(
"1" ) );
2665 QDomDocument document;
2668 maplayerElem = document.firstChildElement();
2672 QgsDebugMsg( QStringLiteral(
"Could not restore layer properties for layer %1" ).arg( ml->
id() ) );
2678 projectLayersNode.appendChild( maplayerElem );
2684 if ( emIt.value().second )
2686 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2687 mapLayerElem.setAttribute( QStringLiteral(
"embedded" ), 1 );
2688 mapLayerElem.setAttribute( QStringLiteral(
"project" ),
writePath( emIt.value().first ) );
2689 mapLayerElem.setAttribute( QStringLiteral(
"id" ), ml->
id() );
2690 projectLayersNode.appendChild( mapLayerElem );
2697 qgisNode.appendChild( projectLayersNode );
2699 QDomElement layerOrderNode = doc->createElement( QStringLiteral(
"layerorder" ) );
2701 for (
QgsMapLayer *layer : constCustomLayerOrder )
2703 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"layer" ) );
2704 mapLayerElem.setAttribute( QStringLiteral(
"id" ), layer->id() );
2705 layerOrderNode.appendChild( mapLayerElem );
2707 qgisNode.appendChild( layerOrderNode );
2709 mLabelingEngineSettings->writeSettingsToProject(
this );
2711 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorRedPart" ), mBackgroundColor.red() );
2712 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), mBackgroundColor.green() );
2713 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), mBackgroundColor.blue() );
2715 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorRedPart" ), mSelectionColor.red() );
2716 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), mSelectionColor.green() );
2717 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), mSelectionColor.blue() );
2718 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), mSelectionColor.alpha() );
2725 dump_( mProperties );
2728 QgsDebugMsgLevel( QStringLiteral(
"there are %1 property scopes" ).arg(
static_cast<int>( mProperties.
count() ) ), 2 );
2733 mProperties.
writeXml( QStringLiteral(
"properties" ), qgisNode, *doc );
2736 QDomElement ddElem = doc->createElement( QStringLiteral(
"dataDefinedServerProperties" ) );
2737 mDataDefinedServerProperties.
writeXml( ddElem, dataDefinedServerPropertyDefinitions() );
2738 qgisNode.appendChild( ddElem );
2740 mMapThemeCollection->writeXml( *doc );
2742 mTransformContext.
writeXml( qgisNode, context );
2744 QDomElement metadataElem = doc->createElement( QStringLiteral(
"projectMetadata" ) );
2746 qgisNode.appendChild( metadataElem );
2748 const QDomElement annotationsElem = mAnnotationManager->writeXml( *doc, context );
2749 qgisNode.appendChild( annotationsElem );
2751 const QDomElement layoutElem = mLayoutManager->writeXml( *doc );
2752 qgisNode.appendChild( layoutElem );
2754 const QDomElement views3DElem = m3DViewsManager->writeXml( *doc );
2755 qgisNode.appendChild( views3DElem );
2757 const QDomElement bookmarkElem = mBookmarkManager->
writeXml( *doc );
2758 qgisNode.appendChild( bookmarkElem );
2760 const QDomElement viewSettingsElem = mViewSettings->
writeXml( *doc, context );
2761 qgisNode.appendChild( viewSettingsElem );
2763 const QDomElement styleSettingsElem = mStyleSettings->
writeXml( *doc, context );
2764 qgisNode.appendChild( styleSettingsElem );
2766 const QDomElement timeSettingsElement = mTimeSettings->
writeXml( *doc, context );
2767 qgisNode.appendChild( timeSettingsElement );
2769 const QDomElement elevationPropertiesElement = mElevationProperties->
writeXml( *doc, context );
2770 qgisNode.appendChild( elevationPropertiesElement );
2772 const QDomElement displaySettingsElem = mDisplaySettings->
writeXml( *doc, context );
2773 qgisNode.appendChild( displaySettingsElem );
2781 QFile backupFile( QStringLiteral(
"%1~" ).arg( filename ) );
2783 ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
2784 ok &= projectFile.open( QIODevice::ReadOnly );
2787 while ( ok && !projectFile.atEnd() )
2789 ba = projectFile.read( 10240 );
2790 ok &= backupFile.write( ba ) == ba.size();
2793 projectFile.close();
2798 setError( tr(
"Unable to create backup file %1" ).arg( backupFile.fileName() ) );
2803 struct utimbuf tb = {
static_cast<time_t
>( fi.lastRead().toSecsSinceEpoch() ),
static_cast<time_t
>( fi.lastModified().toSecsSinceEpoch() ) };
2804 utime( backupFile.fileName().toUtf8().constData(), &tb );
2807 if ( !projectFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
2809 projectFile.close();
2812 setError( tr(
"Unable to save to file %1" ).arg( projectFile.fileName() ) );
2816 QTemporaryFile tempFile;
2817 bool ok = tempFile.open();
2820 QTextStream projectFileStream( &tempFile );
2821 doc->save( projectFileStream, 2 );
2822 ok &= projectFileStream.pos() > -1;
2824 ok &= tempFile.seek( 0 );
2827 while ( ok && !tempFile.atEnd() )
2829 ba = tempFile.read( 10240 );
2830 ok &= projectFile.write( ba ) == ba.size();
2833 ok &= projectFile.error() == QFile::NoError;
2835 projectFile.close();
2842 setError( tr(
"Unable to save to file %1. Your project "
2843 "may be corrupted on disk. Try clearing some space on the volume and "
2844 "check file permissions before pressing save again." )
2845 .arg( projectFile.fileName() ) );
2857 bool propertiesModified;
2858 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2860 if ( propertiesModified )
2868 bool propertiesModified;
2869 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2871 if ( propertiesModified )
2879 bool propertiesModified;
2880 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2882 if ( propertiesModified )
2890 bool propertiesModified;
2891 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2893 if ( propertiesModified )
2901 bool propertiesModified;
2902 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2904 if ( propertiesModified )
2912 const QStringList &def,
2921 value =
property->value();
2923 const bool valid = QVariant::StringList == value.type();
2929 return value.toStringList();
2951 value =
property->value();
2953 const bool valid = value.canConvert( QVariant::String );
2958 return value.toString();
2975 value =
property->value();
2978 const bool valid = value.canConvert( QVariant::Int );
2987 return value.toInt();
3000 const QVariant value =
property->value();
3002 const bool valid = value.canConvert( QVariant::Double );
3007 return value.toDouble();
3022 const QVariant value =
property->value();
3024 const bool valid = value.canConvert( QVariant::Bool );
3029 return value.toBool();
3039 if (
findKey_( scope, key, mProperties ) )
3045 return !
findKey_( scope, key, mProperties );
3053 QStringList entries;
3055 if ( foundProperty )
3070 QStringList entries;
3072 if ( foundProperty )
3085 dump_( mProperties );
3103 filePath = storage->filePath( mFile.fileName() );
3126void QgsProject::setError(
const QString &errorMessage )
3128 mErrorMessage = errorMessage;
3133 return mErrorMessage;
3136void QgsProject::clearError()
3138 setError( QString() );
3143 delete mBadLayerHandler;
3144 mBadLayerHandler = handler;
3149 const QHash< QString, QPair< QString, bool > >::const_iterator it = mEmbeddedLayers.find(
id );
3150 if ( it == mEmbeddedLayers.constEnd() )
3154 return it.value().first;
3158 bool saveFlag, Qgis::ProjectReadFlags flags )
3162 static QString sPrevProjectFilePath;
3163 static QDateTime sPrevProjectFileTimestamp;
3164 static QDomDocument sProjectDocument;
3166 QString qgsProjectFile = projectFilePath;
3168 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3170 archive.
unzip( projectFilePath );
3174 const QDateTime projectFileTimestamp = QFileInfo( projectFilePath ).lastModified();
3176 if ( projectFilePath != sPrevProjectFilePath || projectFileTimestamp != sPrevProjectFileTimestamp )
3178 sPrevProjectFilePath.clear();
3180 QFile projectFile( qgsProjectFile );
3181 if ( !projectFile.open( QIODevice::ReadOnly ) )
3186 if ( !sProjectDocument.setContent( &projectFile ) )
3191 sPrevProjectFilePath = projectFilePath;
3192 sPrevProjectFileTimestamp = projectFileTimestamp;
3196 bool useAbsolutePaths =
true;
3198 const QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
3199 if ( !propertiesElem.isNull() )
3201 const QDomElement absElem = propertiesElem.firstChildElement( QStringLiteral(
"Paths" ) ).firstChildElement( QStringLiteral(
"Absolute" ) );
3202 if ( !absElem.isNull() )
3204 useAbsolutePaths = absElem.text().compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0;
3209 if ( !useAbsolutePaths )
3214 const QDomElement projectLayersElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) );
3215 if ( projectLayersElem.isNull() )
3220 QDomElement mapLayerElem = projectLayersElem.firstChildElement( QStringLiteral(
"maplayer" ) );
3221 while ( ! mapLayerElem.isNull() )
3224 const QString
id = mapLayerElem.firstChildElement( QStringLiteral(
"id" ) ).text();
3225 if (
id == layerId )
3228 if ( mapLayerElem.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
3233 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
3235 if ( addLayer( mapLayerElem, brokenNodes, embeddedContext,
flags ) )
3241 mEmbeddedLayers.remove( layerId );
3245 mapLayerElem = mapLayerElem.nextSiblingElement( QStringLiteral(
"maplayer" ) );
3254 QString qgsProjectFile = projectFilePath;
3256 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3258 archive.
unzip( projectFilePath );
3263 QFile projectFile( qgsProjectFile );
3264 if ( !projectFile.open( QIODevice::ReadOnly ) )
3269 QDomDocument projectDocument;
3270 if ( !projectDocument.setContent( &projectFile ) )
3282 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
3283 if ( !layerTreeElem.isNull() )
3293 if ( !group || group->
customProperty( QStringLiteral(
"embedded" ) ).toBool() )
3306 newGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectFilePath );
3309 mLayerTreeRegistryBridge->
setEnabled(
false );
3310 initializeEmbeddedSubtree( projectFilePath, newGroup,
flags );
3311 mLayerTreeRegistryBridge->
setEnabled(
true );
3314 const auto constFindLayerIds = newGroup->
findLayerIds();
3315 for (
const QString &layerId : constFindLayerIds )
3328void QgsProject::initializeEmbeddedSubtree(
const QString &projectFilePath,
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
3330 const auto constChildren = group->
children();
3334 child->setCustomProperty( QStringLiteral(
"embedded" ), 1 );
3343 QList<QDomNode> brokenNodes;
3361 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), ( enabled ? 1 : 0 ) );
3367 return readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), 0 );
3372 if ( mDistanceUnits == unit )
3375 mDistanceUnits = unit;
3382 if ( mAreaUnits == unit )
3392 if ( !mCachedHomePath.isEmpty() )
3393 return mCachedHomePath;
3397 if ( !mHomePath.isEmpty() )
3399 const QFileInfo homeInfo( mHomePath );
3400 if ( !homeInfo.isRelative() )
3402 mCachedHomePath = mHomePath;
3408 mCachedHomePath = pfi.path();
3410 return mCachedHomePath;
3413 if ( !pfi.exists() )
3415 mCachedHomePath = mHomePath;
3419 if ( !mHomePath.isEmpty() )
3422 mCachedHomePath = QDir::cleanPath( pfi.path() +
'/' + mHomePath );
3426 mCachedHomePath = pfi.canonicalPath();
3428 return mCachedHomePath;
3438 return mRelationManager;
3443 return mLayoutManager.get();
3448 return mLayoutManager.get();
3453 return m3DViewsManager.get();
3458 return m3DViewsManager.get();
3463 return mBookmarkManager;
3468 return mBookmarkManager;
3473 return mViewSettings;
3478 return mViewSettings;
3483 return mStyleSettings;
3488 return mStyleSettings;
3493 return mTimeSettings;
3498 return mTimeSettings;
3503 return mElevationProperties;
3508 return mElevationProperties;
3513 return mDisplaySettings;
3518 return mDisplaySettings;
3528 return mMapThemeCollection.get();
3533 return mAnnotationManager.get();
3538 return mAnnotationManager.get();
3543 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
3544 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
3549 if (
layers.contains( it.value() ) )
3564 for (
const QString &layerId : layerIds )
3580 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
3610 updateTransactionGroups();
3615 return mTransactionMode;
3624 const auto constLayers =
mapLayers().values();
3627 if ( layer->isEditable() )
3629 QgsLogger::warning( tr(
"Transaction mode can be changed only if all layers are not editable." ) );
3635 updateTransactionGroups();
3641 return mTransactionGroups;
3652 return mLayerStore->count();
3657 return mLayerStore->validCount();
3662 return mLayerStore->mapLayer( layerId );
3667 return mLayerStore->mapLayersByName( layerName );
3672 QList<QgsMapLayer *>
layers;
3673 const auto constMapLayers { mLayerStore->mapLayers() };
3674 for (
const auto &l : constMapLayers )
3676 if ( ! l->shortName().isEmpty() )
3678 if ( l->shortName() == shortName )
3681 else if ( l->name() == shortName )
3689bool QgsProject::unzip(
const QString &filename, Qgis::ProjectReadFlags flags )
3695 if ( !archive->unzip( filename ) )
3697 setError( tr(
"Unable to unzip file '%1'" ).arg( filename ) );
3702 if ( archive->projectFile().isEmpty() )
3704 setError( tr(
"Zip archive does not provide a project file" ) );
3709 mArchive = std::move( archive );
3726 setError( tr(
"Cannot read unzipped qgs project file" ) );
3736bool QgsProject::zip(
const QString &filename )
3742 const QString
baseName = QFileInfo( filename ).baseName();
3743 const QString qgsFileName = QStringLiteral(
"%1.qgs" ).arg(
baseName );
3744 QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
3746 bool writeOk =
false;
3747 if ( qgsFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3749 writeOk = writeProjectFile( qgsFile.fileName() );
3756 setError( tr(
"Unable to write temporary qgs file" ) );
3761 const QFileInfo info( qgsFile );
3763 const QString asFileName = info.path() + QDir::separator() + info.completeBaseName() + asExt;
3765 bool auxiliaryStorageSavedOk =
true;
3766 if ( ! saveAuxiliaryStorage( asFileName ) )
3768 const QString err = mAuxiliaryStorage->errorString();
3769 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 ) );
3770 auxiliaryStorageSavedOk =
false;
3773 if ( !mArchive->exists() )
3776 mArchive->unzip( mFile.fileName() );
3779 const QString auxiliaryStorageFile =
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile();
3780 if ( ! auxiliaryStorageFile.isEmpty() )
3782 archive->
addFile( auxiliaryStorageFile );
3791 if ( QFile::exists( asFileName ) )
3793 archive->addFile( asFileName );
3798 archive->addFile( qgsFile.fileName() );
3801 const QStringList &files = mArchive->files();
3802 for (
const QString &file : files )
3804 if ( !file.endsWith( QLatin1String(
".qgs" ), Qt::CaseInsensitive ) && !file.endsWith( asExt, Qt::CaseInsensitive ) )
3806 archive->addFile( file );
3812 if ( !archive->zip( filename ) )
3814 setError( tr(
"Unable to perform zip" ) );
3818 return auxiliaryStorageSavedOk && zipOk;
3827 const QList<QgsMapLayer *> &layers,
3829 bool takeOwnership )
3831 const QList<QgsMapLayer *> myResultList { mLayerStore->addMapLayers(
layers, takeOwnership ) };
3832 if ( !myResultList.isEmpty() )
3835 for (
auto &l : myResultList )
3845 if ( mAuxiliaryStorage )
3860 mProjectScope.reset();
3862 return myResultList;
3868 bool takeOwnership )
3870 QList<QgsMapLayer *> addedLayers;
3871 addedLayers =
addMapLayers( QList<QgsMapLayer *>() << layer, addToLegend, takeOwnership );
3872 return addedLayers.isEmpty() ? nullptr : addedLayers[0];
3875void QgsProject::removeAuxiliaryLayer(
const QgsMapLayer *ml )
3880 const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( ml );
3890 for (
const auto &layerId : layerIds )
3891 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
3893 mProjectScope.reset();
3894 mLayerStore->removeMapLayers( layerIds );
3899 for (
const auto &layer :
layers )
3900 removeAuxiliaryLayer( layer );
3902 mProjectScope.reset();
3903 mLayerStore->removeMapLayers(
layers );
3908 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
3909 mProjectScope.reset();
3910 mLayerStore->removeMapLayer( layerId );
3915 removeAuxiliaryLayer( layer );
3916 mProjectScope.reset();
3917 mLayerStore->removeMapLayer( layer );
3922 mProjectScope.reset();
3923 return mLayerStore->takeMapLayer( layer );
3928 return mMainAnnotationLayer;
3933 if ( mLayerStore->count() == 0 )
3936 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
3937 mProjectScope.reset();
3938 mLayerStore->removeAllMapLayers();
3940 snapSingleBlocker.release();
3942 if ( !mBlockSnappingUpdates )
3948 const QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
3949 QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin();
3950 for ( ; it !=
layers.constEnd(); ++it )
3952 it.value()->reload();
3958 return validOnly ? mLayerStore->validMapLayers() : mLayerStore->mapLayers();
3963 return mTransactionGroups.value( qMakePair( providerKey, connString ) );
3968 return &mEditBufferGroup;
3977 if ( mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), QStringLiteral(
"NoAction" ),
QgsSettings::App ).toString() == QStringLiteral(
"UseProjectCrs" )
3978 || mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), 0,
QgsSettings::App ).toString() == QLatin1String(
"2" ) )
3986 const QString layerDefaultCrs = mSettings.
value( QStringLiteral(
"/Projections/layerDefaultCrs" ),
geoEpsgCrsAuthId() ).toString();
4003bool QgsProject::saveAuxiliaryStorage(
const QString &filename )
4007 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4012 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
4020 if ( !mAuxiliaryStorage->exists( *
this ) && empty )
4024 else if ( !filename.isEmpty() )
4026 return mAuxiliaryStorage->saveAs( filename );
4030 return mAuxiliaryStorage->saveAs( *
this );
4039 QgsProject::DataDefinedServerProperty::WMSOnlineResource,
4043 return sPropertyDefinitions;
4048 return mAuxiliaryStorage.get();
4053 return mAuxiliaryStorage.get();
4058 const QDir archiveDir( mArchive->dir() );
4059 QTemporaryFile tmpFile( archiveDir.filePath(
"XXXXXX_" + nameTemplate ),
this );
4060 tmpFile.setAutoRemove(
false );
4062 mArchive->addFile( tmpFile.fileName() );
4063 return tmpFile.fileName();
4068 QStringList attachments;
4070 const QStringList files = mArchive->files();
4071 attachments.reserve( files.size() );
4072 for (
const QString &file : files )
4076 attachments.append( file );
4084 return mArchive->removeFile( path );
4089 return QStringLiteral(
"attachment:///%1" ).arg( QFileInfo( attachedFile ).
fileName() );
4094 if ( identifier.startsWith( QLatin1String(
"attachment:///" ) ) )
4096 return QDir( mArchive->dir() ).absoluteFilePath( identifier.mid( 14 ) );
4112 mProjectScope.reset();
4124 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4136 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
4137 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
4142 if (
layers.contains( it.value() ) )
4152 QStringList customColors;
4153 QStringList customColorLabels;
4155 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
4156 for ( ; colorIt != colors.constEnd(); ++colorIt )
4159 const QString label = ( *colorIt ).second;
4160 customColors.append( color );
4161 customColorLabels.append( label );
4163 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ), customColors );
4164 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ), customColorLabels );
4165 mProjectScope.reset();
4171 if ( mBackgroundColor == color )
4174 mBackgroundColor = color;
4180 return mBackgroundColor;
4185 if ( mSelectionColor == color )
4188 mSelectionColor = color;
4194 return mSelectionColor;
4228QString
QgsProject::translate(
const QString &context,
const QString &sourceText,
const char *disambiguation,
int n )
const
4235 QString result = mTranslator->translate( context.toUtf8(), sourceText.toUtf8(), disambiguation, n );
4237 if ( result.isEmpty() )
4249 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4254 if ( !( ( *it )->accept( visitor ) ) )
4263 if ( !mLayoutManager->accept( visitor ) )
4266 if ( !mAnnotationManager->accept( visitor ) )
4272void QgsProject::loadProjectFlags(
const QDomDocument *doc )
4274 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectFlags" ) );
4275 Qgis::ProjectFlags
flags;
4276 if ( !element.isNull() )
4283 element = doc->documentElement().firstChildElement( QStringLiteral(
"evaluateDefaultValues" ) );
4284 if ( !element.isNull() )
4286 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
4291 element = doc->documentElement().firstChildElement( QStringLiteral(
"trust" ) );
4292 if ( !element.isNull() )
4294 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
4303GetNamedProjectColor::GetNamedProjectColor(
const QgsProject *project )
4310 QStringList colorStrings = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ) );
4311 const QStringList colorLabels = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ) );
4315 for ( QStringList::iterator it = colorStrings.begin();
4316 it != colorStrings.end(); ++it )
4320 if ( colorLabels.length() > colorIndex )
4322 label = colorLabels.at( colorIndex );
4325 mColors.insert( label.toLower(), color );
4330GetNamedProjectColor::GetNamedProjectColor(
const QHash<QString, QColor> &colors )
4338 const QString colorName = values.at( 0 ).toString().toLower();
4339 if ( mColors.contains( colorName ) )
4341 return QStringLiteral(
"%1,%2,%3" ).arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
4349 return new GetNamedProjectColor( mColors );
@ ForceReadOnlyLayers
Open layers in a read-only mode. (since QGIS 3.28)
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.
static bool deleteTable(const QgsDataSourceUri &uri)
Removes a table from the auxiliary storage.
Manages storage of a set of bookmarks.
bool readXml(const QDomElement &element, const QDomDocument &doc)
Reads the manager's state from a DOM element, restoring all bookmarks present in the XML document.
void clear()
Removes and deletes all bookmarks from the manager.
QDomElement writeXml(QDomDocument &doc) const
Returns a DOM element representing the state of the manager.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
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 ...
Class for storing the component parts of a RDBMS data source URI (e.g.
Single scope for storing variables and functions for use within a QgsExpressionContext.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
An expression node for expression functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
Encapsulate a field in an attribute table or data source.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
bool isEmpty() const
Checks whether the container is empty.
Stores global configuration for labeling engine.
Class used to work with layer dependencies stored in a XML project or layer definition file.
Layer tree group node serves as a container for layers and further groups.
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Calls resolveReferences() on child tree nodes.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name.
QList< QgsLayerTreeGroup * > findGroups(bool recursive=false) const
Find group layer nodes.
QString name() const override
Returns the group's name.
QStringList findLayerIds() const
Find layer IDs used in all layer nodes.
void insertChildNodes(int index, const QList< QgsLayerTreeNode * > &nodes)
Insert existing nodes at specified position.
void readChildrenFromXml(QDomElement &element, const QgsReadWriteContext &context)
Read children from XML and append them to the group.
QgsLayerTreeGroup * clone() const override
Returns a clone of the group.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
Layer tree node points to a map layer.
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Resolves reference to layer from stored layer ID (if it has not been resolved already)
This class is a base class for nodes in a layer tree.
QList< QgsLayerTreeNode * > abandonChildren()
Removes the childrens, disconnect all the forwarded and external signals and sets their parent to nul...
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file.
virtual void writeXml(QDomElement &parentElement, const QgsReadWriteContext &context)=0
Write layer tree to XML.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
Listens to the updates in map layer registry and does changes in layer tree.
void setEnabled(bool enabled)
static void replaceChildrenOfEmbeddedGroups(QgsLayerTreeGroup *group)
Remove subtree of embedded groups and replaces it with a custom property embedded-visible-layers.
static void storeOriginalLayersProperties(QgsLayerTreeGroup *group, const QDomDocument *doc)
Stores in a layer's originalXmlProperties the layer properties information.
static void updateEmbeddedGroupsProjectPath(QgsLayerTreeGroup *group, const QgsProject *project)
Updates an embedded group from a project.
static bool readOldLegend(QgsLayerTreeGroup *root, const QDomElement &legendElem)
Try to load layer tree from.
Namespace with helper functions for layer tree operations.
void readLayerOrderFromXml(const QDomElement &doc)
Load the layer order from an XML element.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
void clear()
Clear any information from this layer tree.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
QList< QgsMapLayer * > customLayerOrder() const
The order in which layers will be rendered on the canvas.
QgsLayerTree * clone() const override
Create a copy of the node. Returns new instance.
Manages storage of a set of layouts.
static void warning(const QString &msg)
Goes to qWarning.
static QgsMapLayerType typeFromString(const QString &string, bool &ok)
Returns the map layer type corresponding a string value.
A storage object for map layers, in which the layers are owned by the store and have their lifetime b...
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the store.
void layerWillBeRemoved(const QString &layerId)
Emitted when a layer is about to be removed from the store.
void layersRemoved(const QStringList &layerIds)
Emitted after one or more layers were removed from the store.
void allLayersRemoved()
Emitted when all layers are removed, before layersWillBeRemoved() and layerWillBeRemoved() signals ar...
void layerRemoved(const QString &layerId)
Emitted after a layer was removed from the store.
void layerWasAdded(QgsMapLayer *layer)
Emitted when a layer was added to the store.
QgsMapLayer * mapLayer(const QString &id) const
Retrieve a pointer to a layer by layer id.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the store.
Base class for all map layer types.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
void configChanged()
Emitted whenever the configuration is changed.
QgsCoordinateReferenceSystem crs
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QString originalXmlProperties() const
Returns the XML properties of the original layer as they were when the layer was first read from the ...
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
virtual bool isEditable() const
Returns true if the layer can be edited.
bool writeLayerXml(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores state in DOM node.
bool readLayerXml(const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags=QgsMapLayer::ReadFlags())
Sets state from DOM document.
@ Identifiable
If the layer is identifiable using the identify map tool and as a WMS layer.
@ Removable
If the layer can be removed from the project. The layer will not be removable from the legend menu en...
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
@ FlagForceReadOnly
Force open as read only.
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Container class that allows storage of map themes consisting of visible map layers and layer styles.
Manages storage of a set of views.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
Class allowing to manage the zip/unzip actions on project file.
QString projectFile() const
Returns the current .qgs project file or an empty string if there's none.
QString auxiliaryStorageFile() const
Returns the current .qgd auxiliary storage file or an empty string if there's none.
bool unzip(const QString &zipFilename) override
Clear the current content of this archive and unzip.
Interface for classes that handle missing layer files when reading project file.
virtual void handleBadLayers(const QList< QDomNode > &layers)
This method will be called whenever the project tries to load layers which cannot be accessed.
Contains settings and properties relating to how a QgsProject should display values such as map coord...
void reset()
Resets the settings to a default state.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
Contains elevation properties for a QgsProject.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the property state from a DOM element.
void reset()
Resets the properties to a default state.
QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Returns a DOM element representing the properties.
void resolveReferences(const QgsProject *project)
Resolves reference to layers from stored layer ID.
Project property key node.
QString name() const
The name of the property is used as identifier.
QgsProjectProperty * find(const QString &propertyName) const
Attempts to find a property with a matching sub-key name.
void removeKey(const QString &keyName)
Removes the specified key.
void dump(int tabs=0) const override
Dumps out the keys and values.
bool isEmpty() const
Returns true if this property contains no sub-keys.
virtual void clearKeys()
Deletes any sub-nodes from the property.
bool writeXml(const QString &nodeName, QDomElement &element, QDomDocument &document) override
Writes the property hierarchy to a specified DOM element.
void subkeyList(QStringList &entries) const
Returns any sub-keys contained by this property which themselves contain other keys.
void setName(const QString &name)
The name of the property is used as identifier.
QgsProjectPropertyKey * addKey(const QString &keyName)
Adds the specified property key as a sub-key.
QVariant value() const override
If this key has a value, it will be stored by its name in its properties.
QgsProjectPropertyValue * setValue(const QString &name, const QVariant &value)
Sets the value associated with this key.
void entryList(QStringList &entries) const
Returns any sub-keys contained by this property that do not contain other keys.
int count() const
Returns the number of sub-keys contained by this property.
bool readXml(const QDomNode &keyNode) override
Restores the property hierarchy from a specified DOM node.
An Abstract Base Class for QGIS project property hierarchys.
virtual bool isKey() const =0
Returns true if the property is a QgsProjectPropertyKey.
virtual bool isValue() const =0
Returns true if the property is a QgsProjectPropertyValue.
QgsProjectStorage * projectStorageFromUri(const QString &uri)
Returns storage implementation if the URI matches one. Returns nullptr otherwise (it is a normal file...
Abstract interface for project storage - to be implemented by various backends and registered in QgsP...
Contains settings and properties relating to how a QgsProject should handle styling.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
void setDefaultSymbol(Qgis::SymbolType symbolType, QgsSymbol *symbol)
Sets the project default symbol for a given type.
void reset()
Resets the settings to a default state.
void setRandomizeDefaultSymbolColor(bool randomized)
Sets whether the default symbol fill color is randomized.
void setDefaultColorRamp(QgsColorRamp *colorRamp)
Sets the project default color ramp.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context, Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
Reads the settings's state from a DOM element.
void setDefaultSymbolOpacity(double opacity)
Sets the default symbol opacity.
Contains temporal settings and properties for the project, this may be used when animating maps or sh...
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
void reset()
Resets the settings to a default state.
QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
A class to describe the version of a project.
QString text() const
Returns a string representation of the version.
int majorVersion() const
Returns the major version number.
Contains settings and properties relating to how a QgsProject should be displayed inside map canvas,...
bool useProjectScales() const
Returns true if project mapScales() are enabled.
void reset()
Resets the settings to a default state.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
void setMapScales(const QVector< double > &scales)
Sets the list of custom project map scales.
void setUseProjectScales(bool enabled)
Sets whether project mapScales() are enabled.
QVector< double > mapScales() const
Returns the list of custom project map scales.
void mapScalesChanged()
Emitted when the list of custom project map scales changes.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
bool isZipped() const
Returns true if the project comes from a zip archive, false otherwise.
bool removeAttachedFile(const QString &path)
Removes the attached file.
QgsRelationManager * relationManager
bool write()
Writes the project to its current associated file (see fileName() ).
QgsProject(QObject *parent=nullptr, Qgis::ProjectCapabilities capabilities=Qgis::ProjectCapability::ProjectStyles)
Create a new QgsProject.
void removeMapLayer(const QString &layerId)
Remove a layer from the registry by layer ID.
Q_DECL_DEPRECATED bool evaluateDefaultValues() const
Should default values be evaluated on provider side when requested and not when committed.
void setAreaUnits(QgsUnitTypes::AreaUnit unit)
Sets the default area measurement units for the project.
void layersRemoved(const QStringList &layerIds)
Emitted after one or more layers were removed from the registry.
void clear()
Clears the project, removing all settings and resetting it back to an empty, default state.
QString error() const
Returns error message from previous read/write.
Q_DECL_DEPRECATED void setUseProjectScales(bool enabled)
Sets whether project mapScales() are enabled.
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
Reads an integer from the specified scope and key.
Q_DECL_DEPRECATED void setNonIdentifiableLayers(const QList< QgsMapLayer * > &layers)
Set a list of layers which should not be taken into account on map identification.
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer * > &mapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
Qgis::ProjectFlags flags() const
Returns the project's flags, which dictate the behavior of the project.
Q_DECL_DEPRECATED QFileInfo fileInfo() const
Returns QFileInfo object for the project's associated file.
QString presetHomePath() const
Returns any manual project home path setting, or an empty string if not set.
void setBackgroundColor(const QColor &color)
Sets the default background color used by default map canvases.
void setCrs(const QgsCoordinateReferenceSystem &crs, bool adjustEllipsoid=false)
Sets the project's native coordinate reference system.
QString title() const
Returns the project's title.
bool commitChanges(QStringList &commitErrors, bool stopEditing=true, QgsVectorLayer *vectorLayer=nullptr)
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
void mapThemeCollectionChanged()
Emitted when the map theme collection changes.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Qgis::FilePathType filePathStorage() const
Returns the type of paths used when storing file paths in a QGS/QGZ project file.
QString createAttachedFile(const QString &nameTemplate)
Attaches a file to the project.
Q_DECL_DEPRECATED void mapScalesChanged()
Emitted when the list of custom project map scales changes.
void readVersionMismatchOccurred(const QString &fileVersion)
Emitted when a project is read and the version of QGIS used to save the project differs from the curr...
void fileNameChanged()
Emitted when the file name of the project changes.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QgsUnitTypes::DistanceUnit distanceUnits
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.
void areaUnitsChanged()
Emitted when the default area units changes.
QgsPropertyCollection dataDefinedServerProperties() const
Returns the data defined properties used for overrides in user defined server parameters.
Q_DECL_DEPRECATED void nonIdentifiableLayersChanged(QStringList nonIdentifiableLayers)
Emitted when the list of layer which are excluded from map identification changes.
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QString attachmentIdentifier(const QString &attachedFile) const
Returns an identifier for an attachment file path An attachment identifier is a string which does not...
QgsVectorLayerEditBufferGroup * editBufferGroup()
Returns the edit buffer group.
void setSelectionColor(const QColor &color)
Sets the color used to highlight selected features.
bool rollBack(QStringList &rollbackErrors, bool stopEditing=true, QgsVectorLayer *vectorLayer=nullptr)
Stops a current editing operation on vectorLayer and discards any uncommitted edits.
void snappingConfigChanged(const QgsSnappingConfig &config)
Emitted whenever the configuration for snapping has changed.
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
void setBadLayerHandler(QgsProjectBadLayerHandler *handler)
Change handler for missing layers.
Q_DECL_DEPRECATED void setEvaluateDefaultValues(bool evaluateDefaultValues)
Defines if default values should be evaluated on provider side when requested and not when committed.
void crsChanged()
Emitted when the CRS of the project has changed.
QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const override
Translates the project with QTranslator and qm file.
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
QgsSnappingConfig snappingConfig
void setFileName(const QString &name)
Sets the file name associated with the project.
void avoidIntersectionsLayersChanged()
Emitted whenever avoidIntersectionsLayers has changed.
void setDataDefinedServerProperties(const QgsPropertyCollection &properties)
Sets the data defined properties used for overrides in user defined server parameters to properties.
void registerTranslatableObjects(QgsTranslationContext *translationContext)
Registers the objects that require translation into the translationContext.
void distanceUnitsChanged()
Emitted when the default distance units changes.
QgsAnnotationLayer * mainAnnotationLayer()
Returns the main annotation layer associated with the project.
const QgsBookmarkManager * bookmarkManager() const
Returns the project's bookmark manager, which manages bookmarks within the project.
void readMapLayer(QgsMapLayer *mapLayer, const QDomElement &layerNode)
Emitted after the basic initialization of a layer from the project file is done.
Q_DECL_DEPRECATED void setAutoTransaction(bool autoTransaction)
Transactional editing means that on supported datasources (postgres databases) the edit state of all ...
bool startEditing(QgsVectorLayer *vectorLayer=nullptr)
Makes the layer editable.
Q_DECL_DEPRECATED void setTrustLayerMetadata(bool trust)
Sets the trust option allowing to indicate if the extent has to be read from the XML document when da...
void cleared()
Emitted when the project is cleared (and additionally when an open project is cleared just before a n...
Q_DECL_DEPRECATED void oldProjectVersionWarning(const QString &)
Emitted when an old project file is read.
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets project's global labeling engine settings.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void metadataChanged()
Emitted when the project's metadata is changed.
QgsUnitTypes::AreaUnit areaUnits
QString resolveAttachmentIdentifier(const QString &identifier) const
Resolves an attachment identifier to a attachment file path.
const QgsProjectElevationProperties * elevationProperties() const
Returns the project's elevation properties, which contains the project's elevation related settings.
QString absolutePath() const
Returns full absolute path to the project folder if the project is stored in a file system - derived ...
void removeMapLayers(const QStringList &layerIds)
Remove a set of layers from the registry by layer ID.
Q_DECL_DEPRECATED void setRequiredLayers(const QSet< QgsMapLayer * > &layers)
Configures a set of map layers that are required in the project and therefore they should not get rem...
bool createEmbeddedLayer(const QString &layerId, const QString &projectFilePath, QList< QDomNode > &brokenNodes, bool saveFlag=true, Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
Creates a maplayer instance defined in an arbitrary project file.
QList< QgsVectorLayer * > avoidIntersectionsLayers
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Reads a string from the specified scope and key.
QgsExpressionContextScope * createExpressionContextScope() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QString baseName() const
Returns the base name of the project file without the path and without extension - derived from fileN...
void ellipsoidChanged(const QString &ellipsoid)
Emitted when the project ellipsoid is changed.
QgsMapThemeCollection * mapThemeCollection
void generateTsFile(const QString &locale)
Triggers the collection strings of .qgs to be included in ts file and calls writeTsFile()
QStringList entryList(const QString &scope, const QString &key) const
Returns a list of child keys with values which exist within the the specified scope and key.
QgsAnnotationManager * annotationManager()
Returns pointer to the project's annotation manager.
QgsProjectDisplaySettings * displaySettings
Qgis::TransactionMode transactionMode() const
Returns the transaction mode.
QgsProjectMetadata metadata
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
QString saveUser() const
Returns the user name that did the last save.
QVector< T > layers() const
Returns a list of registered map layers with a specified layer type.
void setProjectColors(const QgsNamedColorList &colors)
Sets the colors for the project's color scheme (see QgsProjectColorScheme).
bool setTransactionMode(Qgis::TransactionMode transactionMode)
Set transaction mode.
QgsCoordinateTransformContext transformContext
void labelingEngineSettingsChanged()
Emitted when global configuration of the labeling engine changes.
void customVariablesChanged()
Emitted whenever the expression variables stored in the project have been changed.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
bool readBoolEntry(const QString &scope, const QString &key, bool def=false, bool *ok=nullptr) const
Reads a boolean from the specified scope and key.
QgsMapLayerStore * layerStore()
Returns a pointer to the project's internal layer store.
void readProject(const QDomDocument &)
Emitted when a project is being read.
QString originalPath() const
Returns the original path associated with the project.
void setOriginalPath(const QString &path)
Sets the original path associated with the project.
void dumpProperties() const
Dump out current project properties to stderr.
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.
QString saveUserFullName() const
Returns the full user name that did the last save.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the registry.
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
bool isDirty() const
Returns true if the project has been modified since the last write()
QgsMapLayer * takeMapLayer(QgsMapLayer *layer)
Takes a layer from the registry.
void isDirtyChanged(bool dirty)
Emitted when the project dirty status changes.
Q_DECL_DEPRECATED bool useProjectScales() const
Returns true if project mapScales() are enabled.
Q_DECL_DEPRECATED void setMapScales(const QVector< double > &scales)
Sets the list of custom project map scales.
void setPresetHomePath(const QString &path)
Sets the project's home path.
void setFlags(Qgis::ProjectFlags flags)
Sets the project's flags, which dictate the behavior of the project.
QList< QgsMapLayer * > mapLayersByShortName(const QString &shortName) const
Retrieves a list of matching registered layers by layer shortName.
QgsProjectStorage * projectStorage() const
Returns pointer to project storage implementation that handles read/write of the project file.
QString layerIsEmbedded(const QString &id) const
Returns the source project file path if the layer with matching id is embedded from other project fil...
const QgsProjectTimeSettings * timeSettings() const
Returns the project's time settings, which contains the project's temporal range and other time based...
void topologicalEditingChanged()
Emitted when the topological editing flag has changed.
bool removeEntry(const QString &scope, const QString &key)
Remove the given key from the specified scope.
QgsProjectVersion lastSaveVersion() const
Returns the QGIS version which the project was last saved using.
void avoidIntersectionsModeChanged()
Emitted whenever the avoid intersections mode has changed.
void loadingLayer(const QString &layerName)
Emitted when a layer is loaded.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
Definition for a property.
@ String
Any string value.
The class is used as a container of context for various read/write operations on other objects.
void setTransformContext(const QgsCoordinateTransformContext &transformContext)
Sets data coordinate transform context to transformContext.
QList< QgsReadWriteContext::ReadWriteMessage > takeMessages()
Returns the stored messages and remove them.
void setProjectTranslator(QgsProjectTranslator *projectTranslator)
Sets the project translator.
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
This class manages a set of relations between layers.
void clear()
Remove any relation managed by this class.
QMap< QString, QgsRelation > relations() const
Gets access to the relations managed by this class.
void clear(const QString &group="startup")
clear Clear all profile data.
Expression function for use within a QgsExpressionContextScope.
Scoped object for logging of the runtime for a single operation or group of operations.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
This is a container for configuration of the snapping of the project.
bool addLayers(const QList< QgsMapLayer * > &layers)
Adds the specified layers as individual layers to the configuration with standard configuration.
void readProject(const QDomDocument &doc)
Reads the configuration from the specified QGIS project document.
void reset()
reset to default values
void writeProject(QDomDocument &doc)
Writes the configuration to the specified QGIS project document.
void clearIndividualLayerSettings()
Removes all individual layer snapping settings.
bool removeLayers(const QList< QgsMapLayer * > &layers)
Removes the specified layers from the individual layer configuration.
An interface for classes which can visit style entity (e.g.
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
static QgsStyle * defaultStyle()
Returns default application-wide style.
void triggerIconRebuild()
Triggers emission of the rebuildIconPreviews() signal.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
bool addLayer(QgsVectorLayer *layer)
Add a layer to this transaction group.
static bool supportsTransaction(const QgsVectorLayer *layer)
Checks if the provider of a given layer supports transactions.
QString connectionString() const
Returns the connection string of the transaction.
Used for the collecting of strings from projects for translation and creation of ts files.
void registerTranslation(const QString &context, const QString &source)
Registers the source to be translated.
void setFileName(const QString &fileName)
Sets the fileName of the TS file.
void writeTsFile(const QString &locale) const
Writes the Ts-file.
void setProject(QgsProject *project)
Sets the project being translated.
DistanceUnit
Units of distance.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
static Q_INVOKABLE QgsUnitTypes::AreaUnit decodeAreaUnit(const QString &string, bool *ok=nullptr)
Decodes an areal unit from a string.
@ AreaSquareMeters
Square meters.
The edit buffer group manages a group of edit buffers.
bool commitChanges(QStringList &commitErrors, bool stopEditing=true)
Attempts to commit any changes to disk.
bool startEditing()
Start editing.
void clear()
Remove all layers from this edit buffer group.
bool rollBack(QStringList &rollbackErrors, bool stopEditing=true)
Stop editing and discard the edits.
void addLayer(QgsVectorLayer *layer)
Add a layer to this edit buffer group.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE bool startEditing()
Makes the layer editable.
bool loadAuxiliaryLayer(const QgsAuxiliaryStorage &storage, const QString &key=QString())
Loads the auxiliary layer for this vector layer.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
Q_INVOKABLE bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits.
Q_INVOKABLE bool commitChanges(bool stopEditing=true)
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
QgsEditFormConfig editFormConfig
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
QgsMapLayerType
Types of layers that can be added to a map.
@ PointCloudLayer
Point cloud layer. Added in QGIS 3.18.
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
@ VectorLayer
Vector layer.
@ RasterLayer
Raster layer.
@ GroupLayer
Composite group layer. Added in QGIS 3.24.
@ VectorTileLayer
Vector tile layer. Added in QGIS 3.14.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ PluginLayer
Plugin based layer.
CORE_EXPORT bool isZipFile(const QString &filename)
Returns true if the file name is a zipped file ( i.e with a '.qgz' extension, false otherwise.
CONSTLATIN1STRING geoNone()
Constant that holds the string representation for "No ellips/No CRS".
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
#define Q_NOWARN_DEPRECATED_POP
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
#define Q_NOWARN_DEPRECATED_PUSH
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
#define QgsDebugMsgLevel(str, level)
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
void _getProperties(const QDomDocument &doc, QgsProjectPropertyKey &project_properties)
Restores any optional properties found in "doc" to "properties".
QgsPropertyCollection getDataDefinedServerProperties(const QDomDocument &doc, const QgsPropertiesDefinition &dataDefinedServerPropertyDefinitions)
Returns the data defined server properties collection found in "doc" to "dataDefinedServerProperties"...
void removeKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
Removes a given key.
QgsProjectVersion getVersion(const QDomDocument &doc)
Returns the version string found in the given DOM document.
QStringList makeKeyTokens_(const QString &scope, const QString &key)
Takes the given scope and key and convert them to a string list of key tokens that will be used to na...
void dump_(const QgsProjectPropertyKey &topQgsPropertyKey)
QgsProjectProperty * findKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
Returns the property that matches the given key sequence, if any.
QgsProjectProperty * addKey_(const QString &scope, const QString &key, QgsProjectPropertyKey *rootProperty, const QVariant &value, bool &propertiesModified)
Adds the given key and value.
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
const QgsCoordinateReferenceSystem & crs
Setting options for loading annotation layers.
Single variable definition for use within a QgsExpressionContextScope.
Setting options for loading group layers.
Contains information relating to a node (i.e.