fsleyes.actions

This package provides a collection of actions, classes - the Action class and the ActionProvider class, and the action() and toggleAction() decorators.

The Action class represents some sort of action which may be performed, enabled and disabled, and may be bound to a GUI menu item or button. The ActionProvider class represents some entity which can perform one or more actions. As the FSLeyesPanel class derives from ActionProvider pretty much everything in FSLeyes is an ActionProvider.

Many of the modules in this package also contain standalone functions for doing various things, such as the screenshot.screenshot() function, and the loadoverlay.loadImage() function.

The action() and toggleAction() functions are intended to be used as decorators upon the methods of a class which derives from ActionProvider. For example:

>>> import fsleyes.actions as actions
>>> class Thing(actions.ActionProvider):
        @actions.action
        def doFirstThing(self):
            print 'First thing done'
        @actions.action
        def doSecondThing(self):
            print 'Second thing done'
        @actions.toggleAction
        def toggleOtherThing(self):
            print 'Other thing toggled'

In this example, when an instance of Thing is defined, each of the methods that are defined as actions will be available through the methods defined in the ActionProvder. For example:

>>> t = Thing()
>>> print t.getActions()
[('doFirstThing', Action(doFirstThing)),
 ('doSecondThing', Action(doSecondThing)),
 ('toggleOtherThing', ToggleAction(toggleOtherThing))]

You can enable/disable actions through the ActionProvider.enableAction() and ActionProvider.disableAction() methods:

>>> t.disableAction('doFirstThing')
>>> t.doFirstThing()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../fsleyes/actions/__init__.py", line 139, in __call__
    self.__name))
fsleyes.actions.ActionDisabledError: Action doFirstThing is disabled

It is useful to know that each method on the t instance has actually been replaced with an Action instance, which encapsulates the method. Using this knowledge, you can access the Action instances directly:

>>> t.doFirstThing.enabled = True
>>> t.doFirstThing()
First thing done

The Action.bindToWidget() method allows a widget to be bound to an Action. For example:

# We're assuming here that a wx.App, and
# a parent window, has been created
>>> button = wx.Button(parent, label='Do the first thing!')
>>> t.doSecondThing.bindToWidget(parent, button, wx.EVT_BUTTON)

All bound widgets of an Action can be accessed through the Action.getBoundWidgets() method, and can be unbound via the Action.unbindAllWidgets() method.

This module also provides two classes which allow a widget to be automatically created for, and bound to an Action or ToggleAction (through the props.build package):

ActionButton

Extends the props.Button class to encapsulate an Action instance.

ToggleActionButton

Extends the props.Toggle class to encapsulate a ToggleAction instance.

fsleyes.actions.action(*args, **kwargs)[source]

A decorator which identifies a class method as an action.

fsleyes.actions.toggleAction(*args, **kwargs)[source]

A decorator which identifies a class method as a toggle action.

fsleyes.actions.toggleControlAction(*args, **kwargs)[source]

A decorator which identifies a class method as a ToggleControlPanelAction.

class fsleyes.actions.ActionProvider(overlayList, displayCtx)[source]

Bases: object

The ActionProvider class is intended to be used as a base class for classes which contain actions. The action() and toggleAction() functions can be used as decorators on class methods, to denote them as actions.

__init__(overlayList, displayCtx)[source]

Create an ActionProvider.

Parameters:
property overlayList

Return a reference to the OverlayList.

property displayCtx

Return a reference to the DisplayContext.

destroy()[source]

Must be called when this ActionProvider is no longer needed. Calls the Action.destroy() method of all Action instances.

getAction(name)[source]

Return the Action instance with the specified name.

hasAction(name)[source]

Return True if this ActionProvider has an action with the given name, False otherwise

enableAction(name, enable=True)[source]

Enable/disable the named Action.

disableAction(name)[source]

Disable the named Action.

getActions()[source]

Return a list containing the (name, Action) of all Action instances in this ActionProvider.

Sub-classes may wish to override this method to enforce a specific ordering of their actions.

Note

The list returned by this method may contain entries equal to (None, None). This is used as a hint for the FSLeyesFrame, which creates menu items, to indicate that a separator should be inserted.

