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() ) )
515 if ( vl->dataProvider() )
522 if ( oldTrustLayerMetadata != newTrustLayerMetadata )
525 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
527 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
529 vl->setReadExtentFromXml( newTrustLayerMetadata );
534 if ( mFlags !=
flags )
543 Qgis::ProjectFlags newFlags = mFlags;
547 newFlags &= ~(
static_cast< int >( flag ) );
558 return mSaveUserFull;
563 return mSaveDateTime;
578 if ( dirty && mDirtyBlockCount > 0 )
584 if ( mDirty == dirty )
593 if ( path == mHomePath )
597 mCachedHomePath.clear();
598 mProjectScope.reset();
607 const QList<QgsAttributeEditorElement *> elements = parent->
children();
615 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:formcontainers" ).arg( layerId ), container->
name() );
617 if ( !container->
children().empty() )
630 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1" ).arg( layer->layerId() ), layer->name() );
647 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( vlayer->
id() ), fieldName );
662 const QList<QgsLayerTreeGroup *> groupLayers = mRootGroup->
findGroups();
665 translationContext->
registerTranslation( QStringLiteral(
"project:layergroups" ), groupLayer->name() );
669 const QList<QgsRelation> &relations = mRelationManager->
relations().values();
672 translationContext->
registerTranslation( QStringLiteral(
"project:relations" ), relation.name() );
678 mDataDefinedServerProperties = properties;
683 return mDataDefinedServerProperties;
688 switch ( mTransactionMode )
707 switch ( mTransactionMode )
714 commitErrors.append( tr(
"Trying to commit changes without a layer specified. This only works if the transaction mode is buffered" ) );
723 return mEditBufferGroup.
commitChanges( commitErrors, stopEditing );
731 switch ( mTransactionMode )
738 rollbackErrors.append( tr(
"Trying to roll back changes without a layer specified. This only works if the transaction mode is buffered" ) );
741 bool success = vectorLayer->
rollBack( stopEditing );
747 return mEditBufferGroup.
rollBack( rollbackErrors, stopEditing );
755 if ( name == mFile.fileName() )
758 const QString oldHomePath =
homePath();
760 mFile.setFileName( name );
761 mCachedHomePath.clear();
762 mProjectScope.reset();
766 const QString newHomePath =
homePath();
767 if ( newHomePath != oldHomePath )
775 return mFile.fileName();
780 mOriginalPath = path;
785 return mOriginalPath;
790 return QFileInfo( mFile );
803 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
808 return QFileInfo( mFile.fileName() ).lastModified();
817 if ( mFile.fileName().isEmpty() )
820 return QFileInfo( mFile.fileName() ).absolutePath();
828 if ( mFile.fileName().isEmpty() )
831 return QFileInfo( mFile.fileName() ).absoluteFilePath();
839 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
844 return QFileInfo( mFile.fileName() ).completeBaseName();
850 const bool absolutePaths =
readBoolEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
859 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
true );
862 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
877 writeEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ),
crs.
isValid() ? 1 : 0 );
878 mProjectScope.reset();
889 if ( adjustEllipsoid )
895 if ( !
crs().isValid() )
898 return readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ),
geoNone() );
903 if (
ellipsoid ==
readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ) ) )
906 mProjectScope.reset();
913 return mTransformContext;
918 if ( context == mTransformContext )
921 mTransformContext = context;
922 mProjectScope.reset();
925 for (
auto &layer : mLayerStore.get()->mapLayers() )
927 layer->setTransformContext( context );
934 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
936 mProjectScope.reset();
937 mFile.setFileName( QString() );
940 mSaveUserFull.clear();
941 mSaveDateTime = QDateTime();
944 mCachedHomePath.clear();
946 mFlags = Qgis::ProjectFlags();
948 mCustomVariables.clear();
951 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_new_projects" ),
false,
QgsSettings::Core ).toBool() )
970 mEmbeddedLayers.clear();
971 mRelationManager->
clear();
972 mAnnotationManager->clear();
973 mLayoutManager->clear();
974 m3DViewsManager->clear();
975 mBookmarkManager->
clear();
976 mViewSettings->
reset();
977 mTimeSettings->
reset();
978 mElevationProperties->
reset();
979 mDisplaySettings->
reset();
980 mSnappingConfig.
reset();
988 mLabelingEngineSettings->clear();
994 mStyleSettings->
reset();
998 if ( !mIsBeingDeleted )
1006 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/Automatic" ),
true );
1007 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/DecimalPlaces" ), 2 );
1009 const bool defaultRelativePaths = mSettings.
value( QStringLiteral(
"/qgis/defaultProjectPathsRelative" ),
true ).toBool();
1012 int red = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_red" ), 255 ).toInt();
1013 int green = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_green" ), 255 ).toInt();
1014 int blue = mSettings.
value( QStringLiteral(
"qgis/default_canvas_color_blue" ), 255 ).toInt();
1017 red = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_red" ), 255 ).toInt();
1018 green = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_green" ), 255 ).toInt();
1019 blue = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_blue" ), 0 ).toInt();
1020 const int alpha = mSettings.
value( QStringLiteral(
"qgis/default_selection_color_alpha" ), 255 ).toInt();
1026 mRootGroup->
clear();
1027 if ( mMainAnnotationLayer )
1028 mMainAnnotationLayer->
reset();
1030 snapSingleBlocker.release();
1032 if ( !mBlockSnappingUpdates )
1044 topQgsPropertyKey.
dump();
1077 const QDomElement propertiesElem = doc.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
1079 if ( propertiesElem.isNull() )
1084 const QDomNodeList scopes = propertiesElem.childNodes();
1086 if ( propertiesElem.firstChild().isNull() )
1088 QgsDebugMsg( QStringLiteral(
"empty ``properties'' XML tag ... bailing" ) );
1092 if ( ! project_properties.
readXml( propertiesElem ) )
1094 QgsDebugMsg( QStringLiteral(
"Project_properties.readXml() failed" ) );
1108 const QDomElement ddElem = doc.documentElement().firstChildElement( QStringLiteral(
"dataDefinedServerProperties" ) );
1109 if ( !ddElem.isNull() )
1111 if ( !ddServerProperties.
readXml( ddElem, dataDefinedServerPropertyDefinitions ) )
1113 QgsDebugMsg( QStringLiteral(
"dataDefinedServerProperties.readXml() failed" ) );
1116 return ddServerProperties;
1123static void _getTitle(
const QDomDocument &doc, QString &title )
1125 const QDomElement titleNode = doc.documentElement().firstChildElement( QStringLiteral(
"title" ) );
1129 if ( titleNode.isNull() )
1135 if ( !titleNode.hasChildNodes() )
1141 const QDomNode titleTextNode = titleNode.firstChild();
1143 if ( !titleTextNode.isText() )
1149 const QDomText titleText = titleTextNode.toText();
1151 title = titleText.data();
1155static void readProjectFileMetadata(
const QDomDocument &doc, QString &lastUser, QString &lastUserFull, QDateTime &lastSaveDateTime )
1157 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1161 QgsDebugMsg( QStringLiteral(
"unable to find qgis element" ) );
1165 const QDomNode qgisNode = nl.item( 0 );
1167 const QDomElement qgisElement = qgisNode.toElement();
1168 lastUser = qgisElement.attribute( QStringLiteral(
"saveUser" ), QString() );
1169 lastUserFull = qgisElement.attribute( QStringLiteral(
"saveUserFull" ), QString() );
1170 lastSaveDateTime = QDateTime::fromString( qgisElement.attribute( QStringLiteral(
"saveDateTime" ), QString() ), Qt::ISODate );
1176 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1180 QgsDebugMsg( QStringLiteral(
" unable to find qgis element in project file" ) );
1184 const QDomNode qgisNode = nl.item( 0 );
1186 const QDomElement qgisElement = qgisNode.toElement();
1187 QgsProjectVersion projectVersion( qgisElement.attribute( QStringLiteral(
"version" ) ) );
1188 return projectVersion;
1194 return mSnappingConfig;
1209 if ( mAvoidIntersectionsMode == mode )
1212 mAvoidIntersectionsMode = mode;
1216bool QgsProject::_getMapLayers(
const QDomDocument &doc, QList<QDomNode> &brokenNodes, Qgis::ProjectReadFlags flags )
1221 QDomElement layerElement = doc.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
1225 if ( layerElement.isNull() )
1235 bool returnStatus =
true;
1238 while ( ! layerElement.isNull() )
1241 layerElement = layerElement.nextSiblingElement( QStringLiteral(
"maplayer" ) );
1247 if ( depSorter.hasCycle() )
1251 if ( depSorter.hasMissingDependency() )
1252 returnStatus =
false;
1256 const QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
1257 const int totalLayerCount = sortedLayerNodes.count();
1260 for (
const QDomNode &node : sortedLayerNodes )
1262 const QDomElement element = node.toElement();
1264 const QString name =
translate( QStringLiteral(
"project:layers:%1" ).arg( node.namedItem( QStringLiteral(
"id" ) ).toElement().text() ), node.namedItem( QStringLiteral(
"layername" ) ).toElement().text() );
1265 if ( !name.isNull() )
1266 emit
loadingLayer( tr(
"Loading layer %1" ).arg( name ) );
1268 profile.switchTask( name );
1270 if ( element.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
1272 createEmbeddedLayer( element.attribute( QStringLiteral(
"id" ) ),
readPath( element.attribute( QStringLiteral(
"project" ) ) ), brokenNodes,
true,
flags );
1281 if ( !addLayer( element, brokenNodes, context,
flags ) )
1283 returnStatus =
false;
1286 if ( !messages.isEmpty() )
1295 return returnStatus;
1298bool QgsProject::addLayer(
const QDomElement &layerElem, QList<QDomNode> &brokenNodes,
QgsReadWriteContext &context, Qgis::ProjectReadFlags flags )
1300 const QString type = layerElem.attribute( QStringLiteral(
"type" ) );
1302 std::unique_ptr<QgsMapLayer>
mapLayer;
1310 QgsDebugMsg( QStringLiteral(
"Unknown layer type \"%1\"" ).arg( type ) );
1314 switch ( layerType )
1317 mapLayer = std::make_unique<QgsVectorLayer>();
1321 mapLayer = std::make_unique<QgsRasterLayer>();
1325 mapLayer = std::make_unique<QgsMeshLayer>();
1329 mapLayer = std::make_unique<QgsVectorTileLayer>();
1333 mapLayer = std::make_unique<QgsPointCloudLayer>();
1338 const QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
1346 mapLayer = std::make_unique<QgsAnnotationLayer>( QString(), options );
1353 mapLayer = std::make_unique<QgsGroupLayer>( QString(), options );
1360 QgsDebugMsg( QStringLiteral(
"Unable to create layer" ) );
1368 const QString layerId { layerElem.namedItem( QStringLiteral(
"id" ) ).toElement().text() };
1369 Q_ASSERT( ! layerId.isEmpty() );
1373 QgsMapLayer::ReadFlags layerFlags = QgsMapLayer::ReadFlags();
1383 profile.switchTask( tr(
"Load layer source" ) );
1390 if ( vl->dataProvider() )
1397 profile.switchTask( tr(
"Add layer to project" ) );
1398 QList<QgsMapLayer *> newLayers;
1410 vLayer->joinBuffer()->resolveReferences(
this );
1418 QgsDebugMsg(
"Unable to load " + type +
" layer" );
1419 brokenNodes.push_back( layerElem );
1422 const bool wasEditable = layerElem.attribute( QStringLiteral(
"editable" ), QStringLiteral(
"0" ) ).toInt();
1434 if ( ! layerWasStored )
1439 return layerIsValid;
1444 mFile.setFileName( filename );
1445 mCachedHomePath.clear();
1446 mProjectScope.reset();
1453 const QString filename = mFile.fileName();
1458 QTemporaryFile inDevice;
1459 if ( !inDevice.open() )
1461 setError( tr(
"Unable to open %1" ).arg( inDevice.fileName() ) );
1467 if ( !storage->readProject( filename, &inDevice, context ) )
1469 QString err = tr(
"Unable to open %1" ).arg( filename );
1470 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
1471 if ( !messages.isEmpty() )
1472 err += QStringLiteral(
"\n\n" ) + messages.last().message();
1476 returnValue = unzip( inDevice.fileName(),
flags );
1482 returnValue = unzip( mFile.fileName(),
flags );
1487 const QFileInfo finfo( mFile.fileName() );
1488 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
1489 if ( QFile( attachmentsZip ).exists() )
1491 std::unique_ptr<QgsArchive> archive(
new QgsArchive() );
1492 if ( archive->unzip( attachmentsZip ) )
1494 mArchive = std::move( archive );
1497 returnValue = readProjectFile( mFile.fileName(),
flags );
1503 mFile.setFileName( filename );
1504 mCachedHomePath.clear();
1505 mProjectScope.reset();
1510 mTranslator.reset(
nullptr );
1517bool QgsProject::readProjectFile(
const QString &filename, Qgis::ProjectReadFlags flags )
1520 ScopedIntIncrementor snapSignalBlock( &mBlockSnappingUpdates );
1522 QFile projectFile( filename );
1530 if ( QFile( QStringLiteral(
"%1/%2.qm" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) ).exists() )
1532 mTranslator.reset(
new QTranslator() );
1533 ( void )mTranslator->load( localeFileName, QFileInfo( projectFile.fileName() ).absolutePath() );
1536 profile.switchTask( tr(
"Reading project file" ) );
1537 std::unique_ptr<QDomDocument> doc(
new QDomDocument( QStringLiteral(
"qgis" ) ) );
1539 if ( !projectFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
1541 projectFile.close();
1543 setError( tr(
"Unable to open %1" ).arg( projectFile.fileName() ) );
1552 if ( !doc->setContent( &projectFile, &errorMsg, &line, &column ) )
1554 const QString errorString = tr(
"Project file read error in file %1: %2 at line %3 column %4" )
1555 .arg( projectFile.fileName(), errorMsg ).arg( line ).arg( column );
1559 projectFile.close();
1561 setError( errorString );
1566 projectFile.close();
1574 profile.switchTask( tr(
"Updating project file" ) );
1575 if ( thisVersion > fileVersion )
1577 const bool isOlderMajorVersion = fileVersion.
majorVersion() < thisVersion.majorVersion();
1579 if ( isOlderMajorVersion )
1582 "version of qgis (saved in " + fileVersion.
text() +
1584 "). Problems may occur." );
1595 projectFile.updateRevision( thisVersion );
1597 else if ( fileVersion > thisVersion )
1600 "version of qgis (saved in " + fileVersion.
text() +
1602 "). Problems may occur." );
1608 profile.switchTask( tr(
"Creating auxiliary storage" ) );
1609 const QString
fileName = mFile.fileName();
1610 std::unique_ptr<QgsAuxiliaryStorage> aStorage = std::move( mAuxiliaryStorage );
1611 std::unique_ptr<QgsArchive> archive = std::move( mArchive );
1613 mAuxiliaryStorage = std::move( aStorage );
1614 mArchive = std::move( archive );
1616 mCachedHomePath.clear();
1617 mProjectScope.reset();
1618 mSaveVersion = fileVersion;
1621 profile.switchTask( tr(
"Reading properties" ) );
1630 dump_( mProperties );
1635 _getTitle( *doc, oldTitle );
1637 readProjectFileMetadata( *doc, mSaveUser, mSaveUserFull, mSaveDateTime );
1639 const QDomNodeList homePathNl = doc->elementsByTagName( QStringLiteral(
"homePath" ) );
1640 if ( homePathNl.count() > 0 )
1642 const QDomElement homePathElement = homePathNl.at( 0 ).toElement();
1643 const QString
homePath = homePathElement.attribute( QStringLiteral(
"path" ) );
1653 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), 255 ),
1654 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), 255 ) );
1657 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), 255 ),
1658 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), 255 ),
1659 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), 255 ) );
1663 const QString distanceUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), QString() );
1664 if ( !distanceUnitString.isEmpty() )
1667 const QString areaUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), QString() );
1668 if ( !areaUnitString.isEmpty() )
1677 if (
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ), 0 ) )
1680 const QDomNode srsNode = doc->documentElement().namedItem( QStringLiteral(
"projectCrs" ) );
1681 if ( !srsNode.isNull() )
1683 projectCrs.
readXml( srsNode );
1688 const QString projCrsString =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSProj4String" ) );
1689 const long currentCRS =
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSID" ), -1 );
1690 const QString authid =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCrs" ) );
1693 const bool isUserAuthId = authid.startsWith( QLatin1String(
"USER:" ), Qt::CaseInsensitive );
1694 if ( !authid.isEmpty() && !isUserAuthId )
1698 if ( !projectCrs.
isValid() && currentCRS >= 0 )
1704 if ( !projCrsString.isEmpty() && ( authid.isEmpty() || isUserAuthId ) && ( !projectCrs.
isValid() || projectCrs.
toProj() != projCrsString ) )
1718 QStringList datumErrors;
1719 if ( !mTransformContext.
readXml( doc->documentElement(), context, datumErrors ) && !datumErrors.empty() )
1727 const QStringList variableNames =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ) );
1728 const QStringList variableValues =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ) );
1730 mCustomVariables.clear();
1731 if ( variableNames.length() == variableValues.length() )
1733 for (
int i = 0; i < variableNames.length(); ++i )
1735 mCustomVariables.insert( variableNames.at( i ), variableValues.at( i ) );
1740 QgsMessageLog::logMessage( tr(
"Project Variables Invalid" ), tr(
"The project contains invalid variable settings." ) );
1743 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectMetadata" ) );
1745 if ( !element.isNull() )
1754 if ( mMetadata.
title().isEmpty() && !oldTitle.isEmpty() )
1762 element = doc->documentElement().firstChildElement( QStringLiteral(
"transaction" ) );
1763 if ( !element.isNull() )
1770 element = doc->documentElement().firstChildElement( QStringLiteral(
"autotransaction" ) );
1771 if ( ! element.isNull() )
1773 mTransactionMode =
static_cast<Qgis::TransactionMode>( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() );
1778 profile.switchTask( tr(
"Loading layer tree" ) );
1781 QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
1782 if ( !layerTreeElem.isNull() )
1794 mLayerTreeRegistryBridge->
setEnabled(
false );
1797 profile.switchTask( tr(
"Reading map layers" ) );
1799 loadProjectFlags( doc.get() );
1801 QList<QDomNode> brokenNodes;
1802 const bool clean = _getMapLayers( *doc, brokenNodes,
flags );
1807 QgsDebugMsg( QStringLiteral(
"Unable to get map layers from project file." ) );
1809 if ( !brokenNodes.isEmpty() )
1811 QgsDebugMsg(
"there are " + QString::number( brokenNodes.size() ) +
" broken layers" );
1819 mMainAnnotationLayer->
readLayerXml( doc->documentElement().firstChildElement( QStringLiteral(
"main-annotation-layer" ) ), context );
1823 profile.switchTask( tr(
"Loading embedded layers" ) );
1824 loadEmbeddedNodes( mRootGroup,
flags );
1828 profile.switchTask( tr(
"Resolving layer references" ) );
1829 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
1830 for ( QMap<QString, QgsMapLayer *>::iterator it =
layers.begin(); it !=
layers.end(); ++it )
1832 it.value()->resolveReferences(
this );
1835 mLayerTreeRegistryBridge->
setEnabled(
true );
1838 profile.switchTask( tr(
"Resolving references" ) );
1841 if ( !layerTreeElem.isNull() )
1847 const QDomElement layerTreeCanvasElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-canvas" ) );
1848 if ( !layerTreeCanvasElem.isNull( ) )
1856 const QStringList requiredLayerIds =
readListEntry( QStringLiteral(
"RequiredLayers" ), QStringLiteral(
"Layers" ) );
1857 for (
const QString &layerId : requiredLayerIds )
1864 const QStringList disabledLayerIds =
readListEntry( QStringLiteral(
"Identify" ), QStringLiteral(
"/disabledLayers" ) );
1865 for (
const QString &layerId : disabledLayerIds )
1878 QString styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1879 if ( !styleName.isEmpty() )
1884 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
1885 if ( !styleName.isEmpty() )
1890 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
1891 if ( !styleName.isEmpty() )
1896 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
1897 if ( !styleName.isEmpty() )
1907 double opacity = 1.0;
1910 double alpha =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ), 255, &ok );
1912 opacity = alpha / 255.0;
1913 double newOpacity =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ), 1.0, &ok );
1915 opacity = newOpacity;
1919 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
1920 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
1921 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
1922 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
1923 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/RandomColors" ) );
1924 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ) );
1925 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ) );
1933 profile.switchTask( tr(
"Storing original layer properties" ) );
1939 profile.switchTask( tr(
"Loading map themes" ) );
1942 mMapThemeCollection->readXml( *doc );
1944 profile.switchTask( tr(
"Loading label settings" ) );
1945 mLabelingEngineSettings->readSettingsFromProject(
this );
1948 profile.switchTask( tr(
"Loading annotations" ) );
1949 mAnnotationManager->readXml( doc->documentElement(), context );
1952 profile.switchTask( tr(
"Loading layouts" ) );
1953 mLayoutManager->readXml( doc->documentElement(), *doc );
1958 profile.switchTask( tr(
"Loading 3D Views" ) );
1959 m3DViewsManager->readXml( doc->documentElement(), *doc );
1962 profile.switchTask( tr(
"Loading bookmarks" ) );
1963 mBookmarkManager->
readXml( doc->documentElement(), *doc );
1966 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
1967 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); ++it )
1969 it.value()->setDependencies( it.value()->dependencies() );
1972 profile.switchTask( tr(
"Loading snapping settings" ) );
1976 profile.switchTask( tr(
"Loading view settings" ) );
1979 const QStringList scales =
readListEntry( QStringLiteral(
"Scales" ), QStringLiteral(
"/ScalesList" ) );
1980 QVector<double> res;
1981 for (
const QString &scale : scales )
1983 const QStringList parts = scale.split(
':' );
1984 if ( parts.size() != 2 )
1988 const double denominator = QLocale().toDouble( parts[1], &ok );
1995 const QDomElement viewSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectViewSettings" ) );
1996 if ( !viewSettingsElement.isNull() )
1997 mViewSettings->
readXml( viewSettingsElement, context );
2000 profile.switchTask( tr(
"Loading style properties" ) );
2001 const QDomElement styleSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectStyleSettings" ) );
2002 if ( !styleSettingsElement.isNull() )
2003 mStyleSettings->
readXml( styleSettingsElement, context,
flags );
2006 profile.switchTask( tr(
"Loading temporal settings" ) );
2007 const QDomElement timeSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectTimeSettings" ) );
2008 if ( !timeSettingsElement.isNull() )
2009 mTimeSettings->
readXml( timeSettingsElement, context );
2012 profile.switchTask( tr(
"Loading elevation properties" ) );
2013 const QDomElement elevationPropertiesElement = doc->documentElement().firstChildElement( QStringLiteral(
"ElevationProperties" ) );
2014 if ( !elevationPropertiesElement.isNull() )
2015 mElevationProperties->
readXml( elevationPropertiesElement, context );
2018 profile.switchTask( tr(
"Loading display settings" ) );
2019 const QDomElement displaySettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectDisplaySettings" ) );
2020 if ( !displaySettingsElement.isNull() )
2021 mDisplaySettings->
readXml( displaySettingsElement, context );
2023 profile.switchTask( tr(
"Updating variables" ) );
2025 profile.switchTask( tr(
"Updating CRS" ) );
2030 profile.switchTask( tr(
"Reading external settings" ) );
2034 profile.switchTask( tr(
"Updating interface" ) );
2036 snapSignalBlock.release();
2037 if ( !mBlockSnappingUpdates )
2048 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUser ), 2 );
2049 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUserFull ), 2 );
2058 const QString newFileName( QStringLiteral(
"%1/%2.qgs" ).arg( QFileInfo( projectFile.fileName() ).absolutePath(), localeFileName ) );
2073 const QMap<QString, QgsMapLayer *> loadedLayers =
mapLayers();
2074 for (
auto it = loadedLayers.constBegin(); it != loadedLayers.constEnd(); ++it )
2076 if ( it.value()->isValid() && it.value()->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2078 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( it.value() ) )
2080 it.value()->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2088bool QgsProject::loadEmbeddedNodes(
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
2091 const auto constChildren = group->
children();
2097 if ( childGroup->
customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2100 const QString projectPath =
readPath( childGroup->
customProperty( QStringLiteral(
"embedded_project" ) ).toString() );
2101 childGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectPath );
2105 QList<QgsLayerTreeNode *> clonedChildren;
2106 const QList<QgsLayerTreeNode *> constChildren = newGroup->
children();
2107 clonedChildren.reserve( constChildren.size() );
2109 clonedChildren << newGroupChild->clone();
2117 loadEmbeddedNodes( childGroup,
flags );
2122 if ( child->customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2124 QList<QDomNode> brokenNodes;
2127 valid = valid &&
false;
2139 return mCustomVariables;
2144 if ( variables == mCustomVariables )
2148 QStringList variableNames;
2149 QStringList variableValues;
2151 QVariantMap::const_iterator it = variables.constBegin();
2152 for ( ; it != variables.constEnd(); ++it )
2154 variableNames << it.key();
2155 variableValues << it.value().toString();
2158 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ), variableNames );
2159 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ), variableValues );
2161 mCustomVariables = variables;
2162 mProjectScope.reset();
2169 *mLabelingEngineSettings = settings;
2175 return *mLabelingEngineSettings;
2180 mProjectScope.reset();
2181 return mLayerStore.get();
2186 return mLayerStore.get();
2191 QList<QgsVectorLayer *>
layers;
2192 const QStringList layerIds =
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), QStringList() );
2193 const auto constLayerIds = layerIds;
2194 for (
const QString &layerId : constLayerIds )
2205 list.reserve(
layers.size() );
2207 list << layer->id();
2208 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), list );
2225 if ( mProjectScope )
2227 std::unique_ptr< QgsExpressionContextScope > projectScope = std::make_unique< QgsExpressionContextScope >( *mProjectScope );
2231 return projectScope.release();
2234 mProjectScope = std::make_unique< QgsExpressionContextScope >( QObject::tr(
"Project" ) );
2238 QVariantMap::const_iterator it = vars.constBegin();
2240 for ( ; it != vars.constEnd(); ++it )
2242 mProjectScope->setVariable( it.key(), it.value(),
true );
2246 if ( projectPath.isEmpty() )
2247 projectPath = mOriginalPath;
2248 const QString projectFolder = QFileInfo( projectPath ).path();
2249 const QString projectFilename = QFileInfo( projectPath ).fileName();
2250 const QString projectBasename =
baseName();
2279 QVariantMap keywords;
2281 for (
auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
2283 keywords.insert( it.key(), it.value() );
2288 QVariantList layersIds;
2290 const QMap<QString, QgsMapLayer *> layersInProject = mLayerStore->mapLayers();
2291 layersIds.reserve( layersInProject.count() );
2292 layers.reserve( layersInProject.count() );
2293 for (
auto it = layersInProject.constBegin(); it != layersInProject.constEnd(); ++it )
2295 layersIds << it.value()->id();
2301 mProjectScope->addFunction( QStringLiteral(
"project_color" ),
new GetNamedProjectColor(
this ) );
2306void QgsProject::onMapLayersAdded(
const QList<QgsMapLayer *> &layers )
2308 const QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2310 const auto constLayers =
layers;
2313 if ( ! layer->isValid() )
2316 if (
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer ) )
2319 if ( vlayer->dataProvider() )
2327 for ( QMap<QString, QgsMapLayer *>::const_iterator it = existingMaps.cbegin(); it != existingMaps.cend(); ++it )
2329 const QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
2330 if ( deps.contains( layer->id() ) )
2333 it.value()->setDependencies( deps );
2338 updateTransactionGroups();
2344void QgsProject::onMapLayersRemoved(
const QList<QgsMapLayer *> &layers )
2350void QgsProject::cleanTransactionGroups(
bool force )
2352 bool changed =
false;
2353 for ( QMap< QPair< QString, QString>,
QgsTransactionGroup *>::Iterator tg = mTransactionGroups.begin(); tg != mTransactionGroups.end(); )
2355 if ( tg.value()->isEmpty() || force )
2358 tg = mTransactionGroups.erase( tg );
2370void QgsProject::updateTransactionGroups()
2372 mEditBufferGroup.
clear();
2374 switch ( mTransactionMode )
2378 cleanTransactionGroups(
true );
2383 cleanTransactionGroups(
true );
2386 cleanTransactionGroups(
false );
2390 bool tgChanged =
false;
2391 const auto constLayers =
mapLayers().values();
2394 if ( ! layer->isValid() )
2397 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
2401 switch ( mTransactionMode )
2418 mTransactionGroups.insert( qMakePair( key, connString ), tg );
2428 mEditBufferGroup.
addLayer( vlayer );
2444 QList<QDomNode> brokenNodes;
2445 if ( addLayer( layerNode.toElement(), brokenNodes, context ) )
2449 const QVector<QgsVectorLayer *> vectorLayers = layers<QgsVectorLayer *>();
2453 layer->resolveReferences(
this );
2455 if ( layer->isValid() && layer->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2457 layer->startEditing();
2458 layer->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2468 mFile.setFileName( filename );
2469 mCachedHomePath.clear();
2475 mProjectScope.reset();
2481 const QString storageFilePath { storage->filePath( mFile.fileName() ) };
2482 if ( storageFilePath.isEmpty() )
2488 const QString tempPath = QStandardPaths::standardLocations( QStandardPaths::TempLocation ).at( 0 );
2489 const QString tmpZipFilename( tempPath + QDir::separator() + QUuid::createUuid().toString() );
2491 if ( !zip( tmpZipFilename ) )
2494 QFile tmpZipFile( tmpZipFilename );
2495 if ( !tmpZipFile.open( QIODevice::ReadOnly ) )
2497 setError( tr(
"Unable to read file %1" ).arg( tmpZipFilename ) );
2502 if ( !storage->writeProject( mFile.fileName(), &tmpZipFile, context ) )
2504 QString err = tr(
"Unable to save project to storage %1" ).arg( mFile.fileName() );
2505 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
2506 if ( !messages.isEmpty() )
2507 err += QStringLiteral(
"\n\n" ) + messages.last().message();
2513 QFile::remove( tmpZipFilename );
2520 return zip( mFile.fileName() );
2526 const bool asOk = saveAuxiliaryStorage();
2527 const bool writeOk = writeProjectFile( mFile.fileName() );
2528 bool attachmentsOk =
true;
2529 if ( !mArchive->files().isEmpty() )
2531 const QFileInfo finfo( mFile.fileName() );
2532 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
2533 attachmentsOk = mArchive->zip( attachmentsZip );
2537 if ( ( !asOk || !attachmentsOk ) && writeOk )
2539 QStringList errorMessage;
2542 const QString err = mAuxiliaryStorage->errorString();
2543 errorMessage.append( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
2545 if ( !attachmentsOk )
2547 errorMessage.append( tr(
"Unable to save attachments archive" ) );
2549 setError( errorMessage.join(
'\n' ) );
2552 return asOk && writeOk && attachmentsOk;
2556bool QgsProject::writeProjectFile(
const QString &filename )
2558 QFile projectFile( filename );
2564 const QFileInfo myFileInfo( projectFile );
2565 if ( myFileInfo.exists() && !myFileInfo.isWritable() )
2567 setError( tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
2568 .arg( projectFile.fileName() ) );
2576 QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
2578 const QDomDocumentType documentType =
2579 QDomImplementation().createDocumentType( QStringLiteral(
"qgis" ), QStringLiteral(
"http://mrcc.com/qgis.dtd" ),
2580 QStringLiteral(
"SYSTEM" ) );
2581 std::unique_ptr<QDomDocument> doc(
new QDomDocument( documentType ) );
2583 QDomElement qgisNode = doc->createElement( QStringLiteral(
"qgis" ) );
2584 qgisNode.setAttribute( QStringLiteral(
"projectname" ),
title() );
2585 qgisNode.setAttribute( QStringLiteral(
"version" ),
Qgis::version() );
2587 if ( !mSettings.
value( QStringLiteral(
"projects/anonymize_saved_projects" ),
false,
QgsSettings::Core ).toBool() )
2591 qgisNode.setAttribute( QStringLiteral(
"saveUser" ), newSaveUser );
2592 qgisNode.setAttribute( QStringLiteral(
"saveUserFull" ), newSaveUserFull );
2593 mSaveUser = newSaveUser;
2594 mSaveUserFull = newSaveUserFull;
2595 mSaveDateTime = QDateTime::currentDateTime();
2596 qgisNode.setAttribute( QStringLiteral(
"saveDateTime" ), mSaveDateTime.toString( Qt::ISODate ) );
2601 mSaveUserFull.clear();
2602 mSaveDateTime = QDateTime();
2604 doc->appendChild( qgisNode );
2607 QDomElement homePathNode = doc->createElement( QStringLiteral(
"homePath" ) );
2608 homePathNode.setAttribute( QStringLiteral(
"path" ), mHomePath );
2609 qgisNode.appendChild( homePathNode );
2612 QDomElement titleNode = doc->createElement( QStringLiteral(
"title" ) );
2613 qgisNode.appendChild( titleNode );
2615 QDomElement transactionNode = doc->createElement( QStringLiteral(
"transaction" ) );
2616 transactionNode.setAttribute( QStringLiteral(
"mode" ),
qgsEnumValueToKey( mTransactionMode ) );
2617 qgisNode.appendChild( transactionNode );
2619 QDomElement flagsNode = doc->createElement( QStringLiteral(
"projectFlags" ) );
2621 qgisNode.appendChild( flagsNode );
2623 const QDomText titleText = doc->createTextNode(
title() );
2624 titleNode.appendChild( titleText );
2627 QDomElement srsNode = doc->createElement( QStringLiteral(
"projectCrs" ) );
2629 qgisNode.appendChild( srsNode );
2636 clonedRoot->
writeXml( qgisNode, context );
2640 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsMode" ),
static_cast<int>( mAvoidIntersectionsMode ) );
2648 QDomElement annotationLayerNode = doc->createElement( QStringLiteral(
"main-annotation-layer" ) );
2649 mMainAnnotationLayer->
writeLayerXml( annotationLayerNode, *doc, context );
2650 qgisNode.appendChild( annotationLayerNode );
2654 QDomElement projectLayersNode = doc->createElement( QStringLiteral(
"projectlayers" ) );
2656 QMap<QString, QgsMapLayer *>::ConstIterator li =
layers.constBegin();
2657 while ( li !=
layers.end() )
2663 const QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.constFind( ml->
id() );
2664 if ( emIt == mEmbeddedLayers.constEnd() )
2666 QDomElement maplayerElem;
2672 maplayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2676 maplayerElem.setAttribute( QStringLiteral(
"editable" ), QStringLiteral(
"1" ) );
2680 QDomDocument document;
2683 maplayerElem = document.firstChildElement();
2687 QgsDebugMsg( QStringLiteral(
"Could not restore layer properties for layer %1" ).arg( ml->
id() ) );
2693 projectLayersNode.appendChild( maplayerElem );
2699 if ( emIt.value().second )
2701 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
2702 mapLayerElem.setAttribute( QStringLiteral(
"embedded" ), 1 );
2703 mapLayerElem.setAttribute( QStringLiteral(
"project" ),
writePath( emIt.value().first ) );
2704 mapLayerElem.setAttribute( QStringLiteral(
"id" ), ml->
id() );
2705 projectLayersNode.appendChild( mapLayerElem );
2712 qgisNode.appendChild( projectLayersNode );
2714 QDomElement layerOrderNode = doc->createElement( QStringLiteral(
"layerorder" ) );
2716 for (
QgsMapLayer *layer : constCustomLayerOrder )
2718 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"layer" ) );
2719 mapLayerElem.setAttribute( QStringLiteral(
"id" ), layer->id() );
2720 layerOrderNode.appendChild( mapLayerElem );
2722 qgisNode.appendChild( layerOrderNode );
2724 mLabelingEngineSettings->writeSettingsToProject(
this );
2726 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorRedPart" ), mBackgroundColor.red() );
2727 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), mBackgroundColor.green() );
2728 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), mBackgroundColor.blue() );
2730 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorRedPart" ), mSelectionColor.red() );
2731 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), mSelectionColor.green() );
2732 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), mSelectionColor.blue() );
2733 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), mSelectionColor.alpha() );
2740 dump_( mProperties );
2743 QgsDebugMsgLevel( QStringLiteral(
"there are %1 property scopes" ).arg(
static_cast<int>( mProperties.
count() ) ), 2 );
2748 mProperties.
writeXml( QStringLiteral(
"properties" ), qgisNode, *doc );
2751 QDomElement ddElem = doc->createElement( QStringLiteral(
"dataDefinedServerProperties" ) );
2752 mDataDefinedServerProperties.
writeXml( ddElem, dataDefinedServerPropertyDefinitions() );
2753 qgisNode.appendChild( ddElem );
2755 mMapThemeCollection->writeXml( *doc );
2757 mTransformContext.
writeXml( qgisNode, context );
2759 QDomElement metadataElem = doc->createElement( QStringLiteral(
"projectMetadata" ) );
2761 qgisNode.appendChild( metadataElem );
2763 const QDomElement annotationsElem = mAnnotationManager->writeXml( *doc, context );
2764 qgisNode.appendChild( annotationsElem );
2766 const QDomElement layoutElem = mLayoutManager->writeXml( *doc );
2767 qgisNode.appendChild( layoutElem );
2769 const QDomElement views3DElem = m3DViewsManager->writeXml( *doc );
2770 qgisNode.appendChild( views3DElem );
2772 const QDomElement bookmarkElem = mBookmarkManager->
writeXml( *doc );
2773 qgisNode.appendChild( bookmarkElem );
2775 const QDomElement viewSettingsElem = mViewSettings->
writeXml( *doc, context );
2776 qgisNode.appendChild( viewSettingsElem );
2778 const QDomElement styleSettingsElem = mStyleSettings->
writeXml( *doc, context );
2779 qgisNode.appendChild( styleSettingsElem );
2781 const QDomElement timeSettingsElement = mTimeSettings->
writeXml( *doc, context );
2782 qgisNode.appendChild( timeSettingsElement );
2784 const QDomElement elevationPropertiesElement = mElevationProperties->
writeXml( *doc, context );
2785 qgisNode.appendChild( elevationPropertiesElement );
2787 const QDomElement displaySettingsElem = mDisplaySettings->
writeXml( *doc, context );
2788 qgisNode.appendChild( displaySettingsElem );
2796 QFile backupFile( QStringLiteral(
"%1~" ).arg( filename ) );
2798 ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
2799 ok &= projectFile.open( QIODevice::ReadOnly );
2802 while ( ok && !projectFile.atEnd() )
2804 ba = projectFile.read( 10240 );
2805 ok &= backupFile.write( ba ) == ba.size();
2808 projectFile.close();
2813 setError( tr(
"Unable to create backup file %1" ).arg( backupFile.fileName() ) );
2818 struct utimbuf tb = {
static_cast<time_t
>( fi.lastRead().toSecsSinceEpoch() ),
static_cast<time_t
>( fi.lastModified().toSecsSinceEpoch() ) };
2819 utime( backupFile.fileName().toUtf8().constData(), &tb );
2822 if ( !projectFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
2824 projectFile.close();
2827 setError( tr(
"Unable to save to file %1" ).arg( projectFile.fileName() ) );
2831 QTemporaryFile tempFile;
2832 bool ok = tempFile.open();
2835 QTextStream projectFileStream( &tempFile );
2836 doc->save( projectFileStream, 2 );
2837 ok &= projectFileStream.pos() > -1;
2839 ok &= tempFile.seek( 0 );
2842 while ( ok && !tempFile.atEnd() )
2844 ba = tempFile.read( 10240 );
2845 ok &= projectFile.write( ba ) == ba.size();
2848 ok &= projectFile.error() == QFile::NoError;
2850 projectFile.close();
2857 setError( tr(
"Unable to save to file %1. Your project "
2858 "may be corrupted on disk. Try clearing some space on the volume and "
2859 "check file permissions before pressing save again." )
2860 .arg( projectFile.fileName() ) );
2872 bool propertiesModified;
2873 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2875 if ( propertiesModified )
2883 bool propertiesModified;
2884 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2886 if ( propertiesModified )
2894 bool propertiesModified;
2895 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2897 if ( propertiesModified )
2905 bool propertiesModified;
2906 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2908 if ( propertiesModified )
2916 bool propertiesModified;
2917 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
2919 if ( propertiesModified )
2927 const QStringList &def,
2936 value =
property->value();
2938 const bool valid = QVariant::StringList == value.type();
2944 return value.toStringList();
2966 value =
property->value();
2968 const bool valid = value.canConvert( QVariant::String );
2973 return value.toString();
2990 value =
property->value();
2993 const bool valid = value.canConvert( QVariant::Int );
3002 return value.toInt();
3015 const QVariant value =
property->value();
3017 const bool valid = value.canConvert( QVariant::Double );
3022 return value.toDouble();
3037 const QVariant value =
property->value();
3039 const bool valid = value.canConvert( QVariant::Bool );
3044 return value.toBool();
3054 if (
findKey_( scope, key, mProperties ) )
3060 return !
findKey_( scope, key, mProperties );
3068 QStringList entries;
3070 if ( foundProperty )
3085 QStringList entries;
3087 if ( foundProperty )
3100 dump_( mProperties );
3118 filePath = storage->filePath( mFile.fileName() );
3141void QgsProject::setError(
const QString &errorMessage )
3143 mErrorMessage = errorMessage;
3148 return mErrorMessage;
3151void QgsProject::clearError()
3153 setError( QString() );
3158 delete mBadLayerHandler;
3159 mBadLayerHandler = handler;
3164 const QHash< QString, QPair< QString, bool > >::const_iterator it = mEmbeddedLayers.find(
id );
3165 if ( it == mEmbeddedLayers.constEnd() )
3169 return it.value().first;
3173 bool saveFlag, Qgis::ProjectReadFlags flags )
3177 static QString sPrevProjectFilePath;
3178 static QDateTime sPrevProjectFileTimestamp;
3179 static QDomDocument sProjectDocument;
3181 QString qgsProjectFile = projectFilePath;
3183 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3185 archive.
unzip( projectFilePath );
3189 const QDateTime projectFileTimestamp = QFileInfo( projectFilePath ).lastModified();
3191 if ( projectFilePath != sPrevProjectFilePath || projectFileTimestamp != sPrevProjectFileTimestamp )
3193 sPrevProjectFilePath.clear();
3195 QFile projectFile( qgsProjectFile );
3196 if ( !projectFile.open( QIODevice::ReadOnly ) )
3201 if ( !sProjectDocument.setContent( &projectFile ) )
3206 sPrevProjectFilePath = projectFilePath;
3207 sPrevProjectFileTimestamp = projectFileTimestamp;
3211 bool useAbsolutePaths =
true;
3213 const QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
3214 if ( !propertiesElem.isNull() )
3216 const QDomElement absElem = propertiesElem.firstChildElement( QStringLiteral(
"Paths" ) ).firstChildElement( QStringLiteral(
"Absolute" ) );
3217 if ( !absElem.isNull() )
3219 useAbsolutePaths = absElem.text().compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0;
3224 if ( !useAbsolutePaths )
3229 const QDomElement projectLayersElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) );
3230 if ( projectLayersElem.isNull() )
3235 QDomElement mapLayerElem = projectLayersElem.firstChildElement( QStringLiteral(
"maplayer" ) );
3236 while ( ! mapLayerElem.isNull() )
3239 const QString
id = mapLayerElem.firstChildElement( QStringLiteral(
"id" ) ).text();
3240 if (
id == layerId )
3243 if ( mapLayerElem.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
3248 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
3250 if ( addLayer( mapLayerElem, brokenNodes, embeddedContext,
flags ) )
3256 mEmbeddedLayers.remove( layerId );
3260 mapLayerElem = mapLayerElem.nextSiblingElement( QStringLiteral(
"maplayer" ) );
3269 QString qgsProjectFile = projectFilePath;
3271 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3273 archive.
unzip( projectFilePath );
3278 QFile projectFile( qgsProjectFile );
3279 if ( !projectFile.open( QIODevice::ReadOnly ) )
3284 QDomDocument projectDocument;
3285 if ( !projectDocument.setContent( &projectFile ) )
3297 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
3298 if ( !layerTreeElem.isNull() )
3308 if ( !group || group->
customProperty( QStringLiteral(
"embedded" ) ).toBool() )
3321 newGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectFilePath );
3324 mLayerTreeRegistryBridge->
setEnabled(
false );
3325 initializeEmbeddedSubtree( projectFilePath, newGroup,
flags );
3326 mLayerTreeRegistryBridge->
setEnabled(
true );
3329 const auto constFindLayerIds = newGroup->
findLayerIds();
3330 for (
const QString &layerId : constFindLayerIds )
3343void QgsProject::initializeEmbeddedSubtree(
const QString &projectFilePath,
QgsLayerTreeGroup *group, Qgis::ProjectReadFlags flags )
3345 const auto constChildren = group->
children();
3349 child->setCustomProperty( QStringLiteral(
"embedded" ), 1 );
3358 QList<QDomNode> brokenNodes;
3376 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), ( enabled ? 1 : 0 ) );
3382 return readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), 0 );
3387 if ( mDistanceUnits == unit )
3390 mDistanceUnits = unit;
3397 if ( mAreaUnits == unit )
3407 if ( !mCachedHomePath.isEmpty() )
3408 return mCachedHomePath;
3412 if ( !mHomePath.isEmpty() )
3414 const QFileInfo homeInfo( mHomePath );
3415 if ( !homeInfo.isRelative() )
3417 mCachedHomePath = mHomePath;
3427 const QString storagePath { storage->filePath(
fileName() ) };
3428 if ( ! storagePath.isEmpty() && QFileInfo::exists( storagePath ) )
3430 mCachedHomePath = QFileInfo( storagePath ).path();
3431 return mCachedHomePath;
3435 mCachedHomePath = pfi.path();
3436 return mCachedHomePath;
3439 if ( !pfi.exists() )
3441 mCachedHomePath = mHomePath;
3445 if ( !mHomePath.isEmpty() )
3448 mCachedHomePath = QDir::cleanPath( pfi.path() +
'/' + mHomePath );
3452 mCachedHomePath = pfi.canonicalPath();
3454 return mCachedHomePath;
3464 return mRelationManager;
3469 return mLayoutManager.get();
3474 return mLayoutManager.get();
3479 return m3DViewsManager.get();
3484 return m3DViewsManager.get();
3489 return mBookmarkManager;
3494 return mBookmarkManager;
3499 return mViewSettings;
3504 return mViewSettings;
3509 return mStyleSettings;
3514 return mStyleSettings;
3519 return mTimeSettings;
3524 return mTimeSettings;
3529 return mElevationProperties;
3534 return mElevationProperties;
3539 return mDisplaySettings;
3544 return mDisplaySettings;
3554 return mMapThemeCollection.get();
3559 return mAnnotationManager.get();
3564 return mAnnotationManager.get();
3569 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
3570 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
3575 if (
layers.contains( it.value() ) )
3576 it.value()->setFlags( it.value()->flags() &
~QgsMapLayer::Identifiable );
3590 for (
const QString &layerId : layerIds )
3606 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
3636 updateTransactionGroups();
3641 return mTransactionMode;
3650 const auto constLayers =
mapLayers().values();
3653 if ( layer->isEditable() )
3655 QgsLogger::warning( tr(
"Transaction mode can be changed only if all layers are not editable." ) );
3661 updateTransactionGroups();
3667 return mTransactionGroups;
3678 return mLayerStore->count();
3683 return mLayerStore->validCount();
3688 return mLayerStore->mapLayer( layerId );
3693 return mLayerStore->mapLayersByName( layerName );
3698 QList<QgsMapLayer *>
layers;
3699 const auto constMapLayers { mLayerStore->mapLayers() };
3700 for (
const auto &l : constMapLayers )
3702 if ( ! l->shortName().isEmpty() )
3704 if ( l->shortName() == shortName )
3707 else if ( l->name() == shortName )
3715bool QgsProject::unzip(
const QString &filename, Qgis::ProjectReadFlags flags )
3721 if ( !archive->unzip( filename ) )
3723 setError( tr(
"Unable to unzip file '%1'" ).arg( filename ) );
3728 if ( archive->projectFile().isEmpty() )
3730 setError( tr(
"Zip archive does not provide a project file" ) );
3735 mArchive = std::move( archive );
3752 setError( tr(
"Cannot read unzipped qgs project file" ) + QStringLiteral(
": " ) +
error() );
3762bool QgsProject::zip(
const QString &filename )
3768 const QString
baseName = QFileInfo( filename ).baseName();
3769 const QString qgsFileName = QStringLiteral(
"%1.qgs" ).arg(
baseName );
3770 QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
3772 bool writeOk =
false;
3773 if ( qgsFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3775 writeOk = writeProjectFile( qgsFile.fileName() );
3782 setError( tr(
"Unable to write temporary qgs file" ) );
3787 const QFileInfo info( qgsFile );
3789 const QString asFileName = info.path() + QDir::separator() + info.completeBaseName() + asExt;
3791 bool auxiliaryStorageSavedOk =
true;
3792 if ( ! saveAuxiliaryStorage( asFileName ) )
3794 const QString err = mAuxiliaryStorage->errorString();
3795 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 ) );
3796 auxiliaryStorageSavedOk =
false;
3799 if ( !mArchive->exists() )
3802 mArchive->unzip( mFile.fileName() );
3805 const QString auxiliaryStorageFile =
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile();
3806 if ( ! auxiliaryStorageFile.isEmpty() )
3808 archive->
addFile( auxiliaryStorageFile );
3817 if ( QFile::exists( asFileName ) )
3819 archive->addFile( asFileName );
3824 archive->addFile( qgsFile.fileName() );
3827 const QStringList &
files = mArchive->files();
3828 for (
const QString &file :
files )
3830 if ( !file.endsWith( QLatin1String(
".qgs" ), Qt::CaseInsensitive ) && !file.endsWith( asExt, Qt::CaseInsensitive ) )
3832 archive->addFile( file );
3838 if ( !archive->zip( filename ) )
3840 setError( tr(
"Unable to perform zip" ) );
3844 return auxiliaryStorageSavedOk && zipOk;
3853 const QList<QgsMapLayer *> &layers,
3855 bool takeOwnership )
3857 const QList<QgsMapLayer *> myResultList { mLayerStore->addMapLayers(
layers, takeOwnership ) };
3858 if ( !myResultList.isEmpty() )
3861 for (
auto &l : myResultList )
3871 if ( mAuxiliaryStorage )
3886 mProjectScope.reset();
3888 return myResultList;
3894 bool takeOwnership )
3896 QList<QgsMapLayer *> addedLayers;
3897 addedLayers =
addMapLayers( QList<QgsMapLayer *>() << layer, addToLegend, takeOwnership );
3898 return addedLayers.isEmpty() ? nullptr : addedLayers[0];
3901void QgsProject::removeAuxiliaryLayer(
const QgsMapLayer *ml )
3906 const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( ml );
3916 for (
const auto &layerId : layerIds )
3917 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
3919 mProjectScope.reset();
3920 mLayerStore->removeMapLayers( layerIds );
3925 for (
const auto &layer :
layers )
3926 removeAuxiliaryLayer( layer );
3928 mProjectScope.reset();
3929 mLayerStore->removeMapLayers(
layers );
3934 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
3935 mProjectScope.reset();
3936 mLayerStore->removeMapLayer( layerId );
3941 removeAuxiliaryLayer( layer );
3942 mProjectScope.reset();
3943 mLayerStore->removeMapLayer( layer );
3948 mProjectScope.reset();
3949 return mLayerStore->takeMapLayer( layer );
3954 return mMainAnnotationLayer;
3959 if ( mLayerStore->count() == 0 )
3962 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
3963 mProjectScope.reset();
3964 mLayerStore->removeAllMapLayers();
3966 snapSingleBlocker.release();
3968 if ( !mBlockSnappingUpdates )
3974 const QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
3975 QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin();
3976 for ( ; it !=
layers.constEnd(); ++it )
3978 it.value()->reload();
3984 return validOnly ? mLayerStore->validMapLayers() : mLayerStore->mapLayers();
3989 return mTransactionGroups.value( qMakePair( providerKey, connString ) );
3994 return &mEditBufferGroup;
4003 if ( mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), QStringLiteral(
"NoAction" ),
QgsSettings::App ).toString() == QStringLiteral(
"UseProjectCrs" )
4004 || mSettings.
value( QStringLiteral(
"/projections/unknownCrsBehavior" ), 0,
QgsSettings::App ).toString() == QLatin1String(
"2" ) )
4012 const QString layerDefaultCrs = mSettings.
value( QStringLiteral(
"/Projections/layerDefaultCrs" ),
geoEpsgCrsAuthId() ).toString();
4029bool QgsProject::saveAuxiliaryStorage(
const QString &filename )
4033 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4038 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
4046 if ( !mAuxiliaryStorage->exists( *
this ) && empty )
4050 else if ( !filename.isEmpty() )
4052 return mAuxiliaryStorage->saveAs( filename );
4056 return mAuxiliaryStorage->saveAs( *
this );
4069 return sPropertyDefinitions;
4074 return mAuxiliaryStorage.get();
4079 return mAuxiliaryStorage.get();
4084 const QDir archiveDir( mArchive->dir() );
4085 QTemporaryFile tmpFile( archiveDir.filePath(
"XXXXXX_" + nameTemplate ),
this );
4086 tmpFile.setAutoRemove(
false );
4088 mArchive->addFile( tmpFile.fileName() );
4089 return tmpFile.fileName();
4094 QStringList attachments;
4096 const QStringList files = mArchive->files();
4097 attachments.reserve( files.size() );
4098 for (
const QString &file : files )
4100 if ( QFileInfo( file ).baseName() !=
baseName )
4102 attachments.append( file );
4110 return mArchive->removeFile( path );
4115 return QStringLiteral(
"attachment:///%1" ).arg( QFileInfo( attachedFile ).
fileName() );
4120 if ( identifier.startsWith( QLatin1String(
"attachment:///" ) ) )
4122 return QDir( mArchive->dir() ).absoluteFilePath( identifier.mid( 14 ) );
4138 mProjectScope.reset();
4150 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4162 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
4163 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
4168 if (
layers.contains( it.value() ) )
4169 it.value()->setFlags( it.value()->flags() &
~QgsMapLayer::Removable );
4178 QStringList customColors;
4179 QStringList customColorLabels;
4181 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
4182 for ( ; colorIt != colors.constEnd(); ++colorIt )
4185 const QString label = ( *colorIt ).second;
4186 customColors.append( color );
4187 customColorLabels.append( label );
4189 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ), customColors );
4190 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ), customColorLabels );
4191 mProjectScope.reset();
4197 if ( mBackgroundColor == color )
4200 mBackgroundColor = color;
4206 return mBackgroundColor;
4211 if ( mSelectionColor == color )
4214 mSelectionColor = color;
4220 return mSelectionColor;
4254QString
QgsProject::translate(
const QString &context,
const QString &sourceText,
const char *disambiguation,
int n )
const
4261 QString result = mTranslator->translate( context.toUtf8(), sourceText.toUtf8(), disambiguation, n );
4263 if ( result.isEmpty() )
4275 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4280 if ( !( ( *it )->accept( visitor ) ) )
4289 if ( !mLayoutManager->accept( visitor ) )
4292 if ( !mAnnotationManager->accept( visitor ) )
4298void QgsProject::loadProjectFlags(
const QDomDocument *doc )
4300 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectFlags" ) );
4301 Qgis::ProjectFlags
flags;
4302 if ( !element.isNull() )
4309 element = doc->documentElement().firstChildElement( QStringLiteral(
"evaluateDefaultValues" ) );
4310 if ( !element.isNull() )
4312 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
4317 element = doc->documentElement().firstChildElement( QStringLiteral(
"trust" ) );
4318 if ( !element.isNull() )
4320 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
4329GetNamedProjectColor::GetNamedProjectColor(
const QgsProject *project )
4336 QStringList colorStrings = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ) );
4337 const QStringList colorLabels = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ) );
4341 for ( QStringList::iterator it = colorStrings.begin();
4342 it != colorStrings.end(); ++it )
4346 if ( colorLabels.length() > colorIndex )
4348 label = colorLabels.at( colorIndex );
4351 mColors.insert( label.toLower(), color );
4356GetNamedProjectColor::GetNamedProjectColor(
const QHash<QString, QColor> &colors )
4364 const QString colorName = values.at( 0 ).toString().toLower();
4365 if ( mColors.contains( colorName ) )
4367 return QStringLiteral(
"%1,%2,%3" ).arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
4375 return new GetNamedProjectColor( mColors );
@ DontLoad3DViews
Skip loading 3D views (since QGIS 3.26)
@ DontStoreOriginalStyles
Skip the initial XML style storage for layers. Useful for minimising project load times in non-intera...
@ ForceReadOnlyLayers
Open layers in a read-only mode. (since QGIS 3.28)
@ TrustLayerMetadata
Trust layer metadata. Improves project read time. Do not use it if layers' extent is not fixed during...
@ DontLoadLayouts
Don't load print layouts. Improves project read time if layouts are not required, and allows projects...
@ DontResolveLayers
Don't resolve layer paths (i.e. don't load any layer content). Dramatically improves project read tim...
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.
@ Critical
Critical/error message.
@ Success
Used for reporting a successful operation.
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.
QgsUnitTypes::DistanceUnit mapUnits
static QgsCoordinateReferenceSystem fromProj(const QString &proj)
Creates a CRS from a proj style formatted string.
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Contains information about the context in which a coordinate transform is executed.
void readSettings()
Reads the context's state from application settings.
void writeXml(QDomElement &element, const QgsReadWriteContext &context) const
Writes the context's state to a DOM element.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context, QStringList &missingTransforms)
Reads the context's state from a DOM element.
@ EvaluateDefaultValues
Evaluate default values on provider side when calling QgsVectorDataProvider::defaultValue( int index ...
Class for storing the component parts of a RDBMS data source URI (e.g.
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...
@ WMSOnlineResource
Alias.
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.
CORE_EXPORT const QStringList files(const QString &zip)
Returns the list of files within a zip file.
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.
CORE_EXPORT QgsProjectVersion getVersion(QDomDocument const &doc)
Returns the version string found in the given DOM document.
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.