84#include <QApplication>
89#include <QRegularExpression>
90#include <QStandardPaths>
91#include <QTemporaryFile>
97#include "moc_qgsproject.cpp"
100#include <sys/utime.h>
116QStringList makeKeyTokens_(
const QString &scope,
const QString &key )
118 QStringList keyTokens = QStringList( scope );
119 keyTokens += key.split(
'/', Qt::SkipEmptyParts );
122 keyTokens.push_front( QStringLiteral(
"properties" ) );
145 QStringList keySequence = makeKeyTokens_( scope, key );
147 while ( !keySequence.isEmpty() )
151 if ( keySequence.first() == currentProperty->
name() )
154 keySequence.pop_front();
156 if ( 1 == keySequence.count() )
159 return currentProperty->
find( keySequence.front() );
161 else if ( keySequence.isEmpty() )
166 return currentProperty;
168 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
170 if ( nextProperty->
isKey() )
174 else if ( nextProperty->
isValue() && 1 == keySequence.count() )
180 return currentProperty;
218 const QVariant &value,
219 bool &propertiesModified )
221 QStringList keySequence = makeKeyTokens_( scope, key );
228 propertiesModified =
false;
229 while ( ! keySequence.isEmpty() )
233 if ( keySequence.first() == currentProperty->
name() )
236 keySequence.pop_front();
240 if ( 1 == keySequence.count() )
243 if ( !property || property->value() != value )
245 currentProperty->
setValue( keySequence.front(), value );
246 propertiesModified =
true;
249 return currentProperty;
253 else if ( keySequence.isEmpty() )
255 if ( currentProperty->
value() != value )
258 propertiesModified =
true;
261 return currentProperty;
263 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
267 if ( currentProperty )
278 if ( ( newPropertyKey = currentProperty->
addKey( keySequence.first() ) ) )
280 currentProperty = newPropertyKey;
310 QStringList keySequence = makeKeyTokens_( scope, key );
312 while ( ! keySequence.isEmpty() )
316 if ( keySequence.first() == currentProperty->
name() )
319 keySequence.pop_front();
323 if ( 1 == keySequence.count() )
325 currentProperty->
removeKey( keySequence.front() );
330 else if ( keySequence.isEmpty() )
332 previousQgsPropertyKey->
removeKey( currentProperty->
name() );
334 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
336 previousQgsPropertyKey = currentProperty;
339 if ( currentProperty )
366 , mSnappingConfig( this )
385 mProperties.setName( QStringLiteral(
"properties" ) );
388 mMainAnnotationLayer->setParent(
this );
395 mLayerTreeRegistryBridge = std::make_unique<QgsLayerTreeRegistryBridge>( mRootGroup.get(),
this,
this );
402 this, [
this](
const QStringList &
layers ) { mProjectScope.reset(); emit layersWillBeRemoved( layers ); } );
404 this, [
this](
const QList<QgsMapLayer *> &
layers ) { mProjectScope.reset(); emit layersWillBeRemoved( layers ); } );
406 this, [
this](
const QString & layer ) { mProjectScope.reset(); emit layerWillBeRemoved( layer ); } );
408 this, [
this](
QgsMapLayer * layer ) { mProjectScope.reset(); emit layerWillBeRemoved( layer ); } );
410 [
this](
const QStringList &
layers ) { mProjectScope.reset(); emit layersRemoved( layers ); } );
412 [
this](
const QString & layer ) { mProjectScope.reset(); emit layerRemoved( layer ); } );
414 [
this]() { mProjectScope.reset(); emit removeAll(); } );
416 [
this](
const QList< QgsMapLayer * > &
layers ) { mProjectScope.reset(); emit layersAdded( layers ); } );
418 [
this](
QgsMapLayer * layer ) { mProjectScope.reset(); emit layerWasAdded( layer ); } );
426 [
this](
const QList<QgsMapLayer *> &
layers )
428 for ( const auto &layer : layers )
430 disconnect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager.get(), &QgsRelationManager::updateRelationsStatus );
435 [
this](
const QList<QgsMapLayer *> &layers )
437 for ( const auto &layer : layers )
439 connect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager.get(), &QgsRelationManager::updateRelationsStatus );
448 mStyleSettings->combinedStyleModel()->addDefaultStyle();
454 mIsBeingDeleted =
true;
457 releaseHandlesToProjectArchive();
459 if (
this == sProject )
486 if (
title == mMetadata.title() )
489 mMetadata.setTitle(
title );
490 mProjectScope.reset();
502 return mMetadata.title();
511 if ( oldEvaluateDefaultValues != newEvaluateDefaultValues )
514 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
516 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
517 if ( vl->dataProvider() )
524 if ( oldTrustLayerMetadata != newTrustLayerMetadata )
527 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
529 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
531 vl->setReadExtentFromXml( newTrustLayerMetadata );
536 if ( mFlags !=
flags )
551 newFlags &= ~(
static_cast< int >( flag ) );
566 return mSaveUserFull;
573 return mSaveDateTime;
594 if ( dirty && mDirtyBlockCount > 0 )
600 if ( mDirty == dirty )
611 if ( path == mHomePath )
615 mCachedHomePath.clear();
616 mProjectScope.reset();
627 const QList<QgsAttributeEditorElement *> elements = parent->
children();
635 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:formcontainers" ).arg( layerId ), container->
name() );
637 if ( !container->
children().empty() )
648 const QList<QgsLayerTreeLayer *>
layers = mRootGroup->findLayers();
652 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1" ).arg( layer->layerId() ), layer->name() );
664 for (
const QgsField &field : fields )
667 if ( field.alias().isEmpty() )
668 fieldName = field.name();
670 fieldName = field.alias();
672 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fieldaliases" ).arg( vlayer->
id() ), fieldName );
674 if ( field.editorWidgetSetup().type() == QLatin1String(
"ValueRelation" ) )
676 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fields:%2:valuerelationvalue" ).arg( vlayer->
id(), field.name() ), field.editorWidgetSetup().config().value( QStringLiteral(
"Value" ) ).toString() );
678 if ( field.editorWidgetSetup().type() == QLatin1String(
"ValueMap" ) )
680 if ( field.editorWidgetSetup().config().value( QStringLiteral(
"map" ) ).canConvert<QList<QVariant>>() )
682 const QList<QVariant> valueList = field.editorWidgetSetup().config().value( QStringLiteral(
"map" ) ).toList();
684 for (
int i = 0, row = 0; i < valueList.count(); i++, row++ )
686 translationContext->
registerTranslation( QStringLiteral(
"project:layers:%1:fields:%2:valuemapdescriptions" ).arg( vlayer->
id(), field.name() ), valueList[i].toMap().constBegin().key() );
709 mapLayer->metadata().registerTranslations( translationContext );
714 const QList<QgsLayerTreeGroup *> groupLayers = mRootGroup->findGroups();
717 translationContext->
registerTranslation( QStringLiteral(
"project:layergroups" ), groupLayer->name() );
721 const QList<QgsRelation> &relations = mRelationManager->relations().values();
724 translationContext->
registerTranslation( QStringLiteral(
"project:relations" ), relation.name() );
728 mMetadata.registerTranslations( translationContext );
735 mDataDefinedServerProperties = properties;
742 return mDataDefinedServerProperties;
749 switch ( mTransactionMode )
760 return mEditBufferGroup.startEditing();
770 switch ( mTransactionMode )
777 commitErrors.append( tr(
"Trying to commit changes without a layer specified. This only works if the transaction mode is buffered" ) );
786 return mEditBufferGroup.commitChanges( commitErrors, stopEditing );
796 switch ( mTransactionMode )
803 rollbackErrors.append( tr(
"Trying to roll back changes without a layer specified. This only works if the transaction mode is buffered" ) );
806 bool success = vectorLayer->
rollBack( stopEditing );
812 return mEditBufferGroup.rollBack( rollbackErrors, stopEditing );
822 if ( name == mFile.fileName() )
825 const QString oldHomePath =
homePath();
827 mFile.setFileName( name );
828 mCachedHomePath.clear();
829 mProjectScope.reset();
833 const QString newHomePath =
homePath();
834 if ( newHomePath != oldHomePath )
845 return mFile.fileName();
852 mOriginalPath = path;
859 return mOriginalPath;
866 return QFileInfo( mFile );
884 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
889 return QFileInfo( mFile.fileName() ).lastModified();
900 if ( mFile.fileName().isEmpty() )
903 return QFileInfo( mFile.fileName() ).absolutePath();
914 if ( mFile.fileName().isEmpty() )
917 return QFileInfo( mFile.fileName() ).absoluteFilePath();
928 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
933 return QFileInfo( mFile.fileName() ).completeBaseName();
941 const bool absolutePaths =
readBoolEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
952 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
true );
955 writeEntry( QStringLiteral(
"Paths" ), QStringLiteral(
"/Absolute" ),
false );
972 return mCrs3D.isValid() ? mCrs3D : mCrs;
984 writeEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ),
crs.isValid() ? 1 : 0 );
985 mProjectScope.reset();
989 if ( !mMainAnnotationLayer->crs().isValid() || mMainAnnotationLayer->isEmpty() )
990 mMainAnnotationLayer->setCrs(
crs );
999 if ( oldCrs3D != mCrs3D )
1003 if ( adjustEllipsoid )
1012 if ( !
crs().isValid() )
1022 if (
ellipsoid ==
readEntry( QStringLiteral(
"Measure" ), QStringLiteral(
"/Ellipsoid" ) ) )
1025 mProjectScope.reset();
1035 switch ( mCrs.type() )
1038 QgsDebugError( QStringLiteral(
"Project has a vertical CRS set as the horizontal CRS!" ) );
1042 return mCrs.verticalCrs();
1057 return mVerticalCrs;
1064 if (
crs.isValid() )
1067 switch (
crs.type() )
1085 *errorMessage = QObject::tr(
"Specified CRS is a %1 CRS, not a Vertical CRS" ).arg(
qgsEnumValueToKey(
crs.type() ) );
1090 if (
crs != mVerticalCrs )
1095 switch ( mCrs.type() )
1098 if (
crs != oldVerticalCrs )
1101 *errorMessage = QObject::tr(
"Project CRS is a Compound CRS, specified Vertical CRS will be ignored" );
1107 if (
crs != oldVerticalCrs )
1110 *errorMessage = QObject::tr(
"Project CRS is a Geographic 3D CRS, specified Vertical CRS will be ignored" );
1116 if (
crs != oldVerticalCrs )
1119 *errorMessage = QObject::tr(
"Project CRS is a Geocentric CRS, specified Vertical CRS will be ignored" );
1125 if ( mCrs.hasVerticalAxis() &&
crs != oldVerticalCrs )
1128 *errorMessage = QObject::tr(
"Project CRS is a Projected 3D CRS, specified Vertical CRS will be ignored" );
1146 res = rebuildCrs3D( errorMessage );
1147 mProjectScope.reset();
1154 if ( mCrs3D != oldCrs3D )
1165 return mTransformContext;
1172 if ( context == mTransformContext )
1175 mTransformContext = context;
1176 mProjectScope.reset();
1178 mMainAnnotationLayer->setTransformContext( context );
1179 for (
auto &layer : mLayerStore.get()->mapLayers() )
1181 layer->setTransformContext( context );
1190 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
1194 if ( !mIsBeingDeleted )
1203 mProjectScope.reset();
1204 mFile.setFileName( QString() );
1205 mProperties.clearKeys();
1207 mSaveUserFull.clear();
1208 mSaveDateTime = QDateTime();
1211 mCachedHomePath.clear();
1215 mCustomVariables.clear();
1221 if ( !mSettings.value( QStringLiteral(
"projects/anonymize_new_projects" ),
false,
QgsSettings::Core ).toBool() )
1223 mMetadata.setCreationDateTime( QDateTime::currentDateTime() );
1242 mEmbeddedLayers.clear();
1243 mRelationManager->clear();
1244 mAnnotationManager->clear();
1245 mLayoutManager->clear();
1246 mElevationProfileManager->clear();
1247 m3DViewsManager->clear();
1248 mBookmarkManager->clear();
1249 mSensorManager->clear();
1250 mViewSettings->reset();
1251 mTimeSettings->reset();
1252 mElevationProperties->reset();
1253 mDisplaySettings->reset();
1254 mGpsSettings->reset();
1255 mSnappingConfig.reset();
1260 mMapThemeCollection = std::make_unique< QgsMapThemeCollection >(
this );
1263 mLabelingEngineSettings->clear();
1267 releaseHandlesToProjectArchive();
1269 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >();
1270 mArchive = std::make_unique< QgsArchive >();
1273 mStyleSettings->reset();
1277 if ( !mIsBeingDeleted )
1285 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/Automatic" ),
true );
1286 writeEntry( QStringLiteral(
"PositionPrecision" ), QStringLiteral(
"/DecimalPlaces" ), 2 );
1288 const bool defaultRelativePaths = mSettings.value( QStringLiteral(
"/qgis/defaultProjectPathsRelative" ),
true ).toBool();
1291 int red = mSettings.value( QStringLiteral(
"qgis/default_canvas_color_red" ), 255 ).toInt();
1292 int green = mSettings.value( QStringLiteral(
"qgis/default_canvas_color_green" ), 255 ).toInt();
1293 int blue = mSettings.value( QStringLiteral(
"qgis/default_canvas_color_blue" ), 255 ).toInt();
1296 red = mSettings.value( QStringLiteral(
"qgis/default_selection_color_red" ), 255 ).toInt();
1297 green = mSettings.value( QStringLiteral(
"qgis/default_selection_color_green" ), 255 ).toInt();
1298 blue = mSettings.value( QStringLiteral(
"qgis/default_selection_color_blue" ), 0 ).toInt();
1299 const int alpha = mSettings.value( QStringLiteral(
"qgis/default_selection_color_alpha" ), 255 ).toInt();
1302 mSnappingConfig.clearIndividualLayerSettings();
1305 mRootGroup->clear();
1306 if ( mMainAnnotationLayer )
1307 mMainAnnotationLayer->reset();
1309 snapSingleBlocker.release();
1311 if ( !mBlockSnappingUpdates )
1317 if ( !mBlockChangeSignalsDuringClear )
1329 topQgsPropertyKey.
dump();
1362 const QDomElement propertiesElem = doc.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
1364 if ( propertiesElem.isNull() )
1369 const QDomNodeList scopes = propertiesElem.childNodes();
1371 if ( propertiesElem.firstChild().isNull() )
1373 QgsDebugError( QStringLiteral(
"empty ``properties'' XML tag ... bailing" ) );
1377 if ( ! project_properties.
readXml( propertiesElem ) )
1379 QgsDebugError( QStringLiteral(
"Project_properties.readXml() failed" ) );
1393 const QDomElement ddElem = doc.documentElement().firstChildElement( QStringLiteral(
"dataDefinedServerProperties" ) );
1394 if ( !ddElem.isNull() )
1396 if ( !ddServerProperties.
readXml( ddElem, dataDefinedServerPropertyDefinitions ) )
1398 QgsDebugError( QStringLiteral(
"dataDefinedServerProperties.readXml() failed" ) );
1401 return ddServerProperties;
1408static void _getTitle(
const QDomDocument &doc, QString &title )
1410 const QDomElement titleNode = doc.documentElement().firstChildElement( QStringLiteral(
"title" ) );
1414 if ( titleNode.isNull() )
1420 if ( !titleNode.hasChildNodes() )
1426 const QDomNode titleTextNode = titleNode.firstChild();
1428 if ( !titleTextNode.isText() )
1434 const QDomText titleText = titleTextNode.toText();
1436 title = titleText.data();
1440static void readProjectFileMetadata(
const QDomDocument &doc, QString &lastUser, QString &lastUserFull, QDateTime &lastSaveDateTime )
1442 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1446 QgsDebugError( QStringLiteral(
"unable to find qgis element" ) );
1450 const QDomNode qgisNode = nl.item( 0 );
1452 const QDomElement qgisElement = qgisNode.toElement();
1453 lastUser = qgisElement.attribute( QStringLiteral(
"saveUser" ), QString() );
1454 lastUserFull = qgisElement.attribute( QStringLiteral(
"saveUserFull" ), QString() );
1455 lastSaveDateTime = QDateTime::fromString( qgisElement.attribute( QStringLiteral(
"saveDateTime" ), QString() ), Qt::ISODate );
1460 const QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"qgis" ) );
1464 QgsDebugError( QStringLiteral(
" unable to find qgis element in project file" ) );
1468 const QDomNode qgisNode = nl.item( 0 );
1470 const QDomElement qgisElement = qgisNode.toElement();
1471 QgsProjectVersion projectVersion( qgisElement.attribute( QStringLiteral(
"version" ) ) );
1472 return projectVersion;
1479 return mSnappingConfig;
1498 if ( mAvoidIntersectionsMode == mode )
1501 mAvoidIntersectionsMode = mode;
1535void QgsProject::preloadProviders(
const QVector<QDomNode> ¶llelLayerNodes,
1537 QMap<QString, QgsDataProvider *> &loadedProviders,
1539 int totalProviderCount )
1544 QMap<QString, LayerToLoad> layersToLoad;
1546 for (
const QDomNode &node : parallelLayerNodes )
1550 const QDomElement layerElement = node.toElement();
1552 layerToLoad.
layerId = layerElement.namedItem( QStringLiteral(
"id" ) ).toElement().text();
1553 layerToLoad.
provider = layerElement.namedItem( QStringLiteral(
"provider" ) ).toElement().text();
1554 layerToLoad.
dataSource = layerElement.namedItem( QStringLiteral(
"datasource" ) ).toElement().text();
1565 layersToLoad.insert( layerToLoad.
layerId, layerToLoad );
1568 while ( !layersToLoad.isEmpty() )
1570 const QList<LayerToLoad> layersToAttemptInParallel = layersToLoad.values();
1571 QString layerToAttemptInMainThread;
1573 QHash<QString, QgsRunnableProviderCreator *> runnables;
1574 QThreadPool threadPool;
1577 for (
const LayerToLoad &lay : layersToAttemptInParallel )
1579 QgsRunnableProviderCreator *run =
new QgsRunnableProviderCreator( lay.layerId, lay.provider, lay.dataSource, lay.options, lay.flags );
1580 runnables.insert( lay.layerId, run );
1586 layersToLoad.remove( layId );
1588 QgsRunnableProviderCreator *finishedRun = runnables.value( layId,
nullptr );
1589 Q_ASSERT( finishedRun );
1591 std::unique_ptr<QgsDataProvider> provider( finishedRun->
dataProvider() );
1592 Q_ASSERT( provider && provider->isValid() );
1594 loadedProviders.insert( layId, provider.release() );
1599 if ( layerToAttemptInMainThread.isEmpty() )
1600 layerToAttemptInMainThread = layId;
1604 if ( i == parallelLayerNodes.count() || !isValid )
1607 threadPool.start( run );
1611 threadPool.waitForDone();
1613 qDeleteAll( runnables );
1616 auto it = layersToLoad.find( layerToAttemptInMainThread );
1617 if ( it != layersToLoad.end() )
1619 std::unique_ptr<QgsDataProvider> provider;
1622 const LayerToLoad &lay = it.value();
1626 QgsScopedRuntimeProfile profile(
"Create data providers/" + lay.
layerId, QStringLiteral(
"projectload" ) );
1629 if ( provider && provider->isValid() )
1634 layersToLoad.erase( it );
1637 loadedProviders.insert( layerId, provider.release() );
1645void QgsProject::releaseHandlesToProjectArchive()
1647 mStyleSettings->removeProjectStyle();
1650bool QgsProject::rebuildCrs3D( QString *error )
1653 if ( !mCrs.isValid() )
1655 mCrs3D = QgsCoordinateReferenceSystem();
1657 else if ( !mVerticalCrs.isValid() )
1663 switch ( mCrs.type() )
1675 res = mCrs3D.isValid();
1681 mCrs3D = QgsCoordinateReferenceSystem();
1696 res = mCrs3D.isValid();
1704bool QgsProject::_getMapLayers(
const QDomDocument &doc, QList<QDomNode> &brokenNodes,
Qgis::ProjectReadFlags flags )
1711 QDomElement layerElement = doc.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
1715 if ( layerElement.isNull() )
1725 bool returnStatus =
true;
1728 while ( ! layerElement.isNull() )
1731 layerElement = layerElement.nextSiblingElement( QStringLiteral(
"maplayer" ) );
1735 QgsScopedRuntimeProfile profile( tr(
"Sorting layers" ), QStringLiteral(
"projectload" ) );
1736 const QgsLayerDefinition::DependencySorter depSorter( doc );
1737 if ( depSorter.hasCycle() )
1741 if ( depSorter.hasMissingDependency() )
1742 returnStatus =
false;
1746 const QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
1747 const int totalLayerCount = sortedLayerNodes.count();
1749 QVector<QDomNode> parallelLoading;
1750 QMap<QString, QgsDataProvider *> loadedProviders;
1755 profile.switchTask( tr(
"Load providers in parallel" ) );
1756 for (
const QDomNode &node : sortedLayerNodes )
1758 const QDomElement element = node.toElement();
1759 if ( element.attribute( QStringLiteral(
"embedded" ) ) != QLatin1String(
"1" ) )
1761 const QString layerId = node.namedItem( QStringLiteral(
"id" ) ).toElement().text();
1762 if ( !depSorter.isLayerDependent( layerId ) )
1764 const QDomNode mnl = element.namedItem( QStringLiteral(
"provider" ) );
1765 const QDomElement mne = mnl.toElement();
1766 const QString provider = mne.text();
1770 parallelLoading.append( node );
1777 QgsReadWriteContext context;
1779 if ( !parallelLoading.isEmpty() )
1780 preloadProviders( parallelLoading, context, loadedProviders, projectFlagsToLayerReadFlags(
flags, mFlags ), sortedLayerNodes.count() );
1783 int i = loadedProviders.count();
1784 for (
const QDomNode &node : std::as_const( sortedLayerNodes ) )
1786 const QDomElement element = node.toElement();
1787 const QString name =
translate( QStringLiteral(
"project:layers:%1" ).arg( node.namedItem( QStringLiteral(
"id" ) ).toElement().text() ), node.namedItem( QStringLiteral(
"layername" ) ).toElement().text() );
1788 if ( !name.isNull() )
1789 emit
loadingLayer( tr(
"Loading layer %1" ).arg( name ) );
1791 profile.switchTask( name );
1792 if ( element.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
1794 createEmbeddedLayer( element.attribute( QStringLiteral(
"id" ) ),
readPath( element.attribute( QStringLiteral(
"project" ) ) ), brokenNodes,
true,
flags );
1798 QgsReadWriteContext context;
1802 QString layerId = element.namedItem( QStringLiteral(
"id" ) ).toElement().text();
1804 if ( !addLayer( element, brokenNodes, context,
flags, loadedProviders.take( layerId ) ) )
1806 returnStatus =
false;
1809 if ( !messages.isEmpty() )
1818 return returnStatus;
1821bool QgsProject::addLayer(
const QDomElement &layerElem,
1822 QList<QDomNode> &brokenNodes,
1829 const QString type = layerElem.attribute( QStringLiteral(
"type" ) );
1831 std::unique_ptr<QgsMapLayer>
mapLayer;
1833 QgsScopedRuntimeProfile profile( tr(
"Create layer" ), QStringLiteral(
"projectload" ) );
1839 QgsDebugError( QStringLiteral(
"Unknown layer type \"%1\"" ).arg( type ) );
1843 switch ( layerType )
1846 mapLayer = std::make_unique<QgsVectorLayer>();
1850 mapLayer = std::make_unique<QgsRasterLayer>();
1854 mapLayer = std::make_unique<QgsMeshLayer>();
1858 mapLayer = std::make_unique<QgsVectorTileLayer>();
1862 mapLayer = std::make_unique<QgsPointCloudLayer>();
1866 mapLayer = std::make_unique<QgsTiledSceneLayer>();
1871 const QString typeName = layerElem.attribute( QStringLiteral(
"name" ) );
1878 const QgsAnnotationLayer::LayerOptions options( mTransformContext );
1879 mapLayer = std::make_unique<QgsAnnotationLayer>( QString(), options );
1885 const QgsGroupLayer::LayerOptions options( mTransformContext );
1886 mapLayer = std::make_unique<QgsGroupLayer>( QString(), options );
1893 QgsDebugError( QStringLiteral(
"Unable to create layer" ) );
1901 const QString layerId { layerElem.namedItem( QStringLiteral(
"id" ) ).toElement().text() };
1902 Q_ASSERT( ! layerId.isEmpty() );
1908 profile.switchTask( tr(
"Load layer source" ) );
1909 const bool layerIsValid =
mapLayer->readLayerXml( layerElem, context, layerFlags, provider ) &&
mapLayer->isValid();
1912 if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>(
mapLayer.get() ) )
1915 if ( vl->dataProvider() )
1922 profile.switchTask( tr(
"Add layer to project" ) );
1923 QList<QgsMapLayer *> newLayers;
1933 if ( QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>(
mapLayer.get() ) )
1935 vLayer->joinBuffer()->resolveReferences(
this );
1944 brokenNodes.push_back( layerElem );
1947 const bool wasEditable = layerElem.attribute( QStringLiteral(
"editable" ), QStringLiteral(
"0" ) ).toInt();
1950 mapLayer->setCustomProperty( QStringLiteral(
"_layer_was_editable" ),
true );
1954 mapLayer->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
1959 if ( ! layerWasStored )
1964 return layerIsValid;
1971 mFile.setFileName( filename );
1972 mCachedHomePath.clear();
1973 mProjectScope.reset();
1982 const QString filename = mFile.fileName();
1987 QTemporaryFile inDevice;
1988 if ( !inDevice.open() )
1990 setError( tr(
"Unable to open %1" ).arg( inDevice.fileName() ) );
1996 if ( !storage->readProject( filename, &inDevice, context ) )
1998 QString err = tr(
"Unable to open %1" ).arg( filename );
1999 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
2000 if ( !messages.isEmpty() )
2001 err += QStringLiteral(
"\n\n" ) + messages.last().message();
2005 returnValue = unzip( inDevice.fileName(),
flags );
2011 returnValue = unzip( mFile.fileName(),
flags );
2015 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >( *
this );
2016 const QFileInfo finfo( mFile.fileName() );
2017 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
2018 if ( QFile( attachmentsZip ).exists() )
2020 auto archive = std::make_unique<QgsArchive>();
2021 if ( archive->unzip( attachmentsZip ) )
2023 releaseHandlesToProjectArchive();
2024 mArchive = std::move( archive );
2027 returnValue = readProjectFile( mFile.fileName(),
flags );
2033 mFile.setFileName( filename );
2034 mCachedHomePath.clear();
2035 mProjectScope.reset();
2040 mTranslator.reset(
nullptr );
2053 ScopedIntIncrementor snapSignalBlock( &mBlockSnappingUpdates );
2055 QFile projectFile( filename );
2063 if ( QFile( QStringLiteral(
"%1/%2.qm" ).arg( QFileInfo( mFile ).
absolutePath(), localeFileName ) ).exists() )
2065 mTranslator = std::make_unique< QTranslator >();
2066 ( void )mTranslator->load( localeFileName, QFileInfo( mFile ).
absolutePath() );
2069 profile.switchTask( tr(
"Reading project file" ) );
2070 auto doc = std::make_unique<QDomDocument>( QStringLiteral(
"qgis" ) );
2072 if ( !projectFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
2074 projectFile.close();
2076 setError( tr(
"Unable to open %1" ).arg( projectFile.fileName() ) );
2081 QTextStream textStream( &projectFile );
2082#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2083 textStream.setCodec(
"UTF-8" );
2085 QString projectString = textStream.readAll();
2086 projectFile.close();
2088 for (
int i = 0; i < 32; i++ )
2090 if ( i == 9 || i == 10 || i == 13 )
2094 projectString.replace( QChar( i ), QStringLiteral(
"%1%2%1" ).arg(
FONTMARKER_CHR_FIX, QString::number( i ) ) );
2100 if ( !doc->setContent( projectString, &errorMsg, &line, &column ) )
2102 const QString errorString = tr(
"Project file read error in file %1: %2 at line %3 column %4" )
2103 .arg( projectFile.fileName(), errorMsg ).arg( line ).arg( column );
2105 setError( errorString );
2110 projectFile.close();
2115 const QgsProjectVersion fileVersion =
getVersion( *doc );
2118 profile.switchTask( tr(
"Updating project file" ) );
2119 if ( thisVersion > fileVersion )
2121 const bool isOlderMajorVersion = fileVersion.
majorVersion() < thisVersion.majorVersion();
2123 if ( isOlderMajorVersion )
2126 "version of qgis (saved in " + fileVersion.
text() +
2128 "). Problems may occur." );
2131 QgsProjectFileTransform projectFile( *doc, fileVersion );
2139 projectFile.updateRevision( thisVersion );
2141 else if ( fileVersion > thisVersion )
2144 "version of qgis (saved in " + fileVersion.
text() +
2146 "). Problems may occur." );
2152 profile.switchTask( tr(
"Creating auxiliary storage" ) );
2153 const QString
fileName = mFile.fileName();
2155 const QgsCoordinateReferenceSystem oldVerticalCrs =
verticalCrs();
2156 const QgsCoordinateReferenceSystem oldCrs3D = mCrs3D;
2160 std::unique_ptr<QgsAuxiliaryStorage> aStorage = std::move( mAuxiliaryStorage );
2161 std::unique_ptr<QgsArchive> archive = std::move( mArchive );
2165 mBlockChangeSignalsDuringClear =
true;
2167 mBlockChangeSignalsDuringClear =
false;
2172 releaseHandlesToProjectArchive();
2174 mAuxiliaryStorage = std::move( aStorage );
2175 mArchive = std::move( archive );
2178 mCachedHomePath.clear();
2179 mProjectScope.reset();
2180 mSaveVersion = fileVersion;
2183 profile.switchTask( tr(
"Reading properties" ) );
2189 QgsDebugMsgLevel( QString::number( mProperties.count() ) +
" properties read", 2 );
2192 dump_( mProperties );
2197 _getTitle( *doc, oldTitle );
2199 readProjectFileMetadata( *doc, mSaveUser, mSaveUserFull, mSaveDateTime );
2201 const QDomNodeList homePathNl = doc->elementsByTagName( QStringLiteral(
"homePath" ) );
2202 if ( homePathNl.count() > 0 )
2204 const QDomElement homePathElement = homePathNl.at( 0 ).toElement();
2205 const QString
homePath = homePathElement.attribute( QStringLiteral(
"path" ) );
2215 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), 255 ),
2216 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), 255 ) );
2219 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), 255 ),
2220 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), 255 ),
2221 readNumEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), 255 ) );
2225 const QString distanceUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/DistanceUnits" ), QString() );
2226 if ( !distanceUnitString.isEmpty() )
2229 const QString areaUnitString =
readEntry( QStringLiteral(
"Measurement" ), QStringLiteral(
"/AreaUnits" ), QString() );
2230 if ( !areaUnitString.isEmpty() )
2235 QgsReadWriteContext context;
2240 QgsCoordinateReferenceSystem projectCrs;
2241 if (
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectionsEnabled" ), 0 ) )
2244 const QDomNode srsNode = doc->documentElement().namedItem( QStringLiteral(
"projectCrs" ) );
2245 if ( !srsNode.isNull() )
2247 projectCrs.
readXml( srsNode );
2252 const QString projCrsString =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSProj4String" ) );
2253 const long currentCRS =
readNumEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCRSID" ), -1 );
2254 const QString authid =
readEntry( QStringLiteral(
"SpatialRefSys" ), QStringLiteral(
"/ProjectCrs" ) );
2257 const bool isUserAuthId = authid.startsWith( QLatin1String(
"USER:" ), Qt::CaseInsensitive );
2258 if ( !authid.isEmpty() && !isUserAuthId )
2259 projectCrs = QgsCoordinateReferenceSystem( authid );
2262 if ( !projectCrs.
isValid() && currentCRS >= 0 )
2268 if ( !projCrsString.isEmpty() && ( authid.isEmpty() || isUserAuthId ) && ( !projectCrs.
isValid() || projectCrs.
toProj() != projCrsString ) )
2285 const QDomNode verticalCrsNode = doc->documentElement().namedItem( QStringLiteral(
"verticalCrs" ) );
2286 if ( !verticalCrsNode.isNull() )
2294 QStringList datumErrors;
2295 if ( !mTransformContext.readXml( doc->documentElement(), context, datumErrors ) && !datumErrors.empty() )
2302 const QDomNode elevationShadingNode = doc->documentElement().namedItem( QStringLiteral(
"elevation-shading-renderer" ) );
2303 if ( !elevationShadingNode.isNull() )
2305 mElevationShadingRenderer.readXml( elevationShadingNode.toElement(), context );
2312 const QStringList variableNames =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ) );
2313 const QStringList variableValues =
readListEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ) );
2315 mCustomVariables.clear();
2316 if ( variableNames.length() == variableValues.length() )
2318 for (
int i = 0; i < variableNames.length(); ++i )
2320 mCustomVariables.insert( variableNames.at( i ), variableValues.at( i ) );
2325 QgsMessageLog::logMessage( tr(
"Project Variables Invalid" ), tr(
"The project contains invalid variable settings." ) );
2333 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectMetadata" ) );
2335 if ( !element.isNull() )
2337 mMetadata.readMetadataXml( element, context );
2342 mMetadata = QgsProjectMetadata();
2344 if ( mMetadata.title().isEmpty() && !oldTitle.isEmpty() )
2347 mMetadata.setTitle( oldTitle );
2353 element = doc->documentElement().firstChildElement( QStringLiteral(
"transaction" ) );
2354 if ( !element.isNull() )
2361 element = doc->documentElement().firstChildElement( QStringLiteral(
"autotransaction" ) );
2362 if ( ! element.isNull() )
2364 mTransactionMode =
static_cast<Qgis::TransactionMode>( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() );
2369 profile.switchTask( tr(
"Loading layer tree" ) );
2370 mRootGroup->setCustomProperty( QStringLiteral(
"loading" ), 1 );
2372 QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
2373 if ( !layerTreeElem.isNull() )
2376 QgsLayerTree tempTree;
2385 mLayerTreeRegistryBridge->setEnabled(
false );
2388 profile.switchTask( tr(
"Reading map layers" ) );
2390 loadProjectFlags( doc.get() );
2392 QList<QDomNode> brokenNodes;
2393 const bool clean = _getMapLayers( *doc, brokenNodes,
flags );
2398 QgsDebugError( QStringLiteral(
"Unable to get map layers from project file." ) );
2400 if ( !brokenNodes.isEmpty() )
2402 QgsDebugError(
"there are " + QString::number( brokenNodes.size() ) +
" broken layers" );
2407 mBadLayerHandler->handleBadLayers( brokenNodes );
2410 mMainAnnotationLayer->readLayerXml( doc->documentElement().firstChildElement( QStringLiteral(
"main-annotation-layer" ) ), context );
2411 mMainAnnotationLayer->setTransformContext( mTransformContext );
2414 profile.switchTask( tr(
"Loading embedded layers" ) );
2415 loadEmbeddedNodes( mRootGroup.get(),
flags );
2419 profile.switchTask( tr(
"Resolving layer references" ) );
2420 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
2421 for ( QMap<QString, QgsMapLayer *>::iterator it =
layers.begin(); it !=
layers.end(); ++it )
2423 it.value()->resolveReferences(
this );
2425 mMainAnnotationLayer->resolveReferences(
this );
2427 mLayerTreeRegistryBridge->setEnabled(
true );
2430 profile.switchTask( tr(
"Resolving references" ) );
2431 mRootGroup->resolveReferences(
this );
2434 if ( QgsProjectVersion( 3, 28, 0 ) > mSaveVersion )
2441 if ( !layerTreeElem.isNull() )
2443 mRootGroup->readLayerOrderFromXml( layerTreeElem );
2447 const QDomElement layerTreeCanvasElem = doc->documentElement().firstChildElement( QStringLiteral(
"layer-tree-canvas" ) );
2448 if ( !layerTreeCanvasElem.isNull( ) )
2450 mRootGroup->readLayerOrderFromXml( layerTreeCanvasElem );
2454 if ( QgsProjectVersion( 3, 4, 0 ) > mSaveVersion )
2456 const QStringList requiredLayerIds =
readListEntry( QStringLiteral(
"RequiredLayers" ), QStringLiteral(
"Layers" ) );
2457 for (
const QString &layerId : requiredLayerIds )
2459 if ( QgsMapLayer *layer =
mapLayer( layerId ) )
2464 const QStringList disabledLayerIds =
readListEntry( QStringLiteral(
"Identify" ), QStringLiteral(
"/disabledLayers" ) );
2465 for (
const QString &layerId : disabledLayerIds )
2467 if ( QgsMapLayer *layer =
mapLayer( layerId ) )
2475 if ( QgsProjectVersion( 3, 26, 0 ) > mSaveVersion )
2478 QString styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
2479 if ( !styleName.isEmpty() )
2484 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
2485 if ( !styleName.isEmpty() )
2490 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
2491 if ( !styleName.isEmpty() )
2496 styleName =
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
2497 if ( !styleName.isEmpty() )
2507 double opacity = 1.0;
2510 double alpha =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ), 255, &ok );
2512 opacity = alpha / 255.0;
2513 double newOpacity =
readDoubleEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ), 1.0, &ok );
2515 opacity = newOpacity;
2519 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Marker" ) );
2520 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Line" ) );
2521 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Fill" ) );
2522 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ) );
2523 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/RandomColors" ) );
2524 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/AlphaInt" ) );
2525 removeEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/Opacity" ) );
2533 profile.switchTask( tr(
"Storing original layer properties" ) );
2537 mRootGroup->removeCustomProperty( QStringLiteral(
"loading" ) );
2539 profile.switchTask( tr(
"Loading map themes" ) );
2540 mMapThemeCollection = std::make_unique< QgsMapThemeCollection >(
this );
2542 mMapThemeCollection->readXml( *doc );
2544 profile.switchTask( tr(
"Loading label settings" ) );
2545 mLabelingEngineSettings->readSettingsFromProject(
this );
2547 const QDomElement labelEngineSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"labelEngineSettings" ) );
2548 mLabelingEngineSettings->readXml( labelEngineSettingsElement, context );
2550 mLabelingEngineSettings->resolveReferences(
this );
2554 profile.switchTask( tr(
"Loading annotations" ) );
2557 mAnnotationManager->readXml( doc->documentElement(), context );
2561 mAnnotationManager->readXmlAndUpgradeToAnnotationLayerItems( doc->documentElement(), context, mMainAnnotationLayer, mTransformContext );
2565 profile.switchTask( tr(
"Loading layouts" ) );
2566 mLayoutManager->readXml( doc->documentElement(), *doc );
2570 profile.switchTask( tr(
"Loading elevation profiles" ) );
2571 mElevationProfileManager->readXml( doc->documentElement(), *doc, context );
2572 mElevationProfileManager->resolveReferences(
this );
2577 profile.switchTask( tr(
"Loading 3D Views" ) );
2578 m3DViewsManager->readXml( doc->documentElement(), *doc );
2581 profile.switchTask( tr(
"Loading bookmarks" ) );
2582 mBookmarkManager->readXml( doc->documentElement(), *doc );
2584 profile.switchTask( tr(
"Loading sensors" ) );
2585 mSensorManager->readXml( doc->documentElement(), *doc );
2588 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2589 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); ++it )
2591 it.value()->setDependencies( it.value()->dependencies() );
2594 profile.switchTask( tr(
"Loading snapping settings" ) );
2595 mSnappingConfig.readProject( *doc );
2598 profile.switchTask( tr(
"Loading view settings" ) );
2600 mViewSettings->setUseProjectScales(
readBoolEntry( QStringLiteral(
"Scales" ), QStringLiteral(
"/useProjectScales" ) ) );
2601 const QStringList scales =
readListEntry( QStringLiteral(
"Scales" ), QStringLiteral(
"/ScalesList" ) );
2602 QVector<double> res;
2603 for (
const QString &scale : scales )
2605 const QStringList parts = scale.split(
':' );
2606 if ( parts.size() != 2 )
2610 const double denominator = QLocale().toDouble( parts[1], &ok );
2616 mViewSettings->setMapScales( res );
2617 const QDomElement viewSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectViewSettings" ) );
2618 if ( !viewSettingsElement.isNull() )
2619 mViewSettings->readXml( viewSettingsElement, context );
2622 profile.switchTask( tr(
"Loading style properties" ) );
2623 const QDomElement styleSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectStyleSettings" ) );
2624 if ( !styleSettingsElement.isNull() )
2626 mStyleSettings->removeProjectStyle();
2627 mStyleSettings->readXml( styleSettingsElement, context,
flags );
2631 profile.switchTask( tr(
"Loading temporal settings" ) );
2632 const QDomElement timeSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectTimeSettings" ) );
2633 if ( !timeSettingsElement.isNull() )
2634 mTimeSettings->readXml( timeSettingsElement, context );
2637 profile.switchTask( tr(
"Loading elevation properties" ) );
2638 const QDomElement elevationPropertiesElement = doc->documentElement().firstChildElement( QStringLiteral(
"ElevationProperties" ) );
2639 if ( !elevationPropertiesElement.isNull() )
2640 mElevationProperties->readXml( elevationPropertiesElement, context );
2641 mElevationProperties->resolveReferences(
this );
2643 profile.switchTask( tr(
"Loading display settings" ) );
2645 const QDomElement displaySettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectDisplaySettings" ) );
2646 if ( !displaySettingsElement.isNull() )
2647 mDisplaySettings->readXml( displaySettingsElement, context );
2650 profile.switchTask( tr(
"Loading GPS settings" ) );
2652 const QDomElement gpsSettingsElement = doc->documentElement().firstChildElement( QStringLiteral(
"ProjectGpsSettings" ) );
2653 if ( !gpsSettingsElement.isNull() )
2654 mGpsSettings->readXml( gpsSettingsElement, context );
2655 mGpsSettings->resolveReferences(
this );
2658 profile.switchTask( tr(
"Updating variables" ) );
2660 profile.switchTask( tr(
"Updating CRS" ) );
2664 if ( mCrs3D != oldCrs3D )
2669 profile.switchTask( tr(
"Reading external settings" ) );
2673 profile.switchTask( tr(
"Updating interface" ) );
2675 snapSignalBlock.release();
2676 if ( !mBlockSnappingUpdates )
2687 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUser ), 2 );
2688 QgsDebugMsgLevel( QStringLiteral(
"Project save user: %1" ).arg( mSaveUserFull ), 2 );
2697 const QString newFileName( QStringLiteral(
"%1/%2.qgs" ).arg( QFileInfo( mFile ).
absolutePath(), localeFileName ) );
2711 const QMap<QString, QgsMapLayer *> loadedLayers =
mapLayers();
2712 for (
auto it = loadedLayers.constBegin(); it != loadedLayers.constEnd(); ++it )
2714 if ( it.value()->isValid() && it.value()->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
2716 if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( it.value() ) )
2718 it.value()->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
2730 const auto constChildren = group->
children();
2731 for ( QgsLayerTreeNode *child : constChildren )
2736 if ( childGroup->
customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2739 const QString projectPath =
readPath( childGroup->
customProperty( QStringLiteral(
"embedded_project" ) ).toString() );
2740 childGroup->
setCustomProperty( QStringLiteral(
"embedded_project" ), projectPath );
2744 QList<QgsLayerTreeNode *> clonedChildren;
2745 const QList<QgsLayerTreeNode *> constChildren = newGroup->children();
2746 clonedChildren.reserve( constChildren.size() );
2747 for ( QgsLayerTreeNode *newGroupChild : constChildren )
2748 clonedChildren << newGroupChild->clone();
2755 loadEmbeddedNodes( childGroup,
flags );
2760 if ( child->customProperty( QStringLiteral(
"embedded" ) ).toInt() )
2762 QList<QDomNode> brokenNodes;
2765 valid = valid &&
false;
2780 return mCustomVariables;
2787 if ( variables == mCustomVariables )
2791 QStringList variableNames;
2792 QStringList variableValues;
2794 QVariantMap::const_iterator it = variables.constBegin();
2795 for ( ; it != variables.constEnd(); ++it )
2797 variableNames << it.key();
2798 variableValues << it.value().toString();
2801 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableNames" ), variableNames );
2802 writeEntry( QStringLiteral(
"Variables" ), QStringLiteral(
"/variableValues" ), variableValues );
2804 mCustomVariables = variables;
2805 mProjectScope.reset();
2814 *mLabelingEngineSettings = settings;
2822 return *mLabelingEngineSettings;
2829 mProjectScope.reset();
2830 return mLayerStore.get();
2837 return mLayerStore.get();
2844 QList<QgsVectorLayer *>
layers;
2845 const QStringList layerIds =
readListEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), QStringList() );
2846 const auto constLayerIds = layerIds;
2847 for (
const QString &layerId : constLayerIds )
2860 list.reserve(
layers.size() );
2865 list << layer->id();
2868 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsList" ), list );
2890 if ( mProjectScope )
2892 auto projectScope = std::make_unique< QgsExpressionContextScope >( *mProjectScope );
2899 projectScope->addFunction( QStringLiteral(
"sensor_data" ),
new GetSensorData(
sensorManager()->sensorsData() ) );
2901 return projectScope.release();
2904 mProjectScope = std::make_unique< QgsExpressionContextScope >( QObject::tr(
"Project" ) );
2908 QVariantMap::const_iterator it = vars.constBegin();
2910 for ( ; it != vars.constEnd(); ++it )
2912 mProjectScope->setVariable( it.key(), it.value(),
true );
2916 if ( projectPath.isEmpty() )
2917 projectPath = mOriginalPath;
2918 const QString projectFolder = QFileInfo( projectPath ).path();
2919 const QString projectFilename = QFileInfo( projectPath ).fileName();
2920 const QString projectBasename =
baseName();
2957 QVariantMap keywords;
2959 for (
auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
2961 keywords.insert( it.key(), it.value() );
2966 QVariantList layersIds;
2968 const QMap<QString, QgsMapLayer *> layersInProject = mLayerStore->mapLayers();
2969 layersIds.reserve( layersInProject.count() );
2970 layers.reserve( layersInProject.count() );
2971 for (
auto it = layersInProject.constBegin(); it != layersInProject.constEnd(); ++it )
2973 layersIds << it.value()->id();
2979 mProjectScope->addFunction( QStringLiteral(
"project_color" ),
new GetNamedProjectColor(
this ) );
2980 mProjectScope->addFunction( QStringLiteral(
"project_color_object" ),
new GetNamedProjectColorObject(
this ) );
2985void QgsProject::onMapLayersAdded(
const QList<QgsMapLayer *> &layers )
2989 const QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2991 const auto constLayers =
layers;
2994 if ( ! layer->isValid() )
2997 if (
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer ) )
3000 if ( vlayer->dataProvider() )
3008 for ( QMap<QString, QgsMapLayer *>::const_iterator it = existingMaps.cbegin(); it != existingMaps.cend(); ++it )
3010 const QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
3011 if ( deps.contains( layer->id() ) )
3014 it.value()->setDependencies( deps );
3019 updateTransactionGroups();
3021 if ( !mBlockSnappingUpdates && mSnappingConfig.addLayers(
layers ) )
3025void QgsProject::onMapLayersRemoved(
const QList<QgsMapLayer *> &layers )
3029 if ( !mBlockSnappingUpdates && mSnappingConfig.removeLayers(
layers ) )
3032 for ( QgsMapLayer *layer :
layers )
3034 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
3038 mEditBufferGroup.removeLayer( vlayer );
3042void QgsProject::cleanTransactionGroups(
bool force )
3046 bool changed =
false;
3047 for ( QMap< QPair< QString, QString>, QgsTransactionGroup *>::Iterator tg = mTransactionGroups.begin(); tg != mTransactionGroups.end(); )
3049 if ( tg.value()->isEmpty() || force )
3052 tg = mTransactionGroups.erase( tg );
3064void QgsProject::updateTransactionGroups()
3068 mEditBufferGroup.clear();
3070 switch ( mTransactionMode )
3074 cleanTransactionGroups(
true );
3079 cleanTransactionGroups(
true );
3082 cleanTransactionGroups(
false );
3086 bool tgChanged =
false;
3087 const auto constLayers =
mapLayers().values();
3088 for ( QgsMapLayer *layer : constLayers )
3090 if ( ! layer->isValid() )
3093 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
3097 switch ( mTransactionMode )
3109 QgsTransactionGroup *tg = mTransactionGroups.value( qMakePair( key, connString ) );
3113 tg =
new QgsTransactionGroup();
3114 mTransactionGroups.insert( qMakePair( key, connString ), tg );
3124 mEditBufferGroup.addLayer( vlayer );
3140 context.setProjectTranslator(
this );
3142 QList<QDomNode> brokenNodes;
3143 if ( addLayer( layerNode.toElement(), brokenNodes, context ) )
3151 layer->resolveReferences(
this );
3153 if ( layer->isValid() && layer->customProperty( QStringLiteral(
"_layer_was_editable" ) ).toBool() )
3155 layer->startEditing();
3156 layer->removeCustomProperty( QStringLiteral(
"_layer_was_editable" ) );
3168 mFile.setFileName( filename );
3170 mCachedHomePath.clear();
3178 mProjectScope.reset();
3184 const QString storageFilePath { storage->filePath( mFile.fileName() ) };
3185 if ( storageFilePath.isEmpty() )
3191 const QString tempPath = QStandardPaths::standardLocations( QStandardPaths::TempLocation ).at( 0 );
3192 const QString tmpZipFilename( tempPath + QDir::separator() + QUuid::createUuid().toString() );
3194 if ( !zip( tmpZipFilename ) )
3197 QFile tmpZipFile( tmpZipFilename );
3198 if ( !tmpZipFile.open( QIODevice::ReadOnly ) )
3200 setError( tr(
"Unable to read file %1" ).arg( tmpZipFilename ) );
3205 if ( !storage->writeProject( mFile.fileName(), &tmpZipFile, context ) )
3207 QString err = tr(
"Unable to save project to storage %1" ).arg( mFile.fileName() );
3208 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
3209 if ( !messages.isEmpty() )
3210 err += QStringLiteral(
"\n\n" ) + messages.last().message();
3216 QFile::remove( tmpZipFilename );
3223 return zip( mFile.fileName() );
3229 const bool asOk = saveAuxiliaryStorage();
3230 const bool writeOk = writeProjectFile( mFile.fileName() );
3231 bool attachmentsOk =
true;
3232 if ( !mArchive->files().isEmpty() )
3234 const QFileInfo finfo( mFile.fileName() );
3235 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( QStringLiteral(
"%1_attachments.zip" ).arg( finfo.completeBaseName() ) );
3236 attachmentsOk = mArchive->zip( attachmentsZip );
3240 if ( ( !asOk || !attachmentsOk ) && writeOk )
3242 QStringList errorMessage;
3245 const QString err = mAuxiliaryStorage->errorString();
3246 errorMessage.append( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
3248 if ( !attachmentsOk )
3250 errorMessage.append( tr(
"Unable to save attachments archive" ) );
3252 setError( errorMessage.join(
'\n' ) );
3255 return asOk && writeOk && attachmentsOk;
3259bool QgsProject::writeProjectFile(
const QString &filename )
3263 QFile projectFile( filename );
3269 const QFileInfo myFileInfo( projectFile );
3270 if ( myFileInfo.exists() && !myFileInfo.isWritable() )
3272 setError( tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." )
3273 .arg( projectFile.fileName() ) );
3277 QgsReadWriteContext context;
3281 QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
3283 const QDomDocumentType documentType =
3284 QDomImplementation().createDocumentType( QStringLiteral(
"qgis" ), QStringLiteral(
"http://mrcc.com/qgis.dtd" ),
3285 QStringLiteral(
"SYSTEM" ) );
3286 auto doc = std::make_unique<QDomDocument>( documentType );
3288 QDomElement qgisNode = doc->createElement( QStringLiteral(
"qgis" ) );
3289 qgisNode.setAttribute( QStringLiteral(
"projectname" ),
title() );
3290 qgisNode.setAttribute( QStringLiteral(
"version" ),
Qgis::version() );
3292 if ( !mSettings.value( QStringLiteral(
"projects/anonymize_saved_projects" ),
false,
QgsSettings::Core ).toBool() )
3296 qgisNode.setAttribute( QStringLiteral(
"saveUser" ), newSaveUser );
3297 qgisNode.setAttribute( QStringLiteral(
"saveUserFull" ), newSaveUserFull );
3298 mSaveUser = newSaveUser;
3299 mSaveUserFull = newSaveUserFull;
3300 if ( mMetadata.author().isEmpty() )
3304 if ( !mMetadata.creationDateTime().isValid() )
3306 mMetadata.setCreationDateTime( QDateTime( QDateTime::currentDateTime() ) );
3308 mSaveDateTime = QDateTime::currentDateTime();
3309 qgisNode.setAttribute( QStringLiteral(
"saveDateTime" ), mSaveDateTime.toString( Qt::ISODate ) );
3314 mSaveUserFull.clear();
3315 mMetadata.setAuthor( QString() );
3316 mMetadata.setCreationDateTime( QDateTime() );
3317 mSaveDateTime = QDateTime();
3319 doc->appendChild( qgisNode );
3322 QDomElement homePathNode = doc->createElement( QStringLiteral(
"homePath" ) );
3323 homePathNode.setAttribute( QStringLiteral(
"path" ), mHomePath );
3324 qgisNode.appendChild( homePathNode );
3327 QDomElement titleNode = doc->createElement( QStringLiteral(
"title" ) );
3328 qgisNode.appendChild( titleNode );
3330 QDomElement transactionNode = doc->createElement( QStringLiteral(
"transaction" ) );
3331 transactionNode.setAttribute( QStringLiteral(
"mode" ),
qgsEnumValueToKey( mTransactionMode ) );
3332 qgisNode.appendChild( transactionNode );
3334 QDomElement flagsNode = doc->createElement( QStringLiteral(
"projectFlags" ) );
3336 qgisNode.appendChild( flagsNode );
3338 const QDomText titleText = doc->createTextNode(
title() );
3339 titleNode.appendChild( titleText );
3343 QDomElement srsNode = doc->createElement( QStringLiteral(
"projectCrs" ) );
3344 mCrs.writeXml( srsNode, *doc );
3345 qgisNode.appendChild( srsNode );
3348 QDomElement verticalSrsNode = doc->createElement( QStringLiteral(
"verticalCrs" ) );
3349 mVerticalCrs.writeXml( verticalSrsNode, *doc );
3350 qgisNode.appendChild( verticalSrsNode );
3353 QDomElement elevationShadingNode = doc->createElement( QStringLiteral(
"elevation-shading-renderer" ) );
3354 mElevationShadingRenderer.writeXml( elevationShadingNode, context );
3355 qgisNode.appendChild( elevationShadingNode );
3358 std::unique_ptr< QgsLayerTreeNode > clonedRoot( mRootGroup->clone() );
3362 clonedRoot->writeXml( qgisNode, context );
3365 mSnappingConfig.writeProject( *doc );
3366 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/AvoidIntersectionsMode" ),
static_cast<int>( mAvoidIntersectionsMode ) );
3374 QDomElement annotationLayerNode = doc->createElement( QStringLiteral(
"main-annotation-layer" ) );
3375 mMainAnnotationLayer->writeLayerXml( annotationLayerNode, *doc, context );
3376 qgisNode.appendChild( annotationLayerNode );
3380 QDomElement projectLayersNode = doc->createElement( QStringLiteral(
"projectlayers" ) );
3382 QMap<QString, QgsMapLayer *>::ConstIterator li =
layers.constBegin();
3383 while ( li !=
layers.end() )
3385 QgsMapLayer *ml = li.value();
3389 const QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.constFind( ml->
id() );
3390 if ( emIt == mEmbeddedLayers.constEnd() )
3392 QDomElement maplayerElem;
3398 maplayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
3402 maplayerElem.setAttribute( QStringLiteral(
"editable" ), QStringLiteral(
"1" ) );
3406 QDomDocument document;
3409 maplayerElem = document.firstChildElement();
3413 QgsDebugError( QStringLiteral(
"Could not restore layer properties for layer %1" ).arg( ml->
id() ) );
3419 projectLayersNode.appendChild( maplayerElem );
3425 if ( emIt.value().second )
3427 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"maplayer" ) );
3428 mapLayerElem.setAttribute( QStringLiteral(
"embedded" ), 1 );
3429 mapLayerElem.setAttribute( QStringLiteral(
"project" ),
writePath( emIt.value().first ) );
3430 mapLayerElem.setAttribute( QStringLiteral(
"id" ), ml->
id() );
3431 projectLayersNode.appendChild( mapLayerElem );
3438 qgisNode.appendChild( projectLayersNode );
3440 QDomElement layerOrderNode = doc->createElement( QStringLiteral(
"layerorder" ) );
3441 const auto constCustomLayerOrder = mRootGroup->customLayerOrder();
3442 for ( QgsMapLayer *layer : constCustomLayerOrder )
3444 QDomElement mapLayerElem = doc->createElement( QStringLiteral(
"layer" ) );
3445 mapLayerElem.setAttribute( QStringLiteral(
"id" ), layer->id() );
3446 layerOrderNode.appendChild( mapLayerElem );
3448 qgisNode.appendChild( layerOrderNode );
3450 mLabelingEngineSettings->writeSettingsToProject(
this );
3452 QDomElement labelEngineSettingsElement = doc->createElement( QStringLiteral(
"labelEngineSettings" ) );
3453 mLabelingEngineSettings->writeXml( *doc, labelEngineSettingsElement, context );
3454 qgisNode.appendChild( labelEngineSettingsElement );
3457 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorRedPart" ), mBackgroundColor.red() );
3458 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorGreenPart" ), mBackgroundColor.green() );
3459 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/CanvasColorBluePart" ), mBackgroundColor.blue() );
3461 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorRedPart" ), mSelectionColor.red() );
3462 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorGreenPart" ), mSelectionColor.green() );
3463 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorBluePart" ), mSelectionColor.blue() );
3464 writeEntry( QStringLiteral(
"Gui" ), QStringLiteral(
"/SelectionColorAlphaPart" ), mSelectionColor.alpha() );
3472 dump_( mProperties );
3475 QgsDebugMsgLevel( QStringLiteral(
"there are %1 property scopes" ).arg(
static_cast<int>( mProperties.count() ) ), 2 );
3477 if ( !mProperties.isEmpty() )
3480 mProperties.writeXml( QStringLiteral(
"properties" ), qgisNode, *doc );
3483 QDomElement ddElem = doc->createElement( QStringLiteral(
"dataDefinedServerProperties" ) );
3484 mDataDefinedServerProperties.writeXml( ddElem, dataDefinedServerPropertyDefinitions() );
3485 qgisNode.appendChild( ddElem );
3487 mMapThemeCollection->writeXml( *doc );
3489 mTransformContext.writeXml( qgisNode, context );
3491 QDomElement metadataElem = doc->createElement( QStringLiteral(
"projectMetadata" ) );
3492 mMetadata.writeMetadataXml( metadataElem, *doc );
3493 qgisNode.appendChild( metadataElem );
3496 const QDomElement annotationsElem = mAnnotationManager->writeXml( *doc, context );
3497 qgisNode.appendChild( annotationsElem );
3501 const QDomElement layoutElem = mLayoutManager->writeXml( *doc );
3502 qgisNode.appendChild( layoutElem );
3506 const QDomElement elevationProfileElem = mElevationProfileManager->writeXml( *doc, context );
3507 qgisNode.appendChild( elevationProfileElem );
3511 const QDomElement views3DElem = m3DViewsManager->writeXml( *doc );
3512 qgisNode.appendChild( views3DElem );
3516 const QDomElement bookmarkElem = mBookmarkManager->writeXml( *doc );
3517 qgisNode.appendChild( bookmarkElem );
3521 const QDomElement sensorElem = mSensorManager->writeXml( *doc );
3522 qgisNode.appendChild( sensorElem );
3526 const QDomElement viewSettingsElem = mViewSettings->writeXml( *doc, context );
3527 qgisNode.appendChild( viewSettingsElem );
3531 const QDomElement styleSettingsElem = mStyleSettings->writeXml( *doc, context );
3532 qgisNode.appendChild( styleSettingsElem );
3536 const QDomElement timeSettingsElement = mTimeSettings->writeXml( *doc, context );
3537 qgisNode.appendChild( timeSettingsElement );
3541 const QDomElement elevationPropertiesElement = mElevationProperties->writeXml( *doc, context );
3542 qgisNode.appendChild( elevationPropertiesElement );
3546 const QDomElement displaySettingsElem = mDisplaySettings->writeXml( *doc, context );
3547 qgisNode.appendChild( displaySettingsElem );
3551 const QDomElement gpsSettingsElem = mGpsSettings->writeXml( *doc, context );
3552 qgisNode.appendChild( gpsSettingsElem );
3561 QFile backupFile( QStringLiteral(
"%1~" ).arg( filename ) );
3563 ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
3564 ok &= projectFile.open( QIODevice::ReadOnly );
3567 while ( ok && !projectFile.atEnd() )
3569 ba = projectFile.read( 10240 );
3570 ok &= backupFile.write( ba ) == ba.size();
3573 projectFile.close();
3578 setError( tr(
"Unable to create backup file %1" ).arg( backupFile.fileName() ) );
3583 struct utimbuf tb = {
static_cast<time_t
>( fi.lastRead().toSecsSinceEpoch() ),
static_cast<time_t
>( fi.lastModified().toSecsSinceEpoch() ) };
3584 utime( backupFile.fileName().toUtf8().constData(), &tb );
3587 if ( !projectFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3589 projectFile.close();
3592 setError( tr(
"Unable to save to file %1" ).arg( projectFile.fileName() ) );
3596 QTemporaryFile tempFile;
3597 bool ok = tempFile.open();
3600 QTextStream projectFileStream( &tempFile );
3601 doc->save( projectFileStream, 2 );
3602 ok &= projectFileStream.pos() > -1;
3604 ok &= tempFile.seek( 0 );
3607 while ( ok && !tempFile.atEnd() )
3609 ba = tempFile.read( 10240 );
3610 ok &= projectFile.write( ba ) == ba.size();
3613 ok &= projectFile.error() == QFile::NoError;
3615 projectFile.close();
3622 setError( tr(
"Unable to save to file %1. Your project "
3623 "may be corrupted on disk. Try clearing some space on the volume and "
3624 "check file permissions before pressing save again." )
3625 .arg( projectFile.fileName() ) );
3639 bool propertiesModified;
3640 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3642 if ( propertiesModified )
3652 bool propertiesModified;
3653 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3655 if ( propertiesModified )
3665 bool propertiesModified;
3666 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3668 if ( propertiesModified )
3678 bool propertiesModified;
3679 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3681 if ( propertiesModified )
3691 bool propertiesModified;
3692 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3694 if ( propertiesModified )
3702 const QStringList &def,
3714 value =
property->value();
3716 const bool valid = QMetaType::Type::QStringList == value.userType();
3722 return value.toStringList();
3745 value =
property->value();
3747 const bool valid = value.canConvert( QMetaType::Type::QString );
3752 return value.toString();
3771 value =
property->value();
3774 const bool valid = value.canConvert( QMetaType::Type::Int );
3783 return value.toInt();
3798 const QVariant value =
property->value();
3800 const bool valid = value.canConvert( QMetaType::Type::Double );
3805 return value.toDouble();
3822 const QVariant value =
property->value();
3824 const bool valid = value.canConvert( QMetaType::Type::Bool );
3829 return value.toBool();
3841 if (
findKey_( scope, key, mProperties ) )
3847 return !
findKey_( scope, key, mProperties );
3856 QStringList entries;
3858 if ( foundProperty )
3875 QStringList entries;
3877 if ( foundProperty )
3892 dump_( mProperties );
3912 filePath = storage->filePath( mFile.fileName() );
3939void QgsProject::setError(
const QString &errorMessage )
3943 mErrorMessage = errorMessage;
3950 return mErrorMessage;
3953void QgsProject::clearError()
3957 setError( QString() );
3964 mBadLayerHandler.reset( handler );
3971 const QHash< QString, QPair< QString, bool > >::const_iterator it = mEmbeddedLayers.find(
id );
3972 if ( it == mEmbeddedLayers.constEnd() )
3976 return it.value().first;
3986 static QString sPrevProjectFilePath;
3987 static QDateTime sPrevProjectFileTimestamp;
3988 static QDomDocument sProjectDocument;
3990 QString qgsProjectFile = projectFilePath;
3992 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
3994 archive.
unzip( projectFilePath );
3998 const QDateTime projectFileTimestamp = QFileInfo( projectFilePath ).lastModified();
4000 if ( projectFilePath != sPrevProjectFilePath || projectFileTimestamp != sPrevProjectFileTimestamp )
4002 sPrevProjectFilePath.clear();
4004 QFile projectFile( qgsProjectFile );
4005 if ( !projectFile.open( QIODevice::ReadOnly ) )
4010 if ( !sProjectDocument.setContent( &projectFile ) )
4015 sPrevProjectFilePath = projectFilePath;
4016 sPrevProjectFileTimestamp = projectFileTimestamp;
4020 bool useAbsolutePaths =
true;
4022 const QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"properties" ) );
4023 if ( !propertiesElem.isNull() )
4025 QDomElement e = propertiesElem.firstChildElement( QStringLiteral(
"Paths" ) );
4028 e = propertiesElem.firstChildElement( QStringLiteral(
"properties" ) );
4029 while ( !e.isNull() && e.attribute( QStringLiteral(
"name" ) ) != QLatin1String(
"Paths" ) )
4030 e = e.nextSiblingElement( QStringLiteral(
"properties" ) );
4032 e = e.firstChildElement( QStringLiteral(
"properties" ) );
4033 while ( !e.isNull() && e.attribute( QStringLiteral(
"name" ) ) != QLatin1String(
"Absolute" ) )
4034 e = e.nextSiblingElement( QStringLiteral(
"properties" ) );
4038 e = e.firstChildElement( QStringLiteral(
"Absolute" ) );
4043 useAbsolutePaths = e.text().compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0;
4048 if ( !useAbsolutePaths )
4053 const QDomElement projectLayersElem = sProjectDocument.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) );
4054 if ( projectLayersElem.isNull() )
4059 QDomElement mapLayerElem = projectLayersElem.firstChildElement( QStringLiteral(
"maplayer" ) );
4060 while ( ! mapLayerElem.isNull() )
4063 const QString
id = mapLayerElem.firstChildElement( QStringLiteral(
"id" ) ).text();
4064 if (
id == layerId )
4067 if ( mapLayerElem.attribute( QStringLiteral(
"embedded" ) ) == QLatin1String(
"1" ) )
4072 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
4074 if ( addLayer( mapLayerElem, brokenNodes, embeddedContext,
flags ) )
4080 mEmbeddedLayers.remove( layerId );
4084 mapLayerElem = mapLayerElem.nextSiblingElement( QStringLiteral(
"maplayer" ) );
4094 QString qgsProjectFile = projectFilePath;
4096 if ( projectFilePath.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
4098 archive.
unzip( projectFilePath );
4103 QFile projectFile( qgsProjectFile );
4104 if ( !projectFile.open( QIODevice::ReadOnly ) )
4109 QDomDocument projectDocument;
4110 if ( !projectDocument.setContent( &projectFile ) )
4120 auto root = std::make_unique< QgsLayerTreeGroup >();
4122 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
4123 if ( !layerTreeElem.isNull() )
4125 root->readChildrenFromXml( layerTreeElem, context );
4133 if ( !group || group->
customProperty( QStringLiteral(
"embedded" ) ).toBool() )
4143 newGroup->setCustomProperty( QStringLiteral(
"embedded" ), 1 );
4144 newGroup->setCustomProperty( QStringLiteral(
"embedded_project" ), projectFilePath );
4147 mLayerTreeRegistryBridge->setEnabled(
false );
4148 initializeEmbeddedSubtree( projectFilePath, newGroup.get(),
flags );
4149 mLayerTreeRegistryBridge->setEnabled(
true );
4152 const QStringList constFindLayerIds = newGroup->findLayerIds();
4153 for (
const QString &layerId : constFindLayerIds )
4170 const auto constChildren = group->
children();
4174 child->setCustomProperty( QStringLiteral(
"embedded" ), 1 );
4183 QList<QDomNode> brokenNodes;
4207 writeEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), ( enabled ? 1 : 0 ) );
4215 return readNumEntry( QStringLiteral(
"Digitizing" ), QStringLiteral(
"/TopologicalEditing" ), 0 );
4222 if ( mDistanceUnits == unit )
4225 mDistanceUnits = unit;
4234 if ( mAreaUnits == unit )
4246 if ( mScaleMethod == method )
4249 mScaleMethod = method;
4259 if ( !mCachedHomePath.isEmpty() )
4260 return mCachedHomePath;
4264 if ( !mHomePath.isEmpty() )
4266 const QFileInfo homeInfo( mHomePath );
4267 if ( !homeInfo.isRelative() )
4269 mCachedHomePath = mHomePath;
4279 const QString storagePath { storage->filePath(
fileName() ) };
4280 if ( ! storagePath.isEmpty() && QFileInfo::exists( storagePath ) )
4282 mCachedHomePath = QFileInfo( storagePath ).path();
4283 return mCachedHomePath;
4287 mCachedHomePath = pfi.path();
4288 return mCachedHomePath;
4291 if ( !pfi.exists() )
4293 mCachedHomePath = mHomePath;
4297 if ( !mHomePath.isEmpty() )
4300 mCachedHomePath = QDir::cleanPath( pfi.path() +
'/' + mHomePath );
4304 mCachedHomePath = pfi.canonicalPath();
4306 return mCachedHomePath;
4321 return mRelationManager.get();
4328 return mLayoutManager.get();
4335 return mLayoutManager.get();
4342 return mElevationProfileManager.get();
4349 return mElevationProfileManager.get();
4356 return m3DViewsManager.get();
4363 return m3DViewsManager.get();
4370 return mBookmarkManager;
4377 return mBookmarkManager;
4384 return mSensorManager;
4391 return mSensorManager;
4398 return mViewSettings;
4405 return mViewSettings;
4412 return mStyleSettings;
4420 return mStyleSettings;
4427 return mTimeSettings;
4434 return mTimeSettings;
4441 return mElevationProperties;
4448 return mElevationProperties;
4455 return mDisplaySettings;
4462 return mDisplaySettings;
4469 return mGpsSettings;
4476 return mGpsSettings;
4483 return mRootGroup.get();
4490 return mMapThemeCollection.get();
4497 return mAnnotationManager.get();
4504 return mAnnotationManager.get();
4511 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
4512 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
4517 if (
layers.contains( it.value() ) )
4534 for (
const QString &layerId : layerIds )
4552 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4586 updateTransactionGroups();
4593 return mTransactionMode;
4604 const auto constLayers =
mapLayers().values();
4607 if ( layer->isEditable() )
4609 QgsLogger::warning( tr(
"Transaction mode can be changed only if all layers are not editable." ) );
4615 updateTransactionGroups();
4624 return mTransactionGroups;
4637 return mLayerStore->count();
4644 return mLayerStore->validCount();
4652 if ( mMainAnnotationLayer && layerId == mMainAnnotationLayer->id() )
4653 return mMainAnnotationLayer;
4655 return mLayerStore->mapLayer( layerId );
4662 return mLayerStore->mapLayersByName( layerName );
4669 QList<QgsMapLayer *>
layers;
4670 const auto constMapLayers { mLayerStore->mapLayers() };
4671 for (
const auto &l : constMapLayers )
4673 if ( ! l->serverProperties()->shortName().isEmpty() )
4675 if ( l->serverProperties()->shortName() == shortName )
4678 else if ( l->name() == shortName )
4691 auto archive = std::make_unique<QgsProjectArchive>();
4694 if ( !archive->unzip( filename ) )
4696 setError( tr(
"Unable to unzip file '%1'" ).arg( filename ) );
4701 if ( archive->projectFile().isEmpty() )
4703 setError( tr(
"Zip archive does not provide a project file" ) );
4708 releaseHandlesToProjectArchive();
4709 mArchive = std::move( archive );
4712 if ( !
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile().isEmpty() )
4716 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >(
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile(),
false );
4720 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >( *
this );
4724 if ( ! readProjectFile(
static_cast<QgsProjectArchive *
>( mArchive.get() )->projectFile(),
flags ) )
4726 setError( tr(
"Cannot read unzipped qgs project file" ) + QStringLiteral(
": " ) +
error() );
4731 static_cast<QgsProjectArchive *
>( mArchive.get() )->clearProjectFile();
4736bool QgsProject::zip(
const QString &filename )
4743 auto archive = std::make_unique<QgsProjectArchive>();
4744 const QString
baseName = QFileInfo( filename ).baseName();
4745 const QString qgsFileName = QStringLiteral(
"%1.qgs" ).arg(
baseName );
4746 QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
4748 bool writeOk =
false;
4749 if ( qgsFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
4751 writeOk = writeProjectFile( qgsFile.fileName() );
4758 setError( tr(
"Unable to write temporary qgs file" ) );
4763 const QFileInfo info( qgsFile );
4765 const QString asFileName = info.path() + QDir::separator() + info.completeBaseName() + asExt;
4767 bool auxiliaryStorageSavedOk =
true;
4768 if ( ! saveAuxiliaryStorage( asFileName ) )
4770 const QString err = mAuxiliaryStorage->errorString();
4771 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 ) );
4772 auxiliaryStorageSavedOk =
false;
4775 if ( !mArchive->exists() )
4777 releaseHandlesToProjectArchive();
4778 mArchive = std::make_unique< QgsProjectArchive >();
4779 mArchive->unzip( mFile.fileName() );
4780 static_cast<QgsProjectArchive *
>( mArchive.get() )->clearProjectFile();
4782 const QString auxiliaryStorageFile =
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile();
4783 if ( ! auxiliaryStorageFile.isEmpty() )
4785 archive->addFile( auxiliaryStorageFile );
4786 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >( auxiliaryStorageFile,
false );
4794 if ( QFile::exists( asFileName ) )
4796 archive->addFile( asFileName );
4801 archive->addFile( qgsFile.fileName() );
4804 const QStringList &files = mArchive->files();
4805 for (
const QString &file : files )
4807 if ( !file.endsWith( QLatin1String(
".qgs" ), Qt::CaseInsensitive ) && !file.endsWith( asExt, Qt::CaseInsensitive ) )
4809 archive->addFile( file );
4815 if ( !archive->zip( filename ) )
4817 setError( tr(
"Unable to perform zip" ) );
4821 return auxiliaryStorageSavedOk && zipOk;
4832 const QList<QgsMapLayer *> &
layers,
4834 bool takeOwnership )
4838 const QList<QgsMapLayer *> myResultList { mLayerStore->addMapLayers(
layers, takeOwnership ) };
4839 if ( !myResultList.isEmpty() )
4842 for (
auto &l : myResultList )
4852 if ( mAuxiliaryStorage )
4867 mProjectScope.reset();
4869 return myResultList;
4875 bool takeOwnership )
4879 QList<QgsMapLayer *> addedLayers;
4880 addedLayers =
addMapLayers( QList<QgsMapLayer *>() << layer, addToLegend, takeOwnership );
4881 return addedLayers.isEmpty() ? nullptr : addedLayers[0];
4884void QgsProject::removeAuxiliaryLayer(
const QgsMapLayer *ml )
4891 const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( ml );
4903 for (
const auto &layerId : layerIds )
4904 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
4906 mProjectScope.reset();
4907 mLayerStore->removeMapLayers( layerIds );
4914 for (
const auto &layer :
layers )
4915 removeAuxiliaryLayer( layer );
4917 mProjectScope.reset();
4918 mLayerStore->removeMapLayers(
layers );
4925 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
4926 mProjectScope.reset();
4927 mLayerStore->removeMapLayer( layerId );
4934 removeAuxiliaryLayer( layer );
4935 mProjectScope.reset();
4936 mLayerStore->removeMapLayer( layer );
4943 mProjectScope.reset();
4944 return mLayerStore->takeMapLayer( layer );
4951 return mMainAnnotationLayer;
4958 if ( mLayerStore->count() == 0 )
4961 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
4962 mProjectScope.reset();
4963 mLayerStore->removeAllMapLayers();
4965 snapSingleBlocker.release();
4966 mSnappingConfig.clearIndividualLayerSettings();
4967 if ( !mBlockSnappingUpdates )
4975 const QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
4976 QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin();
4977 for ( ; it !=
layers.constEnd(); ++it )
4979 it.value()->reload();
4988 return validOnly ? mLayerStore->validMapLayers() : mLayerStore->mapLayers();
4995 return mTransactionGroups.value( qMakePair( providerKey, connString ) );
5002 return &mEditBufferGroup;
5013 if ( mSettings.value( QStringLiteral(
"/projections/unknownCrsBehavior" ), QStringLiteral(
"NoAction" ),
QgsSettings::App ).toString() == QStringLiteral(
"UseProjectCrs" )
5014 || mSettings.value( QStringLiteral(
"/projections/unknownCrsBehavior" ), 0,
QgsSettings::App ).toString() == QLatin1String(
"2" ) )
5022 const QString layerDefaultCrs = mSettings.value( QStringLiteral(
"/Projections/layerDefaultCrs" ), QStringLiteral(
"EPSG:4326" ) ).toString();
5043bool QgsProject::saveAuxiliaryStorage(
const QString &filename )
5049 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
5054 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
5062 if ( !mAuxiliaryStorage->exists( *
this ) && empty )
5066 else if ( !filename.isEmpty() )
5068 return mAuxiliaryStorage->saveAs( filename );
5072 return mAuxiliaryStorage->saveAs( *
this );
5085 return sPropertyDefinitions;
5098 return mAuxiliaryStorage.get();
5105 return mAuxiliaryStorage.get();
5112 const QDir archiveDir( mArchive->dir() );
5113 QTemporaryFile tmpFile( archiveDir.filePath(
"XXXXXX_" + nameTemplate ),
this );
5114 tmpFile.setAutoRemove(
false );
5115 if ( !tmpFile.open() )
5117 setError( tr(
"Unable to open %1" ).arg( tmpFile.fileName() ) );
5120 mArchive->addFile( tmpFile.fileName() );
5121 return tmpFile.fileName();
5128 QStringList attachments;
5130 const QStringList files = mArchive->files();
5131 attachments.reserve( files.size() );
5132 for (
const QString &file : files )
5136 attachments.append( file );
5146 return mArchive->removeFile( path );
5153 return QStringLiteral(
"attachment:///%1" ).arg( QFileInfo( attachedFile ).
fileName() );
5160 if ( identifier.startsWith( QLatin1String(
"attachment:///" ) ) )
5162 return QDir( mArchive->dir() ).absoluteFilePath( identifier.mid( 14 ) );
5183 mProjectScope.reset();
5198 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
5212 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
5213 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
5218 if (
layers.contains( it.value() ) )
5230 QStringList customColors;
5231 QStringList customColorLabels;
5233 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
5234 for ( ; colorIt != colors.constEnd(); ++colorIt )
5237 const QString label = ( *colorIt ).second;
5238 customColors.append( color );
5239 customColorLabels.append( label );
5241 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ), customColors );
5242 writeEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ), customColorLabels );
5243 mProjectScope.reset();
5251 if ( mBackgroundColor == color )
5254 mBackgroundColor = color;
5262 return mBackgroundColor;
5269 if ( mSelectionColor == color )
5272 mSelectionColor = color;
5280 return mSelectionColor;
5287 mViewSettings->setMapScales( scales );
5294 return mViewSettings->mapScales();
5301 mViewSettings->setUseProjectScales( enabled );
5308 return mViewSettings->useProjectScales();
5317 translationContext.setFileName( QStringLiteral(
"%1/%2.ts" ).arg(
absolutePath(),
baseName() ) );
5321 translationContext.writeTsFile( locale );
5324QString
QgsProject::translate(
const QString &context,
const QString &sourceText,
const char *disambiguation,
int n )
const
5333 QString result = mTranslator->translate( context.toUtf8(), sourceText.toUtf8(), disambiguation, n );
5335 if ( result.isEmpty() )
5349 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
5354 if ( !( ( *it )->accept( visitor ) ) )
5363 if ( !mLayoutManager->accept( visitor ) )
5366 if ( !mAnnotationManager->accept( visitor ) )
5376 const QString macros =
readEntry( QStringLiteral(
"Macros" ), QStringLiteral(
"/pythonCode" ), QString() );
5377 if ( !macros.isEmpty() )
5386 const QString expressionFunctions =
readEntry( QStringLiteral(
"ExpressionFunctions" ), QStringLiteral(
"/pythonCode" ) );
5387 if ( !expressionFunctions.isEmpty() )
5399 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
5401 if ( !( ( *it )->accept( visitor, context ) ) )
5413 return mElevationShadingRenderer;
5416void QgsProject::loadProjectFlags(
const QDomDocument *doc )
5420 QDomElement element = doc->documentElement().firstChildElement( QStringLiteral(
"projectFlags" ) );
5422 if ( !element.isNull() )
5429 element = doc->documentElement().firstChildElement( QStringLiteral(
"evaluateDefaultValues" ) );
5430 if ( !element.isNull() )
5432 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
5437 element = doc->documentElement().firstChildElement( QStringLiteral(
"trust" ) );
5438 if ( !element.isNull() )
5440 if ( element.attribute( QStringLiteral(
"active" ), QStringLiteral(
"0" ) ).toInt() == 1 )
5454 const QString projectFunctions =
readEntry( QStringLiteral(
"ExpressionFunctions" ), QStringLiteral(
"/pythonCode" ), QString() );
5455 if ( !projectFunctions.isEmpty() )
5475QHash< QString, QColor > loadColorsFromProject(
const QgsProject *project )
5477 QHash< QString, QColor > colors;
5480 QStringList colorStrings = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Colors" ) );
5481 const QStringList colorLabels = project->
readListEntry( QStringLiteral(
"Palette" ), QStringLiteral(
"/Labels" ) );
5485 for ( QStringList::iterator it = colorStrings.begin();
5486 it != colorStrings.end(); ++it )
5490 if ( colorLabels.length() > colorIndex )
5492 label = colorLabels.at( colorIndex );
5495 colors.insert( label.toLower(), color );
5503GetNamedProjectColor::GetNamedProjectColor(
const QgsProject *project )
5509 mColors = loadColorsFromProject( project );
5512GetNamedProjectColor::GetNamedProjectColor(
const QHash<QString, QColor> &colors )
5520 const QString colorName = values.at( 0 ).toString().toLower();
5521 if ( mColors.contains( colorName ) )
5523 return QStringLiteral(
"%1,%2,%3" ).arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
5531 return new GetNamedProjectColor( mColors );
5534GetNamedProjectColorObject::GetNamedProjectColorObject(
const QgsProject *project )
5540 mColors = loadColorsFromProject( project );
5543GetNamedProjectColorObject::GetNamedProjectColorObject(
const QHash<QString, QColor> &colors )
5551 const QString colorName = values.at( 0 ).toString().toLower();
5552 if ( mColors.contains( colorName ) )
5554 return mColors.value( colorName );
5562 return new GetNamedProjectColorObject( mColors );
5567GetSensorData::GetSensorData(
const QMap<QString, QgsAbstractSensor::SensorData> &sensorData )
5570 QStringLiteral(
"Sensors" ) )
5571 , mSensorData( sensorData )
5577 const QString sensorName = values.at( 0 ).toString();
5578 const int expiration = values.at( 1 ).toInt();
5579 const qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
5580 if ( mSensorData.contains( sensorName ) )
5582 if ( expiration <= 0 || ( timestamp - mSensorData[sensorName].lastTimestamp.toMSecsSinceEpoch() ) < expiration )
5584 return mSensorData[sensorName].lastValue;
5593 return new GetSensorData( mSensorData );
@ ExpressionFunction
Project macros.
@ DontLoad3DViews
Skip loading 3D views.
@ 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.
@ TrustLayerMetadata
Trust layer metadata. Improves project read time. Do not use it if layers' extent is not fixed during...
@ DontUpgradeAnnotations
Don't upgrade old annotation items to QgsAnnotationItem.
@ 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.
@ Trusted
The project trust has not yet been determined by the user.
QFlags< ProjectCapability > ProjectCapabilities
Flags which control project capabilities.
QFlags< ProjectReadFlag > ProjectReadFlags
Project load flags.
DistanceUnit
Units of distance.
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.
@ SquareMeters
Square meters.
@ Critical
Critical/error message.
@ Success
Used for reporting a successful operation.
@ Compound
Compound (horizontal + vertical) CRS.
@ Projected
Projected CRS.
@ DerivedProjected
Derived projected CRS.
@ Engineering
Engineering CRS.
@ Geographic3d
3D geopraphic CRS
@ Geographic2d
2D geographic CRS
@ Geocentric
Geocentric CRS.
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...
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
LayerType
Types of layers that can be added to a map.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
ScaleCalculationMethod
Scale calculation logic.
@ HorizontalMiddle
Calculate horizontally, across midle of map.
@ SkipCredentialsRequest
Skip credentials if the provided one are not valid, let the provider be invalid, avoiding to block th...
@ ParallelThreadLoading
Provider is created in a parallel thread than the one where it will live.
QFlags< ProjectFlag > ProjectFlags
static QString geoNone()
Constant that holds the string representation for "No ellipse/No CRS".
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
Represents a map layer containing a set of georeferenced annotations, e.g.
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 const QgsSettingsEntryString * settingsLocaleUserLocale
Settings entry locale user locale.
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.
Manages zip/unzip operations for an archive.
A container for attribute editors, used to group them visually in the attribute form if it is set to ...
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
An abstract base class for any elements of a drag and drop form.
QString name() const
Returns the name of this element.
QgsFields auxiliaryFields() const
Returns a list of all auxiliary fields currently managed by the layer.
bool save()
Commits changes and starts editing then.
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.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
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.
static QgsCoordinateReferenceSystem createCompoundCrs(const QgsCoordinateReferenceSystem &horizontalCrs, const QgsCoordinateReferenceSystem &verticalCrs, QString &error)
Given a horizontal and vertical CRS, attempts to create a compound CRS from them.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
QString projectionAcronym() const
Returns the projection acronym for the projection used by the CRS.
static QgsCoordinateReferenceSystem fromProj(const QString &proj)
Creates a CRS from a proj style formatted string.
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
void readSettings()
Reads the context's state from application settings.
Abstract base class for spatial data provider implementations.
@ EvaluateDefaultValues
Evaluate default values on provider side when calling QgsVectorDataProvider::defaultValue( int index ...
Stores the component parts of a data source URI (e.g.
Manages storage of a set of elevation profiles.
Renders elevation shading on an image with different methods (eye dome lighting, hillshading,...
A embedded script entity for QgsObjectEntityVisitorInterface.
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 abstract base class for defining QgsExpression functions.
An expression node for expression functions.
Handles parsing and evaluation of expressions (formerly called "search strings").
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
Stores global configuration for labeling engine.
Layer tree group node serves as a container for layers and further groups.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name.
void readChildrenFromXml(const QDomElement &element, const QgsReadWriteContext &context)
Read children from XML and append them to the group.
QString name() const override
Returns the group's name.
void insertChildNodes(int index, const QList< QgsLayerTreeNode * > &nodes)
Insert existing nodes at specified position.
QgsLayerTreeGroup * clone() const override
Returns a clone of the group.
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).
Base class for nodes in a layer tree.
QList< QgsLayerTreeNode * > abandonChildren()
Removes the children, disconnect all the forwarded and external signals and sets their parent to null...
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.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
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).
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.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
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.
Manages storage of a set of layouts.
static void warning(const QString &msg)
Goes to qWarning.
static Qgis::LayerType 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.
QFlags< ReadFlag > ReadFlags
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void configChanged()
Emitted whenever the configuration is changed.
static Qgis::DataProviderReadFlags providerReadFlags(const QDomNode &layerNode, QgsMapLayer::ReadFlags layerReadFlags)
Returns provider read flag deduced from layer read flags layerReadFlags and a dom node layerNode that...
QString originalXmlProperties() const
Returns the XML properties of the original layer as they were when the layer was first read from the ...
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.
@ 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...
@ FlagReadExtentFromXml
Read extent from xml and skip get extent from provider.
@ 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.
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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
An interface for classes which can visit various object entity (e.g.
virtual bool visitEmbeddedScript(const QgsEmbeddedScriptEntity &entity, const QgsObjectVisitorContext &context)
Called when the visitor will visit an embedded script entity.
A QgsObjectEntityVisitorInterface context object.
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.
Allows managing the zip/unzip actions on project files.
QString projectFile() const
Returns the current .qgs project 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 files.
Contains settings and properties relating to how a QgsProject should display values such as map coord...
Contains elevation properties for a QgsProject.
Contains settings and properties relating to how a QgsProject should interact with a GPS device.
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.
void subkeyList(QStringList &entries) const
Returns any sub-keys contained by this property which themselves contain other keys.
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.
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.
void setDefaultSymbol(Qgis::SymbolType symbolType, QgsSymbol *symbol)
Sets the project default symbol for a given type.
void setRandomizeDefaultSymbolColor(bool randomized)
Sets whether the default symbol fill color is randomized.
void setDefaultColorRamp(QgsColorRamp *colorRamp)
Sets the project default color ramp.
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...
static Qgis::ProjectTrustStatus checkUserTrust(QgsProject *project)
Returns the current trust status of the specified project.
Describes 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,...
void mapScalesChanged()
Emitted when the list of custom project map scales changes.
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 void oldProjectVersionWarning(const QString &warning)
Emitted when an old project file is read.
Q_DECL_DEPRECATED bool evaluateDefaultValues() const
Should default values be evaluated on provider side when requested and not when committed.
Qgis::DistanceUnit distanceUnits
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.
void readProjectWithContext(const QDomDocument &document, QgsReadWriteContext &context)
Emitted when a project is being read.
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.
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.
void titleChanged()
Emitted when the title of the project changes.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
void writeMapLayer(QgsMapLayer *mapLayer, QDomElement &layerElem, QDomDocument &doc)
Emitted when a layer is being saved.
const QgsSensorManager * sensorManager() const
Returns the project's sensor manager, which manages sensors within the project.
void setSnappingConfig(const QgsSnappingConfig &snappingConfig)
The snapping configuration for this 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...
void setScaleMethod(Qgis::ScaleCalculationMethod method)
Sets the method to use for map scale calculations for the project.
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 a string using the Qt QTranslator mechanism.
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
QgsSnappingConfig snappingConfig
const QgsProjectGpsSettings * gpsSettings() const
Returns the project's GPS settings, which contains settings and properties relating to how a QgsProje...
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.
std::unique_ptr< 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.
Q_DECL_DEPRECATED void setAutoTransaction(bool autoTransaction)
Transactional editing means that on supported datasources (postgres databases) the edit state of all ...
@ WMSOnlineResource
Alias.
bool startEditing(QgsVectorLayer *vectorLayer=nullptr)
Makes the layer editable.
void aboutToBeCleared()
Emitted when the project is about to be cleared.
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...
bool setVerticalCrs(const QgsCoordinateReferenceSystem &crs, QString *errorMessage=nullptr)
Sets the project's vertical coordinate reference system.
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets project's global labeling engine settings.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void metadataChanged()
Emitted when the project's metadata is changed.
QString resolveAttachmentIdentifier(const QString &identifier) const
Resolves an attachment identifier to a attachment file path.
const QgsProjectElevationProperties * elevationProperties() const
Returns the project's elevation properties, which contains the project's elevation related settings.
QString absolutePath() const
Returns full absolute path to the project folder if the project is stored in a file system - derived ...
void crs3DChanged()
Emitted when the crs3D() of the project has changed.
void scaleMethodChanged()
Emitted when the project's scale method is changed.
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.
Qgis::TransactionMode transactionMode
QgsAnnotationManager * annotationManager()
Returns pointer to the project's annotation manager.
QgsProjectDisplaySettings * displaySettings
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 transactionModeChanged()
Emitted when the transaction mode has changed.
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.
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.
QgsElevationShadingRenderer elevationShadingRenderer() const
Returns the elevation shading renderer used for map shading.
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...
void elevationShadingRendererChanged()
Emitted when the map shading renderer changes.
Q_INVOKABLE QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
QgsCoordinateReferenceSystem crs3D() const
Returns the CRS to use for the project when transforming 3D data, or when z/elevation value handling ...
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
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 setAreaUnits(Qgis::AreaUnit unit)
Sets the default area measurement units for the project.
void setTitle(const QString &title)
Sets the project's title.
QMap< QPair< QString, QString >, QgsTransactionGroup * > transactionGroups()
Map of transaction groups.
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...
Qgis::ProjectCapabilities capabilities() const
Returns the project's capabilities, which dictate optional functionality which can be selectively ena...
bool loadFunctionsFromProject(bool force=false)
Loads python expression functions stored in the current project.
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...
const QgsElevationProfileManager * elevationProfileManager() const
Returns the project's elevation profile manager, which manages elevation profiles within the project.
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 readProject(const QDomDocument &document)
Emitted when a project is being read.
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.
const QgsProjectViewSettings * viewSettings() const
Returns the project's view settings, which contains settings and properties relating to how a QgsProj...
void cleanFunctionsFromProject()
Unloads python expression functions stored in the current project and reloads local functions from th...
QgsCoordinateReferenceSystem verticalCrs() const
Returns the project's vertical coordinate reference system.
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 setElevationShadingRenderer(const QgsElevationShadingRenderer &elevationShadingRenderer)
Sets the elevation shading renderer used for global map shading.
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.
void writeProject(QDomDocument &document)
Emitted when the project is being written.
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.
void setDistanceUnits(Qgis::DistanceUnit unit)
Sets the default distance measurement units for the project.
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 verticalCrsChanged()
Emitted when the verticalCrs() of the project has changed.
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 an integer key value.
void clear() final
Removes all properties from the collection.
@ String
Any string value.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString relativeToAbsoluteUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
static bool run(const QString &command, const QString &messageOnError=QString())
Execute a Python statement.
static bool isValid()
Returns true if the runner has an instance (and thus is able to run commands).
A container for the context for various read/write operations on objects.
void setTransformContext(const QgsCoordinateTransformContext &transformContext)
Sets data coordinate transform context to transformContext.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
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.
Manages a set of relations between layers.
Represents a relationship between two vector layers.
void providerCreated(bool isValid, const QString &layerId)
Emitted when a provider is created with isValid set to True when the provider is valid.
QgsDataProvider * dataProvider()
Returns the created data provider.
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.
static const QgsSettingsEntryInteger * settingsLayerParallelLoadingMaxCount
Settings entry maximum thread count used to load layer in parallel.
static const QgsSettingsEntryBool * settingsLayerParallelLoading
Settings entry whether layer are loading in parallel.
Stores configuration of snapping settings for the project.
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.
void triggerIconRebuild()
Triggers emission of the rebuildIconPreviews() signal.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Represents a transaction group.
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 setProject(QgsProject *project)
Sets the project being translated.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
static Q_INVOKABLE Qgis::AreaUnit decodeAreaUnit(const QString &string, bool *ok=nullptr)
Decodes an areal unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE Qgis::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
The edit buffer group manages a group of edit buffers.
Represents a vector layer which manages a vector based dataset.
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.
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
static bool isZipFile(const QString &filename)
Returns true if the file name is a zipped file ( i.e with a '.qgz' extension, false otherwise.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
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
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
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.
void dump_(const QgsProjectPropertyKey &topQgsPropertyKey)
QgsProjectProperty * findKey_(const QString &scope, const QString &key, QgsProjectPropertyKey &rootProperty)
Takes the given scope and key and convert them to a string list of key tokens that will be used to na...
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.
#define FONTMARKER_CHR_FIX
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS_NON_FATAL
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Qgis::DataProviderReadFlags flags
QgsDataProvider::ProviderOptions options
Setting options for loading annotation layers.
Setting options for creating vector data providers.
Single variable definition for use within a QgsExpressionContextScope.
Contains information relating to a node (i.e.