From f35745fc7033e9cf2dbfe53b58723abd3b4fcad0 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 24 Feb 2018 15:52:08 +1000 Subject: [PATCH] Follow up map layer action changes - Switch to flags instead of boolean argument - Move logic for layer validity to canRunUsingLayer - Add unit test Also remove settings flag to hide duplicate features action --- python/gui/qgsmaplayeractionregistry.sip.in | 31 +++++- resources/qgis_global_settings.ini | 4 - src/app/qgisapp.cpp | 45 ++++----- .../attributetable/qgsattributetableview.cpp | 3 - src/gui/attributetable/qgsdualview.cpp | 3 - src/gui/qgsactionmenu.cpp | 3 - src/gui/qgsidentifymenu.cpp | 1 + src/gui/qgsmaplayeractionregistry.cpp | 36 +++++-- src/gui/qgsmaplayeractionregistry.h | 62 +++++++----- tests/src/python/CMakeLists.txt | 1 + tests/src/python/test_qgsmaplayeraction.py | 96 +++++++++++++++++++ 11 files changed, 214 insertions(+), 71 deletions(-) create mode 100644 tests/src/python/test_qgsmaplayeraction.py diff --git a/python/gui/qgsmaplayeractionregistry.sip.in b/python/gui/qgsmaplayeractionregistry.sip.in index c9890983b12..371106d4d35 100644 --- a/python/gui/qgsmaplayeractionregistry.sip.in +++ b/python/gui/qgsmaplayeractionregistry.sip.in @@ -30,7 +30,15 @@ An action which can run on map layers typedef QFlags Targets; - QgsMapLayerAction( const QString &name, QObject *parent /TransferThis/, Targets targets = AllActions, const QIcon &icon = QIcon() ); + enum Flag + { + EnabledOnlyWhenEditable, + }; + + typedef QFlags Flags; + + + QgsMapLayerAction( const QString &name, QObject *parent /TransferThis/, Targets targets = AllActions, const QIcon &icon = QIcon(), QgsMapLayerAction::Flags flags = 0 ); %Docstring Creates a map layer action which can run on any layer @@ -39,18 +47,25 @@ Creates a map layer action which can run on any layer using AllActions as a target probably does not make a lot of sense. This default action was settled for API compatibility reasons. %End - QgsMapLayerAction( const QString &name, QObject *parent /TransferThis/, QgsMapLayer *layer, Targets targets = AllActions, const QIcon &icon = QIcon() ); + QgsMapLayerAction( const QString &name, QObject *parent /TransferThis/, QgsMapLayer *layer, Targets targets = AllActions, const QIcon &icon = QIcon(), QgsMapLayerAction::Flags flags = 0 ); %Docstring Creates a map layer action which can run only on a specific layer %End - QgsMapLayerAction( const QString &name, QObject *parent /TransferThis/, QgsMapLayer::LayerType layerType, Targets targets = AllActions, const QIcon &icon = QIcon() ); + QgsMapLayerAction( const QString &name, QObject *parent /TransferThis/, QgsMapLayer::LayerType layerType, Targets targets = AllActions, const QIcon &icon = QIcon(), QgsMapLayerAction::Flags flags = 0 ); %Docstring Creates a map layer action which can run on a specific type of layer %End ~QgsMapLayerAction(); + QgsMapLayerAction::Flags flags() const; +%Docstring +Layer behavior flags. + +.. versionadded:: 3.0 +%End + bool canRunUsingLayer( QgsMapLayer *layer ) const; %Docstring True if action can run using the specified layer @@ -78,6 +93,13 @@ Define the targets of the action const Targets &targets() const; %Docstring Return availibity of action +%End + + bool isEnabledOnlyWhenEditable() const; +%Docstring +Returns true if the action is only enabled for layers in editable mode. + +.. versionadded:: 3.0 %End signals: @@ -158,6 +180,9 @@ Triggered when an action is added or removed from the registry }; +QFlags operator|(QgsMapLayerAction::Flag f1, QFlags f2); + + /************************************************************************ * This file has been generated automatically from * * * diff --git a/resources/qgis_global_settings.ini b/resources/qgis_global_settings.ini index 9790d9cbb26..a85f9f53d01 100644 --- a/resources/qgis_global_settings.ini +++ b/resources/qgis_global_settings.ini @@ -34,7 +34,3 @@ connections-xyz\OpenStreetMap\zmin=0 # for now this is online version of the User Guide for latest (LTR) release helpSearchPath=https://docs.qgis.org/$qgis_short_version/$qgis_locale/docs/user_manual/ -[app] - -# If true, the experimental "duplicate feature" actions will be shown in the QGIS UI -tools\showDuplicateFeatureActions=false \ No newline at end of file diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 53871d020dc..4aa817b20f9 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -6488,9 +6488,6 @@ void QgisApp::refreshFeatureActions() for ( int i = 0; i < registeredActions.size(); i++ ) { - if ( !vlayer->isEditable() && registeredActions.at( i )->isEnabledOnlyWhenEditable() ) - continue; - mFeatureActionMenu->addAction( registeredActions.at( i ) ); if ( registeredActions.at( i ) == QgsGui::mapLayerActionRegistry()->defaultActionForLayer( vlayer ) ) { @@ -7498,31 +7495,27 @@ void QgisApp::setupLayoutManagerConnections() void QgisApp::setupDuplicateFeaturesAction() { - QgsSettings settings; - if ( settings.value( QStringLiteral( "tools/showDuplicateFeatureActions" ), false, QgsSettings::App ).toBool() ) + mDuplicateFeatureAction.reset( new QgsMapLayerAction( tr( "Duplicate feature" ), + nullptr, QgsMapLayerAction::SingleFeature, + QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateFeature.svg" ) ), QgsMapLayerAction::EnabledOnlyWhenEditable ) ); + + QgsGui::mapLayerActionRegistry()->addMapLayerAction( mDuplicateFeatureAction.get() ); + connect( mDuplicateFeatureAction.get(), &QgsMapLayerAction::triggeredForFeature, this, [this]( QgsMapLayer * layer, const QgsFeature & feat ) { - mDuplicateFeatureAction.reset( new QgsMapLayerAction( tr( "Duplicate feature" ), - nullptr, QgsMapLayerAction::SingleFeature, - QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateFeature.svg" ) ), true ) ); - - QgsGui::mapLayerActionRegistry()->addMapLayerAction( mDuplicateFeatureAction.get() ); - connect( mDuplicateFeatureAction.get(), &QgsMapLayerAction::triggeredForFeature, this, [this]( QgsMapLayer * layer, const QgsFeature & feat ) - { - duplicateFeatures( layer, feat ); - } - ); - - mDuplicateFeatureDigitizeAction.reset( new QgsMapLayerAction( tr( "Duplicate feature and digitize" ), - nullptr, QgsMapLayerAction::SingleFeature, - QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateFeatureDigitized.svg" ) ), true ) ); - - QgsGui::mapLayerActionRegistry()->addMapLayerAction( mDuplicateFeatureDigitizeAction.get() ); - connect( mDuplicateFeatureDigitizeAction.get(), &QgsMapLayerAction::triggeredForFeature, this, [this]( QgsMapLayer * layer, const QgsFeature & feat ) - { - duplicateFeatureDigitized( layer, feat ); - } - ); + duplicateFeatures( layer, feat ); } + ); + + mDuplicateFeatureDigitizeAction.reset( new QgsMapLayerAction( tr( "Duplicate feature and digitize" ), + nullptr, QgsMapLayerAction::SingleFeature, + QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateFeatureDigitized.svg" ) ), QgsMapLayerAction::EnabledOnlyWhenEditable ) ); + + QgsGui::mapLayerActionRegistry()->addMapLayerAction( mDuplicateFeatureDigitizeAction.get() ); + connect( mDuplicateFeatureDigitizeAction.get(), &QgsMapLayerAction::triggeredForFeature, this, [this]( QgsMapLayer * layer, const QgsFeature & feat ) + { + duplicateFeatureDigitized( layer, feat ); + } + ); } void QgisApp::setupAtlasMapLayerAction( QgsPrintLayout *layout, bool enableAction ) diff --git a/src/gui/attributetable/qgsattributetableview.cpp b/src/gui/attributetable/qgsattributetableview.cpp index 0208a966734..80fc01e345c 100644 --- a/src/gui/attributetable/qgsattributetableview.cpp +++ b/src/gui/attributetable/qgsattributetableview.cpp @@ -201,9 +201,6 @@ QWidget *QgsAttributeTableView::createActionWidget( QgsFeatureId fid ) QgsGui::mapLayerActionRegistry()->mapLayerActions( mFilterModel->layer(), QgsMapLayerAction::SingleFeature ) ) { - if ( !mFilterModel->layer()->isEditable() && mapLayerAction->isEnabledOnlyWhenEditable() ) - continue; - QAction *action = new QAction( mapLayerAction->icon(), mapLayerAction->text(), container ); action->setData( "map_layer_action" ); action->setToolTip( mapLayerAction->text() ); diff --git a/src/gui/attributetable/qgsdualview.cpp b/src/gui/attributetable/qgsdualview.cpp index cc89c791bc6..197c77815eb 100644 --- a/src/gui/attributetable/qgsdualview.cpp +++ b/src/gui/attributetable/qgsdualview.cpp @@ -592,9 +592,6 @@ void QgsDualView::viewWillShowContextMenu( QMenu *menu, const QModelIndex &atInd Q_FOREACH ( QgsMapLayerAction *action, registeredActions ) { - if ( !vl->isEditable() && action->isEnabledOnlyWhenEditable() ) - continue; - QgsAttributeTableMapLayerAction *a = new QgsAttributeTableMapLayerAction( action->text(), this, action, sourceIndex ); #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) menu->addAction( action->text(), a, SLOT( execut() ) ); diff --git a/src/gui/qgsactionmenu.cpp b/src/gui/qgsactionmenu.cpp index b44f2c3f2e5..3b0eda3e995 100644 --- a/src/gui/qgsactionmenu.cpp +++ b/src/gui/qgsactionmenu.cpp @@ -154,9 +154,6 @@ void QgsActionMenu::reloadActions() { QgsMapLayerAction *qaction = mapLayerActions.at( i ); - if ( !mLayer->isEditable() && qaction->isEnabledOnlyWhenEditable() ) - continue; - if ( qaction->isEnabledOnlyWhenEditable() && ( mMode == QgsAttributeForm::AddFeatureMode || mMode == QgsAttributeForm::IdentifyMode ) ) continue; diff --git a/src/gui/qgsidentifymenu.cpp b/src/gui/qgsidentifymenu.cpp index 3a18c6e0732..45ecae22ebc 100644 --- a/src/gui/qgsidentifymenu.cpp +++ b/src/gui/qgsidentifymenu.cpp @@ -346,6 +346,7 @@ void QgsIdentifyMenu::addVectorLayer( QgsVectorLayer *layer, const QListsetMode( QgsAttributeForm::IdentifyMode ); featureActionMenu->setExpressionContextScope( mExpressionContextScope ); } diff --git a/src/gui/qgsmaplayeractionregistry.cpp b/src/gui/qgsmaplayeractionregistry.cpp index c86a5fe73a1..f555a182f47 100644 --- a/src/gui/qgsmaplayeractionregistry.cpp +++ b/src/gui/qgsmaplayeractionregistry.cpp @@ -15,35 +15,36 @@ #include "qgsmaplayeractionregistry.h" #include "qgsgui.h" +#include "qgsvectorlayer.h" -QgsMapLayerAction::QgsMapLayerAction( const QString &name, QObject *parent, Targets targets, const QIcon &icon, const bool enabledOnlyWhenEditable ) +QgsMapLayerAction::QgsMapLayerAction( const QString &name, QObject *parent, Targets targets, const QIcon &icon, QgsMapLayerAction::Flags flags ) : QAction( icon, name, parent ) , mSingleLayer( false ) , mSpecificLayerType( false ) , mLayerType( QgsMapLayer::VectorLayer ) , mTargets( targets ) - , mEnabledOnlyWhenEditable( enabledOnlyWhenEditable ) + , mFlags( flags ) { } -QgsMapLayerAction::QgsMapLayerAction( const QString &name, QObject *parent, QgsMapLayer *layer, Targets targets, const QIcon &icon, const bool enabledOnlyWhenEditable ) +QgsMapLayerAction::QgsMapLayerAction( const QString &name, QObject *parent, QgsMapLayer *layer, Targets targets, const QIcon &icon, QgsMapLayerAction::Flags flags ) : QAction( icon, name, parent ) , mSingleLayer( true ) , mActionLayer( layer ) , mSpecificLayerType( false ) , mLayerType( QgsMapLayer::VectorLayer ) , mTargets( targets ) - , mEnabledOnlyWhenEditable( enabledOnlyWhenEditable ) + , mFlags( flags ) { } -QgsMapLayerAction::QgsMapLayerAction( const QString &name, QObject *parent, QgsMapLayer::LayerType layerType, Targets targets, const QIcon &icon, const bool enabledOnlyWhenEditable ) +QgsMapLayerAction::QgsMapLayerAction( const QString &name, QObject *parent, QgsMapLayer::LayerType layerType, Targets targets, const QIcon &icon, QgsMapLayerAction::Flags flags ) : QAction( icon, name, parent ) , mSingleLayer( false ) , mSpecificLayerType( true ) , mLayerType( layerType ) , mTargets( targets ) - , mEnabledOnlyWhenEditable( enabledOnlyWhenEditable ) + , mFlags( flags ) { } @@ -53,8 +54,24 @@ QgsMapLayerAction::~QgsMapLayerAction() QgsGui::mapLayerActionRegistry()->removeMapLayerAction( this ); } +QgsMapLayerAction::Flags QgsMapLayerAction::flags() const +{ + return mFlags; +} + bool QgsMapLayerAction::canRunUsingLayer( QgsMapLayer *layer ) const { + if ( mFlags & EnabledOnlyWhenEditable ) + { + // action is only enabled for editable layers + if ( !layer ) + return false; + if ( layer->type() != QgsMapLayer::VectorLayer ) + return false; + if ( !qobject_cast( layer )->isEditable() ) + return false; + } + //check layer details if ( !mSingleLayer && !mSpecificLayerType ) { @@ -67,7 +84,7 @@ bool QgsMapLayerAction::canRunUsingLayer( QgsMapLayer *layer ) const //action is a single layer type and layer matches return true; } - else if ( mSpecificLayerType && layer->type() == mLayerType ) + else if ( mSpecificLayerType && layer && layer->type() == mLayerType ) { //action is for a layer type and layer type matches return true; @@ -91,6 +108,11 @@ void QgsMapLayerAction::triggerForLayer( QgsMapLayer *layer ) emit triggeredForLayer( layer ); } +bool QgsMapLayerAction::isEnabledOnlyWhenEditable() const +{ + return mFlags & EnabledOnlyWhenEditable; +} + // // Main class begins now... // diff --git a/src/gui/qgsmaplayeractionregistry.h b/src/gui/qgsmaplayeractionregistry.h index 5d567d43a9f..fcb2c2d964f 100644 --- a/src/gui/qgsmaplayeractionregistry.h +++ b/src/gui/qgsmaplayeractionregistry.h @@ -46,29 +46,42 @@ class GUI_EXPORT QgsMapLayerAction : public QAction Q_DECLARE_FLAGS( Targets, Target ) Q_FLAG( Targets ) + /** + * Flags which control action behavior + * /since QGIS 3.0 + */ + enum Flag + { + EnabledOnlyWhenEditable = 1 << 1, //!< Action should be shown only for editable layers + }; + + /** + * Action behavior flags. + * \since QGIS 3.0 + */ + Q_DECLARE_FLAGS( Flags, Flag ) + Q_FLAG( Flags ) + /** * Creates a map layer action which can run on any layer * \note using AllActions as a target probably does not make a lot of sense. This default action was settled for API compatibility reasons. */ -#ifndef SIP_RUN - QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, Targets targets = AllActions, const QIcon &icon = QIcon(), const bool enabledOnlyWhenEditable = false ); -#else - QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, Targets targets = AllActions, const QIcon &icon = QIcon() ); -#endif + QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, Targets targets = AllActions, const QIcon &icon = QIcon(), QgsMapLayerAction::Flags flags = nullptr ); + //! Creates a map layer action which can run only on a specific layer -#ifndef SIP_RUN - QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, QgsMapLayer *layer, Targets targets = AllActions, const QIcon &icon = QIcon(), const bool enabledOnlyWhenEditable = false ); -#else - QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, QgsMapLayer *layer, Targets targets = AllActions, const QIcon &icon = QIcon() ); -#endif + QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, QgsMapLayer *layer, Targets targets = AllActions, const QIcon &icon = QIcon(), QgsMapLayerAction::Flags flags = nullptr ); + //! Creates a map layer action which can run on a specific type of layer -#ifndef SIP_RUN - QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, QgsMapLayer::LayerType layerType, Targets targets = AllActions, const QIcon &icon = QIcon(), const bool enabledOnlyWhenEditable = false ); -#else - QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, QgsMapLayer::LayerType layerType, Targets targets = AllActions, const QIcon &icon = QIcon() ); -#endif + QgsMapLayerAction( const QString &name, QObject *parent SIP_TRANSFERTHIS, QgsMapLayer::LayerType layerType, Targets targets = AllActions, const QIcon &icon = QIcon(), QgsMapLayerAction::Flags flags = nullptr ); + ~QgsMapLayerAction() override; + /** + * Layer behavior flags. + * \since QGIS 3.0 + */ + QgsMapLayerAction::Flags flags() const; + //! True if action can run using the specified layer bool canRunUsingLayer( QgsMapLayer *layer ) const; @@ -86,8 +99,11 @@ class GUI_EXPORT QgsMapLayerAction : public QAction //! Return availibity of action const Targets &targets() const {return mTargets;} - //! Return whether only enabled in editable mode - bool isEnabledOnlyWhenEditable() const { return mEnabledOnlyWhenEditable; } + /** + * Returns true if the action is only enabled for layers in editable mode. + * \since QGIS 3.0 + */ + bool isEnabledOnlyWhenEditable() const; signals: //! Triggered when action has been run for a specific list of features @@ -102,19 +118,19 @@ class GUI_EXPORT QgsMapLayerAction : public QAction private: // true if action is only valid for a single layer - bool mSingleLayer; + bool mSingleLayer = false; // layer if action is only valid for a single layer QgsMapLayer *mActionLayer = nullptr; // true if action is only valid for a specific layer type - bool mSpecificLayerType; + bool mSpecificLayerType = false; // layer type if action is only valid for a specific layer type - QgsMapLayer::LayerType mLayerType; + QgsMapLayer::LayerType mLayerType = QgsMapLayer::VectorLayer; // determine if the action can be run on layer and/or single feature and/or multiple features - Targets mTargets; + Targets mTargets = nullptr; - bool mEnabledOnlyWhenEditable; + QgsMapLayerAction::Flags mFlags = nullptr; }; Q_DECLARE_OPERATORS_FOR_FLAGS( QgsMapLayerAction::Targets ) @@ -168,4 +184,6 @@ class GUI_EXPORT QgsMapLayerActionRegistry : public QObject }; +Q_DECLARE_OPERATORS_FOR_FLAGS( QgsMapLayerAction::Flags ) + #endif // QGSMAPLAYERACTIONREGISTRY_H diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index 42d10fe40e8..ad75d0d93b8 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -101,6 +101,7 @@ ADD_PYTHON_TEST(PyQgsLocator test_qgslocator.py) ADD_PYTHON_TEST(PyQgsMapCanvas test_qgsmapcanvas.py) ADD_PYTHON_TEST(PyQgsMapCanvasAnnotationItem test_qgsmapcanvasannotationitem.py) ADD_PYTHON_TEST(PyQgsMapLayer test_qgsmaplayer.py) +ADD_PYTHON_TEST(PyQgsMapLayerAction test_qgsmaplayeraction.py) ADD_PYTHON_TEST(PyQgsMapLayerModel test_qgsmaplayermodel.py) ADD_PYTHON_TEST(PyQgsMapLayerStore test_qgsmaplayerstore.py) ADD_PYTHON_TEST(PyQgsMapRenderer test_qgsmaprenderer.py) diff --git a/tests/src/python/test_qgsmaplayeraction.py b/tests/src/python/test_qgsmaplayeraction.py new file mode 100644 index 00000000000..8306dd574c0 --- /dev/null +++ b/tests/src/python/test_qgsmaplayeraction.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +"""QGIS Unit tests for QgsMapLayerAction. + +.. note:: This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. +""" +__author__ = 'Nyall Dawson' +__date__ = '24/02/2018' +__copyright__ = 'Copyright 2018, The QGIS Project' +# This will get replaced with a git SHA1 when you do a git archive +__revision__ = '$Format:%H$' + +import qgis # NOQA switch sip api + +from qgis.core import (QgsVectorLayer, + QgsRasterLayer, + QgsMapLayer) +from qgis.gui import (QgsMapLayerActionRegistry, + QgsMapLayerAction) + +from qgis.testing import start_app, unittest +from utilities import unitTestDataPath + +import os + +start_app() + + +class TestQgsMapLayerAction(unittest.TestCase): + + def __init__(self, methodName): + """Run once on class initialization.""" + unittest.TestCase.__init__(self, methodName) + + self.vector_layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddate:datetime", + "test_layer", "memory") + assert self.vector_layer.isValid() + self.vector_layer2 = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddate:datetime", + "test_layer", "memory") + assert self.vector_layer2.isValid() + raster_path = os.path.join(unitTestDataPath(), 'landsat.tif') + self.raster_layer = QgsRasterLayer(raster_path, 'raster') + assert self.raster_layer.isValid() + + def testCanRunUsingLayer(self): + """ + Test that actions correctly indicate when they can run for a layer + """ + action_all_layers = QgsMapLayerAction('action1', None) + self.assertTrue(action_all_layers.canRunUsingLayer(None)) + self.assertTrue(action_all_layers.canRunUsingLayer(self.vector_layer)) + self.assertTrue(action_all_layers.canRunUsingLayer(self.raster_layer)) + + action_vector_layers_only = QgsMapLayerAction('action2', None, QgsMapLayer.VectorLayer) + self.assertFalse(action_vector_layers_only.canRunUsingLayer(None)) + self.assertTrue(action_vector_layers_only.canRunUsingLayer(self.vector_layer)) + self.assertFalse(action_vector_layers_only.canRunUsingLayer(self.raster_layer)) + + action_raster_layers_only = QgsMapLayerAction('action3', None, QgsMapLayer.RasterLayer) + self.assertFalse(action_raster_layers_only.canRunUsingLayer(None)) + self.assertFalse(action_raster_layers_only.canRunUsingLayer(self.vector_layer)) + self.assertTrue(action_raster_layers_only.canRunUsingLayer(self.raster_layer)) + + action_specific_layer_only = QgsMapLayerAction('action4', None, self.vector_layer) + self.assertFalse(action_specific_layer_only.canRunUsingLayer(None)) + self.assertTrue(action_specific_layer_only.canRunUsingLayer(self.vector_layer)) + self.assertFalse(action_specific_layer_only.canRunUsingLayer(self.vector_layer2)) + self.assertFalse(action_specific_layer_only.canRunUsingLayer(self.raster_layer)) + + action_specific_raster_layer_only = QgsMapLayerAction('action4', None, self.raster_layer) + self.assertFalse(action_specific_raster_layer_only.canRunUsingLayer(None)) + self.assertFalse(action_specific_raster_layer_only.canRunUsingLayer(self.vector_layer)) + self.assertFalse(action_specific_raster_layer_only.canRunUsingLayer(self.vector_layer2)) + self.assertTrue(action_specific_raster_layer_only.canRunUsingLayer(self.raster_layer)) + + action_editable_layer_only = QgsMapLayerAction('action1', None, flags=QgsMapLayerAction.EnabledOnlyWhenEditable) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(None)) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(self.vector_layer)) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(self.vector_layer2)) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(self.raster_layer)) + self.vector_layer.startEditing() + self.assertFalse(action_editable_layer_only.canRunUsingLayer(None)) + self.assertTrue(action_editable_layer_only.canRunUsingLayer(self.vector_layer)) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(self.vector_layer2)) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(self.raster_layer)) + self.vector_layer.commitChanges() + self.assertFalse(action_editable_layer_only.canRunUsingLayer(None)) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(self.vector_layer)) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(self.vector_layer2)) + self.assertFalse(action_editable_layer_only.canRunUsingLayer(self.raster_layer)) + + +if __name__ == '__main__': + unittest.main()