Skip to content

Commit

Permalink
Also use context when determining which actions can run
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 23, 2022
1 parent 0c4aff9 commit 4f1cc22
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 31 deletions.
24 changes: 20 additions & 4 deletions python/gui/auto_generated/qgsmaplayeractionregistry.sip.in
Expand Up @@ -124,9 +124,23 @@ Layer behavior flags.
.. versionadded:: 3.0
%End

virtual bool canRunUsingLayer( QgsMapLayer *layer ) const;
virtual bool canRunUsingLayer( QgsMapLayer *layer ) const /Deprecated/;
%Docstring
True if action can run using the specified layer
Returns ``True`` if the action can run using the specified layer.

.. deprecated::
use the version with :py:class:`QgsMapLayerActionContext` instead.
%End

virtual bool canRunUsingLayer( QgsMapLayer *layer, const QgsMapLayerActionContext &context ) const;
%Docstring
Returns ``True`` if the action can run using the specified layer.

.. note::

Classes which implement this should return ``False`` to the deprecated :py:func:`~QgsMapLayerAction.canRunUsingLayer` method which does not accept a :py:class:`QgsMapLayerActionContext` argument.

.. versionadded:: 3.30
%End

virtual void triggerForFeatures( QgsMapLayer *layer, const QList<QgsFeature> &featureList ) /Deprecated/;
Expand Down Expand Up @@ -269,9 +283,11 @@ QgsMapLayerActionRegistry is not usually directly created, but rather accessed t
Adds a map layer action to the registry
%End

QList<QgsMapLayerAction *> mapLayerActions( QgsMapLayer *layer, QgsMapLayerAction::Targets targets = QgsMapLayerAction::AllActions );
QList<QgsMapLayerAction *> mapLayerActions( QgsMapLayer *layer, QgsMapLayerAction::Targets targets = QgsMapLayerAction::AllActions, const QgsMapLayerActionContext &context = QgsMapLayerActionContext() );
%Docstring
Returns the map layer actions which can run on the specified layer
Returns the map layer actions which can run on the specified layer.

The ``context`` argument was added in QGIS 3.30.
%End

bool removeMapLayerAction( QgsMapLayerAction *action );
Expand Down
9 changes: 6 additions & 3 deletions src/app/qgisapp.cpp
Expand Up @@ -7481,7 +7481,8 @@ void QgisApp::refreshFeatureActions()
}

//add actions registered in QgsMapLayerActionRegistry
QList<QgsMapLayerAction *> registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, QgsMapLayerAction::SingleFeature );
QgsMapLayerActionContext context;
QList<QgsMapLayerAction *> registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, QgsMapLayerAction::SingleFeature, context );
if ( !actions.isEmpty() && !registeredActions.empty() )
{
//add a separator between user defined and standard actions
Expand Down Expand Up @@ -14894,7 +14895,8 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )

bool isEditable = vlayer->isEditable();
bool layerHasSelection = vlayer->selectedFeatureCount() > 0;
bool layerHasActions = !vlayer->actions()->actions( QStringLiteral( "Canvas" ) ).isEmpty() || !QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer ).isEmpty();
QgsMapLayerActionContext context;
bool layerHasActions = !vlayer->actions()->actions( QStringLiteral( "Canvas" ) ).isEmpty() || !QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, QgsMapLayerAction::AllActions, context ).isEmpty();
bool isSpatial = vlayer->isSpatial();

mActionLocalHistogramStretch->setEnabled( false );
Expand Down Expand Up @@ -15526,7 +15528,8 @@ void QgisApp::refreshActionFeatureAction()
if ( !vlayer )
return;

bool layerHasActions = !vlayer->actions()->actions( QStringLiteral( "Canvas" ) ).isEmpty() || !QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer ).isEmpty();
QgsMapLayerActionContext context;
bool layerHasActions = !vlayer->actions()->actions( QStringLiteral( "Canvas" ) ).isEmpty() || !QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, QgsMapLayerAction::AllActions, context ).isEmpty();
mActionFeatureAction->setEnabled( layerHasActions );
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/qgsapplayertreeviewmenuprovider.cpp
Expand Up @@ -413,11 +413,11 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
else
target = QgsMapLayerAction::Target::MultipleFeatures;