__dict__ = mappingproxy({'__module__': 'fsleyes.actions', '__doc__': 'The ``ActionProvider`` class is intended to be used as a base class for\n    classes which contain actions. The :func:`action` and :func:`toggleAction`\n    functions can be used as decorators on class methods, to denote them as\n    actions.\n    ', '__init__': <function ActionProvider.__init__>, 'overlayList': <property object>, 'displayCtx': <property object>, 'destroy': <function ActionProvider.destroy>, 'getAction': <function ActionProvider.getAction>, 'hasAction': <function ActionProvider.hasAction>, 'enableAction': <function ActionProvider.enableAction>, 'disableAction': <function ActionProvider.disableAction>, 'getActions': <function ActionProvider.getActions>, '__dict__': <attribute '__dict__' of 'ActionProvider' objects>, '__weakref__': <attribute '__weakref__' of 'ActionProvider' objects>, '__annotations__': {}})
__module__ = 'fsleyes.actions'
__weakref__

list of weak references to the object

class fsleyes.actions.ActionFactory(actionType, *args, **kwargs)[source]

Bases: object

The ActionFactory is used by the action(), toggleAction(), and toggleControlPanelAction() decorators. Its job is to create Action instances for ActionProvider instances.

Warning

This class contains difficult-to-understand code. Read up on decorators and descriptors before proceeding.

Note

This class has no use outside of this module, except for use with custom Action/ToggleAction sub-classes and corresponding decorators (along the lines of action() and toggleAction()). A custom decorator simply needs to return ActionFactory(CustomActionClass, *args, **kwargs), where the *args and **kwargs are the arguments passed to the Action sub-class.

See the toggleControlAction() decorator for an example.

Boring technical details

Consider the following class:

class MyThing(ActionProvider):

    @action
    def myAction(self):
        # do things here

The MyClass.myAction method has been marked as an action, using the action() decorator. However, the action() decorator cannot create an Action instance at the point of class definition, because this would lead to a single Action instance being shared by multiple MyThing instances. We need to be able to create an Action instance for every MyThing instance, whilst still allowing the action decorator to be used on class methods.

So when the action() or toggleAction() is used in a class definition, an ActionFactory is created, and used as the decorator of the unbound class method.

Later on, when the ActionFactory detects that it being is accessed through an instance of the class (a MyThing instance in the example above), it creates an Action instance, and then replaces itself with this Action instance - the Action instance becomes the decorator of the bound method. This is possible because the ActionFactory is a descriptor - it uses the __get__() method so it can differentiate between class-level and instance-level accesses of the decorated method.

The ActionFactory supports class-method decorators both with and without arguments. While neither the Action, nor the ToggleAction classes accept any optional arguments, this may be useful for custom sub-classes, i.e.:

class MyThing(ActionProvider):

    @action
    def myAction(self):
        # do things here

    @customAction()
    def myAction2(self):
        # do things here

    @otherCustomAction(arg1=8)
    def myAction3(self):
        # do things here

Todo

Merge/replace this class with the memoize.Instanceify decorator.

__init__(actionType, *args, **kwargs)[source]

Create an ActionFactory.

Parameters:

actionType – The action type (e.g. Action or ToggleAction).

The remaining arguments may comprise a single callable object, (an @action style decorator was used) or a collection of arguments passed to the decorator (an @action(...) style decorator was used).

__call__(func=None)[source]

If this ActionFactory was instantiated through a brackets-style decorator (e.g. @action(arg1=1, arg2=2)), this method is called immediately after __init__(), with a reference to the decorated function. Otherwise, (an @action style decorator was used), this method should never be called.

__get__(instance, cls)[source]

When this ActionFactory is accessed through an instance, an Action instance is created. This ActionFactory is then replaced by the Action instance.

If this ActionFactory is accessed through a class, the encapsulated function is returned.

