56 #include <QApplication> 60 #include <QTextStream> 61 #include <QTemporaryFile> 67 #include <sys/utime.h> 85 QStringList keyTokens = QStringList( scope );
86 keyTokens += key.split(
'/', QString::SkipEmptyParts );
89 keyTokens.push_front( QStringLiteral(
"properties" ) );
92 for (
int i = 0; i < keyTokens.size(); ++i )
94 QString keyToken = keyTokens.at( i );
98 QString nameCharRegexp = QStringLiteral(
"[^:A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\x2FF\\x370-\\x37D\\x37F-\\x1FFF\\x200C-\\x200D\\x2070-\\x218F\\x2C00-\\x2FEF\\x3001-\\xD7FF\\xF900-\\xFDCF\\xFDF0-\\xFFFD\\-\\.0-9\\xB7\\x0300-\\x036F\\x203F-\\x2040]" );
99 QString nameStartCharRegexp = QStringLiteral(
"^[^:A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\x2FF\\x370-\\x37D\\x37F-\\x1FFF\\x200C-\\x200D\\x2070-\\x218F\\x2C00-\\x2FEF\\x3001-\\xD7FF\\xF900-\\xFDCF\\xFDF0-\\xFFFD]" );
101 if ( keyToken.contains( QRegExp( nameCharRegexp ) ) || keyToken.contains( QRegExp( nameStartCharRegexp ) ) )
104 QString errorString = QObject::tr(
"Entry token invalid : '%1'. The token will not be saved to file." ).arg( keyToken );
134 while ( !keySequence.isEmpty() )
138 if ( keySequence.first() == currentProperty->
name() )
141 keySequence.pop_front();
143 if ( 1 == keySequence.count() )
146 return currentProperty->
find( keySequence.front() );
148 else if ( keySequence.isEmpty() )
153 return currentProperty;
155 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
157 if ( nextProperty->
isKey() )
161 else if ( nextProperty->
isValue() && 1 == keySequence.count() )
167 return currentProperty;
205 const QVariant &value,
206 bool &propertiesModified )
215 propertiesModified =
false;
216 while ( ! keySequence.isEmpty() )
220 if ( keySequence.first() == currentProperty->
name() )
223 keySequence.pop_front();
227 if ( 1 == keySequence.count() )
230 if ( !property || property->value() != value )
232 currentProperty->
setValue( keySequence.front(), value );
233 propertiesModified =
true;
236 return currentProperty;
240 else if ( keySequence.isEmpty() )
242 if ( currentProperty->
value() != value )
245 propertiesModified =
true;
248 return currentProperty;
250 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
254 if ( currentProperty )
265 if ( ( newPropertyKey = currentProperty->
addKey( keySequence.first() ) ) )
267 currentProperty = newPropertyKey;
300 while ( ! keySequence.isEmpty() )
304 if ( keySequence.first() == currentProperty->
name() )
307 keySequence.pop_front();
311 if ( 1 == keySequence.count() )
313 currentProperty->
removeKey( keySequence.front() );
318 else if ( keySequence.isEmpty() )
320 previousQgsPropertyKey->
removeKey( currentProperty->
name() );
322 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
324 previousQgsPropertyKey = currentProperty;
327 if ( currentProperty )
353 , mSnappingConfig( this )
362 mProperties.
setName( QStringLiteral(
"properties" ) );
395 delete mBadLayerHandler;
396 delete mRelationManager;
397 delete mLayerTreeRegistryBridge;
399 if (
this == sProject )
405 void QgsProject::setInstance(
QgsProject *project )
422 if ( title == mMetadata.
title() )
433 return mMetadata.
title();
443 if ( dirty && mDirtyBlockCount > 0 )
446 if ( mDirty == dirty )
455 if ( path == mHomePath )
466 const QList<QgsAttributeEditorElement *> elements = parent->
children();
474 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:formcontainers" ).arg( layerId ), container->
name() );
476 if ( !container->
children().empty() )
489 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1" ).arg( layer->layerId() ), layer->name() );
498 for (
const QgsField &field : fields )
501 if ( field.alias().isEmpty() )
502 fieldName = field.name();
504 fieldName = field.alias();
506 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( vlayer->
id() ), fieldName );
508 if ( field.editorWidgetSetup().type() == QStringLiteral(
"ValueRelation" ) )
510 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fields:%2:valuerelationvalue" ).arg( vlayer->
id(), field.name() ), field.editorWidgetSetup().config().value( QStringLiteral(
"Value" ) ).toString() );
521 const QList<QgsLayerTreeGroup *> groupLayers = mRootGroup->
findGroups();
524 translationContext->
registerTranslation( QStringLiteral(
"project:layergroups" ), groupLayer->name() );
528 const QList<QgsRelation> &relations = mRelationManager->
relations().values();
531 translationContext->
registerTranslation( QStringLiteral(
"project:relations" ), relation.name() );
537 if ( name == mFile.fileName() )
542 mFile.setFileName( name );
546 if ( newHomePath != oldHomePath )
554 return mFile.fileName();
559 return QFileInfo( mFile );
572 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
586 if ( mFile.fileName().isEmpty() )
597 if ( mFile.fileName().isEmpty() )
608 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
609 return metadata.
name;
613 return QFileInfo( mFile.fileName() ).completeBaseName();
628 writeEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ), crs.
isValid() ? 1 : 0 );
635 if ( !
crs().isValid() )
638 return readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ),
GEO_NONE );
643 writeEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ), ellipsoid );
649 return mTransformContext;
654 if ( context == mTransformContext )
657 mTransformContext = context;
665 mFile.setFileName( QString() );
668 mAutoTransaction =
false;
669 mEvaluateDefaultValues =
false;
671 mTrustLayerMetadata =
false;
672 mCustomVariables.clear();
685 mEmbeddedLayers.clear();
686 mRelationManager->
clear();
687 mAnnotationManager->clear();
688 mLayoutManager->clear();
689 mSnappingConfig.
reset();
696 mLabelingEngineSettings->clear();
705 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/Automatic" ),
true );
706 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/DecimalPlaces" ), 2 );
707 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
710 writeEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), s.
value( QStringLiteral(
"/qgis/measure/displayunits" ) ).toString() );
711 writeEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), s.
value( QStringLiteral(
"/qgis/measure/areaunits" ) ).toString() );
723 QgsDebugMsg( QStringLiteral(
"current properties:" ) );
724 topQgsPropertyKey.
dump();
760 QDomElement propertiesElem = doc.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
762 if ( propertiesElem.isNull() )
767 QDomNodeList scopes = propertiesElem.childNodes();
769 if ( scopes.count() < 1 )
771 QgsDebugMsg( QStringLiteral(
"empty ``properties'' XML tag ... bailing" ) );
775 if ( ! project_properties.
readXml( propertiesElem ) )
777 QgsDebugMsg( QStringLiteral(
"Project_properties.readXml() failed" ) );
786 static void _getTitle(
const QDomDocument &doc, QString &
title )
788 QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"title" ) );
794 QgsDebugMsg( QStringLiteral(
"unable to find title element" ) );
798 QDomNode titleNode = nl.item( 0 );
800 if ( !titleNode.hasChildNodes() )
802 QgsDebugMsg( QStringLiteral(
"unable to find title element" ) );
806 QDomNode titleTextNode = titleNode.firstChild();
808 if ( !titleTextNode.isText() )
810 QgsDebugMsg( QStringLiteral(
"unable to find title element" ) );
814 QDomText titleText = titleTextNode.toText();
816 title = titleText.data();
822 QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
826 QgsDebugMsg( QStringLiteral(
" unable to find qgis element in project file" ) );
830 QDomNode qgisNode = nl.item( 0 );
832 QDomElement qgisElement = qgisNode.toElement();
833 QgsProjectVersion projectVersion( qgisElement.attribute( QStringLiteral(
"version" ) ) );
834 return projectVersion;
840 return mSnappingConfig;
845 if ( mSnappingConfig == snappingConfig )
853 bool QgsProject::_getMapLayers(
const QDomDocument &doc, QList<QDomNode> &brokenNodes )
858 QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"maplayer" ) );
862 if ( 0 == nl.count() )
872 bool returnStatus =
true;
878 if ( depSorter.hasCycle() || depSorter.hasMissingDependency() )
881 QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
884 Q_FOREACH (
const QDomNode &node, sortedLayerNodes )
886 QDomElement element = node.toElement();
888 QString name =
translate( QStringLiteral(
"project:layers:%1" ).arg( node.namedItem( QStringLiteral(
"id" ) ).toElement().text() ), node.namedItem( QStringLiteral(
"layername" ) ).toElement().text() );
889 if ( !name.isNull() )
890 emit
loadingLayer( tr(
"Loading layer %1" ).arg( name ) );
892 if ( element.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
894 createEmbeddedLayer( element.attribute( QStringLiteral(
"id" ) ),
readPath( element.attribute( QStringLiteral(
"project" ) ) ), brokenNodes );
901 if ( !addLayer( element, brokenNodes, context ) )
903 returnStatus =
false;
906 if ( messages.count() )
918 bool QgsProject::addLayer(
const QDomElement &layerElem, QList<QDomNode> &brokenNodes,
QgsReadWriteContext &context )
920 QString type = layerElem.attribute( QStringLiteral(
"type" ) );
924 if ( type == QLatin1String(
"vector" ) )
929 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mapLayer ) )
934 else if ( type == QLatin1String(
"raster" ) )
938 else if ( type == QLatin1String(
"mesh" ) )
942 else if ( type == QLatin1String(
"plugin" ) )
944 QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
950 QgsDebugMsg( QStringLiteral(
"Unable to create layer" ) );
955 Q_CHECK_PTR( mapLayer );
962 QList<QgsMapLayer *> myLayers;
972 QgsDebugMsg(
"Unable to load " + type +
" layer" );
973 brokenNodes.push_back( layerElem );
980 mFile.setFileName( filename );
987 QString filename = mFile.fileName();
992 QTemporaryFile inDevice;
993 if ( !inDevice.open() )
995 setError( tr(
"Unable to open %1" ).arg( inDevice.fileName() ) );
1001 if ( !storage->readProject( filename, &inDevice, context ) )
1003 QString err = tr(
"Unable to open %1" ).arg( filename );
1004 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
1005 if ( !messages.isEmpty() )
1006 err += QStringLiteral(
"\n\n" ) + messages.last().message();
1011 return unzip( inDevice.fileName() );
1016 rc = unzip( mFile.fileName() );
1021 rc = readProjectFile( mFile.fileName() );
1027 mFile.setFileName( filename );
1032 mTranslator.reset(
nullptr );
1038 bool QgsProject::readProjectFile(
const QString &filename )
1040 QFile projectFile( filename );
1045 QString localeFileName = QStringLiteral(
"%1_%2" ).arg( QFileInfo( projectFile.fileName() ).
baseName(), settings.
value( QStringLiteral(
"locale/userLocale" ), QString() ).toString() );
1047 if ( QFile( QStringLiteral(
"%1/%2.qm" ).arg( QFileInfo( projectFile.fileName() ).
absolutePath(), localeFileName ) ).exists() )
1049 mTranslator.reset(
new QTranslator() );
1050 mTranslator->load( localeFileName, QFileInfo( projectFile.fileName() ).
absolutePath() );
1053 std::unique_ptr<QDomDocument> doc(
new QDomDocument( QStringLiteral(
"qgis" ) ) );
1055 if ( !projectFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
1057 projectFile.close();
1059 setError( tr(
"Unable to open %1" ).arg( projectFile.fileName() ) );
1068 if ( !doc->setContent( &projectFile, &errorMsg, &line, &column ) )
1072 QMessageBox::critical( 0, tr(
"Read Project File" ),
1073 tr(
"%1 at line %2 column %3" ).arg( errorMsg ).arg( line ).arg( column ) );
1076 QString errorString = tr(
"Project file read error in file %1: %2 at line %3 column %4" )
1077 .arg( projectFile.fileName(), errorMsg ).arg( line ).arg( column );
1081 projectFile.close();
1083 setError( tr(
"%1 for file %2" ).arg( errorString, projectFile.fileName() ) );
1088 projectFile.close();
1090 QgsDebugMsg(
"Opened document " + projectFile.fileName() );
1096 if ( thisVersion > fileVersion )
1099 "version of qgis (saved in " + fileVersion.text() +
1101 "). Problems may occur." );
1107 QgsDebugMsg( QStringLiteral(
"Emitting oldProjectVersionWarning(oldVersion)." ) );
1109 projectFile.updateRevision( thisVersion );
1113 QString
fileName = mFile.fileName();
1114 std::unique_ptr<QgsAuxiliaryStorage> aStorage = std::move( mAuxiliaryStorage );
1116 mAuxiliaryStorage = std::move( aStorage );
1117 mFile.setFileName( fileName );
1122 QgsDebugMsg( QString::number( mProperties.
count() ) +
" properties read" );
1124 dump_( mProperties );
1128 _getTitle( *doc, oldTitle );
1130 QDomNodeList homePathNl = doc->elementsByTagName( QStringLiteral(
"homePath" ) );
1131 if ( homePathNl.count() > 0 )
1133 QDomElement homePathElement = homePathNl.at( 0 ).toElement();
1134 QString
homePath = homePathElement.attribute( QStringLiteral(
"path" ) );
1135 if ( !homePath.isEmpty() )
1149 if (
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ), 0 ) )
1152 QDomNode srsNode = doc->documentElement().namedItem( QStringLiteral(
"projectCrs" ) );
1153 if ( !srsNode.isNull() )
1155 projectCrs.
readXml( srsNode );
1160 QString projCrsString =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSProj4String" ) );
1161 long currentCRS =
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSID" ), -1 );
1164 if ( currentCRS >= 0 )
1170 if ( !projCrsString.isEmpty() && ( !projectCrs.
isValid() || projectCrs.
toProj4() != projCrsString ) )
1184 QStringList datumErrors;
1185 if ( !mTransformContext.
readXml( doc->documentElement(), context, datumErrors ) )
1191 QDomNodeList nl = doc->elementsByTagName( QStringLiteral(
"projectMetadata" ) );
1192 if ( !nl.isEmpty() )
1194 QDomElement metadataElement = nl.at( 0 ).toElement();
1202 if ( mMetadata.
title().isEmpty() && !oldTitle.isEmpty() )
1209 nl = doc->elementsByTagName( QStringLiteral(
"autotransaction" ) );
1212 QDomElement transactionElement = nl.at( 0 ).toElement();
1213 if ( transactionElement.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
1214 mAutoTransaction =
true;
1217 nl = doc->elementsByTagName( QStringLiteral(
"evaluateDefaultValues" ) );
1220 QDomElement evaluateDefaultValuesElement = nl.at( 0 ).toElement();
1221 if ( evaluateDefaultValuesElement.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
1222 mEvaluateDefaultValues =
true;
1225 nl = doc->elementsByTagName( QStringLiteral(
"trust" ) );
1228 QDomElement trustElement = nl.at( 0 ).toElement();
1229 if ( trustElement.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
1230 mTrustLayerMetadata =
true;
1237 QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
1238 if ( !layerTreeElem.isNull() )
1247 mLayerTreeRegistryBridge->
setEnabled(
false );
1250 QList<QDomNode> brokenNodes;
1251 bool clean = _getMapLayers( *doc, brokenNodes );
1256 QgsDebugMsg( QStringLiteral(
"Unable to get map layers from project file." ) );
1258 if ( !brokenNodes.isEmpty() )
1260 QgsDebugMsg(
"there are " + QString::number( brokenNodes.size() ) +
" broken layers" );
1270 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
1271 for ( QMap<QString, QgsMapLayer *>::iterator it = layers.begin(); it != layers.end(); it++ )
1273 it.value()->resolveReferences(
this );
1276 mLayerTreeRegistryBridge->
setEnabled(
true );
1279 loadEmbeddedNodes( mRootGroup );
1285 if ( !layerTreeElem.isNull() )
1291 QDomElement layerTreeCanvasElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-canvas" ) );
1292 if ( !layerTreeCanvasElem.isNull( ) )
1300 const QStringList requiredLayerIds =
readListEntry( QStringLiteral(
"RequiredLayers" ), QStringLiteral(
"Layers" ) );
1301 for (
const QString &layerId : requiredLayerIds )
1305 layer->setFlags( layer->flags() & ~
QgsMapLayer::Removable );
1308 const QStringList disabledLayerIds =
readListEntry( QStringLiteral(
"Identify" ), QStringLiteral(
"/disabledLayers" ) );
1309 for (
const QString &layerId : disabledLayerIds )
1313 layer->setFlags( layer->flags() & ~
QgsMapLayer::Identifiable );
1325 mMapThemeCollection->readXml( *doc );
1327 mLabelingEngineSettings->readSettingsFromProject(
this );
1330 mAnnotationManager->readXml( doc->documentElement(), context );
1331 mLayoutManager->readXml( doc->documentElement(), *doc );
1334 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
1335 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); it++ )
1337 it.value()->setDependencies( it.value()->dependencies() );
1342 QStringList variableNames =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ) );
1343 QStringList variableValues =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ) );
1345 mCustomVariables.clear();
1346 if ( variableNames.length() == variableValues.length() )
1348 for (
int i = 0; i < variableNames.length(); ++i )
1350 mCustomVariables.insert( variableNames.at( i ), variableValues.at( i ) );
1355 QgsMessageLog::logMessage( tr(
"Project Variables Invalid" ), tr(
"The project contains invalid variable settings." ) );
1378 QString newFileName( QStringLiteral(
"%1/%2.qgs" ).arg( QFileInfo( projectFile.fileName() ).
absolutePath(), localeFileName ) );
1403 if ( childGroup->
customProperty( QStringLiteral(
"embedded" ) ).toInt() )
1406 QString projectPath =
readPath( childGroup->
customProperty( QStringLiteral(
"embedded_project" ) ).toString() );
1407 childGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectPath );
1411 QList<QgsLayerTreeNode *> clonedChildren;
1413 clonedChildren << newGroupChild->
clone();
1421 loadEmbeddedNodes( childGroup );
1426 if ( child->
customProperty( QStringLiteral(
"embedded" ) ).toInt() )
1428 QList<QDomNode> brokenNodes;
1438 return mCustomVariables;
1443 if ( variables == mCustomVariables )
1447 QStringList variableNames;
1448 QStringList variableValues;
1450 QVariantMap::const_iterator it = variables.constBegin();
1451 for ( ; it != variables.constEnd(); ++it )
1453 variableNames << it.key();
1454 variableValues << it.value().toString();
1457 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ), variableNames );
1458 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ), variableValues );
1460 mCustomVariables = variables;
1467 *mLabelingEngineSettings = settings;
1473 return *mLabelingEngineSettings;
1478 return mLayerStore.get();
1483 return mLayerStore.get();
1488 QList<QgsVectorLayer *>
layers;
1489 QStringList layerIds =
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), QStringList() );
1490 Q_FOREACH (
const QString &layerId, layerIds )
1502 list << layer->
id();
1503 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), list );
1517 void QgsProject::onMapLayersAdded(
const QList<QgsMapLayer *> &
layers )
1519 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
1521 bool tgChanged =
false;
1540 mTransactionGroups.insert( qMakePair( key, connString ), tg );
1555 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); it++ )
1557 QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
1558 if ( deps.contains( layer->
id() ) )
1561 it.value()->setDependencies( deps );
1566 if ( mSnappingConfig.
addLayers( layers ) )
1570 void QgsProject::onMapLayersRemoved(
const QList<QgsMapLayer *> &
layers )
1576 void QgsProject::cleanTransactionGroups(
bool force )
1578 bool changed =
false;
1579 for ( QMap< QPair< QString, QString>,
QgsTransactionGroup *>::Iterator tg = mTransactionGroups.begin(); tg != mTransactionGroups.end(); )
1581 if ( tg.value()->isEmpty() || force )
1584 tg = mTransactionGroups.erase( tg );
1601 QList<QDomNode> brokenNodes;
1602 if ( addLayer( layerNode.toElement(), brokenNodes, context ) )
1606 QVector<QgsVectorLayer *> vectorLayers = layers<QgsVectorLayer *>();
1620 mFile.setFileName( filename );
1631 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
true );
1633 QString tempPath = QStandardPaths::standardLocations( QStandardPaths::TempLocation ).at( 0 );
1634 QString tmpZipFilename( tempPath + QDir::separator() + QUuid::createUuid().toString() );
1636 if ( !zip( tmpZipFilename ) )
1639 QFile tmpZipFile( tmpZipFilename );
1640 if ( !tmpZipFile.open( QIODevice::ReadOnly ) )
1642 setError( tr(
"Unable to read file %1" ).arg( tmpZipFilename ) );
1647 if ( !storage->writeProject( mFile.fileName(), &tmpZipFile, context ) )
1649 QString err = tr(
"Unable to save project to storage %1" ).arg( mFile.fileName() );
1650 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
1651 if ( !messages.isEmpty() )
1652 err += QStringLiteral(
"\n\n" ) + messages.last().message();
1658 QFile::remove( tmpZipFilename );
1665 return zip( mFile.fileName() );
1671 const bool asOk = saveAuxiliaryStorage();
1672 const bool writeOk = writeProjectFile( mFile.fileName() );
1675 if ( !asOk && writeOk )
1677 const QString err = mAuxiliaryStorage->errorString();
1678 setError( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
1681 return asOk && writeOk;
1685 bool QgsProject::writeProjectFile(
const QString &filename )
1687 QFile projectFile( filename );
1693 QFileInfo myFileInfo( projectFile );
1694 if ( myFileInfo.exists() && !myFileInfo.isWritable() )
1696 setError( tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
1697 .arg( projectFile.fileName() ) );
1704 QDomImplementation DomImplementation;
1705 DomImplementation.setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
1707 QDomDocumentType documentType =
1708 DomImplementation.createDocumentType( QStringLiteral(
"qgis" ), QStringLiteral(
"http://mrcc.com/qgis.dtd" ),
1709 QStringLiteral(
"SYSTEM" ) );
1710 std::unique_ptr<QDomDocument> doc(
new QDomDocument( documentType ) );
1712 QDomElement qgisNode = doc->createElement( QStringLiteral(
"qgis" ) );
1713 qgisNode.setAttribute( QStringLiteral(
"projectname" ),
title() );
1714 qgisNode.setAttribute( QStringLiteral(
"version" ), QStringLiteral(
"%1" ).arg(
Qgis::QGIS_VERSION ) );
1716 doc->appendChild( qgisNode );
1718 QDomElement homePathNode = doc->createElement( QStringLiteral(
"homePath" ) );
1719 homePathNode.setAttribute( QStringLiteral(
"path" ), mHomePath );
1720 qgisNode.appendChild( homePathNode );
1723 QDomElement titleNode = doc->createElement( QStringLiteral(
"title" ) );
1724 qgisNode.appendChild( titleNode );
1726 QDomElement transactionNode = doc->createElement( QStringLiteral(
"autotransaction" ) );
1727 transactionNode.setAttribute( QStringLiteral(
"active" ), mAutoTransaction ? 1 : 0 );
1728 qgisNode.appendChild( transactionNode );
1730 QDomElement evaluateDefaultValuesNode = doc->createElement( QStringLiteral(
"evaluateDefaultValues" ) );
1731 evaluateDefaultValuesNode.setAttribute( QStringLiteral(
"active" ), mEvaluateDefaultValues ? 1 : 0 );
1732 qgisNode.appendChild( evaluateDefaultValuesNode );
1734 QDomElement trustNode = doc->createElement( QStringLiteral(
"trust" ) );
1735 trustNode.setAttribute( QStringLiteral(
"active" ), mTrustLayerMetadata ? 1 : 0 );
1736 qgisNode.appendChild( trustNode );
1738 QDomText titleText = doc->createTextNode(
title() );
1739 titleNode.appendChild( titleText );
1742 QDomElement srsNode = doc->createElement( QStringLiteral(
"projectCrs" ) );
1744 qgisNode.appendChild( srsNode );
1751 clonedRoot->
writeXml( qgisNode, context );
1764 QDomElement projectLayersNode = doc->createElement( QStringLiteral(
"projectlayers" ) );
1766 QMap<QString, QgsMapLayer *>::ConstIterator li = layers.constBegin();
1767 while ( li != layers.end() )
1773 QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.constFind( ml->
id() );
1774 if ( emIt == mEmbeddedLayers.constEnd() )
1777 QDomElement maplayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
1783 projectLayersNode.appendChild( maplayerElem );
1789 if ( emIt.value().second )
1791 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
1792 mapLayerElem.setAttribute( QStringLiteral(
"embedded" ), 1 );
1793 mapLayerElem.setAttribute( QStringLiteral(
"project" ),
writePath( emIt.value().first ) );
1794 mapLayerElem.setAttribute( QStringLiteral(
"id" ), ml->
id() );
1795 projectLayersNode.appendChild( mapLayerElem );
1802 qgisNode.appendChild( projectLayersNode );
1804 QDomElement layerOrderNode = doc->createElement( QStringLiteral(
"layerorder" ) );
1807 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"layer" ) );
1808 mapLayerElem.setAttribute( QStringLiteral(
"id" ), layer->
id() );
1809 layerOrderNode.appendChild( mapLayerElem );
1811 qgisNode.appendChild( layerOrderNode );
1813 mLabelingEngineSettings->writeSettingsToProject(
this );
1817 dump_( mProperties );
1819 QgsDebugMsg( QStringLiteral(
"there are %1 property scopes" ).arg( static_cast<int>( mProperties.
count() ) ) );
1824 mProperties.
writeXml( QStringLiteral(
"properties" ), qgisNode, *doc );
1827 mMapThemeCollection->writeXml( *doc );
1829 mTransformContext.
writeXml( qgisNode, context );
1831 QDomElement metadataElem = doc->createElement( QStringLiteral(
"projectMetadata" ) );
1833 qgisNode.appendChild( metadataElem );
1835 QDomElement annotationsElem = mAnnotationManager->writeXml( *doc, context );
1836 qgisNode.appendChild( annotationsElem );
1838 QDomElement layoutElem = mLayoutManager->writeXml( *doc );
1839 qgisNode.appendChild( layoutElem );
1847 QFile backupFile( QStringLiteral(
"%1~" ).arg( filename ) );
1849 ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
1850 ok &= projectFile.open( QIODevice::ReadOnly );
1853 while ( ok && !projectFile.atEnd() )
1855 ba = projectFile.read( 10240 );
1856 ok &= backupFile.write( ba ) == ba.size();
1859 projectFile.close();
1864 setError( tr(
"Unable to create backup file %1" ).arg( backupFile.fileName() ) );
1869 struct utimbuf tb = { fi.lastRead().toTime_t(), fi.lastModified().toTime_t() };
1870 utime( backupFile.fileName().toUtf8().constData(), &tb );
1873 if ( !projectFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
1875 projectFile.close();
1878 setError( tr(
"Unable to save to file %1" ).arg( projectFile.fileName() ) );
1882 QTemporaryFile tempFile;
1883 bool ok = tempFile.open();
1886 QTextStream projectFileStream( &tempFile );
1887 doc->save( projectFileStream, 2 );
1888 ok &= projectFileStream.pos() > -1;
1890 ok &= tempFile.seek( 0 );
1893 while ( ok && !tempFile.atEnd() )
1895 ba = tempFile.read( 10240 );
1896 ok &= projectFile.write( ba ) == ba.size();
1899 ok &= projectFile.error() == QFile::NoError;
1901 projectFile.close();
1908 setError( tr(
"Unable to save to file %1. Your project " 1909 "may be corrupted on disk. Try clearing some space on the volume and " 1910 "check file permissions before pressing save again." )
1911 .arg( projectFile.fileName() ) );
1924 bool propertiesModified;
1925 bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
1927 if ( propertiesModified )
1935 bool propertiesModified;
1936 bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
1938 if ( propertiesModified )
1946 bool propertiesModified;
1947 bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
1949 if ( propertiesModified )
1957 bool propertiesModified;
1958 bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
1960 if ( propertiesModified )
1968 bool propertiesModified;
1969 bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
1971 if ( propertiesModified )
1979 const QStringList &def,
1988 value =
property->value();
1990 bool valid = QVariant::StringList == value.type();
1996 return value.toStringList();
2015 value =
property->value();
2017 bool valid = value.canConvert( QVariant::String );
2022 return value.toString();
2037 value =
property->value();
2040 bool valid = value.canConvert( QVariant::Int );
2049 return value.toInt();
2062 QVariant value =
property->value();
2064 bool valid = value.canConvert( QVariant::Double );
2069 return value.toDouble();
2082 QVariant value =
property->value();
2084 bool valid = value.canConvert( QVariant::Bool );
2089 return value.toBool();
2098 if (
findKey_( scope, key, mProperties ) )
2104 return !
findKey_( scope, key, mProperties );
2112 QStringList entries;
2114 if ( foundProperty )
2129 QStringList entries;
2131 if ( foundProperty )
2144 dump_( mProperties );
2149 bool absolutePaths =
readBoolEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
2163 void QgsProject::setError(
const QString &errorMessage )
2165 mErrorMessage = errorMessage;
2170 return mErrorMessage;
2173 void QgsProject::clearError()
2175 setError( QString() );
2180 delete mBadLayerHandler;
2181 mBadLayerHandler = handler;
2186 QHash< QString, QPair< QString, bool > >::const_iterator it = mEmbeddedLayers.find(
id );
2187 if ( it == mEmbeddedLayers.constEnd() )
2191 return it.value().first;
2199 static QString sPrevProjectFilePath;
2200 static QDateTime sPrevProjectFileTimestamp;
2201 static QDomDocument sProjectDocument;
2203 QDateTime projectFileTimestamp = QFileInfo( projectFilePath ).lastModified();
2205 if ( projectFilePath != sPrevProjectFilePath || projectFileTimestamp != sPrevProjectFileTimestamp )
2207 sPrevProjectFilePath.clear();
2209 QFile projectFile( projectFilePath );
2210 if ( !projectFile.open( QIODevice::ReadOnly ) )
2215 if ( !sProjectDocument.setContent( &projectFile ) )
2220 sPrevProjectFilePath = projectFilePath;
2221 sPrevProjectFileTimestamp = projectFileTimestamp;
2225 bool useAbsolutePaths =
true;
2227 QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
2228 if ( !propertiesElem.isNull() )
2230 QDomElement absElem = propertiesElem.firstChildElement( QStringLiteral(
"Paths" ) ).firstChildElement( QStringLiteral(
"Absolute" ) );
2231 if ( !absElem.isNull() )
2233 useAbsolutePaths = absElem.text().compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0;
2238 if ( !useAbsolutePaths )
2242 QDomElement projectLayersElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) );
2243 if ( projectLayersElem.isNull() )
2248 QDomNodeList mapLayerNodes = projectLayersElem.elementsByTagName( QStringLiteral(
"maplayer" ) );
2249 for (
int i = 0; i < mapLayerNodes.size(); ++i )
2252 QDomElement mapLayerElem = mapLayerNodes.at( i ).toElement();
2253 QString
id = mapLayerElem.firstChildElement( QStringLiteral(
"id" ) ).text();
2254 if (
id == layerId )
2257 if ( mapLayerElem.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
2262 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
2264 if ( addLayer( mapLayerElem, brokenNodes, embeddedContext ) )
2270 mEmbeddedLayers.remove( layerId );
2283 QFile projectFile( projectFilePath );
2284 if ( !projectFile.open( QIODevice::ReadOnly ) )
2289 QDomDocument projectDocument;
2290 if ( !projectDocument.setContent( &projectFile ) )
2301 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
2302 if ( !layerTreeElem.isNull() )
2312 if ( !group || group->customProperty( QStringLiteral(
"embedded" ) ).toBool() )
2325 newGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectFilePath );
2328 mLayerTreeRegistryBridge->
setEnabled(
false );
2329 initializeEmbeddedSubtree( projectFilePath, newGroup );
2330 mLayerTreeRegistryBridge->
setEnabled(
true );
2333 Q_FOREACH (
const QString &layerId, newGroup->
findLayerIds() )
2346 void QgsProject::initializeEmbeddedSubtree(
const QString &projectFilePath,
QgsLayerTreeGroup *group )
2360 QList<QDomNode> brokenNodes;
2368 return mEvaluateDefaultValues;
2373 if ( evaluateDefaultValues == mEvaluateDefaultValues )
2377 QMap<QString, QgsMapLayer *>::const_iterator layerIt = layers.constBegin();
2378 for ( ; layerIt != layers.constEnd(); ++layerIt )
2392 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), ( enabled ? 1 : 0 ) );
2398 return readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), 0 );
2403 QString distanceUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), QString() );
2404 if ( !distanceUnitString.isEmpty() )
2421 QString areaUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), QString() );
2422 if ( !areaUnitString.isEmpty() )
2439 if ( !mHomePath.isEmpty() )
2441 QFileInfo homeInfo( mHomePath );
2442 if ( !homeInfo.isRelative() )
2447 if ( !pfi.exists() )
2450 if ( !mHomePath.isEmpty() )
2453 return QDir::cleanPath( pfi.path() +
'/' + mHomePath );
2457 return pfi.canonicalPath();
2468 return mRelationManager;
2473 return mLayoutManager.get();
2478 return mLayoutManager.get();
2488 return mMapThemeCollection.get();
2493 return mAnnotationManager.get();
2498 return mAnnotationManager.get();
2503 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
2504 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
2509 if ( layers.contains( it.value() ) )
2510 it.value()->setFlags( it.value()->flags() & ~
QgsMapLayer::Identifiable );
2523 nonIdentifiableLayers.reserve( layerIds.count() );
2524 for (
const QString &layerId : layerIds )
2528 nonIdentifiableLayers << layer;
2540 for ( QMap<QString, QgsMapLayer *>::const_iterator it = layers.constBegin(); it != layers.constEnd(); ++it )
2544 nonIdentifiableLayers.append( it.value()->id() );
2552 return mAutoTransaction;
2557 if ( autoTransaction != mAutoTransaction )
2561 if ( autoTransaction )
2562 onMapLayersAdded(
mapLayers().values() );
2564 cleanTransactionGroups(
true );
2570 return mTransactionGroups;
2581 return mLayerStore->count();
2586 return mLayerStore->mapLayer( layerId );
2591 return mLayerStore->mapLayersByName( layerName );
2594 bool QgsProject::unzip(
const QString &filename )
2600 if ( !archive->unzip( filename ) )
2602 setError( tr(
"Unable to unzip file '%1'" ).arg( filename ) );
2607 if ( archive->projectFile().isEmpty() )
2609 setError( tr(
"Zip archive does not provide a project file" ) );
2614 if ( !archive->auxiliaryStorageFile().isEmpty() )
2618 mAuxiliaryStorage.reset(
new QgsAuxiliaryStorage( archive->auxiliaryStorageFile(), false ) );
2626 if ( ! readProjectFile( archive->projectFile() ) )
2628 setError( tr(
"Cannot read unzipped qgs project file" ) );
2633 mArchive = std::move( archive );
2634 mArchive->clearProjectFile();
2639 bool QgsProject::zip(
const QString &filename )
2645 const QString
baseName = QFileInfo( filename ).baseName();
2646 const QString qgsFileName = QStringLiteral(
"%1.qgs" ).arg( baseName );
2647 QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
2649 bool writeOk =
false;
2650 if ( qgsFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
2652 writeOk = writeProjectFile( qgsFile.fileName() );
2659 setError( tr(
"Unable to write temporary qgs file" ) );
2664 const QFileInfo info( qgsFile );
2667 if ( ! saveAuxiliaryStorage( asFileName ) )
2669 const QString err = mAuxiliaryStorage->errorString();
2670 setError( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
2675 archive->addFile( qgsFile.fileName() );
2676 archive->addFile( asFileName );
2679 if ( !archive->zip( filename ) )
2681 setError( tr(
"Unable to perform zip" ) );
2694 const QList<QgsMapLayer *> &
layers,
2696 bool takeOwnership )
2698 const QList<QgsMapLayer *> myResultList = mLayerStore->addMapLayers( layers, takeOwnership );
2699 if ( !myResultList.isEmpty() )
2705 if ( mAuxiliaryStorage )
2720 return myResultList;
2726 bool takeOwnership )
2728 QList<QgsMapLayer *> addedLayers;
2729 addedLayers =
addMapLayers( QList<QgsMapLayer *>() << layer, addToLegend, takeOwnership );
2730 return addedLayers.isEmpty() ?
nullptr : addedLayers[0];
2735 mLayerStore->removeMapLayers( layerIds );
2740 mLayerStore->removeMapLayers( layers );
2745 mLayerStore->removeMapLayer( layerId );
2750 mLayerStore->removeMapLayer( layer );
2755 return mLayerStore->takeMapLayer( layer );
2760 mLayerStore->removeAllMapLayers();
2765 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
2766 QMap<QString, QgsMapLayer *>::const_iterator it = layers.constBegin();
2767 for ( ; it != layers.constEnd(); ++it )
2769 it.value()->reload();
2775 return mLayerStore->mapLayers();
2780 return mTransactionGroups.value( qMakePair( providerKey, connString ) );
2787 if ( settings.
value( QStringLiteral(
"/Projections/defaultBehavior" ), QStringLiteral(
"prompt" ) ).toString() == QStringLiteral(
"useProject" )
2788 || settings.
value( QStringLiteral(
"/Projections/defaultBehavior" ), QStringLiteral(
"prompt" ) ).toString() == QStringLiteral(
"prompt" ) )
2797 QString layerDefaultCrs = settings.
value( QStringLiteral(
"/Projections/layerDefaultCrs" ),
GEO_EPSG_CRS_AUTHID ).toString();
2806 mTrustLayerMetadata = trust;
2809 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
2819 bool QgsProject::saveAuxiliaryStorage(
const QString &filename )
2823 for (
auto it = layers.constBegin(); it != layers.constEnd(); ++it )
2836 if ( !mAuxiliaryStorage->exists( *
this ) && filename.isEmpty() && empty )
2840 else if ( !filename.isEmpty() )
2842 return mAuxiliaryStorage->saveAs( filename );
2846 return mAuxiliaryStorage->saveAs( *
this );
2852 return mAuxiliaryStorage.get();
2857 return mAuxiliaryStorage.get();
2867 if ( metadata == mMetadata )
2881 for ( QMap<QString, QgsMapLayer *>::const_iterator it = layers.constBegin(); it != layers.constEnd(); ++it )
2885 requiredLayers.insert( it.value() );
2893 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
2894 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
2899 if ( layers.contains( it.value() ) )
2900 it.value()->setFlags( it.value()->flags() & ~
QgsMapLayer::Removable );
2917 QString
QgsProject::translate(
const QString &context,
const QString &sourceText,
const char *disambiguation,
int n )
const 2924 QString result = mTranslator->translate( context.toUtf8(), sourceText.toUtf8(), disambiguation, n );
2926 if ( result.isEmpty() )
QgsFields auxiliaryFields() const
Returns a list of all auxiliary fields currently managed by the layer.
int count() const
Returns the number of sub-keys contained by this property.
Layer tree group node serves as a container for layers and further groups.
void setDirty(bool b=true)
Flag the project as dirty (modified).
void setTrustLayerMetadata(bool trust)
Sets the trust option allowing to indicate if the extent has to be read from the XML document when da...
bool topologicalEditing() const
Convenience function to query topological editing status.
The class is used as a container of context for various read/write operations on other objects...
void readChildrenFromXml(QDomElement &element, const QgsReadWriteContext &context)
Read children from XML and append them to the group.
static Q_INVOKABLE AreaUnit decodeAreaUnit(const QString &string, bool *ok=nullptr)
Decodes an areal unit from a string.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
Base class for all map layer types.
static void removeInvalidLayers(QgsLayerTreeGroup *group)
Remove layer nodes that refer to invalid layers.
QList< QgsLayerTreeGroup * > findGroups() const
Find all group layer nodes.
QString title() const
Returns the project's title.
static QgsCoordinateReferenceSystem fromProj4(const QString &proj4)
Creates a CRS from a proj4 style formatted string.
static const QString QGIS_VERSION
Version string.
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
void snappingConfigChanged(const QgsSnappingConfig &config)
Emitted whenever the configuration for snapping has changed.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
Q_DECL_DEPRECATED QStringList nonIdentifiableLayers() const
Gets the list of layers which currently should not be taken into account on map identification.
bool isValid() const
Returns the status of the layer.
This is an abstract base class for any elements of a drag and drop form.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
bool autoTransaction() const
Transactional editing means that on supported datasources (postgres databases) the edit state of all ...
void isDirtyChanged(bool dirty)
Emitted when the project dirty status changes.
QgsTransactionGroup * transactionGroup(const QString &providerKey, const QString &connString)
Returns the matching transaction group from a provider key and connection string. ...
QString absolutePath() const
Returns full absolute path to the project folder if the project is stored in a file system - derived ...
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
void layerWasAdded(QgsMapLayer *layer)
Emitted when a layer was added to the store.
bool save()
Commits changes and starts editing then.
Manages storage of a set of QgsAnnotation annotation objects.
void dump_(const QgsProjectPropertyKey &topQgsPropertyKey)
void setTopologicalEditing(bool enabled)
Convenience function to set topological editing.
void setProjectTranslator(QgsProjectTranslator *projectTranslator)
Sets the project translator.
This class is a composition of two QSettings instances:
void requestForTranslatableObjects(QgsTranslationContext *translationContext)
Emitted when project strings which require translation are being collected for inclusion in a ...
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
void setSnappingConfig(const QgsSnappingConfig &snappingConfig)
The snapping configuration for this project.
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...
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
virtual void writeXml(QDomElement &parentElement, const QgsReadWriteContext &context)=0
Write layer tree to XML.
void writeProject(QDomDocument &doc)
Writes the configuration to the specified QGIS project document.
Q_DECL_DEPRECATED void setNonIdentifiableLayers(const QList< QgsMapLayer * > &layers)
Set a list of layers which should not be taken into account on map identification.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance.
QgsSnappingConfig snappingConfig() const
The snapping configuration for this project.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
static void warning(const QString &msg)
Goes to qWarning.
const QgsProjectMetadata & metadata() const
Returns a reference to the project's metadata store.
Class used to work with layer dependencies stored in a XML project or layer definition file...
int count() const
Returns the number of registered layers.
void layersRemoved(const QStringList &layerIds)
Emitted after one or more layers were removed from the registry.
QgsProjectPropertyKey * addKey(const QString &keyName)
Adds the specified property key as a sub-key.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
void legendLayersAdded(const QList< QgsMapLayer * > &layers)
Emitted, when a layer was added to the registry and the legend.
bool writeLayerXml(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores state in DOM node.
#define Q_NOWARN_DEPRECATED_PUSH
static bool readOldLegend(QgsLayerTreeGroup *root, const QDomElement &legendElem)
Try to load layer tree from.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
void setFileName(const QString &name)
Sets the file name associated with the project.
Class providing some utility methods to manage auxiliary storage.
void crsChanged()
Emitted when the CRS of the project has changed.
void generateTsFile(const QString &locale)
Triggers the collection strings of .qgs to be included in ts file and calls writeTsFile() ...
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the store.
QString presetHomePath() const
Returns any manual project home path setting, or an empty string if not set.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void configChanged()
Emitted whenever the configuration is changed.
Container of fields for a vector layer.
QStringList readListEntry(const QString &scope, const QString &key, const QStringList &def=QStringList(), bool *ok=nullptr) const
Key value accessors.
void labelingEngineSettingsChanged()
Emitted when global configuration of the labeling engine changes.
bool readLayerXml(const QDomElement &layerElement, QgsReadWriteContext &context)
Sets state from DOM document.
QString source() const
Returns the source for the layer.
static QgsPluginLayerRegistry * pluginLayerRegistry()
Returns the application's plugin layer registry, used for managing plugin layer types.
void topologicalEditingChanged()
Emitted when the topological editing flag has changed.
void metadataChanged()
Emitted when the project's metadata is changed.
QString layerIsEmbedded(const QString &id) const
Returns project file path if layer is embedded from other project file. Returns empty string if layer...
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
QString homePath() const
Returns the project's home path.
static Q_INVOKABLE QgsUnitTypes::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
QDateTime lastModified() const
Returns last modified time of the project file as returned by the file system (or other project stora...
void reloadAllLayers()
Reload all registered layer's provider data caches, synchronising the layer with any changes in the d...
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Calls resolveReferences() on child tree nodes.
void resolveReferences(QgsProject *project) FINAL
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects...
void removeKey(const QString &keyName)
Removes the specified key.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
void projectSaved()
Emitted when the project file has been written and closed.
void layerWillBeRemoved(const QString &layerId)
Emitted when a layer is about to be removed from the store.
void reset()
reset to default values
void allLayersRemoved()
Emitted when all layers are removed, before layersWillBeRemoved() and layerWillBeRemoved() signals ar...
QgsMapLayerStore * layerStore()
Returns a pointer to the project's internal layer store.
void clear()
Remove any relation managed by this class.
QgsProject(QObject *parent=nullptr)
Create a new QgsProject.
static QString extension()
Returns the extension used for auxiliary databases.
static QString userFullName()
Returns the user's operating system login account full display name.
QgsProjectVersion getVersion(const QDomDocument &doc)
Returns the version string found in the given DOM document.
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
QString name() const
Returns the name of this element.
void fileNameChanged()
Emitted when the file name of the project changes.
void readProject(const QDomDocument &doc)
Reads the configuration from the specified QGIS project document.
Class allowing to manage the zip/unzip actions on project file.
QMap< QString, QgsRelation > relations() const
Gets access to the relations managed by this class.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the registry.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context, QStringList &missingTransforms)
Reads the context's state from a DOM element.
QgsUnitTypes::AreaUnit areaUnits() const
Convenience function to query default area measurement units for project.
virtual bool isKey() const =0
Returns true if the property is a QgsProjectPropertyKey.
const QgsLayoutManager * layoutManager() const
Returns the project's layout manager, which manages compositions within the project.
bool writeEntry(const QString &scope, const QString &key, bool value)
Write a boolean entry to the project file.
QgsProjectPropertyValue * setValue(const QString &name, const QVariant &value)
Sets the value associated with this key.
void readSettings()
Reads the context's state from application settings.
void missingDatumTransforms(const QStringList &missingTransforms)
Emitted when datum transforms stored in the project are not available locally.
bool read()
Reads the project from its currently associated file (see fileName() ).
void readProjectWithContext(const QDomDocument &, QgsReadWriteContext &context)
Emitted when a project is being read.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
QgsMapLayer * takeMapLayer(QgsMapLayer *layer)
Takes a layer from the registry.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QStringList subkeyList(const QString &scope, const QString &key) const
Returns keys with keys – do not return keys that contain only values.
QgsProjectStorage * projectStorage() const
Returns pointer to project storage implementation that handles read/write of the project file...
Namespace with helper functions for layer tree operations.
QVariant value() const override
If this key has a value, it will be stored by its name in its properties.
QString name() const
The name of the property is used as identifier.
#define QgsDebugMsgLevel(str, level)
QgsCoordinateReferenceSystem defaultCrsForNewLayers() const
Returns the default CRS for new layers based on the settings and the current project CRS...
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
void setAreaUnits(QgsUnitTypes::AreaUnit unit)
Sets the default area measurement units for the project.
A class to describe the version of a project.
virtual void clearKeys()
Deletes any sub-nodes from the property.
void layerRemoved(const QString &layerId)
Emitted after a layer was removed from the store.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setBadLayerHandler(QgsProjectBadLayerHandler *handler)
Change handler for missing layers.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
void readProject(const QDomDocument &)
Emitted when a project is being read.
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.
Listens to the updates in map layer registry and does changes in layer tree.
bool addLayer(QgsVectorLayer *layer)
Add a layer to this transaction group.
void clear()
Clear any information from this layer tree.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the project's native coordinate reference system.
static void replaceChildrenOfEmbeddedGroups(QgsLayerTreeGroup *group)
Remove subtree of embedded groups and replaces it with a custom property embedded-visible-layers.
void layerLoaded(int i, int n)
Emitted when a layer from a projects was read.
void writeXml(QDomElement &element, const QgsReadWriteContext &context) const
Writes the context's state to a DOM element.
void dump(int tabs=0) const override
Dumps out the keys and values.
QString fileName() const
Returns the project's file name.
void setDistanceUnits(QgsUnitTypes::DistanceUnit unit)
Sets the default distance measurement units for the project.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
This class is a base class for nodes in a layer tree.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
bool removeEntry(const QString &scope, const QString &key)
Remove the given key.
Reads and writes project states.
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
void setEllipsoid(const QString &ellipsoid)
Sets the project's ellipsoid from a proj string representation, e.g., "WGS84".
static bool supportsTransaction(const QgsVectorLayer *layer)
Checks if the provider of a given layer supports transactions.
QList< QgsReadWriteContext::ReadWriteMessage > takeMessages()
Returns the stored messages and remove them.
void writeMapLayer(QgsMapLayer *mapLayer, QDomElement &layerElem, QDomDocument &doc)
Emitted when a layer is being saved.
QString error() const
Returns error message from previous read/write.
Encapsulate a field in an attribute table or data source.
void removeAllMapLayers()
Removes all registered layers.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file...
virtual bool isValue() const =0
Returns true if the property is a QgsProjectPropertyValue.
QgsCoordinateTransformContext transformContext() const
Returns a copy of the project's coordinate transform context, which stores various information regard...
Contains information about the context in which a coordinate transform is executed.
void removeKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
Remove a given key.
QList< QgsVectorLayer * > avoidIntersectionsLayers() const
A list of layers with which intersections should be avoided.
QgsEditFormConfig editFormConfig
bool addLayers(const QList< QgsMapLayer * > &layers)
Adds the specified layers as individual layers to the configuration with standard configuration...
void setCustomVariables(const QVariantMap &customVariables)
A map of custom project variables.
Manages storage of a set of layouts.
void layersRemoved(const QStringList &layerIds)
Emitted after one or more layers were removed from the store.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
static QgsProjectStorageRegistry * projectStorageRegistry()
Returns registry of available project storage implementations.
void setProviderProperty(ProviderProperty property, const QVariant &value)
Allows setting arbitrary properties on the provider.
void insertChildNodes(int index, const QList< QgsLayerTreeNode * > &nodes)
Insert existing nodes at specified position.
bool write()
Writes the project to its current associated file (see fileName() ).
Used for the collecting of strings from projects for translation and creation of ts files...
QgsAnnotationManager * annotationManager()
Returns pointer to the project's annotation manager.
const QgsAuxiliaryStorage * auxiliaryStorage() const
Returns the current const auxiliary storage.
void readLayerOrderFromXml(const QDomElement &doc)
Load the layer order from an XML element.
QStringList makeKeyTokens_(const QString &scope, const QString &key)
Take the given scope and key and convert them to a string list of key tokens that will be used to nav...
bool loadAuxiliaryLayer(const QgsAuxiliaryStorage &storage, const QString &key=QString())
Loads the auxiliary layer for this vector layer.
QList< QgsMapLayer * > customLayerOrder() const
The order in which layers will be rendered on the canvas.
QgsLayerTreeGroup * createEmbeddedGroup(const QString &groupName, const QString &projectFilePath, const QStringList &invisibleLayers)
Create layer group instance defined in an arbitrary project file.
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
void registerTranslatableObjects(QgsTranslationContext *translationContext)
Registers the objects that require translation into the translationContext.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
void setMetadata(const QgsProjectMetadata &metadata)
Sets the project's metadata store.
void mapThemeCollectionChanged()
Emitted when the map theme collection changes.
bool readLayer(const QDomNode &layerNode)
Reads the layer described in the associated DOM node.
QgsMapThemeCollection * mapThemeCollection()
Returns pointer to the project's map theme collection.
Project property key node.
DistanceUnit
Units of distance.
QgsRelationManager * relationManager() const
bool isDirty() const
Returns true if the project has been modified since the last write()
bool removeLayers(const QList< QgsMapLayer * > &layers)
Removes the specified layers from the individual layer configuration.
QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
void transactionGroupsChanged()
Emitted whenever a new transaction group has been created or a transaction group has been removed...
QgsProjectProperty * find(const QString &propertyName) const
Attempts to find a property with a matching sub-key name.
void setPresetHomePath(const QString &path)
Sets the project's home path.
void layerWillBeRemoved(const QString &layerId)
Emitted when a layer is about to be removed from the registry.
void writeTsFile(const QString &locale)
Writes the Ts-file.
#define Q_NOWARN_DEPRECATED_POP
void setFileName(const QString &fileName)
Sets the fileName of the TS file.
double readDoubleEntry(const QString &scope, const QString &key, double def=0, bool *ok=nullptr) const
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString providerType() const
Returns the provider type for this layer.
QString baseName() const
Returns the base name of the project file without the path and without extension - derived from fileN...
void registerTranslation(const QString &context, const QString &source)
Registers the source to be translated.
QgsUnitTypes::DistanceUnit distanceUnits() const
Convenience function to query default distance measurement units for project.
void setAvoidIntersectionsLayers(const QList< QgsVectorLayer * > &layers)
A list of layers with which intersections should be avoided.
void writeProject(QDomDocument &)
Emitted when the project is being written.
void oldProjectVersionWarning(const QString &)
Emitted when an old project file is read.
void customVariablesChanged()
Emitted whenever the expression variables stored in the project have been changed.
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 layerRemoved(const QString &layerId)
Emitted after a layer was removed from the registry.
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Resolves reference to layer from stored layer ID (if it has not been resolved already) ...
void cleared()
Emitted when the project is cleared (and additionally when an open project is cleared just before a n...
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...
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QVector< T > layers() const
Returns a list of registered map layers with a specified layer type.
void setAutoTransaction(bool autoTransaction)
Transactional editing means that on supported datasources (postgres databases) the edit state of all ...
QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QMap< QPair< QString, QString >, QgsTransactionGroup * > transactionGroups()
Map of transaction groups.
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns project's global labeling engine settings.
void setProject(QgsProject *project)
Sets the project being translated.
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
void registerTranslatableContainers(QgsTranslationContext *translationContext, QgsAttributeEditorContainer *parent, const QString &layerId)
Registers the containers that require translation into the translationContext.
virtual void handleBadLayers(const QList< QDomNode > &layers)
This method will be called whenever the project tries to load layers which cannot be accessed...
This class manages a set of relations between layers.
QStringList findLayerIds() const
Find layer IDs used in all layer nodes.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name.
QVariantMap customVariables() const
A map of custom project variables.
bool createEmbeddedLayer(const QString &layerId, const QString &projectFilePath, QList< QDomNode > &brokenNodes, bool saveFlag=true)
Creates a maplayer instance defined in an arbitrary project file.
Stores global configuration for labeling engine.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void removeMapLayer(const QString &layerId)
Remove a layer from the registry by layer ID.
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...
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
This class represents a coordinate reference system (CRS).
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the project's coordinate transform context, which stores various information regarding which dat...
void setTitle(const QString &title)
Sets the project's title.
bool isZipped() const
Returns true if the project comes from a zip archive, false otherwise.
This is a container for attribute editors, used to group them visually in the attribute form if it is...
void loadingLayer(const QString &layerName)
Emitted when a layer is loaded.
void setEnabled(bool enabled)
Abstract interface for project storage - to be implemented by various backends and registered in QgsP...
If the layer can be removed from the project. The layer will not be removable from the legend menu en...
QStringList entryList(const QString &scope, const QString &key) const
Returns keys with values – do not return keys that contain other keys.
void loadingLayerMessageReceived(const QString &layerName, const QList< QgsReadWriteContext::ReadWriteMessage > &messages)
Emitted when loading layers has produced some messages.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
An Abstract Base Class for QGIS project property hierarchys.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
QgsMapLayer * addMapLayer(QgsMapLayer *mapLayer, bool addToLegend=true, bool takeOwnership=true)
Add a layer to the map of loaded layers.
QString absoluteFilePath() const
Returns full absolute path to the project file if the project is stored in a file system - derived fr...
void homePathChanged()
Emitted when the home path of the project changes.
void removeMapLayers(const QStringList &layerIds)
Remove a set of layers from the registry by layer ID.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
bool readBoolEntry(const QString &scope, const QString &key, bool def=false, bool *ok=nullptr) const
bool readXml(const QDomNode &keyNode) override
Restores the property hierarchy from a specified DOM node.
A storage object for map layers, in which the layers are owned by the store and have their lifetime b...
QString name() const override
Returns the group's name.
void dumpProperties() const
Dump out current project properties to stderr.
void avoidIntersectionsLayersChanged()
Emitted whenever avoidIntersectionsLayers has changed.
Container class that allows storage of map themes consisting of visible map layers and layer styles...
void transformContextChanged()
Emitted when the project transformContext() is changed.
This is a container for configuration of the snapping of the project.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
void readMapLayer(QgsMapLayer *mapLayer, const QDomElement &layerNode)
Emitted after the basic initialization of a layer from the project file is done.
Q_DECL_DEPRECATED QFileInfo fileInfo() const
Returns QFileInfo object for the project's associated file.
Resolves relative paths into absolute paths and vice versa.
void collectTranslatableObjects(QgsTranslationContext *translationContext)
Emits the signal to collect all the strings of .qgs to be included in ts file.
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
QgsProjectProperty * findKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
return the property that matches the given key sequence, if any
void setEvaluateDefaultValues(bool evaluateDefaultValues)
Defines if default values should be evaluated on provider side when requested and not when committed...
void entryList(QStringList &entries) const
Returns any sub-keys contained by this property that do not contain other keys.
Represents a vector layer which manages a vector based data sets.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
bool isEmpty() const
Checks whether the container is empty.
QgsCoordinateReferenceSystem crs() const
Returns the project's native coordinate reference system.
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer * > &mapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
QgsProjectStorage * projectStorageFromUri(const QString &uri)
Returns storage implementation if the URI matches one. Returns null pointer otherwise (it is a normal...
QgsLayerTree * clone() const override
Create a copy of the node. Returns new instance.
void setName(const QString &name)
The name of the property is used as identifier.
Evaluate default values on provider side when calling QgsVectorDataProvider::defaultValue( int index ...
QgsProjectProperty * addKey_(const QString &scope, const QString &key, QgsProjectPropertyKey *rootProperty, const QVariant &value, bool &propertiesModified)
Add the given key and value.
bool isEmpty() const
Returns true if this property contains no sub-keys.
QString ellipsoid() const
Returns a proj string representing the project's ellipsoid setting, e.g., "WGS84".
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all registered layers by layer ID.
If the layer is identifiable using the identify map tool and as a WMS layer.
void ellipsoidChanged(const QString &ellipsoid)
Emitted when the project ellipsoid is changed.
bool evaluateDefaultValues() const
Should default values be evaluated on provider side when requested and not when committed.
QgsPluginLayer * createLayer(const QString &typeName, const QString &uri=QString())
Returns new layer if corresponding plugin has been found else returns a nullptr.
void removeAll()
Emitted when all layers are removed, before layersWillBeRemoved() and layerWillBeRemoved() signals ar...
void _getProperties(const QDomDocument &doc, QgsProjectPropertyKey &project_properties)
Restore any optional properties found in "doc" to "properties".
bool writeXml(const QString &nodeName, QDomElement &element, QDomDocument &document) override
Writes the property hierarchy to a specified DOM element.
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets project's global labeling engine settings.
void subkeyList(QStringList &entries) const
Returns any sub-keys contained by this property which themselves contain other keys.
void clear()
Clears the project, removing all settings and resetting it back to an empty, default state...
static void updateEmbeddedGroupsProjectPath(QgsLayerTreeGroup *group, const QgsProject *project)
Updates an embedded group from a project.
Interface for classes that handle missing layer files when reading project file.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the store.
Q_DECL_DEPRECATED void nonIdentifiableLayersChanged(QStringList nonIdentifiableLayers)
Emitted when the list of layer which are excluded from map identification changes.
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.
void layerWasAdded(QgsMapLayer *layer)
Emitted when a layer was added to the registry.
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...
Layer tree node points to a map layer.
QString toProj4() const
Returns a Proj4 string representation of this CRS.
void setReadExtentFromXml(bool readExtentFromXml)
Flag allowing to indicate if the extent has to be read from the XML document when data source has no ...