From 96d5cc99b37acb59ed0704da34f7fd2bc49846ce Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Sun, 24 Mar 2024 16:13:45 +0100 Subject: [PATCH] Consider setting layerTreeInsertionMethod when adding content from qlr to canvas --- .../auto_generated/qgslayerdefinition.sip.in | 24 +++++++++++++-- .../auto_generated/qgslayerdefinition.sip.in | 24 +++++++++++++-- src/app/layers/qgsapplayerhandling.cpp | 8 ++--- src/app/layers/qgsapplayerhandling.h | 15 ++++++++-- src/app/qgisapp.cpp | 11 +++++-- src/app/qgisapp.h | 5 ++++ src/core/qgslayerdefinition.cpp | 27 ++++++++++++++--- src/core/qgslayerdefinition.h | 29 ++++++++++++++++--- 8 files changed, 122 insertions(+), 21 deletions(-) diff --git a/python/PyQt6/core/auto_generated/qgslayerdefinition.sip.in b/python/PyQt6/core/auto_generated/qgslayerdefinition.sip.in index a96b4c3d629..ceaa7065380 100644 --- a/python/PyQt6/core/auto_generated/qgslayerdefinition.sip.in +++ b/python/PyQt6/core/auto_generated/qgslayerdefinition.sip.in @@ -25,13 +25,33 @@ files also store the layer tree info for the exported layers, including group in #include "qgslayerdefinition.h" %End public: - static bool loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage /Out/ ); + + static bool loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage /Out/, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint = 0 ); %Docstring Loads the QLR at path into QGIS. New layers are added to given project into layer tree specified by rootGroup + +:param path: file path to the qlr +:param project: the current project +:param rootGroup: the layer tree group to insert the qlr content +:param insertPoint: describes where in rootGroup the qlr layers/groups shall be inserted + +:return: - true in case of success + - errorMessage: the returned error message %End - static bool loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage /Out/, QgsReadWriteContext &context ); + + static bool loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage /Out/, QgsReadWriteContext &context, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint = 0 ); %Docstring Loads the QLR from the XML document. New layers are added to given project into layer tree specified by rootGroup + +:param doc: the xml document +:param project: the current project +:param rootGroup: the layer tree group to insert the qlr content +:param context: the read write context +:param insertPoint: describes where in rootGroup the qlr layers/groups shall be inserted +:param true: in case of success + +:return: - true in case of success + - errorMessage: the returned error message %End static bool exportLayerDefinition( const QString &path, const QList &selectedTreeNodes, QString &errorMessage /Out/ ); diff --git a/python/core/auto_generated/qgslayerdefinition.sip.in b/python/core/auto_generated/qgslayerdefinition.sip.in index a96b4c3d629..ceaa7065380 100644 --- a/python/core/auto_generated/qgslayerdefinition.sip.in +++ b/python/core/auto_generated/qgslayerdefinition.sip.in @@ -25,13 +25,33 @@ files also store the layer tree info for the exported layers, including group in #include "qgslayerdefinition.h" %End public: - static bool loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage /Out/ ); + + static bool loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage /Out/, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint = 0 ); %Docstring Loads the QLR at path into QGIS. New layers are added to given project into layer tree specified by rootGroup + +:param path: file path to the qlr +:param project: the current project +:param rootGroup: the layer tree group to insert the qlr content +:param insertPoint: describes where in rootGroup the qlr layers/groups shall be inserted + +:return: - true in case of success + - errorMessage: the returned error message %End - static bool loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage /Out/, QgsReadWriteContext &context ); + + static bool loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage /Out/, QgsReadWriteContext &context, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint = 0 ); %Docstring Loads the QLR from the XML document. New layers are added to given project into layer tree specified by rootGroup + +:param doc: the xml document +:param project: the current project +:param rootGroup: the layer tree group to insert the qlr content +:param context: the read write context +:param insertPoint: describes where in rootGroup the qlr layers/groups shall be inserted +:param true: in case of success + +:return: - true in case of success + - errorMessage: the returned error message %End static bool exportLayerDefinition( const QString &path, const QList &selectedTreeNodes, QString &errorMessage /Out/ ); diff --git a/src/app/layers/qgsapplayerhandling.cpp b/src/app/layers/qgsapplayerhandling.cpp index 17ba4e979e1..145fa619775 100644 --- a/src/app/layers/qgsapplayerhandling.cpp +++ b/src/app/layers/qgsapplayerhandling.cpp @@ -1209,7 +1209,7 @@ void QgsAppLayerHandling::addMapLayer( QgsMapLayer *mapLayer, bool addToLegend ) } } -void QgsAppLayerHandling::openLayerDefinition( const QString &filename ) +void QgsAppLayerHandling::openLayerDefinition( const QString &filename, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint ) { QString errorMessage; QgsReadWriteContext context; @@ -1236,7 +1236,7 @@ void QgsAppLayerHandling::openLayerDefinition( const QString &filename ) context.setPathResolver( QgsPathResolver( filename ) ); context.setProjectTranslator( QgsProject::instance() ); - loaded = QgsLayerDefinition::loadLayerDefinition( doc, QgsProject::instance(), QgsProject::instance()->layerTreeRoot(), errorMessage, context ); + loaded = QgsLayerDefinition::loadLayerDefinition( doc, QgsProject::instance(), QgsProject::instance()->layerTreeRoot(), errorMessage, context, insertPoint ); } } @@ -1260,7 +1260,7 @@ void QgsAppLayerHandling::openLayerDefinition( const QString &filename ) } } -void QgsAppLayerHandling::addLayerDefinition() +void QgsAppLayerHandling::addLayerDefinition( const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint ) { QgsSettings settings; QString lastUsedDir = settings.value( QStringLiteral( "UI/lastQLRDir" ), QDir::homePath() ).toString(); @@ -1272,7 +1272,7 @@ void QgsAppLayerHandling::addLayerDefinition() QFileInfo fi( path ); settings.setValue( QStringLiteral( "UI/lastQLRDir" ), fi.path() ); - openLayerDefinition( path ); + openLayerDefinition( path, insertPoint ); } QList< QgsMapLayer * > QgsAppLayerHandling::addDatabaseLayers( const QStringList &layerPathList, const QString &providerKey, bool &ok ) diff --git a/src/app/layers/qgsapplayerhandling.h b/src/app/layers/qgsapplayerhandling.h index 7e16fbbcf72..6df5b3f78ce 100644 --- a/src/app/layers/qgsapplayerhandling.h +++ b/src/app/layers/qgsapplayerhandling.h @@ -20,6 +20,7 @@ #include "qgsconfig.h" #include "qgsmaplayer.h" #include "qgsvectorlayerref.h" +#include "qgslayertreeregistrybridge.h" #include @@ -149,10 +150,18 @@ class APP_EXPORT QgsAppLayerHandling //! Add a 'pre-made' map layer to the project static void addMapLayer( QgsMapLayer *mapLayer, bool addToLegend = true ); - static void openLayerDefinition( const QString &filename ); + /** + * Opens qlr + * \param filename file path to the qlr + * \param insertPoint describes where the qlr layers/groups shall be inserted + */ + static void openLayerDefinition( const QString &filename, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint = nullptr ); - //! Add a Layer Definition file - static void addLayerDefinition(); + /** + * Add a Layer Definition file + * \param insertPoint describes where the qlr layers/groups shall be inserted + */ + static void addLayerDefinition( const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint ); //! Add a list of database layers to the map static QList< QgsMapLayer * > addDatabaseLayers( const QStringList &layerPathList, const QString &providerKey, bool &ok ); diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 6a34efc4a6b..b40413bb7bf 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -863,6 +863,12 @@ void QgisApp::annotationItemTypeAdded( int id ) } ); } +void QgisApp::addLayerDefinition() +{ + QgsLayerTreeRegistryBridge::InsertionPoint pt = layerTreeInsertionPoint(); + QgsAppLayerHandling::addLayerDefinition( &pt ); +} + /* * This function contains forced validation of CRS used in QGIS. * There are 4 options depending on the settings: @@ -3030,7 +3036,7 @@ void QgisApp::createActions() connect( mActionShowRasterCalculator, &QAction::triggered, this, &QgisApp::showRasterCalculator ); connect( mActionShowMeshCalculator, &QAction::triggered, this, &QgisApp::showMeshCalculator ); connect( mActionEmbedLayers, &QAction::triggered, this, &QgisApp::embedLayers ); - connect( mActionAddLayerDefinition, &QAction::triggered, this, [] { QgsAppLayerHandling::addLayerDefinition(); } ); + connect( mActionAddLayerDefinition, &QAction::triggered, this, &QgisApp::addLayerDefinition ); connect( mActionAddOgrLayer, &QAction::triggered, this, [ = ] { dataSourceManager( QStringLiteral( "ogr" ) ); } ); connect( mActionAddRasterLayer, &QAction::triggered, this, [ = ] { dataSourceManager( QStringLiteral( "gdal" ) ); } ); connect( mActionAddMeshLayer, &QAction::triggered, this, [ = ] { dataSourceManager( QStringLiteral( "mdal" ) ); } ); @@ -7062,7 +7068,8 @@ QList< QgsMapLayer * > QgisApp::openFile( const QString &fileName, const QString } else if ( fi.suffix().compare( QLatin1String( "qlr" ), Qt::CaseInsensitive ) == 0 ) { - QgsAppLayerHandling::openLayerDefinition( fileName ); + QgsLayerTreeRegistryBridge::InsertionPoint p = layerTreeInsertionPoint(); + QgsAppLayerHandling::openLayerDefinition( fileName, &p ); } else if ( fi.suffix().compare( QLatin1String( "qpt" ), Qt::CaseInsensitive ) == 0 ) { diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index 745c52536a4..a0a986622b9 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -2117,6 +2117,11 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow void annotationItemTypeAdded( int id ); + /** + * Open a qlr file + */ + void addLayerDefinition(); + signals: /** diff --git a/src/core/qgslayerdefinition.cpp b/src/core/qgslayerdefinition.cpp index 307218d1f83..518b87a3045 100644 --- a/src/core/qgslayerdefinition.cpp +++ b/src/core/qgslayerdefinition.cpp @@ -38,7 +38,7 @@ #include "qgslayertreegroup.h" #include "qgslayertreelayer.h" -bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage ) +bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint ) { QFile file( path ); if ( !file.open( QIODevice::ReadOnly ) ) @@ -62,10 +62,10 @@ bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsProject *p context.setPathResolver( QgsPathResolver( path ) ); context.setProjectTranslator( project ); - return loadLayerDefinition( doc, project, rootGroup, errorMessage, context ); + return loadLayerDefinition( doc, project, rootGroup, errorMessage, context, insertPoint ); } -bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage, QgsReadWriteContext &context ) +bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage, QgsReadWriteContext &context, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint ) { errorMessage.clear(); @@ -195,7 +195,26 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject *proj root->abandonChildren(); delete root; - rootGroup->insertChildNodes( -1, nodes ); + QgsSettings settings; + if ( !insertPoint ) + { + rootGroup->insertChildNodes( -1, nodes ); + } + else + { + Qgis::LayerTreeInsertionMethod insertionMethod = settings.enumValue( QStringLiteral( "qgis/layerTreeInsertionMethod" ), Qgis::LayerTreeInsertionMethod::AboveInsertionPoint ); + switch ( insertionMethod ) + { + case Qgis::LayerTreeInsertionMethod::AboveInsertionPoint: + insertPoint->group->insertChildNodes( insertPoint->position, nodes ); + break; + case Qgis::LayerTreeInsertionMethod::TopOfTree: + rootGroup->insertChildNodes( 0, nodes ); + break; + default: + rootGroup->insertChildNodes( -1, nodes ); //Qgis::LayerTreeInsertionMethod::OptimalInInsertionGroup does not really make sense for qlr + } + } return true; } diff --git a/src/core/qgslayerdefinition.h b/src/core/qgslayerdefinition.h index 97d1c472a47..12ed746d609 100644 --- a/src/core/qgslayerdefinition.h +++ b/src/core/qgslayerdefinition.h @@ -19,6 +19,7 @@ #include "qgis_core.h" #include "qgis_sip.h" #include "qgis.h" +#include "qgslayertreeregistrybridge.h" #include #include @@ -44,10 +45,30 @@ class QgsProject; class CORE_EXPORT QgsLayerDefinition { public: - //! Loads the QLR at path into QGIS. New layers are added to given project into layer tree specified by rootGroup - static bool loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage SIP_OUT ); - //! Loads the QLR from the XML document. New layers are added to given project into layer tree specified by rootGroup - static bool loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage SIP_OUT, QgsReadWriteContext &context ); + + /** + * Loads the QLR at path into QGIS. New layers are added to given project into layer tree specified by rootGroup + * \param path file path to the qlr + * \param project the current project + * \param rootGroup the layer tree group to insert the qlr content + * \param errorMessage the returned error message + * \param insertPoint describes where in rootGroup the qlr layers/groups shall be inserted + * \return true in case of success + */ + static bool loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage SIP_OUT, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint = nullptr ); + + /** + * Loads the QLR from the XML document. New layers are added to given project into layer tree specified by rootGroup + * \param doc the xml document + * \param project the current project + * \param rootGroup the layer tree group to insert the qlr content + * \param errorMessage the returned error message + * \param context the read write context + * \param insertPoint describes where in rootGroup the qlr layers/groups shall be inserted + * \param true in case of success + * \return true in case of success + */ + static bool loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage SIP_OUT, QgsReadWriteContext &context, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint = nullptr ); /** * Exports the selected layer tree nodes to a QLR file.