__dict__ = mappingproxy({'__module__': 'fsleyes.actions', '__doc__': 'The ``ActionFactory`` is used by the :func:`action`,\n    :func:`toggleAction`, and :func:`toggleControlPanelAction` decorators.\n    Its job is to create :class:`Action` instances for :class:`ActionProvider`\n    instances.\n\n\n    .. warning:: This class contains difficult-to-understand code. Read up\n                 on decorators and descriptors before proceeding.\n\n\n    .. note:: This class has no use outside of this module, except for use\n              with custom :class:`.Action`/:class:`.ToggleAction` sub-classes\n              and corresponding decorators (along the lines of :func:`.action`\n              and :func:`.toggleAction`). A custom decorator simply needs\n              to return ``ActionFactory(CustomActionClass, *args, **kwargs)``,\n              where the ``*args`` and ``**kwargs`` are the arguments passed to\n              the :class:`Action` sub-class.\n\n              See the :func:`toggleControlAction` decorator for an example.\n\n\n    *Boring technical details*\n\n\n    Consider the following class::\n\n        class MyThing(ActionProvider):\n\n            @action\n            def myAction(self):\n                # do things here\n\n\n    The ``MyClass.myAction`` method has been marked as an action, using the\n    :func:`action` decorator. However, the :func:`action` decorator cannot\n    create an :class:`Action` instance at the point of class definition,\n    because this would lead to a single ``Action`` instance being shared by\n    multiple ``MyThing`` instances.  We need to be able to create an ``Action``\n    instance for every ``MyThing`` instance, whilst still allowing the action\n    decorator to be used on class methods.\n\n\n    So when the :func:`action` or :func:`toggleAction` is used in a class\n    definition, an ``ActionFactory`` is created, and used as the decorator\n    of the unbound class method.\n\n\n    Later on, when the ``ActionFactory`` detects that it being is accessed\n    through an instance of the class (a ``MyThing`` instance in the example\n    above), it creates an :class:`Action` instance, and then replaces itself\n    with this ``Action`` instance - the ``Action`` instance becomes the\n    decorator of the bound method. This is possible because the\n    ``ActionFactory`` is a descriptor - it uses the :meth:`__get__` method\n    so it can differentiate between class-level and instance-level accesses\n    of the decorated method.\n\n\n    The ``ActionFactory`` supports class-method decorators both with and\n    without arguments. While neither the :class:`.Action`, nor the\n    :class:`.ToggleAction` classes accept any optional arguments, this may be\n    useful for custom sub-classes, i.e.::\n\n        class MyThing(ActionProvider):\n\n            @action\n            def myAction(self):\n                # do things here\n\n            @customAction()\n            def myAction2(self):\n                # do things here\n\n            @otherCustomAction(arg1=8)\n            def myAction3(self):\n                # do things here\n\n\n    .. todo:: Merge/replace this class with the :class:`.memoize.Instanceify`\n              decorator.\n    ', '__init__': <function ActionFactory.__init__>, '__call__': <function ActionFactory.__call__>, '__get__': <function ActionFactory.__get__>, '__dict__': <attribute '__dict__' of 'ActionFactory' objects>, '__weakref__': <attribute '__weakref__' of 'ActionFactory' objects>, '__annotations__': {}})
__module__ = 'fsleyes.actions'
__weakref__

list of weak references to the object

class fsleyes.actions.ActionButton(actionName, classType=None, actionArgs=None, actionKwargs=None, **kwargs)[source]

Bases: Button

Extends the props.Button class to encapsulate an Action instance.

Only actions which are defined using the action() or toggleAction() decorator are supported.

__init__(actionName, classType=None, actionArgs=None, actionKwargs=None, **kwargs)[source]

Create an ActionButton.

Parameters:
  • actionName – Name of the action

  • classType – The type which defines the action.

  • kwargs – Passed to the props.Button constructor.

__setup(instance, parent, widget)

Called when the button is created. Binds the button widget to the Action instance.

__onButton(instance, widget)

Called when the button is pushed. Runs the action.

__module__ = 'fsleyes.actions'
class fsleyes.actions.ToggleActionButton(actionName, icon, actionArgs=None, actionKwargs=None, **kwargs)[source]

Bases: Toggle

Extends the props.Toggle class to encapsulate a ToggleAction instance.

Only actions which are defined using the action() or toggleAction() decorator are supported.

__init__(actionName, icon, actionArgs=None, actionKwargs=None, **kwargs)[source]

Create a ToggleActionButton.

Parameters:
  • actionName – Name of the action

  • icon – One or two icon file names to use on the button.

  • actionArgs – Positional arguments to pass to the ToggleAction when it is invoked.

  • actionKwargs – Keyword arguments to pass to the ToggleAction when it is invoked.

  • kwargs – Passed to the props.Toggle constructor.

__setup(instance, parent, widget)

Called when the toggle widget is created. Binds the widget to the ToggleAction instance.

__annotations__ = {}
__module__ = 'fsleyes.actions'
__onToggle(instance, widget)

Called when the widget is toggled. Runs the action.