87#include <QApplication>
92#include <QRegularExpression>
93#include <QStandardPaths>
95#include <QTemporaryFile>
101#include "moc_qgsproject.cpp"
103using namespace Qt::StringLiterals;
106#include <sys/utime.h>
122QStringList makeKeyTokens_(
const QString &scope,
const QString &key )
124 QStringList keyTokens = QStringList( scope );
125 keyTokens += key.split(
'/', Qt::SkipEmptyParts );
128 keyTokens.push_front( u
"properties"_s );
148 QStringList keySequence = makeKeyTokens_( scope, key );
150 while ( !keySequence.isEmpty() )
154 if ( keySequence.first() == currentProperty->
name() )
157 keySequence.pop_front();
159 if ( 1 == keySequence.count() )
162 return currentProperty->
find( keySequence.front() );
164 else if ( keySequence.isEmpty() )
169 return currentProperty;
171 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
173 if ( nextProperty->
isKey() )
177 else if ( nextProperty->
isValue() && 1 == keySequence.count() )
183 return currentProperty;
219 QStringList keySequence = makeKeyTokens_( scope, key );
226 propertiesModified =
false;
227 while ( !keySequence.isEmpty() )
231 if ( keySequence.first() == currentProperty->
name() )
234 keySequence.pop_front();
238 if ( 1 == keySequence.count() )
241 if ( !property || property->value() != value )
243 currentProperty->
setValue( keySequence.front(), value );
244 propertiesModified =
true;
247 return currentProperty;
251 else if ( keySequence.isEmpty() )
253 if ( currentProperty->
value() != value )
256 propertiesModified =
true;
259 return currentProperty;
261 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
265 if ( currentProperty )
276 if ( ( newPropertyKey = currentProperty->
addKey( keySequence.first() ) ) )
278 currentProperty = newPropertyKey;
306 QStringList keySequence = makeKeyTokens_( scope, key );
308 while ( !keySequence.isEmpty() )
312 if ( keySequence.first() == currentProperty->
name() )
315 keySequence.pop_front();
319 if ( 1 == keySequence.count() )
321 currentProperty->
removeKey( keySequence.front() );
326 else if ( keySequence.isEmpty() )
328 previousQgsPropertyKey->
removeKey( currentProperty->
name() );
330 else if ( ( nextProperty = currentProperty->
find( keySequence.first() ) ) )
332 previousQgsPropertyKey = currentProperty;
335 if ( currentProperty )
362 , mSnappingConfig( this )
382 mProperties.setName( u
"properties"_s );
385 mMainAnnotationLayer->setParent(
this );
392 mLayerTreeRegistryBridge = std::make_unique<QgsLayerTreeRegistryBridge>( mRootGroup.get(),
this,
this );
399 mProjectScope.reset();
400 emit layersWillBeRemoved( layers );
403 mProjectScope.reset();
404 emit layersWillBeRemoved( layers );
407 mProjectScope.reset();
408 emit layerWillBeRemoved( layer );
411 mProjectScope.reset();
412 emit layerWillBeRemoved( layer );
415 mProjectScope.reset();
416 emit layersRemoved( layers );
419 mProjectScope.reset();
420 emit layerRemoved( layer );
423 mProjectScope.reset();
427 mProjectScope.reset();
428 emit layersAdded( layers );
431 mProjectScope.reset();
432 emit layerWasAdded( layer );
441 for ( const auto &layer : layers )
443 disconnect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager.get(), &QgsRelationManager::updateRelationsStatus );
446 connect( mLayerStore.get(), qOverload<
const QList<QgsMapLayer *> & >( &
QgsMapLayerStore::layersAdded ),
this, [
this](
const QList<QgsMapLayer *> &layers ) {
447 for ( const auto &layer : layers )
449 connect( layer, &QgsMapLayer::dataSourceChanged, mRelationManager.get(), &QgsRelationManager::updateRelationsStatus );
457 mStyleSettings->combinedStyleModel()->addDefaultStyle();
463 mIsBeingDeleted =
true;
466 releaseHandlesToProjectArchive();
468 if (
this == sProject )
495 if (
title == mMetadata.title() )
498 mMetadata.setTitle(
title );
499 mProjectScope.reset();
511 return mMetadata.title();
520 if ( oldEvaluateDefaultValues != newEvaluateDefaultValues )
523 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
525 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
526 if ( vl->dataProvider() )
533 if ( oldTrustLayerMetadata != newTrustLayerMetadata )
536 for (
auto layerIt =
layers.constBegin(); layerIt !=
layers.constEnd(); ++layerIt )
538 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerIt.value() ) )
540 vl->setReadExtentFromXml( newTrustLayerMetadata );
545 if ( mFlags !=
flags )
560 newFlags &= ~(
static_cast< int >( flag ) );
575 return mSaveUserFull;
582 return mSaveDateTime;
603 if ( dirty && mDirtyBlockCount > 0 )
609 if ( mDirty == dirty )
620 if ( path == mHomePath )
624 mCachedHomePath.clear();
625 mProjectScope.reset();
636 const QList<QgsAttributeEditorElement *> elements = parent->
children();
644 translationContext->
registerTranslation( u
"project:layers:%1:formcontainers"_s.arg( layerId ), container->
name() );
646 if ( !container->
children().empty() )
657 const QList<QgsLayerTreeLayer *>
layers = mRootGroup->findLayers();
661 translationContext->
registerTranslation( u
"project:layers:%1"_s.arg( layer->layerId() ), layer->name() );
673 for (
const QgsField &field : fields )
678 if ( field.alias().isEmpty() )
679 fieldName = field.name();
681 fieldName = field.alias();
683 translationContext->
registerTranslation( u
"project:layers:%1:fieldaliases"_s.arg( vlayer->
id() ), fieldName );
686 if ( !field.constraints().constraintDescription().isEmpty() )
687 translationContext->
registerTranslation( u
"project:layers:%1:constraintdescriptions"_s.arg( vlayer->
id() ), field.constraints().constraintDescription() );
691 if ( field.editorWidgetSetup().type() ==
"ValueRelation"_L1 )
693 translationContext->
registerTranslation( u
"project:layers:%1:fields:%2:valuerelationvalue"_s.arg( vlayer->
id(), field.name() ), field.editorWidgetSetup().config().value( u
"Value"_s ).toString() );
695 ->
registerTranslation( u
"project:layers:%1:fields:%2:valuerelationdescription"_s.arg( vlayer->
id(), field.name() ), field.editorWidgetSetup().config().value( u
"Description"_s ).toString() );
699 if ( field.editorWidgetSetup().type() ==
"ValueMap"_L1 )
701 if ( field.editorWidgetSetup().config().value( u
"map"_s ).canConvert<QList<QVariant>>() )
703 const QList<QVariant> valueList = field.editorWidgetSetup().config().value( u
"map"_s ).toList();
705 for (
int i = 0, row = 0; i < valueList.count(); i++, row++ )
707 translationContext->
registerTranslation( u
"project:layers:%1:fields:%2:valuemapdescriptions"_s.arg( vlayer->
id(), field.name() ), valueList[i].toMap().constBegin().key() );
719 translationContext->
registerTranslation( u
"project:layers:%1:actiondescriptions"_s.arg( vlayer->
id() ), action.name() );
720 translationContext->
registerTranslation( u
"project:layers:%1:actionshorttitles"_s.arg( vlayer->
id() ), action.shortTitle() );
728 translationContext->
registerTranslation( u
"project:layers:%1:legendsymbollabels"_s.arg( vlayer->
id() ), item.label() );
746 mapLayer->metadata().registerTranslations( translationContext );
751 const QList<QgsLayerTreeGroup *> groupLayers = mRootGroup->findGroups(
true );
758 const QList<QgsRelation> &relations = mRelationManager->relations().values();
765 mMetadata.registerTranslations( translationContext );
772 mDataDefinedServerProperties = properties;
779 return mDataDefinedServerProperties;
786 switch ( mTransactionMode )
797 return mEditBufferGroup.startEditing();
807 switch ( mTransactionMode )
814 commitErrors.append( tr(
"Trying to commit changes without a layer specified. This only works if the transaction mode is buffered" ) );
823 return mEditBufferGroup.commitChanges( commitErrors, stopEditing );
833 switch ( mTransactionMode )
840 rollbackErrors.append( tr(
"Trying to roll back changes without a layer specified. This only works if the transaction mode is buffered" ) );
843 bool success = vectorLayer->
rollBack( stopEditing );
849 return mEditBufferGroup.rollBack( rollbackErrors, stopEditing );
859 if ( name == mFile.fileName() )
862 const QString oldHomePath =
homePath();
864 mFile.setFileName( name );
865 mCachedHomePath.clear();
866 mProjectScope.reset();
870 const QString newHomePath =
homePath();
871 if ( newHomePath != oldHomePath )
882 return mFile.fileName();
889 mOriginalPath = path;
896 return mOriginalPath;
903 return QFileInfo( mFile );
921 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
926 return QFileInfo( mFile.fileName() ).lastModified();
937 if ( mFile.fileName().isEmpty() )
940 return QFileInfo( mFile.fileName() ).absolutePath();
951 if ( mFile.fileName().isEmpty() )
954 return QFileInfo( mFile.fileName() ).absoluteFilePath();
965 storage->readProjectStorageMetadata( mFile.fileName(),
metadata );
970 return QFileInfo( mFile.fileName() ).completeBaseName();
978 const bool absolutePaths =
readBoolEntry( u
"Paths"_s, u
"/Absolute"_s,
false );
989 writeEntry( u
"Paths"_s, u
"/Absolute"_s,
true );
992 writeEntry( u
"Paths"_s, u
"/Absolute"_s,
false );
1009 return mCrs3D.isValid() ? mCrs3D : mCrs;
1023 if ( adjustEllipsoid && !mCrs.isSameCelestialBody(
crs ) )
1025 mBlockEllipsoidChangedSignal =
true;
1027 mBlockEllipsoidChangedSignal =
false;
1033 writeEntry( u
"SpatialRefSys"_s, u
"/ProjectionsEnabled"_s,
crs.isValid() ? 1 : 0 );
1034 mProjectScope.reset();
1038 if ( !mMainAnnotationLayer->crs().isValid() || mMainAnnotationLayer->isEmpty() )
1039 mMainAnnotationLayer->setCrs(
crs );
1048 if ( oldCrs3D != mCrs3D )
1052 if ( adjustEllipsoid )
1061 if ( !
crs().isValid() )
1074 mProjectScope.reset();
1077 if ( !mBlockEllipsoidChangedSignal )
1086 switch ( mCrs.type() )
1089 QgsDebugError( u
"Project has a vertical CRS set as the horizontal CRS!"_s );
1093 return mCrs.verticalCrs();
1108 return mVerticalCrs;
1115 if (
crs.isValid() )
1118 switch (
crs.type() )
1136 *errorMessage = QObject::tr(
"Specified CRS is a %1 CRS, not a Vertical CRS" ).arg(
qgsEnumValueToKey(
crs.type() ) );
1141 if (
crs != mVerticalCrs )
1146 switch ( mCrs.type() )
1149 if (
crs != oldVerticalCrs )
1152 *errorMessage = QObject::tr(
"Project CRS is a Compound CRS, specified Vertical CRS will be ignored" );
1158 if (
crs != oldVerticalCrs )
1161 *errorMessage = QObject::tr(
"Project CRS is a Geographic 3D CRS, specified Vertical CRS will be ignored" );
1167 if (
crs != oldVerticalCrs )
1170 *errorMessage = QObject::tr(
"Project CRS is a Geocentric CRS, specified Vertical CRS will be ignored" );
1176 if ( mCrs.hasVerticalAxis() &&
crs != oldVerticalCrs )
1179 *errorMessage = QObject::tr(
"Project CRS is a Projected 3D CRS, specified Vertical CRS will be ignored" );
1197 res = rebuildCrs3D( errorMessage );
1198 mProjectScope.reset();
1205 if ( mCrs3D != oldCrs3D )
1216 return mTransformContext;
1223 if ( context == mTransformContext )
1226 mTransformContext = context;
1227 mProjectScope.reset();
1229 mMainAnnotationLayer->setTransformContext( context );
1230 for (
auto &layer : mLayerStore.get()->mapLayers() )
1232 layer->setTransformContext( context );
1241 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
1245 if ( !mIsBeingDeleted )
1254 mProjectScope.reset();
1255 mFile.setFileName( QString() );
1256 mProperties.clearKeys();
1258 mSaveUserFull.clear();
1259 mSaveDateTime = QDateTime();
1262 mCachedHomePath.clear();
1266 mCustomVariables.clear();
1272 if ( !mSettings.value( u
"projects/anonymize_new_projects"_s,
false,
QgsSettings::Core ).toBool() )
1274 mMetadata.setCreationDateTime( QDateTime::currentDateTime() );
1293 mEmbeddedLayers.clear();
1294 mRelationManager->clear();
1295 mAnnotationManager->clear();
1296 mLayoutManager->clear();
1297 mElevationProfileManager->clear();
1298 mSelectiveMaskingSourceSetManager->clear();
1299 m3DViewsManager->clear();
1300 mBookmarkManager->clear();
1301 mSensorManager->clear();
1302 mViewSettings->reset();
1303 mTimeSettings->reset();
1304 mElevationProperties->reset();
1305 mDisplaySettings->reset();
1306 mGpsSettings->reset();
1307 mSnappingConfig.reset();
1312 mMapThemeCollection = std::make_unique< QgsMapThemeCollection >(
this );
1315 mLabelingEngineSettings->clear();
1319 releaseHandlesToProjectArchive();
1321 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >();
1322 mArchive = std::make_unique< QgsArchive >();
1325 mStyleSettings->reset();
1329 if ( !mIsBeingDeleted )
1337 writeEntry( u
"PositionPrecision"_s, u
"/Automatic"_s,
true );
1338 writeEntry( u
"PositionPrecision"_s, u
"/DecimalPlaces"_s, 2 );
1340 const bool defaultRelativePaths = mSettings.value( u
"/qgis/defaultProjectPathsRelative"_s,
true ).toBool();
1347 mSnappingConfig.clearIndividualLayerSettings();
1350 mRootGroup->clear();
1351 if ( mMainAnnotationLayer )
1352 mMainAnnotationLayer->reset();
1354 snapSingleBlocker.release();
1356 if ( !mBlockSnappingUpdates )
1362 if ( !mBlockChangeSignalsDuringClear )
1374 topQgsPropertyKey.
dump();
1407 const QDomElement propertiesElem = doc.documentElement().firstChildElement( u
"properties"_s );
1409 if ( propertiesElem.isNull() )
1414 const QDomNodeList scopes = propertiesElem.childNodes();
1416 if ( propertiesElem.firstChild().isNull() )
1418 QgsDebugError( u
"empty ``properties'' XML tag ... bailing"_s );
1422 if ( !project_properties.
readXml( propertiesElem ) )
1438 const QDomElement ddElem = doc.documentElement().firstChildElement( u
"dataDefinedServerProperties"_s );
1439 if ( !ddElem.isNull() )
1441 if ( !ddServerProperties.
readXml( ddElem, dataDefinedServerPropertyDefinitions ) )
1443 QgsDebugError( u
"dataDefinedServerProperties.readXml() failed"_s );
1446 return ddServerProperties;
1453static void _getTitle(
const QDomDocument &doc, QString &title )
1455 const QDomElement titleNode = doc.documentElement().firstChildElement( u
"title"_s );
1459 if ( titleNode.isNull() )
1465 if ( !titleNode.hasChildNodes() )
1471 const QDomNode titleTextNode = titleNode.firstChild();
1473 if ( !titleTextNode.isText() )
1479 const QDomText titleText = titleTextNode.toText();
1481 title = titleText.data();
1484static void readProjectFileMetadata(
const QDomDocument &doc, QString &lastUser, QString &lastUserFull, QDateTime &lastSaveDateTime )
1486 const QDomNodeList nl = doc.elementsByTagName( u
"qgis"_s );
1494 const QDomNode qgisNode = nl.item( 0 );
1496 const QDomElement qgisElement = qgisNode.toElement();
1497 lastUser = qgisElement.attribute( u
"saveUser"_s, QString() );
1498 lastUserFull = qgisElement.attribute( u
"saveUserFull"_s, QString() );
1499 lastSaveDateTime = QDateTime::fromString( qgisElement.attribute( u
"saveDateTime"_s, QString() ), Qt::ISODate );
1504 const QDomNodeList nl = doc.elementsByTagName( u
"qgis"_s );
1508 QgsDebugError( u
" unable to find qgis element in project file"_s );
1512 const QDomNode qgisNode = nl.item( 0 );
1514 const QDomElement qgisElement = qgisNode.toElement();
1516 return projectVersion;
1523 return mSnappingConfig;
1542 if ( mAvoidIntersectionsMode == mode )
1545 mAvoidIntersectionsMode = mode;
1579void QgsProject::preloadProviders(
1586 QMap<QString, LayerToLoad> layersToLoad;
1588 for (
const QDomNode &node : parallelLayerNodes )
1592 const QDomElement layerElement = node.toElement();
1594 layerToLoad.
layerId = layerElement.namedItem( u
"id"_s ).toElement().text();
1595 layerToLoad.
provider = layerElement.namedItem( u
"provider"_s ).toElement().text();
1596 layerToLoad.
dataSource = layerElement.namedItem( u
"datasource"_s ).toElement().text();
1607 layersToLoad.insert( layerToLoad.
layerId, layerToLoad );
1610 while ( !layersToLoad.isEmpty() )
1612 const QList<LayerToLoad> layersToAttemptInParallel = layersToLoad.values();
1613 QString layerToAttemptInMainThread;
1615 QHash<QString, QgsRunnableProviderCreator *> runnables;
1616 QThreadPool threadPool;
1619 for (
const LayerToLoad &lay : layersToAttemptInParallel )
1621 QgsRunnableProviderCreator *run =
new QgsRunnableProviderCreator( lay.layerId, lay.provider, lay.dataSource, lay.options, lay.flags );
1622 runnables.insert( lay.layerId, run );
1627 layersToLoad.remove( layId );
1629 QgsRunnableProviderCreator *finishedRun = runnables.value( layId,
nullptr );
1630 Q_ASSERT( finishedRun );
1632 std::unique_ptr<QgsDataProvider> provider( finishedRun->
dataProvider() );
1633 Q_ASSERT( provider && provider->isValid() );
1635 provider->moveToThread( QThread::currentThread() );
1638 loadedProviders.insert( layId, provider.release() );
1643 if ( layerToAttemptInMainThread.isEmpty() )
1644 layerToAttemptInMainThread = layId;
1648 if ( i == parallelLayerNodes.count() || !isValid )
1651 threadPool.start( run );
1655 threadPool.waitForDone();
1657 qDeleteAll( runnables );
1660 auto it = layersToLoad.find( layerToAttemptInMainThread );
1661 if ( it != layersToLoad.end() )
1663 std::unique_ptr<QgsDataProvider> provider;
1666 const LayerToLoad &lay = it.value();
1670 QgsScopedRuntimeProfile profile(
"Create data providers/" + lay.
layerId, u
"projectload"_s );
1673 if ( provider && provider->isValid() )
1678 layersToLoad.erase( it );
1681 loadedProviders.insert( layerId, provider.release() );
1688void QgsProject::releaseHandlesToProjectArchive()
1690 mStyleSettings->removeProjectStyle();
1693bool QgsProject::rebuildCrs3D( QString *error )
1696 if ( !mCrs.isValid() )
1698 mCrs3D = QgsCoordinateReferenceSystem();
1700 else if ( !mVerticalCrs.isValid() )
1706 switch ( mCrs.type() )
1718 res = mCrs3D.isValid();
1724 mCrs3D = QgsCoordinateReferenceSystem();
1739 res = mCrs3D.isValid();
1747bool QgsProject::_getMapLayers(
const QDomDocument &doc, QList<QDomNode> &brokenNodes,
Qgis::ProjectReadFlags flags )
1754 QDomElement layerElement = doc.documentElement().firstChildElement( u
"projectlayers"_s ).firstChildElement( u
"maplayer"_s );
1758 if ( layerElement.isNull() )
1768 bool returnStatus =
true;
1771 while ( !layerElement.isNull() )
1774 layerElement = layerElement.nextSiblingElement( u
"maplayer"_s );
1778 QgsScopedRuntimeProfile profile( tr(
"Sorting layers" ), u
"projectload"_s );
1779 const QgsLayerDefinition::DependencySorter depSorter( doc );
1780 if ( depSorter.hasCycle() )
1784 if ( depSorter.hasMissingDependency() )
1785 returnStatus =
false;
1789 const QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
1790 const int totalLayerCount = sortedLayerNodes.count();
1792 QVector<QDomNode> parallelLoading;
1793 QMap<QString, QgsDataProvider *> loadedProviders;
1797 profile.switchTask( tr(
"Load providers in parallel" ) );
1798 for (
const QDomNode &node : sortedLayerNodes )
1800 const QDomElement element = node.toElement();
1801 if ( element.attribute( u
"embedded"_s ) !=
"1"_L1 )
1803 const QString layerId = node.namedItem( u
"id"_s ).toElement().text();
1804 if ( !depSorter.isLayerDependent( layerId ) )
1806 const QDomNode mnl = element.namedItem( u
"provider"_s );
1807 const QDomElement mne = mnl.toElement();
1808 const QString provider = mne.text();
1812 parallelLoading.append( node );
1819 QgsReadWriteContext context;
1821 if ( !parallelLoading.isEmpty() )
1822 preloadProviders( parallelLoading, context, loadedProviders, projectFlagsToLayerReadFlags(
flags, mFlags ), sortedLayerNodes.count() );
1825 int i = loadedProviders.count();
1826 for (
const QDomNode &node : std::as_const( sortedLayerNodes ) )
1828 const QDomElement element = node.toElement();
1829 const QString name =
translate( u
"project:layers:%1"_s.arg( node.namedItem( u
"id"_s ).toElement().text() ), node.namedItem( u
"layername"_s ).toElement().text() );
1830 if ( !name.isNull() )
1831 emit
loadingLayer( tr(
"Loading layer %1" ).arg( name ) );
1833 profile.switchTask( name );
1834 if ( element.attribute( u
"embedded"_s ) ==
"1"_L1 )
1840 QgsReadWriteContext context;
1844 QString layerId = element.namedItem( u
"id"_s ).toElement().text();
1846 if ( !addLayer( element, brokenNodes, context,
flags, loadedProviders.take( layerId ) ) )
1848 returnStatus =
false;
1851 if ( !messages.isEmpty() )
1860 return returnStatus;
1867 const QString type = layerElem.attribute( u
"type"_s );
1869 std::unique_ptr<QgsMapLayer>
mapLayer;
1871 QgsScopedRuntimeProfile profile( tr(
"Create layer" ), u
"projectload"_s );
1877 QgsDebugError( u
"Unknown layer type \"%1\""_s.arg( type ) );
1881 switch ( layerType )
1884 mapLayer = std::make_unique<QgsVectorLayer>();
1888 mapLayer = std::make_unique<QgsRasterLayer>();
1892 mapLayer = std::make_unique<QgsMeshLayer>();
1896 mapLayer = std::make_unique<QgsVectorTileLayer>();
1900 mapLayer = std::make_unique<QgsPointCloudLayer>();
1904 mapLayer = std::make_unique<QgsTiledSceneLayer>();
1909 const QString typeName = layerElem.attribute( u
"name"_s );
1916 const QgsAnnotationLayer::LayerOptions options( mTransformContext );
1917 mapLayer = std::make_unique<QgsAnnotationLayer>( QString(), options );
1923 const QgsGroupLayer::LayerOptions options( mTransformContext );
1924 mapLayer = std::make_unique<QgsGroupLayer>( QString(), options );
1939 const QString layerId { layerElem.namedItem( u
"id"_s ).toElement().text() };
1940 Q_ASSERT( !layerId.isEmpty() );
1946 profile.switchTask( tr(
"Load layer source" ) );
1947 const bool layerIsValid =
mapLayer->readLayerXml( layerElem, context, layerFlags, provider ) &&
mapLayer->isValid();
1950 if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>(
mapLayer.get() ) )
1953 if ( vl->dataProvider() )
1960 profile.switchTask( tr(
"Add layer to project" ) );
1961 QList<QgsMapLayer *> newLayers;
1971 if ( QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>(
mapLayer.get() ) )
1973 vLayer->joinBuffer()->resolveReferences(
this );
1982 brokenNodes.push_back( layerElem );
1985 const bool wasEditable = layerElem.attribute( u
"editable"_s, u
"0"_s ).toInt();
1988 mapLayer->setCustomProperty( u
"_layer_was_editable"_s,
true );
1992 mapLayer->removeCustomProperty( u
"_layer_was_editable"_s );
1997 if ( !layerWasStored )
2002 return layerIsValid;
2009 mFile.setFileName( filename );
2010 mCachedHomePath.clear();
2011 mProjectScope.reset();
2020 const QString filename = mFile.fileName();
2025 QTemporaryFile inDevice;
2026 if ( !inDevice.open() )
2028 setError( tr(
"Unable to open %1" ).arg( inDevice.fileName() ) );
2034 if ( !storage->readProject( filename, &inDevice, context ) )
2036 QString err = tr(
"Unable to open %1" ).arg( filename );
2037 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
2038 if ( !messages.isEmpty() )
2039 err += u
"\n\n"_s + messages.last().message();
2043 returnValue = unzip( inDevice.fileName(),
flags );
2049 returnValue = unzip( mFile.fileName(),
flags );
2053 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >( *
this );
2054 const QFileInfo finfo( mFile.fileName() );
2055 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( u
"%1_attachments.zip"_s.arg( finfo.completeBaseName() ) );
2056 if ( QFile( attachmentsZip ).exists() )
2058 auto archive = std::make_unique<QgsArchive>();
2059 if ( archive->unzip( attachmentsZip ) )
2061 releaseHandlesToProjectArchive();
2062 mArchive = std::move( archive );
2065 returnValue = readProjectFile( mFile.fileName(),
flags );
2071 mFile.setFileName( filename );
2072 mCachedHomePath.clear();
2073 mProjectScope.reset();
2078 mTranslator.reset(
nullptr );
2091 ScopedIntIncrementor snapSignalBlock( &mBlockSnappingUpdates );
2093 QFile projectFile( filename );
2100 const QString projectBaseName = QFileInfo( mFile ).baseName();
2101 const QString projectDir = QFileInfo( mFile ).absolutePath();
2102 QString localeFileName = u
"%1_%2"_s.arg( projectBaseName, locale );
2104 if ( !QFile( u
"%1/%2.qm"_s.arg( projectDir, localeFileName ) ).exists() && locale.contains(
'_' ) )
2107 localeFileName = u
"%1_%2"_s.arg( projectBaseName, locale.left( locale.indexOf(
'_' ) ) );
2110 if ( QFile( u
"%1/%2.qm"_s.arg( projectDir, localeFileName ) ).exists() )
2112 mTranslator = std::make_unique< QTranslator >();
2113 ( void ) mTranslator->load( localeFileName, projectDir );
2116 profile.switchTask( tr(
"Reading project file" ) );
2117 auto doc = std::make_unique<QDomDocument>( u
"qgis"_s );
2119 if ( !projectFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
2121 projectFile.close();
2123 setError( tr(
"Unable to open %1" ).arg( projectFile.fileName() ) );
2128 QTextStream textStream( &projectFile );
2129 QString projectString = textStream.readAll();
2130 projectFile.close();
2132 for (
int i = 0; i < 32; i++ )
2134 if ( i == 9 || i == 10 || i == 13 )
2138 projectString.replace( QChar( i ), u
"%1%2%1"_s.arg(
FONTMARKER_CHR_FIX, QString::number( i ) ) );
2144 if ( !doc->setContent( projectString, &errorMsg, &line, &column ) )
2146 const QString errorString = tr(
"Project file read error in file %1: %2 at line %3 column %4" ).arg( projectFile.fileName(), errorMsg ).arg( line ).arg( column );
2148 setError( errorString );
2153 projectFile.close();
2158 const QgsProjectVersion fileVersion =
getVersion( *doc );
2161 profile.switchTask( tr(
"Updating project file" ) );
2162 if ( thisVersion > fileVersion )
2164 const bool isOlderMajorVersion = fileVersion.
majorVersion() < thisVersion.majorVersion();
2166 if ( isOlderMajorVersion )
2169 "Loading a file that was saved with an older "
2170 "version of qgis (saved in "
2171 + fileVersion.
text()
2174 +
"). Problems may occur."
2178 QgsProjectFileTransform projectFile( *doc, fileVersion );
2186 projectFile.updateRevision( thisVersion );
2188 else if ( fileVersion > thisVersion )
2191 "Loading a file that was saved with a newer "
2192 "version of qgis (saved in "
2193 + fileVersion.
text()
2196 +
"). Problems may occur."
2203 profile.switchTask( tr(
"Creating auxiliary storage" ) );
2204 const QString
fileName = mFile.fileName();
2206 const QgsCoordinateReferenceSystem oldVerticalCrs =
verticalCrs();
2207 const QgsCoordinateReferenceSystem oldCrs3D = mCrs3D;
2211 std::unique_ptr<QgsAuxiliaryStorage> aStorage = std::move( mAuxiliaryStorage );
2212 std::unique_ptr<QgsArchive> archive = std::move( mArchive );
2216 mBlockChangeSignalsDuringClear =
true;
2218 mBlockChangeSignalsDuringClear =
false;
2223 releaseHandlesToProjectArchive();
2225 mAuxiliaryStorage = std::move( aStorage );
2226 mArchive = std::move( archive );
2229 mCachedHomePath.clear();
2230 mProjectScope.reset();
2231 mSaveVersion = fileVersion;
2234 profile.switchTask( tr(
"Reading properties" ) );
2240 QgsDebugMsgLevel( QString::number( mProperties.count() ) +
" properties read", 2 );
2243 dump_( mProperties );
2248 _getTitle( *doc, oldTitle );
2250 readProjectFileMetadata( *doc, mSaveUser, mSaveUserFull, mSaveDateTime );
2252 const QDomNodeList homePathNl = doc->elementsByTagName( u
"homePath"_s );
2253 if ( homePathNl.count() > 0 )
2255 const QDomElement homePathElement = homePathNl.at( 0 ).toElement();
2256 const QString
homePath = homePathElement.attribute( u
"path"_s );
2268 selectionColor(
readNumEntry( u
"Gui"_s, u
"/SelectionColorRedPart"_s, 255 ),
readNumEntry( u
"Gui"_s, u
"/SelectionColorGreenPart"_s, 255 ),
readNumEntry( u
"Gui"_s, u
"/SelectionColorBluePart"_s, 255 ),
readNumEntry( u
"Gui"_s, u
"/SelectionColorAlphaPart"_s, 255 ) );
2272 const QString distanceUnitString =
readEntry( u
"Measurement"_s, u
"/DistanceUnits"_s, QString() );
2273 if ( !distanceUnitString.isEmpty() )
2276 const QString areaUnitString =
readEntry( u
"Measurement"_s, u
"/AreaUnits"_s, QString() );
2277 if ( !areaUnitString.isEmpty() )
2282 QgsReadWriteContext context;
2287 QgsCoordinateReferenceSystem projectCrs;
2288 if (
readNumEntry( u
"SpatialRefSys"_s, u
"/ProjectionsEnabled"_s, 0 ) )
2291 const QDomNode srsNode = doc->documentElement().namedItem( u
"projectCrs"_s );
2292 if ( !srsNode.isNull() )
2294 projectCrs.
readXml( srsNode );
2299 const QString projCrsString =
readEntry( u
"SpatialRefSys"_s, u
"/ProjectCRSProj4String"_s );
2300 const long currentCRS =
readNumEntry( u
"SpatialRefSys"_s, u
"/ProjectCRSID"_s, -1 );
2301 const QString authid =
readEntry( u
"SpatialRefSys"_s, u
"/ProjectCrs"_s );
2304 const bool isUserAuthId = authid.startsWith(
"USER:"_L1, Qt::CaseInsensitive );
2305 if ( !authid.isEmpty() && !isUserAuthId )
2306 projectCrs = QgsCoordinateReferenceSystem( authid );
2309 if ( !projectCrs.
isValid() && currentCRS >= 0 )
2315 if ( !projCrsString.isEmpty() && ( authid.isEmpty() || isUserAuthId ) && ( !projectCrs.
isValid() || projectCrs.
toProj() != projCrsString ) )
2332 const QDomNode verticalCrsNode = doc->documentElement().namedItem( u
"verticalCrs"_s );
2333 if ( !verticalCrsNode.isNull() )
2341 QStringList datumErrors;
2342 if ( !mTransformContext.readXml( doc->documentElement(), context, datumErrors ) && !datumErrors.empty() )
2349 const QDomNode elevationShadingNode = doc->documentElement().namedItem( u
"elevation-shading-renderer"_s );
2350 if ( !elevationShadingNode.isNull() )
2352 mElevationShadingRenderer.readXml( elevationShadingNode.toElement(), context );
2359 const QStringList variableNames =
readListEntry( u
"Variables"_s, u
"/variableNames"_s );
2360 const QStringList variableValues =
readListEntry( u
"Variables"_s, u
"/variableValues"_s );
2362 mCustomVariables.clear();
2363 if ( variableNames.length() == variableValues.length() )
2365 for (
int i = 0; i < variableNames.length(); ++i )
2367 mCustomVariables.insert( variableNames.at( i ), variableValues.at( i ) );
2372 QgsMessageLog::logMessage( tr(
"Project Variables Invalid" ), tr(
"The project contains invalid variable settings." ) );
2380 QDomElement element = doc->documentElement().firstChildElement( u
"projectMetadata"_s );
2382 if ( !element.isNull() )
2384 mMetadata.readMetadataXml( element, context );
2389 mMetadata = QgsProjectMetadata();
2391 if ( mMetadata.title().isEmpty() && !oldTitle.isEmpty() )
2394 mMetadata.setTitle( oldTitle );
2400 element = doc->documentElement().firstChildElement( u
"transaction"_s );
2401 if ( !element.isNull() )
2408 element = doc->documentElement().firstChildElement( u
"autotransaction"_s );
2409 if ( !element.isNull() )
2411 mTransactionMode =
static_cast<Qgis::TransactionMode>( element.attribute( u
"active"_s, u
"0"_s ).toInt() );
2416 profile.switchTask( tr(
"Loading layer tree" ) );
2417 mRootGroup->setCustomProperty( u
"loading"_s, 1 );
2419 QDomElement layerTreeElem = doc->documentElement().firstChildElement( u
"layer-tree-group"_s );
2420 if ( !layerTreeElem.isNull() )
2423 QgsLayerTree tempTree;
2432 mLayerTreeRegistryBridge->setEnabled(
false );
2435 profile.switchTask( tr(
"Reading map layers" ) );
2437 loadProjectFlags( doc.get() );
2439 QList<QDomNode> brokenNodes;
2440 const bool clean = _getMapLayers( *doc, brokenNodes,
flags );
2445 QgsDebugError( u
"Unable to get map layers from project file."_s );
2447 if ( !brokenNodes.isEmpty() )
2449 QgsDebugError(
"there are " + QString::number( brokenNodes.size() ) +
" broken layers" );
2454 mBadLayerHandler->handleBadLayers( brokenNodes );
2457 mMainAnnotationLayer->readLayerXml( doc->documentElement().firstChildElement( u
"main-annotation-layer"_s ), context );
2458 mMainAnnotationLayer->setTransformContext( mTransformContext );
2461 profile.switchTask( tr(
"Loading embedded layers" ) );
2462 loadEmbeddedNodes( mRootGroup.get(),
flags );
2466 profile.switchTask( tr(
"Resolving layer references" ) );
2467 QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
2468 for ( QMap<QString, QgsMapLayer *>::iterator it =
layers.begin(); it !=
layers.end(); ++it )
2470 it.value()->resolveReferences(
this );
2472 mMainAnnotationLayer->resolveReferences(
this );
2474 mLayerTreeRegistryBridge->setEnabled(
true );
2477 profile.switchTask( tr(
"Resolving references" ) );
2478 mRootGroup->resolveReferences(
this );
2481 if ( QgsProjectVersion( 3, 28, 0 ) > mSaveVersion )
2488 if ( !layerTreeElem.isNull() )
2490 mRootGroup->readLayerOrderFromXml( layerTreeElem );
2494 const QDomElement layerTreeCanvasElem = doc->documentElement().firstChildElement( u
"layer-tree-canvas"_s );
2495 if ( !layerTreeCanvasElem.isNull() )
2497 mRootGroup->readLayerOrderFromXml( layerTreeCanvasElem );
2501 if ( QgsProjectVersion( 3, 4, 0 ) > mSaveVersion )
2503 const QStringList requiredLayerIds =
readListEntry( u
"RequiredLayers"_s, u
"Layers"_s );
2504 for (
const QString &layerId : requiredLayerIds )
2506 if ( QgsMapLayer *layer =
mapLayer( layerId ) )
2511 const QStringList disabledLayerIds =
readListEntry( u
"Identify"_s, u
"/disabledLayers"_s );
2512 for (
const QString &layerId : disabledLayerIds )
2514 if ( QgsMapLayer *layer =
mapLayer( layerId ) )
2522 if ( QgsProjectVersion( 3, 26, 0 ) > mSaveVersion )
2525 QString styleName =
readEntry( u
"DefaultStyles"_s, u
"/Marker"_s );
2526 if ( !styleName.isEmpty() )
2531 styleName =
readEntry( u
"DefaultStyles"_s, u
"/Line"_s );
2532 if ( !styleName.isEmpty() )
2537 styleName =
readEntry( u
"DefaultStyles"_s, u
"/Fill"_s );
2538 if ( !styleName.isEmpty() )
2543 styleName =
readEntry( u
"DefaultStyles"_s, u
"/ColorRamp"_s );
2544 if ( !styleName.isEmpty() )
2554 double opacity = 1.0;
2557 double alpha =
readDoubleEntry( u
"DefaultStyles"_s, u
"/AlphaInt"_s, 255, &ok );
2559 opacity = alpha / 255.0;
2560 double newOpacity =
readDoubleEntry( u
"DefaultStyles"_s, u
"/Opacity"_s, 1.0, &ok );
2562 opacity = newOpacity;
2569 removeEntry( u
"DefaultStyles"_s, u
"/ColorRamp"_s );
2570 removeEntry( u
"DefaultStyles"_s, u
"/RandomColors"_s );
2571 removeEntry( u
"DefaultStyles"_s, u
"/AlphaInt"_s );
2580 profile.switchTask( tr(
"Storing original layer properties" ) );
2584 mRootGroup->removeCustomProperty( u
"loading"_s );
2586 profile.switchTask( tr(
"Loading map themes" ) );
2587 mMapThemeCollection = std::make_unique< QgsMapThemeCollection >(
this );
2589 mMapThemeCollection->readXml( *doc );
2591 profile.switchTask( tr(
"Loading label settings" ) );
2592 mLabelingEngineSettings->readSettingsFromProject(
this );
2594 const QDomElement labelEngineSettingsElement = doc->documentElement().firstChildElement( u
"labelEngineSettings"_s );
2595 mLabelingEngineSettings->readXml( labelEngineSettingsElement, context );
2597 mLabelingEngineSettings->resolveReferences(
this );
2601 profile.switchTask( tr(
"Loading annotations" ) );
2604 mAnnotationManager->readXml( doc->documentElement(), context );
2608 mAnnotationManager->readXmlAndUpgradeToAnnotationLayerItems( doc->documentElement(), context, mMainAnnotationLayer, mTransformContext );
2612 profile.switchTask( tr(
"Loading layouts" ) );
2613 mLayoutManager->readXml( doc->documentElement(), *doc );
2617 profile.switchTask( tr(
"Loading elevation profiles" ) );
2618 mElevationProfileManager->readXml( doc->documentElement(), *doc, context );
2619 mElevationProfileManager->resolveReferences(
this );
2623 profile.switchTask( tr(
"Loading selective masking source sets" ) );
2624 mSelectiveMaskingSourceSetManager->readXml( doc->documentElement(), *doc, context );
2629 profile.switchTask( tr(
"Loading 3D Views" ) );
2630 m3DViewsManager->readXml( doc->documentElement(), *doc );
2633 profile.switchTask( tr(
"Loading bookmarks" ) );
2634 mBookmarkManager->readXml( doc->documentElement(), *doc );
2636 profile.switchTask( tr(
"Loading sensors" ) );
2637 mSensorManager->readXml( doc->documentElement(), *doc );
2640 QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
2641 for ( QMap<QString, QgsMapLayer *>::iterator it = existingMaps.begin(); it != existingMaps.end(); ++it )
2643 it.value()->setDependencies( it.value()->dependencies() );
2646 profile.switchTask( tr(
"Loading snapping settings" ) );
2647 mSnappingConfig.readProject( *doc );
2652 profile.switchTask( tr(
"Loading view settings" ) );
2654 mViewSettings->setUseProjectScales(
readBoolEntry( u
"Scales"_s, u
"/useProjectScales"_s ) );
2655 const QStringList scales =
readListEntry( u
"Scales"_s, u
"/ScalesList"_s );
2656 QVector<double> res;
2657 for (
const QString &scale : scales )
2659 const QStringList parts = scale.split(
':' );
2660 if ( parts.size() != 2 )
2664 const double denominator = QLocale().toDouble( parts[1], &ok );
2670 mViewSettings->setMapScales( res );
2671 const QDomElement viewSettingsElement = doc->documentElement().firstChildElement( u
"ProjectViewSettings"_s );
2672 if ( !viewSettingsElement.isNull() )
2673 mViewSettings->readXml( viewSettingsElement, context );
2676 profile.switchTask( tr(
"Loading style properties" ) );
2677 const QDomElement styleSettingsElement = doc->documentElement().firstChildElement( u
"ProjectStyleSettings"_s );
2678 if ( !styleSettingsElement.isNull() )
2680 mStyleSettings->removeProjectStyle();
2681 mStyleSettings->readXml( styleSettingsElement, context,
flags );
2685 profile.switchTask( tr(
"Loading temporal settings" ) );
2686 const QDomElement timeSettingsElement = doc->documentElement().firstChildElement( u
"ProjectTimeSettings"_s );
2687 if ( !timeSettingsElement.isNull() )
2688 mTimeSettings->readXml( timeSettingsElement, context );
2691 profile.switchTask( tr(
"Loading elevation properties" ) );
2692 const QDomElement elevationPropertiesElement = doc->documentElement().firstChildElement( u
"ElevationProperties"_s );
2693 if ( !elevationPropertiesElement.isNull() )
2694 mElevationProperties->readXml( elevationPropertiesElement, context );
2695 mElevationProperties->resolveReferences(
this );
2697 profile.switchTask( tr(
"Loading display settings" ) );
2699 const QDomElement displaySettingsElement = doc->documentElement().firstChildElement( u
"ProjectDisplaySettings"_s );
2700 if ( !displaySettingsElement.isNull() )
2701 mDisplaySettings->readXml( displaySettingsElement, context );
2704 profile.switchTask( tr(
"Loading GPS settings" ) );
2706 const QDomElement gpsSettingsElement = doc->documentElement().firstChildElement( u
"ProjectGpsSettings"_s );
2707 if ( !gpsSettingsElement.isNull() )
2708 mGpsSettings->readXml( gpsSettingsElement, context );
2709 mGpsSettings->resolveReferences(
this );
2712 profile.switchTask( tr(
"Updating variables" ) );
2714 profile.switchTask( tr(
"Updating CRS" ) );
2718 if ( mCrs3D != oldCrs3D )
2723 profile.switchTask( tr(
"Reading external settings" ) );
2727 profile.switchTask( tr(
"Updating interface" ) );
2729 snapSignalBlock.release();
2730 if ( !mBlockSnappingUpdates )
2751 const QString newFileName( u
"%1/%2.qgs"_s.arg( QFileInfo( mFile ).
absolutePath(), localeFileName ) );
2765 const QMap<QString, QgsMapLayer *> loadedLayers =
mapLayers();
2766 for (
auto it = loadedLayers.constBegin(); it != loadedLayers.constEnd(); ++it )
2768 if ( it.value()->isValid() && it.value()->customProperty( u
"_layer_was_editable"_s ).toBool() )
2770 if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( it.value() ) )
2772 it.value()->removeCustomProperty( u
"_layer_was_editable"_s );
2784 const auto constChildren = group->
children();
2785 for ( QgsLayerTreeNode *child : constChildren )
2798 QList<QgsLayerTreeNode *> clonedChildren;
2799 const QList<QgsLayerTreeNode *> constChildren = newGroup->children();
2800 clonedChildren.reserve( constChildren.size() );
2801 for ( QgsLayerTreeNode *newGroupChild : constChildren )
2802 clonedChildren << newGroupChild->clone();
2809 loadEmbeddedNodes( childGroup,
flags );
2814 if ( child->customProperty( u
"embedded"_s ).toInt() )
2816 QList<QDomNode> brokenNodes;
2819 valid = valid &&
false;
2833 return mCustomVariables;
2840 if ( variables == mCustomVariables )
2844 QStringList variableNames;
2845 QStringList variableValues;
2847 QVariantMap::const_iterator it = variables.constBegin();
2848 for ( ; it != variables.constEnd(); ++it )
2850 variableNames << it.key();
2851 variableValues << it.value().toString();
2854 writeEntry( u
"Variables"_s, u
"/variableNames"_s, variableNames );
2855 writeEntry( u
"Variables"_s, u
"/variableValues"_s, variableValues );
2857 mCustomVariables = variables;
2858 mProjectScope.reset();
2867 *mLabelingEngineSettings = settings;
2875 return *mLabelingEngineSettings;
2882 mProjectScope.reset();
2883 return mLayerStore.get();
2890 return mLayerStore.get();
2897 QList<QgsVectorLayer *>
layers;
2898 const QStringList layerIds =
readListEntry( u
"Digitizing"_s, u
"/AvoidIntersectionsList"_s, QStringList() );
2899 const auto constLayerIds = layerIds;
2900 for (
const QString &layerId : constLayerIds )
2913 list.reserve(
layers.size() );
2918 list << layer->id();
2921 writeEntry( u
"Digitizing"_s, u
"/AvoidIntersectionsList"_s, list );
2942 if ( mProjectScope )
2944 auto projectScope = std::make_unique< QgsExpressionContextScope >( *mProjectScope );
2951 projectScope->addFunction( u
"sensor_data"_s,
new GetSensorData(
sensorManager()->sensorsData() ) );
2953 return projectScope.release();
2956 mProjectScope = std::make_unique< QgsExpressionContextScope >( QObject::tr(
"Project" ) );
2960 QVariantMap::const_iterator it = vars.constBegin();
2962 for ( ; it != vars.constEnd(); ++it )
2964 mProjectScope->setVariable( it.key(), it.value(),
true );
2968 if ( projectPath.isEmpty() )
2969 projectPath = mOriginalPath;
2970 const QString projectFolder = QFileInfo( projectPath ).path();
2971 const QString projectFilename = QFileInfo( projectPath ).fileName();
2972 const QString projectBasename =
baseName();
3009 QVariantMap keywords;
3011 for (
auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
3013 keywords.insert( it.key(), it.value() );
3018 QVariantList layersIds;
3020 const QMap<QString, QgsMapLayer *> layersInProject = mLayerStore->mapLayers();
3021 layersIds.reserve( layersInProject.count() );
3022 layers.reserve( layersInProject.count() );
3023 for (
auto it = layersInProject.constBegin(); it != layersInProject.constEnd(); ++it )
3025 layersIds << it.value()->id();
3031 mProjectScope->addFunction( u
"project_color"_s,
new GetNamedProjectColor(
this ) );
3032 mProjectScope->addFunction( u
"project_color_object"_s,
new GetNamedProjectColorObject(
this ) );
3037void QgsProject::onMapLayersAdded(
const QList<QgsMapLayer *> &layers )
3041 const QMap<QString, QgsMapLayer *> existingMaps =
mapLayers();
3043 const auto constLayers =
layers;
3046 if ( !layer->isValid() )
3049 if (
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer ) )
3052 if ( vlayer->dataProvider() )
3059 for ( QMap<QString, QgsMapLayer *>::const_iterator it = existingMaps.cbegin(); it != existingMaps.cend(); ++it )
3061 const QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
3062 if ( deps.contains( layer->id() ) )
3065 it.value()->setDependencies( deps );
3070 updateTransactionGroups();
3072 if ( !mBlockSnappingUpdates && mSnappingConfig.addLayers(
layers ) )
3076void QgsProject::onMapLayersRemoved(
const QList<QgsMapLayer *> &layers )
3080 if ( !mBlockSnappingUpdates && mSnappingConfig.removeLayers(
layers ) )
3083 for ( QgsMapLayer *layer :
layers )
3085 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
3089 mEditBufferGroup.removeLayer( vlayer );
3093void QgsProject::cleanTransactionGroups(
bool force )
3097 bool changed =
false;
3098 for ( QMap< QPair< QString, QString>, QgsTransactionGroup *>::Iterator tg = mTransactionGroups.begin(); tg != mTransactionGroups.end(); )
3100 if ( tg.value()->isEmpty() || force )
3103 tg = mTransactionGroups.erase( tg );
3115void QgsProject::updateTransactionGroups()
3119 mEditBufferGroup.clear();
3121 switch ( mTransactionMode )
3125 cleanTransactionGroups(
true );
3130 cleanTransactionGroups(
true );
3133 cleanTransactionGroups(
false );
3137 bool tgChanged =
false;
3138 const auto constLayers =
mapLayers().values();
3139 for ( QgsMapLayer *layer : constLayers )
3141 if ( !layer->isValid() )
3144 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
3148 switch ( mTransactionMode )
3160 QgsTransactionGroup *tg = mTransactionGroups.value( qMakePair( key, connString ) );
3164 tg =
new QgsTransactionGroup();
3165 mTransactionGroups.insert( qMakePair( key, connString ), tg );
3175 mEditBufferGroup.addLayer( vlayer );
3191 context.setProjectTranslator(
this );
3193 context.setCurrentLayerId( layerNode.toElement().firstChildElement( u
"id"_s ).text() );
3194 QList<QDomNode> brokenNodes;
3195 if ( addLayer( layerNode.toElement(), brokenNodes, context ) )
3203 layer->resolveReferences(
this );
3205 if ( layer->isValid() && layer->customProperty( u
"_layer_was_editable"_s ).toBool() )
3207 layer->startEditing();
3208 layer->removeCustomProperty( u
"_layer_was_editable"_s );
3220 mFile.setFileName( filename );
3222 mCachedHomePath.clear();
3230 mProjectScope.reset();
3236 const QString storageFilePath { storage->filePath( mFile.fileName() ) };
3237 if ( storageFilePath.isEmpty() )
3243 const QString tempPath = QStandardPaths::standardLocations( QStandardPaths::TempLocation ).at( 0 );
3244 const QString tmpZipFilename( tempPath + QDir::separator() + QUuid::createUuid().toString() );
3246 if ( !zip( tmpZipFilename ) )
3249 QFile tmpZipFile( tmpZipFilename );
3250 if ( !tmpZipFile.open( QIODevice::ReadOnly ) )
3252 setError( tr(
"Unable to read file %1" ).arg( tmpZipFilename ) );
3257 if ( !storage->writeProject( mFile.fileName(), &tmpZipFile, context ) )
3259 QString err = tr(
"Unable to save project to storage %1" ).arg( mFile.fileName() );
3260 QList<QgsReadWriteContext::ReadWriteMessage> messages = context.
takeMessages();
3261 if ( !messages.isEmpty() )
3262 err += u
"\n\n"_s + messages.last().message();
3268 QFile::remove( tmpZipFilename );
3275 return zip( mFile.fileName() );
3281 const bool asOk = saveAuxiliaryStorage();
3282 const bool writeOk = writeProjectFile( mFile.fileName() );
3283 bool attachmentsOk =
true;
3284 if ( !mArchive->files().isEmpty() )
3286 const QFileInfo finfo( mFile.fileName() );
3287 const QString attachmentsZip = finfo.absoluteDir().absoluteFilePath( u
"%1_attachments.zip"_s.arg( finfo.completeBaseName() ) );
3288 attachmentsOk = mArchive->zip( attachmentsZip );
3292 if ( ( !asOk || !attachmentsOk ) && writeOk )
3294 QStringList errorMessage;
3297 const QString err = mAuxiliaryStorage->errorString();
3298 errorMessage.append( tr(
"Unable to save auxiliary storage ('%1')" ).arg( err ) );
3300 if ( !attachmentsOk )
3302 errorMessage.append( tr(
"Unable to save attachments archive" ) );
3304 setError( errorMessage.join(
'\n' ) );
3307 return asOk && writeOk && attachmentsOk;
3311bool QgsProject::writeProjectFile(
const QString &filename )
3315 QFile projectFile( filename );
3321 const QFileInfo myFileInfo( projectFile );
3322 if ( myFileInfo.exists() && !myFileInfo.isWritable() )
3324 setError( tr(
"%1 is not writable. Please adjust permissions (if possible) and try again." ).arg( projectFile.fileName() ) );
3328 QgsReadWriteContext context;
3332 QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
3334 const QDomDocumentType documentType = QDomImplementation().createDocumentType( u
"qgis"_s, u
"http://mrcc.com/qgis.dtd"_s, u
"SYSTEM"_s );
3335 auto doc = std::make_unique<QDomDocument>( documentType );
3337 QDomElement qgisNode = doc->createElement( u
"qgis"_s );
3338 qgisNode.setAttribute( u
"projectname"_s,
title() );
3341 if ( !mSettings.value( u
"projects/anonymize_saved_projects"_s,
false,
QgsSettings::Core ).toBool() )
3345 qgisNode.setAttribute( u
"saveUser"_s, newSaveUser );
3346 qgisNode.setAttribute( u
"saveUserFull"_s, newSaveUserFull );
3347 mSaveUser = newSaveUser;
3348 mSaveUserFull = newSaveUserFull;
3349 if ( mMetadata.author().isEmpty() )
3353 if ( !mMetadata.creationDateTime().isValid() )
3355 mMetadata.setCreationDateTime( QDateTime( QDateTime::currentDateTime() ) );
3357 mSaveDateTime = QDateTime::currentDateTime();
3358 qgisNode.setAttribute( u
"saveDateTime"_s, mSaveDateTime.toString( Qt::ISODate ) );
3363 mSaveUserFull.clear();
3364 mMetadata.setAuthor( QString() );
3365 mMetadata.setCreationDateTime( QDateTime() );
3366 mSaveDateTime = QDateTime();
3368 doc->appendChild( qgisNode );
3371 QDomElement homePathNode = doc->createElement( u
"homePath"_s );
3372 homePathNode.setAttribute( u
"path"_s, mHomePath );
3373 qgisNode.appendChild( homePathNode );
3376 QDomElement titleNode = doc->createElement( u
"title"_s );
3377 qgisNode.appendChild( titleNode );
3379 QDomElement transactionNode = doc->createElement( u
"transaction"_s );
3380 transactionNode.setAttribute( u
"mode"_s,
qgsEnumValueToKey( mTransactionMode ) );
3381 qgisNode.appendChild( transactionNode );
3383 QDomElement flagsNode = doc->createElement( u
"projectFlags"_s );
3385 qgisNode.appendChild( flagsNode );
3387 const QDomText titleText = doc->createTextNode(
title() );
3388 titleNode.appendChild( titleText );
3392 QDomElement srsNode = doc->createElement( u
"projectCrs"_s );
3393 mCrs.writeXml( srsNode, *doc );
3394 qgisNode.appendChild( srsNode );
3397 QDomElement verticalSrsNode = doc->createElement( u
"verticalCrs"_s );
3398 mVerticalCrs.writeXml( verticalSrsNode, *doc );
3399 qgisNode.appendChild( verticalSrsNode );
3402 QDomElement elevationShadingNode = doc->createElement( u
"elevation-shading-renderer"_s );
3403 mElevationShadingRenderer.writeXml( elevationShadingNode, context );
3404 qgisNode.appendChild( elevationShadingNode );
3407 std::unique_ptr< QgsLayerTreeNode > clonedRoot( mRootGroup->clone() );
3411 clonedRoot->writeXml( qgisNode, context );
3414 mSnappingConfig.writeProject( *doc );
3415 writeEntry( u
"Digitizing"_s, u
"/AvoidIntersectionsMode"_s,
static_cast<int>( mAvoidIntersectionsMode ) );
3423 QDomElement annotationLayerNode = doc->createElement( u
"main-annotation-layer"_s );
3424 mMainAnnotationLayer->writeLayerXml( annotationLayerNode, *doc, context );
3425 qgisNode.appendChild( annotationLayerNode );
3429 QDomElement projectLayersNode = doc->createElement( u
"projectlayers"_s );
3431 QMap<QString, QgsMapLayer *>::ConstIterator li =
layers.constBegin();
3432 while ( li !=
layers.end() )
3434 QgsMapLayer *ml = li.value();
3438 const QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.constFind( ml->
id() );
3439 if ( emIt == mEmbeddedLayers.constEnd() )
3441 QDomElement maplayerElem;
3447 maplayerElem = doc->createElement( u
"maplayer"_s );
3451 maplayerElem.setAttribute( u
"editable"_s, u
"1"_s );
3455 QDomDocument document;
3458 maplayerElem = document.firstChildElement();
3462 QgsDebugError( u
"Could not restore layer properties for layer %1"_s.arg( ml->
id() ) );
3468 projectLayersNode.appendChild( maplayerElem );
3474 if ( emIt.value().second )
3476 QDomElement mapLayerElem = doc->createElement( u
"maplayer"_s );
3477 mapLayerElem.setAttribute( u
"embedded"_s, 1 );
3478 mapLayerElem.setAttribute( u
"project"_s,
writePath( emIt.value().first ) );
3479 mapLayerElem.setAttribute( u
"id"_s, ml->
id() );
3480 projectLayersNode.appendChild( mapLayerElem );
3487 qgisNode.appendChild( projectLayersNode );
3489 QDomElement layerOrderNode = doc->createElement( u
"layerorder"_s );
3490 const auto constCustomLayerOrder = mRootGroup->customLayerOrder();
3491 for ( QgsMapLayer *layer : constCustomLayerOrder )
3493 QDomElement mapLayerElem = doc->createElement( u
"layer"_s );
3494 mapLayerElem.setAttribute( u
"id"_s, layer->id() );
3495 layerOrderNode.appendChild( mapLayerElem );
3497 qgisNode.appendChild( layerOrderNode );
3499 mLabelingEngineSettings->writeSettingsToProject(
this );
3501 QDomElement labelEngineSettingsElement = doc->createElement( u
"labelEngineSettings"_s );
3502 mLabelingEngineSettings->writeXml( *doc, labelEngineSettingsElement, context );
3503 qgisNode.appendChild( labelEngineSettingsElement );
3506 writeEntry( u
"Gui"_s, u
"/CanvasColorRedPart"_s, mBackgroundColor.red() );
3507 writeEntry( u
"Gui"_s, u
"/CanvasColorGreenPart"_s, mBackgroundColor.green() );
3508 writeEntry( u
"Gui"_s, u
"/CanvasColorBluePart"_s, mBackgroundColor.blue() );
3510 writeEntry( u
"Gui"_s, u
"/SelectionColorRedPart"_s, mSelectionColor.red() );
3511 writeEntry( u
"Gui"_s, u
"/SelectionColorGreenPart"_s, mSelectionColor.green() );
3512 writeEntry( u
"Gui"_s, u
"/SelectionColorBluePart"_s, mSelectionColor.blue() );
3513 writeEntry( u
"Gui"_s, u
"/SelectionColorAlphaPart"_s, mSelectionColor.alpha() );
3521 dump_( mProperties );
3524 QgsDebugMsgLevel( u
"there are %1 property scopes"_s.arg(
static_cast<int>( mProperties.count() ) ), 2 );
3526 if ( !mProperties.isEmpty() )
3529 mProperties.writeXml( u
"properties"_s, qgisNode, *doc );
3532 QDomElement ddElem = doc->createElement( u
"dataDefinedServerProperties"_s );
3533 mDataDefinedServerProperties.writeXml( ddElem, dataDefinedServerPropertyDefinitions() );
3534 qgisNode.appendChild( ddElem );
3536 mMapThemeCollection->writeXml( *doc );
3538 mTransformContext.writeXml( qgisNode, context );
3540 QDomElement metadataElem = doc->createElement( u
"projectMetadata"_s );
3541 mMetadata.writeMetadataXml( metadataElem, *doc );
3542 qgisNode.appendChild( metadataElem );
3545 const QDomElement annotationsElem = mAnnotationManager->writeXml( *doc, context );
3546 qgisNode.appendChild( annotationsElem );
3550 const QDomElement layoutElem = mLayoutManager->writeXml( *doc );
3551 qgisNode.appendChild( layoutElem );
3555 const QDomElement elevationProfileElem = mElevationProfileManager->writeXml( *doc, context );
3556 qgisNode.appendChild( elevationProfileElem );
3560 const QDomElement selectiveMaskingSourceSetElem = mSelectiveMaskingSourceSetManager->writeXml( *doc, context );
3561 qgisNode.appendChild( selectiveMaskingSourceSetElem );
3565 const QDomElement views3DElem = m3DViewsManager->writeXml( *doc );
3566 qgisNode.appendChild( views3DElem );
3570 const QDomElement bookmarkElem = mBookmarkManager->writeXml( *doc );
3571 qgisNode.appendChild( bookmarkElem );
3575 const QDomElement sensorElem = mSensorManager->writeXml( *doc );
3576 qgisNode.appendChild( sensorElem );
3580 const QDomElement viewSettingsElem = mViewSettings->writeXml( *doc, context );
3581 qgisNode.appendChild( viewSettingsElem );
3585 const QDomElement styleSettingsElem = mStyleSettings->writeXml( *doc, context );
3586 qgisNode.appendChild( styleSettingsElem );
3590 const QDomElement timeSettingsElement = mTimeSettings->writeXml( *doc, context );
3591 qgisNode.appendChild( timeSettingsElement );
3595 const QDomElement elevationPropertiesElement = mElevationProperties->writeXml( *doc, context );
3596 qgisNode.appendChild( elevationPropertiesElement );
3600 const QDomElement displaySettingsElem = mDisplaySettings->writeXml( *doc, context );
3601 qgisNode.appendChild( displaySettingsElem );
3605 const QDomElement gpsSettingsElem = mGpsSettings->writeXml( *doc, context );
3606 qgisNode.appendChild( gpsSettingsElem );
3615 QFile backupFile( u
"%1~"_s.arg( filename ) );
3617 ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
3618 ok &= projectFile.open( QIODevice::ReadOnly );
3621 while ( ok && !projectFile.atEnd() )
3623 ba = projectFile.read( 10240 );
3624 ok &= backupFile.write( ba ) == ba.size();
3627 projectFile.close();
3632 setError( tr(
"Unable to create backup file %1" ).arg( backupFile.fileName() ) );
3637 struct utimbuf tb = {
static_cast<time_t
>( fi.lastRead().toSecsSinceEpoch() ),
static_cast<time_t
>( fi.lastModified().toSecsSinceEpoch() ) };
3638 utime( backupFile.fileName().toUtf8().constData(), &tb );
3641 if ( !projectFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3643 projectFile.close();
3646 setError( tr(
"Unable to save to file %1" ).arg( projectFile.fileName() ) );
3650 QTemporaryFile tempFile;
3651 bool ok = tempFile.open();
3654 QTextStream projectFileStream( &tempFile );
3655 doc->save( projectFileStream, 2 );
3656 ok &= projectFileStream.pos() > -1;
3658 ok &= tempFile.seek( 0 );
3661 while ( ok && !tempFile.atEnd() )
3663 ba = tempFile.read( 10240 );
3664 ok &= projectFile.write( ba ) == ba.size();
3667 ok &= projectFile.error() == QFile::NoError;
3669 projectFile.close();
3677 "Unable to save to file %1. Your project "
3678 "may be corrupted on disk. Try clearing some space on the volume and "
3679 "check file permissions before pressing save again."
3681 .arg( projectFile.fileName() ) );
3695 bool propertiesModified;
3696 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3698 if ( propertiesModified )
3708 bool propertiesModified;
3709 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3711 if ( propertiesModified )
3721 bool propertiesModified;
3722 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3724 if ( propertiesModified )
3734 bool propertiesModified;
3735 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3737 if ( propertiesModified )
3747 bool propertiesModified;
3748 const bool success =
addKey_( scope, key, &mProperties, value, propertiesModified );
3750 if ( propertiesModified )
3767 value =
property->value();
3769 const bool valid = QMetaType::Type::QStringList == value.userType();
3775 return value.toStringList();
3795 value =
property->value();
3797 const bool valid = value.canConvert( QMetaType::Type::QString );
3802 return value.toString();
3820 value =
property->value();
3823 const bool valid = value.canConvert( QMetaType::Type::Int );
3832 return value.toInt();
3845 const QVariant value =
property->value();
3847 const bool valid = value.canConvert( QMetaType::Type::Double );
3852 return value.toDouble();
3868 const QVariant value =
property->value();
3870 const bool valid = value.canConvert( QMetaType::Type::Bool );
3875 return value.toBool();
3887 if (
findKey_( scope, key, mProperties ) )
3893 return !
findKey_( scope, key, mProperties );
3902 QStringList entries;
3904 if ( foundProperty )
3923 QStringList entries;
3925 if ( foundProperty )
3942 dump_( mProperties );
3962 filePath = storage->filePath( mFile.fileName() );
3989void QgsProject::setError(
const QString &errorMessage )
3993 mErrorMessage = errorMessage;
4000 return mErrorMessage;
4003void QgsProject::clearError()
4007 setError( QString() );
4014 mBadLayerHandler.reset( handler );
4021 const QHash< QString, QPair< QString, bool > >::const_iterator it = mEmbeddedLayers.find(
id );
4022 if ( it == mEmbeddedLayers.constEnd() )
4026 return it.value().first;
4035 static QString sPrevProjectFilePath;
4036 static QDateTime sPrevProjectFileTimestamp;
4037 static QDomDocument sProjectDocument;
4039 QString qgsProjectFile = projectFilePath;
4041 if ( projectFilePath.endsWith(
".qgz"_L1, Qt::CaseInsensitive ) )
4043 archive.
unzip( projectFilePath );
4047 const QDateTime projectFileTimestamp = QFileInfo( projectFilePath ).lastModified();
4049 if ( projectFilePath != sPrevProjectFilePath || projectFileTimestamp != sPrevProjectFileTimestamp )
4051 sPrevProjectFilePath.clear();
4053 QFile projectFile( qgsProjectFile );
4054 if ( !projectFile.open( QIODevice::ReadOnly ) )
4059 if ( !sProjectDocument.setContent( &projectFile ) )
4064 sPrevProjectFilePath = projectFilePath;
4065 sPrevProjectFileTimestamp = projectFileTimestamp;
4069 bool useAbsolutePaths =
true;
4071 const QDomElement propertiesElem = sProjectDocument.documentElement().firstChildElement( u
"properties"_s );
4072 if ( !propertiesElem.isNull() )
4074 QDomElement e = propertiesElem.firstChildElement( u
"Paths"_s );
4077 e = propertiesElem.firstChildElement( u
"properties"_s );
4078 while ( !e.isNull() && e.attribute( u
"name"_s ) !=
"Paths"_L1 )
4079 e = e.nextSiblingElement( u
"properties"_s );
4081 e = e.firstChildElement( u
"properties"_s );
4082 while ( !e.isNull() && e.attribute( u
"name"_s ) !=
"Absolute"_L1 )
4083 e = e.nextSiblingElement( u
"properties"_s );
4087 e = e.firstChildElement( u
"Absolute"_s );
4092 useAbsolutePaths = e.text().compare(
"true"_L1, Qt::CaseInsensitive ) == 0;
4097 if ( !useAbsolutePaths )
4103 const QDomElement projectLayersElem = sProjectDocument.documentElement().firstChildElement( u
"projectlayers"_s );
4104 if ( projectLayersElem.isNull() )
4109 QDomElement mapLayerElem = projectLayersElem.firstChildElement( u
"maplayer"_s );
4110 while ( !mapLayerElem.isNull() )
4113 const QString
id = mapLayerElem.firstChildElement( u
"id"_s ).text();
4114 if (
id == layerId )
4117 if ( mapLayerElem.attribute( u
"embedded"_s ) ==
"1"_L1 )
4122 mEmbeddedLayers.insert( layerId, qMakePair( projectFilePath, saveFlag ) );
4124 if ( addLayer( mapLayerElem, brokenNodes, embeddedContext,
flags ) )
4130 mEmbeddedLayers.remove( layerId );
4134 mapLayerElem = mapLayerElem.nextSiblingElement( u
"maplayer"_s );
4144 QString qgsProjectFile = projectFilePath;
4146 if ( projectFilePath.endsWith(
".qgz"_L1, Qt::CaseInsensitive ) )
4148 archive.
unzip( projectFilePath );
4153 QFile projectFile( qgsProjectFile );
4154 if ( !projectFile.open( QIODevice::ReadOnly ) )
4159 QDomDocument projectDocument;
4160 if ( !projectDocument.setContent( &projectFile ) )
4170 auto root = std::make_unique< QgsLayerTreeGroup >();
4172 QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( u
"layer-tree-group"_s );
4173 if ( !layerTreeElem.isNull() )
4175 root->readChildrenFromXml( layerTreeElem, context );
4193 newGroup->setCustomProperty( u
"embedded"_s, 1 );
4194 newGroup->setCustomProperty( u
"embedded_project"_s, projectFilePath );
4197 mLayerTreeRegistryBridge->setEnabled(
false );
4198 initializeEmbeddedSubtree( projectFilePath, newGroup.get(),
flags );
4199 mLayerTreeRegistryBridge->setEnabled(
true );
4202 const QStringList constFindLayerIds = newGroup->findLayerIds();
4203 for (
const QString &layerId : constFindLayerIds )
4220 const auto constChildren = group->
children();
4224 child->setCustomProperty( u
"embedded"_s, 1 );
4233 QList<QDomNode> brokenNodes;
4257 writeEntry( u
"Digitizing"_s, u
"/TopologicalEditing"_s, ( enabled ? 1 : 0 ) );
4265 return readNumEntry( u
"Digitizing"_s, u
"/TopologicalEditing"_s, 0 );
4272 if ( mDistanceUnits == unit )
4275 mDistanceUnits = unit;
4284 if ( mAreaUnits == unit )
4296 if ( mScaleMethod == method )
4299 mScaleMethod = method;
4309 if ( !mCachedHomePath.isEmpty() )
4310 return mCachedHomePath;
4314 if ( !mHomePath.isEmpty() )
4316 const QFileInfo homeInfo( mHomePath );
4317 if ( !homeInfo.isRelative() )
4319 mCachedHomePath = mHomePath;
4328 const QString storagePath { storage->filePath(
fileName() ) };
4329 if ( !storagePath.isEmpty() && QFileInfo::exists( storagePath ) )
4331 mCachedHomePath = QFileInfo( storagePath ).path();
4332 return mCachedHomePath;
4336 mCachedHomePath = pfi.path();
4337 return mCachedHomePath;
4340 if ( !pfi.exists() )
4342 mCachedHomePath = mHomePath;
4346 if ( !mHomePath.isEmpty() )
4349 mCachedHomePath = QDir::cleanPath( pfi.path() +
'/' + mHomePath );
4353 mCachedHomePath = pfi.canonicalPath();
4355 return mCachedHomePath;
4370 return mRelationManager.get();
4377 return mLayoutManager.get();
4384 return mLayoutManager.get();
4391 return mElevationProfileManager.get();
4398 return mElevationProfileManager.get();
4405 return mSelectiveMaskingSourceSetManager.get();
4412 return mSelectiveMaskingSourceSetManager.get();
4419 return m3DViewsManager.get();
4426 return m3DViewsManager.get();
4433 return mBookmarkManager;
4440 return mBookmarkManager;
4447 return mSensorManager;
4454 return mSensorManager;
4461 return mViewSettings;
4468 return mViewSettings;
4475 return mStyleSettings;
4483 return mStyleSettings;
4490 return mTimeSettings;
4497 return mTimeSettings;
4504 return mElevationProperties;
4511 return mElevationProperties;
4518 return mDisplaySettings;
4525 return mDisplaySettings;
4532 return mGpsSettings;
4539 return mGpsSettings;
4546 return mRootGroup.get();
4553 return mMapThemeCollection.get();
4560 return mAnnotationManager.get();
4567 return mAnnotationManager.get();
4574 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
4575 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
4580 if (
layers.contains( it.value() ) )
4597 for (
const QString &layerId : layerIds )
4615 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
4647 updateTransactionGroups();
4654 return mTransactionMode;
4665 const auto constLayers =
mapLayers().values();
4668 if ( layer->isEditable() )
4670 QgsLogger::warning( tr(
"Transaction mode can be changed only if all layers are not editable." ) );
4676 updateTransactionGroups();
4685 return mTransactionGroups;
4698 return mLayerStore->count();
4705 return mLayerStore->validCount();
4713 if ( mMainAnnotationLayer && layerId == mMainAnnotationLayer->id() )
4714 return mMainAnnotationLayer;
4716 return mLayerStore->mapLayer( layerId );
4723 return mLayerStore->mapLayersByName( layerName );
4730 QList<QgsMapLayer *>
layers;
4731 const auto constMapLayers { mLayerStore->mapLayers() };
4732 for (
const auto &l : constMapLayers )
4734 if ( !l->serverProperties()->shortName().isEmpty() )
4736 if ( l->serverProperties()->shortName() == shortName )
4739 else if ( l->name() == shortName )
4752 auto archive = std::make_unique<QgsProjectArchive>();
4755 if ( !archive->unzip( filename ) )
4757 setError( tr(
"Unable to unzip file '%1'" ).arg( filename ) );
4762 if ( archive->projectFile().isEmpty() )
4764 setError( tr(
"Zip archive does not provide a project file" ) );
4769 releaseHandlesToProjectArchive();
4770 mArchive = std::move( archive );
4773 if ( !
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile().isEmpty() )
4777 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >(
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile(),
false );
4781 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >( *
this );
4785 if ( !readProjectFile(
static_cast<QgsProjectArchive *
>( mArchive.get() )->projectFile(),
flags ) )
4787 setError( tr(
"Cannot read unzipped qgs project file" ) + u
": "_s +
error() );
4792 static_cast<QgsProjectArchive *
>( mArchive.get() )->clearProjectFile();
4797bool QgsProject::zip(
const QString &filename )
4804 auto archive = std::make_unique<QgsProjectArchive>();
4805 const QString
baseName = QFileInfo( filename ).baseName();
4806 const QString qgsFileName = u
"%1.qgs"_s.arg(
baseName );
4807 QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
4809 bool writeOk =
false;
4810 if ( qgsFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
4812 writeOk = writeProjectFile( qgsFile.fileName() );
4819 setError( tr(
"Unable to write temporary qgs file" ) );
4824 const QFileInfo info( qgsFile );
4826 const QString asFileName = info.path() + QDir::separator() + info.completeBaseName() + asExt;
4828 bool auxiliaryStorageSavedOk =
true;
4829 if ( !saveAuxiliaryStorage( asFileName ) )
4831 const QString err = mAuxiliaryStorage->errorString();
4833 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 )
4835 auxiliaryStorageSavedOk =
false;
4838 if ( !mArchive->exists() )
4840 releaseHandlesToProjectArchive();
4841 mArchive = std::make_unique< QgsProjectArchive >();
4842 mArchive->unzip( mFile.fileName() );
4843 static_cast<QgsProjectArchive *
>( mArchive.get() )->clearProjectFile();
4845 const QString auxiliaryStorageFile =
static_cast<QgsProjectArchive *
>( mArchive.get() )->auxiliaryStorageFile();
4846 if ( !auxiliaryStorageFile.isEmpty() )
4848 archive->addFile( auxiliaryStorageFile );
4849 mAuxiliaryStorage = std::make_unique< QgsAuxiliaryStorage >( auxiliaryStorageFile,
false );
4857 if ( QFile::exists( asFileName ) )
4859 archive->addFile( asFileName );
4864 archive->addFile( qgsFile.fileName() );
4867 const QStringList &files = mArchive->files();
4868 for (
const QString &file : files )
4870 if ( !file.endsWith(
".qgs"_L1, Qt::CaseInsensitive ) && !file.endsWith( asExt, Qt::CaseInsensitive ) )
4872 archive->addFile( file );
4878 if ( !archive->zip( filename ) )
4880 setError( tr(
"Unable to perform zip" ) );
4884 return auxiliaryStorageSavedOk && zipOk;
4898 const QList<QgsMapLayer *> myResultList { mLayerStore->addMapLayers(
layers, takeOwnership ) };
4899 if ( !myResultList.isEmpty() )
4902 for (
auto &l : myResultList )
4916 if ( mAuxiliaryStorage )
4931 mProjectScope.reset();
4933 return myResultList;
4940 QList<QgsMapLayer *> addedLayers;
4941 addedLayers =
addMapLayers( QList<QgsMapLayer *>() << layer, addToLegend, takeOwnership );
4942 return addedLayers.isEmpty() ? nullptr : addedLayers[0];
4945void QgsProject::removeAuxiliaryLayer(
const QgsMapLayer *ml )
4952 const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( ml );
4964 for (
const auto &layerId : layerIds )
4965 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
4967 mProjectScope.reset();
4968 mLayerStore->removeMapLayers( layerIds );
4975 for (
const auto &layer :
layers )
4976 removeAuxiliaryLayer( layer );
4978 mProjectScope.reset();
4979 mLayerStore->removeMapLayers(
layers );
4986 removeAuxiliaryLayer( mLayerStore->mapLayer( layerId ) );
4987 mProjectScope.reset();
4988 mLayerStore->removeMapLayer( layerId );
4995 removeAuxiliaryLayer( layer );
4996 mProjectScope.reset();
4997 mLayerStore->removeMapLayer( layer );
5004 mProjectScope.reset();
5005 return mLayerStore->takeMapLayer( layer );
5012 return mMainAnnotationLayer;
5019 if ( mLayerStore->count() == 0 )
5022 ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
5023 mProjectScope.reset();
5024 mLayerStore->removeAllMapLayers();
5026 snapSingleBlocker.release();
5027 mSnappingConfig.clearIndividualLayerSettings();
5028 if ( !mBlockSnappingUpdates )
5036 const QMap<QString, QgsMapLayer *>
layers = mLayerStore->mapLayers();
5037 QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin();
5038 for ( ; it !=
layers.constEnd(); ++it )
5040 it.value()->reload();
5049 return validOnly ? mLayerStore->validMapLayers() : mLayerStore->mapLayers();
5056 return mTransactionGroups.value( qMakePair( providerKey, connString ) );
5063 return &mEditBufferGroup;
5074 if ( mSettings.value( u
"/projections/unknownCrsBehavior"_s, u
"NoAction"_s,
QgsSettings::App ).toString() == u
"UseProjectCrs"_s
5075 || mSettings.value( u
"/projections/unknownCrsBehavior"_s, 0,
QgsSettings::App ).toString() ==
"2"_L1 )
5083 const QString layerDefaultCrs = mSettings.value( u
"/Projections/layerDefaultCrs"_s, u
"EPSG:4326"_s ).toString();
5104bool QgsProject::saveAuxiliaryStorage(
const QString &filename )
5110 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
5115 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
5123 if ( !mAuxiliaryStorage->exists( *
this ) && empty )
5127 else if ( !filename.isEmpty() )
5129 return mAuxiliaryStorage->saveAs( filename );
5133 return mAuxiliaryStorage->saveAs( *
this );
5142 return sPropertyDefinitions;
5155 return mAuxiliaryStorage.get();
5162 return mAuxiliaryStorage.get();
5169 const QDir archiveDir( mArchive->dir() );
5170 QTemporaryFile tmpFile( archiveDir.filePath(
"XXXXXX_" + nameTemplate ),
this );
5171 tmpFile.setAutoRemove(
false );
5172 if ( !tmpFile.open() )
5174 setError( tr(
"Unable to open %1" ).arg( tmpFile.fileName() ) );
5177 mArchive->addFile( tmpFile.fileName() );
5178 return tmpFile.fileName();
5185 QStringList attachments;
5187 const QStringList files = mArchive->files();
5188 attachments.reserve( files.size() );
5189 for (
const QString &file : files )
5193 attachments.append( file );
5203 return mArchive->removeFile( path );
5210 return u
"attachment:///%1"_s.arg( QFileInfo( attachedFile ).
fileName() );
5217 if ( identifier.startsWith(
"attachment:///"_L1 ) )
5219 return QDir( mArchive->dir() ).absoluteFilePath( identifier.mid( 14 ) );
5240 mProjectScope.reset();
5255 for ( QMap<QString, QgsMapLayer *>::const_iterator it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
5269 const QMap<QString, QgsMapLayer *> &projectLayers =
mapLayers();
5270 for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
5275 if (
layers.contains( it.value() ) )
5287 QStringList customColors;
5288 QStringList customColorLabels;
5290 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
5291 for ( ; colorIt != colors.constEnd(); ++colorIt )
5294 const QString label = ( *colorIt ).second;
5295 customColors.append( color );
5296 customColorLabels.append( label );
5298 writeEntry( u
"Palette"_s, u
"/Colors"_s, customColors );
5299 writeEntry( u
"Palette"_s, u
"/Labels"_s, customColorLabels );
5300 mProjectScope.reset();
5308 if ( mBackgroundColor == color )
5311 mBackgroundColor = color;
5319 return mBackgroundColor;
5326 if ( mSelectionColor == color )
5329 mSelectionColor = color;
5337 return mSelectionColor;
5344 mViewSettings->setMapScales( scales );
5351 return mViewSettings->mapScales();
5358 mViewSettings->setUseProjectScales( enabled );
5365 return mViewSettings->useProjectScales();
5378 translationContext.writeTsFile( locale );
5381QString
QgsProject::translate(
const QString &context,
const QString &sourceText,
const char *disambiguation,
int n )
const
5390 QString result = mTranslator->translate( context.toUtf8(), sourceText.toUtf8(), disambiguation, n );
5392 if ( result.isEmpty() )
5406 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
5411 if ( !( ( *it )->accept( visitor ) ) )
5420 if ( !mLayoutManager->accept( visitor ) )
5423 if ( !mAnnotationManager->accept( visitor ) )
5433 const QString macros =
readEntry( u
"Macros"_s, u
"/pythonCode"_s, QString() );
5434 if ( !macros.isEmpty() )
5443 const QString expressionFunctions =
readEntry( u
"ExpressionFunctions"_s, u
"/pythonCode"_s );
5444 if ( !expressionFunctions.isEmpty() )
5456 for (
auto it =
layers.constBegin(); it !=
layers.constEnd(); ++it )
5458 if ( !( ( *it )->accept( visitor, context ) ) )
5470 return mElevationShadingRenderer;
5473void QgsProject::loadProjectFlags(
const QDomDocument *doc )
5477 QDomElement element = doc->documentElement().firstChildElement( u
"projectFlags"_s );
5479 if ( !element.isNull() )
5486 element = doc->documentElement().firstChildElement( u
"evaluateDefaultValues"_s );
5487 if ( !element.isNull() )
5489 if ( element.attribute( u
"active"_s, u
"0"_s ).toInt() == 1 )
5494 element = doc->documentElement().firstChildElement( u
"trust"_s );
5495 if ( !element.isNull() )
5497 if ( element.attribute( u
"active"_s, u
"0"_s ).toInt() == 1 )
5511 const QString projectFunctions =
readEntry( u
"ExpressionFunctions"_s, u
"/pythonCode"_s, QString() );
5512 if ( !projectFunctions.isEmpty() )
5532QHash< QString, QColor > loadColorsFromProject(
const QgsProject *project )
5534 QHash< QString, QColor > colors;
5537 QStringList colorStrings = project->
readListEntry( u
"Palette"_s, u
"/Colors"_s );
5538 const QStringList colorLabels = project->
readListEntry( u
"Palette"_s, u
"/Labels"_s );
5542 for ( QStringList::iterator it = colorStrings.begin(); it != colorStrings.end(); ++it )
5546 if ( colorLabels.length() > colorIndex )
5548 label = colorLabels.at( colorIndex );
5551 colors.insert( label.toLower(), color );
5559GetNamedProjectColor::GetNamedProjectColor(
const QgsProject *project )
5565 mColors = loadColorsFromProject( project );
5568GetNamedProjectColor::GetNamedProjectColor(
const QHash<QString, QColor> &colors )
5575 const QString colorName = values.at( 0 ).toString().toLower();
5576 if ( mColors.contains( colorName ) )
5578 return u
"%1,%2,%3"_s.arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
5586 return new GetNamedProjectColor( mColors );
5589GetNamedProjectColorObject::GetNamedProjectColorObject(
const QgsProject *project )
5595 mColors = loadColorsFromProject( project );
5598GetNamedProjectColorObject::GetNamedProjectColorObject(
const QHash<QString, QColor> &colors )
5605 const QString colorName = values.at( 0 ).toString().toLower();
5606 if ( mColors.contains( colorName ) )
5608 return mColors.value( colorName );
5616 return new GetNamedProjectColorObject( mColors );
5621GetSensorData::GetSensorData(
const QMap<QString, QgsAbstractSensor::SensorData> &sensorData )
5623 , mSensorData( sensorData )
5628 const QString sensorName = values.at( 0 ).toString();
5629 const int expiration = values.at( 1 ).toInt();
5630 const qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
5631 if ( mSensorData.contains( sensorName ) )
5633 if ( expiration <= 0 || ( timestamp - mSensorData[sensorName].lastTimestamp.toMSecsSinceEpoch() ) < expiration )
5635 return mSensorData[sensorName].lastValue;
5644 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.
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
Utility class that encapsulates an action based on vector attributes.
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").
virtual QgsLegendSymbolList legendSymbolItems() const
Returns a list of symbology items for the legend.
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.
Stores information about one class/rule of a vector layer renderer in a unified way that can be used ...
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(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
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 layersAddedWithoutLegend(const QList< QgsMapLayer * > &layers)
Emitted when layers were added to the registry without adding to the legend.
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 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 specified scope and key.
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.
const QgsSelectiveMaskingSourceSetManager * selectiveMaskingSourceSetManager() const
Returns the project's selective masking set manager, which manages storage of a set of selective mask...
void legendLayersAdded(const QList< QgsMapLayer * > &layers)
Emitted when layers were 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 setCurrentLayerId(const QString &layerId)
Sets the current layer id.
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.
Manages storage of a set of selective masking source sets.
static const QgsSettingsEntryColor * settingsDefaultCanvasColor
Settings entry for default canvas background color.
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.
static const QgsSettingsEntryColor * settingsDefaultSelectionColor
Settings entry for default selection color.
static const QgsSettingsEntryString * settingsMeasureDisplayUnits
Settings entry for distance display units.
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.
static QString threadDescription(QThread *thread)
Returns a descriptive identifier for a thread.
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...
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
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...
QgsActionManager * actions()
Returns all layer actions defined on this layer.
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.