mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
QgsActionManager: improve docs + add tests
This commit is contained in:
parent
3d494ac9f8
commit
bc779a06ed
@ -54,6 +54,11 @@ class QgsActionManager
|
||||
*/
|
||||
void addAction( QgsAction::ActionType type, const QString& name, const QString& action, const QString& icon, bool capture = false );
|
||||
|
||||
/**
|
||||
* Add a new action to this list.
|
||||
*/
|
||||
void addAction( const QgsAction& action );
|
||||
|
||||
//! Remove an action at given index
|
||||
void removeAction( int index );
|
||||
|
||||
@ -65,6 +70,20 @@ class QgsActionManager
|
||||
const QgsFeature &feat,
|
||||
int defaultValueIndex = 0 ) /PyName=doActionFeature/;
|
||||
|
||||
/** Does the action using the expression engine to replace any embedded expressions
|
||||
* in the action definition.
|
||||
* @param index action index
|
||||
* @param feature feature to run action for
|
||||
* @param context expression context to evalute expressions under
|
||||
* @param substitutionMap deprecated - kept for compatibilty with projects, will be removed for 3.0
|
||||
*/
|
||||
// TODO QGIS 3.0 remove substition map - force use of expression variables
|
||||
void doAction( int index,
|
||||
const QgsFeature& feature,
|
||||
const QgsExpressionContext& context,
|
||||
const QMap<QString, QVariant> *substitutionMap = nullptr );
|
||||
|
||||
|
||||
/** Does the action using the expression builder to expand it
|
||||
* and getting values from the passed feature attribute map.
|
||||
* substitutionMap is used to pass custom substitutions, to replace
|
||||
@ -86,8 +105,9 @@ class QgsActionManager
|
||||
|
||||
/** Expands the given action, replacing all %'s with the value as
|
||||
* given.
|
||||
* @deprecated use QgsExpression::replaceExpressionText() instead
|
||||
*/
|
||||
QString expandAction( QString action, const QMap<int, QVariant> &attributes, uint defaultValueIndex );
|
||||
QString expandAction( QString action, const QMap<int, QVariant> &attributes, uint defaultValueIndex ) /Deprecated/;
|
||||
|
||||
/** Expands the given action using the expression builder
|
||||
* This function currently replaces each expression between [% and %]
|
||||
@ -96,10 +116,11 @@ class QgsActionManager
|
||||
*
|
||||
* Additional substitutions can be passed through the substitutionMap
|
||||
* parameter
|
||||
* @deprecated use QgsExpression::replaceExpressionText() instead
|
||||
*/
|
||||
QString expandAction( const QString& action,
|
||||
QgsFeature &feat,
|
||||
const QMap<QString, QVariant> *substitutionMap = 0 );
|
||||
const QMap<QString, QVariant> *substitutionMap = 0 ) /Deprecated/;
|
||||
|
||||
|
||||
//! Writes the actions out in XML format
|
||||
@ -112,11 +133,34 @@ class QgsActionManager
|
||||
/**
|
||||
* Get the action at the specified index.
|
||||
*/
|
||||
QgsAction at( int idx ) const;
|
||||
QgsAction at( int idx ) const /Factory/;
|
||||
%MethodCode
|
||||
if ( a0 < 0 || a0 >= sipCpp->size() )
|
||||
{
|
||||
PyErr_SetString(PyExc_KeyError, QByteArray::number(a0));
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sipRes = new QgsAction( sipCpp->at( a0 ) );
|
||||
}
|
||||
%End
|
||||
|
||||
/**
|
||||
* Get the action at the specified index.
|
||||
*/
|
||||
QgsAction operator[]( int idx ) const;
|
||||
%MethodCode
|
||||
if ( a0 < 0 || a0 >= sipCpp->size() )
|
||||
{
|
||||
PyErr_SetString(PyExc_KeyError, QByteArray::number(a0));
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sipRes = new QgsAction( sipCpp->at( a0 ) );
|
||||
}
|
||||
%End
|
||||
|
||||
/** @deprecated Initialize QgsPythonRunner instead
|
||||
* @note not available in Python bindings
|
||||
@ -124,11 +168,15 @@ class QgsActionManager
|
||||
// Q_DECL_DEPRECATED static void setPythonExecute( void ( * )( const QString & ) );
|
||||
|
||||
/**
|
||||
* Get the index of the default action
|
||||
* Returns the index of the default action, or -1 if no default action is available.
|
||||
* @see setDefaultAction()
|
||||
*/
|
||||
int defaultAction() const;
|
||||
|
||||
/**
|
||||
* Set the index of the default action
|
||||
* Set the index of the default action.
|
||||
* @param actionNumber index of action which should be made the default for the layer
|
||||
* @see defaultAction()
|
||||
*/
|
||||
void setDefaultAction( int actionNumber );
|
||||
};
|
||||
|
@ -122,8 +122,9 @@ class CORE_EXPORT QgsActionManager
|
||||
|
||||
/** Expands the given action, replacing all %'s with the value as
|
||||
* given.
|
||||
* @deprecated use QgsExpression::replaceExpressionText() instead
|
||||
*/
|
||||
QString expandAction( QString action, const QgsAttributeMap &attributes, uint defaultValueIndex );
|
||||
Q_DECL_DEPRECATED QString expandAction( QString action, const QgsAttributeMap &attributes, uint defaultValueIndex );
|
||||
|
||||
/** Expands the given action using the expression builder
|
||||
* This function currently replaces each expression between [% and %]
|
||||
@ -132,10 +133,11 @@ class CORE_EXPORT QgsActionManager
|
||||
*
|
||||
* Additional substitutions can be passed through the substitutionMap
|
||||
* parameter
|
||||
* @deprecated use QgsExpression::replaceExpressionText() instead
|
||||
*/
|
||||
QString expandAction( const QString& action,
|
||||
QgsFeature &feat,
|
||||
const QMap<QString, QVariant> *substitutionMap = nullptr );
|
||||
Q_DECL_DEPRECATED QString expandAction( const QString& action,
|
||||
QgsFeature &feat,
|
||||
const QMap<QString, QVariant> *substitutionMap = nullptr );
|
||||
|
||||
|
||||
//! Writes the actions out in XML format
|
||||
@ -165,11 +167,15 @@ class CORE_EXPORT QgsActionManager
|
||||
Q_DECL_DEPRECATED static void setPythonExecute( void ( * )( const QString & ) );
|
||||
|
||||
/**
|
||||
* Get the index of the default action
|
||||
* Returns the index of the default action, or -1 if no default action is available.
|
||||
* @see setDefaultAction()
|
||||
*/
|
||||
int defaultAction() const { return mDefaultAction < 0 || mDefaultAction >= size() ? -1 : mDefaultAction; }
|
||||
|
||||
/**
|
||||
* Set the index of the default action
|
||||
* Set the index of the default action.
|
||||
* @param actionNumber index of action which should be made the default for the layer
|
||||
* @see defaultAction()
|
||||
*/
|
||||
void setDefaultAction( int actionNumber ) { mDefaultAction = actionNumber ; }
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
/***************************************************************************
|
||||
qgsactionmanager.h
|
||||
qgsactionmanager.h
|
||||
|
||||
This is a legacy header to keep backwards compatibility until QGIS 3.
|
||||
This is a legacy header to keep backwards compatibility until QGIS 3.
|
||||
|
||||
-------------------
|
||||
begin : Oct 24 2004
|
||||
copyright : (C) 2004 by Gavin Macaulay
|
||||
email : gavin at macaulay dot co dot nz
|
||||
***************************************************************************/
|
||||
-------------------
|
||||
begin : Oct 24 2004
|
||||
copyright : (C) 2004 by Gavin Macaulay
|
||||
email : gavin at macaulay dot co dot nz
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
|
@ -7,6 +7,7 @@ IF (WITH_SERVER)
|
||||
ADD_PYTHON_TEST(PyQgsLocalServer test_qgis_local_server.py)
|
||||
ENDIF (WITH_SERVER)
|
||||
|
||||
ADD_PYTHON_TEST(PyQgsActionManager test_qgsactionmanager.py)
|
||||
ADD_PYTHON_TEST(PyQgsAggregateCalculator test_qgsaggregatecalculator.py)
|
||||
ADD_PYTHON_TEST(PyQgsAnalysis test_qgsanalysis.py)
|
||||
ADD_PYTHON_TEST(PyQgsApplication test_qgsapplication.py)
|
||||
|
229
tests/src/python/test_qgsactionmanager.py
Normal file
229
tests/src/python/test_qgsactionmanager.py
Normal file
@ -0,0 +1,229 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsActionManager.
|
||||
|
||||
.. 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__ = '28/05/2016'
|
||||
__copyright__ = 'Copyright 2016, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import qgis # switch sip api
|
||||
|
||||
from qgis.core import (QgsVectorLayer,
|
||||
QgsFeature,
|
||||
QgsActionManager,
|
||||
QgsAction,
|
||||
QgsExpressionContext,
|
||||
QgsField,
|
||||
QgsFields
|
||||
)
|
||||
from qgis.PyQt.QtCore import QDir, QTemporaryFile
|
||||
|
||||
from qgis.testing import (start_app,
|
||||
unittest
|
||||
)
|
||||
import os
|
||||
import time
|
||||
import platform
|
||||
|
||||
start_app()
|
||||
|
||||
|
||||
class TestQgsActionManager(unittest.TestCase):
|
||||
|
||||
def __init__(self, methodName):
|
||||
"""Run once on class initialization."""
|
||||
unittest.TestCase.__init__(self, methodName)
|
||||
|
||||
self.layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddate:datetime",
|
||||
"test_layer", "memory")
|
||||
self.manager = QgsActionManager(self.layer)
|
||||
|
||||
# make a little script to aid in recording action outputs
|
||||
# this is just a little python file which writes out it's arguments to a text file
|
||||
self.run_script_file = os.path.join(QDir.tempPath(), 'run_action.py')
|
||||
with open(self.run_script_file, 'w') as s:
|
||||
s.write('import sys\n')
|
||||
s.write('open(sys.argv[1], "w").write(" ".join(sys.argv[2:]))\n')
|
||||
|
||||
def get_temp_filename(self):
|
||||
tmpFile = QTemporaryFile()
|
||||
tmpFile.open() # fileName is no available until open
|
||||
tmpName = tmpFile.fileName()
|
||||
tmpFile.close()
|
||||
tmpFile.setAutoRemove(False)
|
||||
return tmpName
|
||||
|
||||
def create_action(self, dest_file, text_to_write):
|
||||
""" returns an action which writes some output to a file """
|
||||
return 'python {} {} {}'.format(self.run_script_file, dest_file, text_to_write)
|
||||
|
||||
def testLayer(self):
|
||||
self.assertEqual(self.manager.layer(), self.layer)
|
||||
|
||||
def testAddAction(self):
|
||||
""" Test adding actions """
|
||||
|
||||
# should be empty to start with
|
||||
self.assertEqual(self.manager.size(), 0)
|
||||
self.assertEqual(self.manager.listActions(), [])
|
||||
|
||||
# add an action
|
||||
self.manager.addAction(QgsAction.GenericPython, 'test_action', 'i=1')
|
||||
self.assertEqual(self.manager.size(), 1)
|
||||
self.assertEqual(self.manager.listActions()[0].type(), QgsAction.GenericPython)
|
||||
self.assertEqual(self.manager.listActions()[0].name(), 'test_action')
|
||||
self.assertEqual(self.manager.listActions()[0].action(), 'i=1')
|
||||
self.assertEqual(self.manager.at(0).name(), 'test_action')
|
||||
self.assertEqual(self.manager[0].name(), 'test_action')
|
||||
|
||||
# add another action
|
||||
self.manager.addAction(QgsAction.Windows, 'test_action2', 'i=2')
|
||||
self.assertEqual(self.manager.size(), 2)
|
||||
self.assertEqual(self.manager.listActions()[1].type(), QgsAction.Windows)
|
||||
self.assertEqual(self.manager.listActions()[1].name(), 'test_action2')
|
||||
self.assertEqual(self.manager.listActions()[1].action(), 'i=2')
|
||||
self.assertEqual(self.manager.at(1).name(), 'test_action2')
|
||||
self.assertEqual(self.manager[1].name(), 'test_action2')
|
||||
|
||||
# add a predefined action
|
||||
action = QgsAction(QgsAction.Unix, 'test_action3', 'i=3', False)
|
||||
self.manager.addAction(action)
|
||||
self.assertEqual(self.manager.size(), 3)
|
||||
self.assertEqual(self.manager.listActions()[2].type(), QgsAction.Unix)
|
||||
self.assertEqual(self.manager.listActions()[2].name(), 'test_action3')
|
||||
self.assertEqual(self.manager.listActions()[2].action(), 'i=3')
|
||||
self.assertEqual(self.manager.at(2).name(), 'test_action3')
|
||||
self.assertEqual(self.manager[2].name(), 'test_action3')
|
||||
|
||||
def testRemoveActions(self):
|
||||
""" test removing actions """
|
||||
|
||||
# add an action
|
||||
self.manager.addAction(QgsAction.GenericPython, 'test_action', 'i=1')
|
||||
|
||||
# clear the manager and check that it's empty
|
||||
self.manager.clearActions()
|
||||
self.assertEqual(self.manager.size(), 0)
|
||||
self.assertEqual(self.manager.listActions(), [])
|
||||
|
||||
# add some actions
|
||||
self.manager.addAction(QgsAction.GenericPython, 'test_action', 'i=1')
|
||||
self.manager.addAction(QgsAction.GenericPython, 'test_action2', 'i=2')
|
||||
self.manager.addAction(QgsAction.GenericPython, 'test_action3', 'i=3')
|
||||
|
||||
# remove non-existant action
|
||||
self.manager.removeAction(5)
|
||||
|
||||
# remove them one by one
|
||||
self.manager.removeAction(1)
|
||||
self.assertEqual(self.manager.size(), 2)
|
||||
self.assertEqual(self.manager.listActions()[0].name(), 'test_action')
|
||||
self.assertEqual(self.manager.listActions()[1].name(), 'test_action3')
|
||||
self.manager.removeAction(0)
|
||||
self.assertEqual(self.manager.size(), 1)
|
||||
self.assertEqual(self.manager.listActions()[0].name(), 'test_action3')
|
||||
self.manager.removeAction(0)
|
||||
self.assertEqual(self.manager.size(), 0)
|
||||
|
||||
def testRetrieveAction(self):
|
||||
""" test retrieving actions """
|
||||
self.manager.clearActions()
|
||||
|
||||
# test that exceptions are thrown when retrieving bad indices
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
self.manager[0]
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
self.manager.at(0)
|
||||
|
||||
self.manager.addAction(QgsAction.GenericPython, 'test_action', 'i=1')
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
self.manager[-1]
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
self.manager.at(-1)
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
self.manager[5]
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
self.manager.at(5)
|
||||
|
||||
def testDefaultAction(self):
|
||||
""" test default action for layer"""
|
||||
|
||||
self.manager.clearActions()
|
||||
self.manager.addAction(QgsAction.GenericPython, 'test_action', 'i=1')
|
||||
self.manager.addAction(QgsAction.GenericPython, 'test_action2', 'i=2')
|
||||
|
||||
# initially should be not set
|
||||
self.assertEqual(self.manager.defaultAction(), -1)
|
||||
|
||||
# set bad default action
|
||||
self.manager.setDefaultAction(10)
|
||||
self.assertEqual(self.manager.defaultAction(), -1)
|
||||
|
||||
# set good default action
|
||||
self.manager.setDefaultAction(1)
|
||||
self.assertEqual(self.manager.defaultAction(), 1)
|
||||
|
||||
# if default action is removed, should be reset to -1
|
||||
self.manager.clearActions()
|
||||
self.assertEqual(self.manager.defaultAction(), -1)
|
||||
|
||||
def check_action_result(self, temp_file):
|
||||
with open(temp_file, 'r') as result:
|
||||
output = result.read()
|
||||
return output
|
||||
|
||||
@unittest.expectedFailure(platform.system() != 'Linux')
|
||||
def testDoAction(self):
|
||||
""" test running action """
|
||||
|
||||
self.manager.clearActions()
|
||||
|
||||
# simple action
|
||||
temp_file = self.get_temp_filename()
|
||||
self.manager.addAction(QgsAction.Unix, 'test_action', self.create_action(temp_file, 'test output'))
|
||||
|
||||
fields = QgsFields()
|
||||
fields.append(QgsField('my_field'))
|
||||
fields.append(QgsField('my_other_field'))
|
||||
|
||||
f = QgsFeature(fields, 1)
|
||||
f.setAttributes([5, 'val'])
|
||||
|
||||
c = QgsExpressionContext()
|
||||
self.manager.doAction(0, f, c)
|
||||
time.sleep(0.05)
|
||||
|
||||
self.assertEqual(self.check_action_result(temp_file), 'test output')
|
||||
|
||||
# action with substitutions
|
||||
temp_file = self.get_temp_filename()
|
||||
self.manager.addAction(QgsAction.Unix, 'test_action', self.create_action(temp_file, 'test [% $id %] output [% @layer_name %]'))
|
||||
self.manager.doAction(1, f, c)
|
||||
time.sleep(0.05)
|
||||
|
||||
self.assertEqual(self.check_action_result(temp_file), 'test 1 output test_layer')
|
||||
|
||||
# test doAction using field variant
|
||||
temp_file = self.get_temp_filename()
|
||||
self.manager.addAction(QgsAction.Unix, 'test_action', self.create_action(temp_file, 'test [% @current_field %]'))
|
||||
self.manager.doActionFeature(2, f, 0)
|
||||
time.sleep(0.05)
|
||||
self.assertEqual(self.check_action_result(temp_file), 'test 5')
|
||||
self.manager.doActionFeature(2, f, 1)
|
||||
time.sleep(0.05)
|
||||
self.assertEqual(self.check_action_result(temp_file), 'test val')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user