:mod:`dip.shell`
================
.. module:: dip.shell

The :mod:`dip.shell` module implements the infrastructure for defining and
interfacing with a :term:`shell`.


:class:`IDisplay`
-----------------
.. class:: IDisplay

    Base class: :class:`~dip.model.Interface`

    The IDisplay interface defines the metadata that an object may provide
    so that it can be referred to in a GUI and be recognisable by the user.
    It's use is usually optional, i.e. an application will normally try to use
    other information if an object does not implement this interface.

    .. attribute:: name = Str()

        The full name of the object.  This should uniquely identify the object
        to the user.

    .. attribute:: short_name = Str()

        The optional short name of the object.


:class:`IShell`
---------------
.. class:: IShell

    Base class: :class:`~dip.model.Interface`

    The IShell interface defines the API of a :term:`shell`.
    
    The following action identifiers are considered to be well known.  A shell
    would normally be expected to honour them.
    
        dip.shell.actions.close
        dip.shell.actions.export
        dip.shell.actions.import
        dip.shell.actions.new
        dip.shell.actions.open
        dip.shell.actions.print
        dip.shell.actions.print_preview
        dip.shell.actions.printer_settings
        dip.shell.actions.quit
        dip.shell.actions.redo
        dip.shell.actions.save
        dip.shell.actions.save_as
        dip.shell.actions.undo
        dip.shell.actions.whats_this
    
    The following action collection identifiers are considered to be well
    known.  A shell, if it supports the concept of action collections, would
    normally be expected to honour them.
    
        dip.shell.collections.edit
        dip.shell.collections.file
        dip.shell.collections.help
        dip.shell.collections.tools
        dip.shell.collections.view

    .. attribute:: actions = List(Instance(IAction))

        The available actions.

    .. attribute:: id = Str()

        The identifier of the shell.  The shell's object name will default to the
        identifier.

    .. attribute:: plugin_manager = Instance(IPluginManager)

        The optional plugin manager.  This is normally set by the plugin that
        publishes the shell as a service.

    .. attribute:: shell_manager = Instance(IShellManager)

        The shell manager.

    .. attribute:: toolkit = Instance(IToolkit)

        The toolkit.

    .. attribute:: widget = Instance(QWidget)

        The :class:`~PyQt4.QtGui.QWidget` instance that implements the shell.

    .. method:: IShell.__init__(**properties)

        Initialise the shell.
        
        :param \*\*properties:
            are keyword arguments used as property names and values that are
            applied to the shell widget.

    .. method:: IShell.add_tool(tool)

        Add a :term:`tool` to the shell.
        
        :param tool:
            is the tool to add.

    .. method:: IShell.perform_close(tool)

        Close a tool asking the user for help where necessary.
        
        :param tool:
            is the tool to close.

    .. method:: IShell.perform_new()

        Create a tool for a new shell object asking the user for help where
        necessary.

    .. method:: IShell.perform_open()

        Create a tool for a shell object read from storage asking the user
        for help where necessary.

    .. method:: IShell.perform_quit()

        Confirm that the user wants to quit given the state of any shell
        objects.

    .. method:: IShell.perform_save(tool)

        Write a shell object to storage at its current location asking the
        user for help where necessary.
        
        :param tool:
            is the tool operating on the shell object to write.

    .. method:: IShell.perform_save_as(tool)

        Write a shell object to storage at a new location asking the user
        for help where necessary.
        
        :param tool:
            is the tool operating on the shell object to write.


:class:`IShellAction`
---------------------
.. class:: IShellAction

    Base class: :class:`~dip.ui.IQActionAction`

    The IShellAction interface defines the API for an :term:`action` that
    changes its state according to the user's interaction with the containing
    shell.

    .. attribute:: enabled = Bool(True)

        This is set if the action is enabled.  If
        :meth:`~dip.shell.IShellAction.validate` returns ``False`` then the
        action will be disabled irrespective of this value.

    .. attribute:: handles = Instance(type)

        This is used by the default implementation of
        :meth:`~dip.shell.IShellAction.validate` to specify the type of the
        active tool that is valid for the action.  If it is not specified then
        the active tool, so long as there is one, will always be considered
        valid.

    .. attribute:: needs_tool = Bool(True)

        This is set if the action requires there to be an active tool.  If this
        is ``True`` then the action will be automatically disabled, and
        :meth:`~dip.shell.IShellAction.validate` will never be called, if there
        is no active tool.

    .. attribute:: on_perform = Callable()

        The default implementation of :meth:`~dip.shell.IShellAction.perform`
        calls this with the shell's active tool as its only argument.

    .. attribute:: shell = Instance(IShell)

        The shell.  This is normally set by the shell itself.

    .. attribute:: visible = Bool(True)

        This is set if the action is visible.

    .. method:: IShellAction.perform(tool)

        Perform the action (probably) on a tool.  This will not be called
        if :meth:`~dip.shell.IShellAction.validate` returns ``False``.
        
        :param tool:
            is the tool.

    .. method:: IShellAction.validate(tool)

        Check if the action can be performed on a tool.
        
        :param tool:
            is the tool.
        :return:
            ``True`` if the action can be performed.