const QList<QgsMapLayerAction *> constRegisteredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, target );
QgsMapLayerActionContext context;
const QList<QgsMapLayerAction *> constRegisteredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, target, context );
if ( !constRegisteredActions.isEmpty() )
{
QMenu *actionMenu = menu->addMenu( tr( "Actions on Selection (%1)" ).arg( selectionCount ) );
QgsMapLayerActionContext context;
for ( QgsMapLayerAction *action : constRegisteredActions )
{
if ( target == QgsMapLayerAction::Target::SingleFeature )
Expand Down
6 changes: 4 additions & 2 deletions src/app/qgsidentifyresultsdialog.cpp
Expand Up @@ -643,7 +643,8 @@ QgsIdentifyResultsFeatureItem *QgsIdentifyResultsDialog::createFeatureItem( QgsV
}

//get valid QgsMapLayerActions for this layer
const QList< QgsMapLayerAction * > registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer );
QgsMapLayerActionContext context;
const QList< QgsMapLayerAction * > registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, QgsMapLayerAction::AllActions, context );
const QList<QgsAction> actions = vlayer->actions()->actions( QStringLiteral( "Feature" ) );

if ( ( !vlayer->fields().isEmpty() || !actions.isEmpty() || !registeredActions.isEmpty() ) && !QgsSettings().value( QStringLiteral( "/Map/hideDerivedAttributes" ), false ).toBool() )
Expand Down Expand Up @@ -1582,7 +1583,8 @@ void QgsIdentifyResultsDialog::contextMenuEvent( QContextMenuEvent *event )
if ( featItem && featItem->data( 0, Qt::UserRole + 1 ).isValid() && vlayer )
{
//get valid QgsMapLayerActions for this layer
const QList< QgsMapLayerAction * > registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer );
QgsMapLayerActionContext context;
const QList< QgsMapLayerAction * > registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, QgsMapLayerAction::AllActions, context );

if ( !registeredActions.isEmpty() )
{
Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptoolfeatureaction.cpp
Expand Up @@ -70,7 +70,8 @@ void QgsMapToolFeatureAction::canvasReleaseEvent( QgsMapMouseEvent *e )
}

QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( vlayer->actions()->actions( QStringLiteral( "Canvas" ) ).isEmpty() && QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer ).isEmpty() )
QgsMapLayerActionContext context;
if ( vlayer->actions()->actions( QStringLiteral( "Canvas" ) ).isEmpty() && QgsGui::mapLayerActionRegistry()->mapLayerActions( vlayer, QgsMapLayerAction::AllActions, context ).isEmpty() )
{
emit messageEmitted( tr( "The active vector layer has no defined actions" ), Qgis::MessageLevel::Info );
return;
Expand Down
3 changes: 2 additions & 1 deletion src/gui/attributetable/qgsattributetableview.cpp
Expand Up @@ -251,7 +251,8 @@ QWidget *QgsAttributeTableView::createActionWidget( QgsFeatureId fid )
defaultAction = act;
}

const auto mapLayerActions {QgsGui::mapLayerActionRegistry()->mapLayerActions( mFilterModel->layer(), QgsMapLayerAction::SingleFeature ) };
QgsMapLayerActionContext context;
const auto mapLayerActions {QgsGui::mapLayerActionRegistry()->mapLayerActions( mFilterModel->layer(), QgsMapLayerAction::SingleFeature, context ) };
// next add any registered actions for this layer
for ( QgsMapLayerAction *mapLayerAction : mapLayerActions )
{
Expand Down
5 changes: 3 additions & 2 deletions src/gui/attributetable/qgsdualview.cpp
Expand Up @@ -872,7 +872,8 @@ void QgsDualView::viewWillShowContextMenu( QMenu *menu, const QModelIndex &maste
}

//add actions from QgsMapLayerActionRegistry to context menu
const QList<QgsMapLayerAction *> registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::Layer | QgsMapLayerAction::SingleFeature );
QgsMapLayerActionContext context;
const QList<QgsMapLayerAction *> registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::Layer | QgsMapLayerAction::SingleFeature, context );
if ( !registeredActions.isEmpty() )
{
//add a separator between user defined and standard actions
Expand All @@ -890,7 +891,7 @@ void QgsDualView::viewWillShowContextMenu( QMenu *menu, const QModelIndex &maste
const QgsFeatureId currentFid = mMasterModel->rowToId( masterIndex.row() );
if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
{
const QList<QgsMapLayerAction *> registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::MultipleFeatures );
const QList<QgsMapLayerAction *> registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::MultipleFeatures, context );
if ( !registeredActions.isEmpty() )
{
menu->addSeparator();
Expand Down
3 changes: 2 additions & 1 deletion src/gui/qgsactionmenu.cpp
Expand Up @@ -42,6 +42,7 @@ QgsActionMenu::QgsActionMenu( QgsVectorLayer *layer, const QgsFeatureId fid, con
void QgsActionMenu::setActionContextGenerator( QgsMapLayerActionContextGenerator *generator )
{
mContextGenerator = generator;
reloadActions();
}

void QgsActionMenu::init()
Expand Down Expand Up @@ -159,7 +160,7 @@ void QgsActionMenu::reloadActions()
mVisibleActionCount++;
}

const QList<QgsMapLayerAction *> mapLayerActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::SingleFeature );
const QList<QgsMapLayerAction *> mapLayerActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::SingleFeature, mContextGenerator ? mContextGenerator->createActionContext() : QgsMapLayerActionContext() );

