From cce776c76a54ea3fbc7a44e5675e166b261ced76 Mon Sep 17 00:00:00 2001 From: "r.abdullaev" <caboose7@yandex.ru> Date: Wed, 25 Sep 2024 09:39:36 +0300 Subject: [PATCH] add possibility to add custom actions for the group-nodes in the layer tree --- .../gui/auto_generated/qgisinterface.sip.in | 13 +++ .../gui/auto_generated/qgisinterface.sip.in | 13 +++ src/app/qgisappinterface.cpp | 18 +++++ src/app/qgisappinterface.h | 3 + src/app/qgsapplayertreeviewmenuprovider.cpp | 81 +++++++++++++++++-- src/app/qgsapplayertreeviewmenuprovider.h | 8 ++ src/gui/qgisinterface.h | 12 +++ 7 files changed, 140 insertions(+), 8 deletions(-) diff --git a/python/PyQt6/gui/auto_generated/qgisinterface.sip.in b/python/PyQt6/gui/auto_generated/qgisinterface.sip.in index 04d4e289c1854..4ba0e3dcb508a 100644 --- a/python/PyQt6/gui/auto_generated/qgisinterface.sip.in +++ b/python/PyQt6/gui/auto_generated/qgisinterface.sip.in @@ -65,6 +65,11 @@ It is necessary to first call :py:func:`~QgisInterface.addCustomActionForLayerTy in order for this method to have any effect. .. seealso:: :py:func:`addCustomActionForLayerType` +%End + + virtual void addCustomActionForGroups( QAction *action, QString menu ) = 0; +%Docstring +Add action to context menu for all group-nodes in the layer tree. %End virtual bool removeCustomActionForLayerType( QAction *action ) = 0; @@ -72,6 +77,14 @@ in order for this method to have any effect. Remove action for layers in the layer tree previously added with :py:func:`~QgisInterface.addCustomActionForLayerType` .. seealso:: :py:func:`addCustomActionForLayerType` +%End + + virtual bool removeCustomActionForGroups( QAction *action ) = 0; +%Docstring +Remove action from the context menu for all group-nodes in the layer tree +previously added with :py:func:`~QgisInterface.addCustomActionForGroups`. + +.. seealso:: :py:func:`addCustomActionForGroups` %End virtual QList< QgsMapCanvas * > mapCanvases() = 0; diff --git a/python/gui/auto_generated/qgisinterface.sip.in b/python/gui/auto_generated/qgisinterface.sip.in index 04d4e289c1854..4ba0e3dcb508a 100644 --- a/python/gui/auto_generated/qgisinterface.sip.in +++ b/python/gui/auto_generated/qgisinterface.sip.in @@ -65,6 +65,11 @@ It is necessary to first call :py:func:`~QgisInterface.addCustomActionForLayerTy in order for this method to have any effect. .. seealso:: :py:func:`addCustomActionForLayerType` +%End + + virtual void addCustomActionForGroups( QAction *action, QString menu ) = 0; +%Docstring +Add action to context menu for all group-nodes in the layer tree. %End virtual bool removeCustomActionForLayerType( QAction *action ) = 0; @@ -72,6 +77,14 @@ in order for this method to have any effect. Remove action for layers in the layer tree previously added with :py:func:`~QgisInterface.addCustomActionForLayerType` .. seealso:: :py:func:`addCustomActionForLayerType` +%End + + virtual bool removeCustomActionForGroups( QAction *action ) = 0; +%Docstring +Remove action from the context menu for all group-nodes in the layer tree +previously added with :py:func:`~QgisInterface.addCustomActionForGroups`. + +.. seealso:: :py:func:`addCustomActionForGroups` %End virtual QList< QgsMapCanvas * > mapCanvases() = 0; diff --git a/src/app/qgisappinterface.cpp b/src/app/qgisappinterface.cpp index ca870fc2040ea..d1ad051c48fa6 100644 --- a/src/app/qgisappinterface.cpp +++ b/src/app/qgisappinterface.cpp @@ -101,6 +101,15 @@ void QgisAppInterface::addCustomActionForLayer( QAction *action, QgsMapLayer *la menuProvider->addLegendLayerActionForLayer( action, layer ); } +void QgisAppInterface::addCustomActionForGroups(QAction *action, QString menu ) +{ + QgsAppLayerTreeViewMenuProvider *menuProvider = dynamic_cast<QgsAppLayerTreeViewMenuProvider *>( qgis->layerTreeView()->menuProvider() ); + if ( !menuProvider ) + return; + + menuProvider->addLegendLayerActionForGroup( action, menu ); +} + bool QgisAppInterface::removeCustomActionForLayerType( QAction *action ) { QgsAppLayerTreeViewMenuProvider *menuProvider = dynamic_cast<QgsAppLayerTreeViewMenuProvider *>( qgis->layerTreeView()->menuProvider() ); @@ -110,6 +119,15 @@ bool QgisAppInterface::removeCustomActionForLayerType( QAction *action ) return menuProvider->removeLegendLayerAction( action ); } +bool QgisAppInterface::removeCustomActionForGroups( QAction *action ) +{ + QgsAppLayerTreeViewMenuProvider *menuProvider = dynamic_cast<QgsAppLayerTreeViewMenuProvider *>( qgis->layerTreeView()->menuProvider() ); + if ( !menuProvider ) + return false; + + return menuProvider->removeLegendLayerActionForGroup( action ); +} + void QgisAppInterface::zoomFull() { qgis->zoomFull(); diff --git a/src/app/qgisappinterface.h b/src/app/qgisappinterface.h index b67407b5d6d9b..e994faef37c73 100644 --- a/src/app/qgisappinterface.h +++ b/src/app/qgisappinterface.h @@ -58,7 +58,10 @@ class APP_EXPORT QgisAppInterface : public QgisInterface void addCustomActionForLayerType( QAction *action, QString menu, Qgis::LayerType type, bool allLayers ) override; void addCustomActionForLayer( QAction *action, QgsMapLayer *layer ) override; + void addCustomActionForGroups( QAction *action, QString menu ) override; + bool removeCustomActionForLayerType( QAction *action ) override; + bool removeCustomActionForGroups( QAction *action ) override; /* Exposed functions */ diff --git a/src/app/qgsapplayertreeviewmenuprovider.cpp b/src/app/qgsapplayertreeviewmenuprovider.cpp index 301a679da8a70..5a01943bcd3f5 100644 --- a/src/app/qgsapplayertreeviewmenuprovider.cpp +++ b/src/app/qgsapplayertreeviewmenuprovider.cpp @@ -105,7 +105,10 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu() menu->addAction( actions->actionRenameGroupOrLayer( menu ) ); + addCustomGroupActions( menu ); + menu->addSeparator(); + menu->addAction( actions->actionAddGroup( menu ) ); QAction *removeAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove Group…" ), QgisApp::instance(), &QgisApp::removeLayer ); removeAction->setEnabled( removeActionEnabled() ); @@ -1014,6 +1017,35 @@ void QgsAppLayerTreeViewMenuProvider::removeLegendLayerActionsForLayer( QgsMapLa } } +void QgsAppLayerTreeViewMenuProvider::addLegendLayerActionForGroup( QAction *action , const QString &menu ) +{ + mGroupLegendLayerActionList.append( LegendLayerAction( action, menu, false ) ); +} + +bool QgsAppLayerTreeViewMenuProvider::removeLegendLayerActionForGroup( QAction *action ) +{ + size_t beforeRemoveSize = mGroupLegendLayerActionList.size(); + mGroupLegendLayerActionList.erase( std::remove_if( mGroupLegendLayerActionList.begin(), mGroupLegendLayerActionList.end(), + [&]( const LegendLayerAction& lla ) + { + return lla.action == action; + } ), mGroupLegendLayerActionList.end() ); + size_t afterRemoveSize = mGroupLegendLayerActionList.size(); + return afterRemoveSize < beforeRemoveSize; +} + +bool QgsAppLayerTreeViewMenuProvider::removeLegendLayerActionsForGroup( const QString &menu ) +{ + size_t beforeRemoveSize = mGroupLegendLayerActionList.size(); + mGroupLegendLayerActionList.erase( std::remove_if( mGroupLegendLayerActionList.begin(), mGroupLegendLayerActionList.end(), + [&]( const LegendLayerAction& lla ) + { + return lla.menu == menu; + } ), mGroupLegendLayerActionList.end() ); + size_t afterRemoveSize = mGroupLegendLayerActionList.size(); + return afterRemoveSize < beforeRemoveSize; +} + QList< LegendLayerAction > QgsAppLayerTreeViewMenuProvider::legendLayerActions( Qgis::LayerType type ) const { #ifdef QGISDEBUG @@ -1033,6 +1065,24 @@ QList< LegendLayerAction > QgsAppLayerTreeViewMenuProvider::legendLayerActions( return mLegendLayerActionMap.contains( type ) ? mLegendLayerActionMap.value( type ) : QList< LegendLayerAction >(); } +QList< LegendLayerAction > QgsAppLayerTreeViewMenuProvider::groupLegendLayerActions() const +{ + return mGroupLegendLayerActionList; +} + +QList< QAction* > QgsAppLayerTreeViewMenuProvider::groupMenuActions( const QString& menu) const +{ + QList< QAction* > actionForGroupMenuList; + for (const auto& groupLegendLayerAction : mGroupLegendLayerActionList) + { + if (groupLegendLayerAction.menu == menu) + { + actionForGroupMenuList.push_back(groupLegendLayerAction.action); + } + } + return actionForGroupMenuList; +} + void QgsAppLayerTreeViewMenuProvider::addCustomLayerActions( QMenu *menu, QgsMapLayer *layer ) { if ( !layer ) @@ -1043,21 +1093,38 @@ void QgsAppLayerTreeViewMenuProvider::addCustomLayerActions( QMenu *menu, QgsMap if ( ! lyrActions.isEmpty() ) { + addCustomActionsToMenu( menu, lyrActions ); + } +} + +void QgsAppLayerTreeViewMenuProvider::addCustomGroupActions(QMenu *menu) +{ + // add custom group actions - should this go at end? + QList< LegendLayerAction > groupActions = groupLegendLayerActions(); + + if ( ! groupActions.isEmpty() ) + { + addCustomActionsToMenu( menu, groupActions ); + } + +} + +void QgsAppLayerTreeViewMenuProvider::addCustomActionsToMenu(QMenu *menu, const QList<LegendLayerAction> &customActions) +{ menu->addSeparator(); QList<QMenu *> menus; - for ( int i = 0; i < lyrActions.count(); i++ ) + for ( int i = 0; i < customActions.count(); i++ ) { - if ( lyrActions[i].allLayers || lyrActions[i].layers.contains( layer ) ) { - if ( lyrActions[i].menu.isEmpty() ) + if ( customActions[i].menu.isEmpty() ) { - menu->addAction( lyrActions[i].action ); + menu->addAction( customActions[i].action ); } else { // find or create menu for given menu name // adapted from QgisApp::getPluginMenu( QString menuName ) - QString menuName = lyrActions[i].menu; + QString menuName = customActions[i].menu; #ifdef Q_OS_MAC // Mac doesn't have '&' keyboard shortcuts. menuName.remove( QChar( '&' ) ); @@ -1093,13 +1160,11 @@ void QgsAppLayerTreeViewMenuProvider::addCustomLayerActions( QMenu *menu, QgsMap // Where to put it? - we worked that out above... menu->insertMenu( before, newMenu ); } - // QMenu* menu = getMenu( lyrActions[i].menu, &beforeSep, &afterSep, &menu ); - newMenu->addAction( lyrActions[i].action ); + newMenu->addAction( customActions[i].action ); } } } menu->addSeparator(); - } } void QgsAppLayerTreeViewMenuProvider::editVectorSymbol( const QString &layerId ) diff --git a/src/app/qgsapplayertreeviewmenuprovider.h b/src/app/qgsapplayertreeviewmenuprovider.h index e3b7afabf76e2..ee69de56c3900 100644 --- a/src/app/qgsapplayertreeviewmenuprovider.h +++ b/src/app/qgsapplayertreeviewmenuprovider.h @@ -51,16 +51,24 @@ class QgsAppLayerTreeViewMenuProvider : public QObject, public QgsLayerTreeViewM bool removeLegendLayerAction( QAction *action ); void addLegendLayerActionForLayer( QAction *action, QgsMapLayer *layer ); void removeLegendLayerActionsForLayer( QgsMapLayer *layer ); + void addLegendLayerActionForGroup( QAction *action, const QString &menu ); + bool removeLegendLayerActionForGroup( QAction *action ); + bool removeLegendLayerActionsForGroup( const QString& menu ); QList< LegendLayerAction > legendLayerActions( Qgis::LayerType type ) const; + QList< LegendLayerAction > groupLegendLayerActions() const; + QList< QAction* > groupMenuActions( const QString& menu ) const; protected: void addCustomLayerActions( QMenu *menu, QgsMapLayer *layer ); + void addCustomGroupActions( QMenu *menu ); + void addCustomActionsToMenu( QMenu *menu, const QList< LegendLayerAction >& customActions ); QgsLayerTreeView *mView = nullptr; QgsMapCanvas *mCanvas = nullptr; QMap< Qgis::LayerType, QList< LegendLayerAction > > mLegendLayerActionMap; + QList< LegendLayerAction > mGroupLegendLayerActionList; private slots: diff --git a/src/gui/qgisinterface.h b/src/gui/qgisinterface.h index 4c454e6c3ba26..f8dc27168772b 100644 --- a/src/gui/qgisinterface.h +++ b/src/gui/qgisinterface.h @@ -129,12 +129,24 @@ class GUI_EXPORT QgisInterface : public QObject */ virtual void addCustomActionForLayer( QAction *action, QgsMapLayer *layer ) = 0; + /** + * Add action to context menu for all group-nodes in the layer tree. + */ + virtual void addCustomActionForGroups( QAction *action, QString menu ) = 0; + /** * Remove action for layers in the layer tree previously added with addCustomActionForLayerType() * \see addCustomActionForLayerType() */ virtual bool removeCustomActionForLayerType( QAction *action ) = 0; + /** + * Remove action from the context menu for all group-nodes in the layer tree + * previously added with addCustomActionForGroups(). + * \see addCustomActionForGroups() + */ + virtual bool removeCustomActionForGroups( QAction *action ) = 0; + /** * Returns a list of all map canvases open in the app. */