Skip to content

Commit

Permalink
add possibility to add custom actions for the group-nodes in the laye…
Browse files Browse the repository at this point in the history
…r tree
  • Loading branch information
notguiltyspark committed Nov 25, 2024
1 parent a4dca08 commit cce776c
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 8 deletions.
13 changes: 13 additions & 0 deletions python/PyQt6/gui/auto_generated/qgisinterface.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,26 @@ 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;
%Docstring
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;
Expand Down
13 changes: 13 additions & 0 deletions python/gui/auto_generated/qgisinterface.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,26 @@ 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;
%Docstring
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;
Expand Down
18 changes: 18 additions & 0 deletions src/app/qgisappinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() );
Expand All @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions src/app/qgisappinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
81 changes: 73 additions & 8 deletions src/app/qgsapplayertreeviewmenuprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() );
Expand Down Expand Up @@ -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
Expand All @@ -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 )
Expand All @@ -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( '&' ) );
Expand Down Expand Up @@ -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 )
Expand Down
8 changes: 8 additions & 0 deletions src/app/qgsapplayertreeviewmenuprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
12 changes: 12 additions & 0 deletions src/gui/qgisinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down

0 comments on commit cce776c

Please sign in to comment.