:class:`IShellManager`
----------------------
.. class:: IShellManager

    Base class: :class:`~dip.model.Interface`

    The IShellManager interface defines the API for a
    :term:`shell manager`.

    .. attribute:: active_tool = Instance(QWidget)

        The currently active tool.

    .. attribute:: io_manager = Instance(IIOManager)

        The :class:`~dip.io.IIOManager`.

    .. attribute:: shell = Instance(dip.shell.IShell)

        The shell.

    .. attribute:: shell_object_factories = List(IShellObjectFactory)

        The available shell object factories.

    .. attribute:: tool_factories = List(IToolFactory)

        The available tool factories.

    .. method:: IShellManager.close(tool)

        Close a tool asking the user for help where necessary.
        
        :param tool:
            is the tool to close.
        :return:
            ``True`` if the user didn't cancel.

    .. method:: IShellManager.new()

        Create a tool for a new shell object asking the user for help where
        necessary.
        
        :return:
            the tool or None if the user cancelled.

    .. method:: IShellManager.open(location='')

        Create a tool for a shell object read from storage asking the user
        for help where necessary.
        
        :param location:
            is the optional location of the object to open.
        :return:
            the object or None if the user cancelled.

    .. method:: IShellManager.quit()

        Confirm that the user wants to quit given the state of any shell
        objects.
        
        :return:
            ``True`` if the user didn't cancel.

    .. method:: IShellManager.save(tool)

        Write a shell object to storage at its current location asking the
        user for help where necessary.
        
        :param tool:
            is the tool operating on the shell object to write.

    .. method:: IShellManager.save_as(tool)

        Write a shell object to storage at a new location asking the user
        for help where necessary.
        
        :param tool:
            is the tool operating on the shell object to write.


:class:`IShellObject`
---------------------
.. class:: IShellObject

    Base class: :class:`~dip.shell.IDisplay`

    The IShellObject interface defines the API of a :term:`shell object`.
        

    .. attribute:: dirty = Bool()

        This is set if the object needs writing to storage if no changes are to
        be lost.  It will be cleared automatically.

    .. attribute:: factory = Instance(IShellObjectFactory)

        The factory that created the object.  It will be set automatically.

    .. attribute:: location = Instance(IStorageLocation)

        The :term:`storage location` of the object.  It will be None if it is
        not stored.  It will be updated automatically.

    .. attribute:: valid = Bool(True)

        This is set if the object is valid and can be written to storage.


:class:`IShellObjectFactory`
----------------------------
.. class:: IShellObjectFactory

    Base class: :class:`~dip.model.Interface`

    The IShellObjectFactory interface defines the API for factories of
    :term:`shell objects<shell object>`.

    .. attribute:: name = Str()

        The name of the type of the shell object.

    .. attribute:: native_format = Str()

        The identifier of the object's native format.

    .. method:: IShellObjectFactory.__call__(shell)

        Create an instance of the shell object.
        
        :param shell:
            is the shell.
        
        :return:
            the instance of the shell object which must implement
            :class:`~dip.shell.IShellObject` or be able to be adapted to it.


:class:`ITool`
--------------
.. class:: ITool

    Base class: :class:`~dip.model.Interface`

    The ITool interface defines the API of a :term:`tool` than operates on
    a :term:`shell object` and relies on a :term:`shell manager` to manage the
    lifecycle of the object.

    .. attribute:: factory = Instance(IToolFactory)

        The factory that created the tool.

    .. attribute:: obj = Any()

        The :term:`shell object` that the tool is operating on.  This will be
        able to be adapted to :class:`~dip.tools.IShellObject` (or implement that
        interface explicitly).


:class:`IToolFactory`
---------------------
.. class:: IToolFactory

    Base class: :class:`~dip.model.Interface`

    The IToolFactory interface defines the API for :term:`tool` factories.
        

    .. attribute:: name = Str()

        The name of the tool.

    .. method:: IToolFactory.__call__(obj, toolkit)

        Create an instance of the tool.
        
        :param obj:
            is the obj on which the tool is to operate on.
        :param toolkit:
            is the :class:`~dip.ui.IToolkit` implementation that can be used to
            create widgets.
        :return:
            the instance of the tool.  This must be a
            :class:`~PyQt4.QtGui.QWidget` instance and, therefore, can be
            adapted to the :class:`~dip.tools.ITool` interface.

    .. method:: IToolFactory.handles(obj)

        Check if the tool can handle an object.
        
        :param obj:
            is the object.
        :return:
            ``True`` if the tool can handle the object.


:class:`IUnmanagedTool`
-----------------------
.. class:: IUnmanagedTool

    Base class: :class:`~dip.ui.IQActionAction`

    The IUnmanagedTool interface defines the API of an
    :term:`unmanaged tool`.

    .. attribute:: name = Str()

        The name of the tool as it appears to the user.

    .. attribute:: widget = Instance(QWidget)

        The :class:`~PyQt4.QtGui.QWidget` sub-class that implements the tool.


:class:`ModelToolFactory`
-------------------------
.. class:: ModelToolFactory

    Base class: :class:`~dip.model.Model`

    The ModelToolFactory class is a :term:`tool` factory for any tool that
    uses an automatically generated :term:`view` to edit a :term:`model`.  It
    is not registered as a tool factory itself, instead it will normally be
    sub-classed and those sub-classes will be registered.

    .. attribute:: model_type = Instance(type)

        The sub-class of Model that the tool can handle.

    .. method:: ModelToolFactory.__call__(model, toolkit)

        Create an instance of the tool.
        
        :param model:
            is the model on which the tool is to operate on.
        :param toolkit:
            is the :class:`~dip.ui.IToolkit` implementation used to create the
            view.
        :return:
            the instance of the tool.

    .. method:: ModelToolFactory.create_view_factory()

        Create the view factory that will be used to create the view.
         This default implementation creates a :class:`~dip.ui.Form`.
        
        :return:
            the view factory.

    .. method:: ModelToolFactory.handles(obj)

        Check if the object can be handled.
        
        :param obj:
            is the object.
        :return:
            ``True`` if the tool can handle the object.