if ( !mapLayerActions.isEmpty() )
{
Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsattributedialog.cpp
Expand Up @@ -19,7 +19,6 @@

#include "qgsattributeform.h"
#include "qgshighlight.h"
#include "qgsapplication.h"
#include "qgssettings.h"
#include "qgsmessagebar.h"

Expand Down Expand Up @@ -177,3 +176,4 @@ QgsMapLayerActionContext QgsAttributeDialog::createActionContext()
context.setAttributeDialog( this );
return context;
}

14 changes: 8 additions & 6 deletions src/gui/qgsidentifymenu.cpp
Expand Up @@ -238,15 +238,16 @@ void QgsIdentifyMenu::addRasterLayer( QgsMapLayer *layer )
QMenu *layerMenu = nullptr;

QList<QgsMapLayerAction *> separators = QList<QgsMapLayerAction *>();
QList<QgsMapLayerAction *> layerActions = mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::Layer );
QgsMapLayerActionContext context;
QList<QgsMapLayerAction *> layerActions = mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::Layer, context );
const int nCustomActions = layerActions.count();
if ( nCustomActions )
{
separators.append( layerActions[0] );
}
if ( mShowFeatureActions )
{
layerActions.append( QgsGui::mapLayerActionRegistry()->mapLayerActions( layer, QgsMapLayerAction::Layer ) );
layerActions.append( QgsGui::mapLayerActionRegistry()->mapLayerActions( layer, QgsMapLayerAction::Layer, context ) );
if ( layerActions.count() > nCustomActions )
{
separators.append( layerActions[nCustomActions] );
Expand Down Expand Up @@ -306,15 +307,16 @@ void QgsIdentifyMenu::addVectorLayer( QgsVectorLayer *layer, const QList<QgsMapT
const QgsMapLayerAction::Targets targets = results.count() > 1 ? QgsMapLayerAction::Layer | QgsMapLayerAction::MultipleFeatures : QgsMapLayerAction::Layer;

QList<QgsMapLayerAction *> separators = QList<QgsMapLayerAction *>();
QList<QgsMapLayerAction *> layerActions = mCustomActionRegistry.mapLayerActions( layer, targets );
QgsMapLayerActionContext actionContext;
QList<QgsMapLayerAction *> layerActions = mCustomActionRegistry.mapLayerActions( layer, targets, actionContext );
const int nCustomActions = layerActions.count();
if ( nCustomActions )
{
separators << layerActions[0];
}
if ( mShowFeatureActions )
{
layerActions << QgsGui::mapLayerActionRegistry()->mapLayerActions( layer, targets );
layerActions << QgsGui::mapLayerActionRegistry()->mapLayerActions( layer, targets, actionContext );

if ( layerActions.count() > nCustomActions )
{
Expand All @@ -333,7 +335,7 @@ void QgsIdentifyMenu::addVectorLayer( QgsVectorLayer *layer, const QList<QgsMapT
// i.e custom actions or map layer actions at feature level
if ( !createMenu )
{
createMenu = !mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::SingleFeature ).isEmpty();
createMenu = !mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::SingleFeature, actionContext ).isEmpty();
if ( !createMenu && mShowFeatureActions )
{
QgsActionMenu *featureActionMenu = new QgsActionMenu( layer, results[0].mFeature, QStringLiteral( "Feature" ), this );
Expand Down Expand Up @@ -410,7 +412,7 @@ void QgsIdentifyMenu::addVectorLayer( QgsVectorLayer *layer, const QList<QgsMapT
QMenu *featureMenu = nullptr;
QgsActionMenu *featureActionMenu = nullptr;

const QList<QgsMapLayerAction *> customFeatureActions = mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::SingleFeature );
const QList<QgsMapLayerAction *> customFeatureActions = mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::SingleFeature, actionContext );
if ( mShowFeatureActions )
{
featureActionMenu = new QgsActionMenu( layer, result.mFeature, QStringLiteral( "Feature" ), layerMenu );
Expand Down
19 changes: 15 additions & 4 deletions src/gui/qgsmaplayeractionregistry.cpp
Expand Up @@ -55,6 +55,11 @@ QgsMapLayerAction::Flags QgsMapLayerAction::flags() const
}

bool QgsMapLayerAction::canRunUsingLayer( QgsMapLayer *layer ) const
{
return canRunUsingLayer( layer, QgsMapLayerActionContext() );
}

bool QgsMapLayerAction::canRunUsingLayer( QgsMapLayer *layer, const QgsMapLayerActionContext & ) const
{
if ( mFlags & EnabledOnlyWhenEditable )
{
Expand Down Expand Up @@ -144,14 +149,20 @@ void QgsMapLayerActionRegistry::addMapLayerAction( QgsMapLayerAction *action )
emit changed();
}

QList< QgsMapLayerAction * > QgsMapLayerActionRegistry::mapLayerActions( QgsMapLayer *layer, QgsMapLayerAction::Targets targets )
QList< QgsMapLayerAction * > QgsMapLayerActionRegistry::mapLayerActions( QgsMapLayer *layer, QgsMapLayerAction::Targets targets, const QgsMapLayerActionContext &context )
{
QList< QgsMapLayerAction * > validActions;

const auto constMMapLayerActionList = mMapLayerActionList;
for ( QgsMapLayerAction *action : constMMapLayerActionList )
for ( QgsMapLayerAction *action : std::as_const( mMapLayerActionList ) )
{
if ( action->canRunUsingLayer( layer ) && ( targets & action->targets() ) )
bool canRun = false;
Q_NOWARN_DEPRECATED_PUSH
canRun = action->canRunUsingLayer( layer );
Q_NOWARN_DEPRECATED_POP
if ( !canRun )
canRun = action->canRunUsingLayer( layer, context );

if ( canRun && ( targets & action->targets() ) )
{
validActions.append( action );
}
Expand Down
25 changes: 21 additions & 4 deletions src/gui/qgsmaplayeractionregistry.h
Expand Up @@ -141,8 +141,21 @@ class GUI_EXPORT QgsMapLayerAction : public QAction
*/
QgsMapLayerAction::Flags flags() const;

//! True if action can run using the specified layer
virtual bool canRunUsingLayer( QgsMapLayer *layer ) const;
/**
* Returns TRUE if the action can run using the specified layer.
*
* \deprecated use the version with QgsMapLayerActionContext instead.
*/
Q_DECL_DEPRECATED virtual bool canRunUsingLayer( QgsMapLayer *layer ) const SIP_DEPRECATED;

/**
* Returns TRUE if the action can run using the specified layer.
*
* \note Classes which implement this should return FALSE to the deprecated canRunUsingLayer() method which does not accept a QgsMapLayerActionContext argument.
*
* \since QGIS 3.30
*/
virtual bool canRunUsingLayer( QgsMapLayer *layer, const QgsMapLayerActionContext &context ) const;

/**
* Triggers the action with the specified layer and list of feature.
Expand Down Expand Up @@ -284,8 +297,12 @@ class GUI_EXPORT QgsMapLayerActionRegistry : public QObject
//! Adds a map layer action to the registry
void addMapLayerAction( QgsMapLayerAction *action );

//! Returns the map layer actions which can run on the specified layer
QList<QgsMapLayerAction *> mapLayerActions( QgsMapLayer *layer, QgsMapLayerAction::Targets targets = QgsMapLayerAction::AllActions );
/**
* Returns the map layer actions which can run on the specified layer.
*
* The \a context argument was added in QGIS 3.30.
*/
QList<QgsMapLayerAction *> mapLayerActions( QgsMapLayer *layer, QgsMapLayerAction::Targets targets = QgsMapLayerAction::AllActions, const QgsMapLayerActionContext &context = QgsMapLayerActionContext() );

//! Removes a map layer action from the registry
bool removeMapLayerAction( QgsMapLayerAction *action );
Expand Down

0 comments on commit 4f1cc22

Please sign in to comment.