Logo Search packages:      
Sourcecode: mayavi2 version File versions  Download package

repository_handler.py

#-------------------------------------------------------------------------------
#
#  Define the repository import view handler
#
#  Written by: David C. Morrill
#
#  Date: 03/22/2006
#
#  (c) Copyright 2006 by Enthought, Inc.
#
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
#  Imports:
#-------------------------------------------------------------------------------

from os \
     import access, W_OK

from os.path \
     import join, split, splitext, basename, isfile, isdir, dirname

from enthought.traits.api \
     import HasPrivateTraits, Button, Instance, List, Str, Any, Property, \
     true,ToolbarButton
     
from enthought.traits.ui.api \
     import Handler, Item, Label, View, VGroup, HFlow, HSplit, \
     InstanceEditor, UIInfo

from enthought.traits.ui.menu \
     import Action

from enthought.envisage.resource.resource_type \
    import ResourceType

from enthought.envisage.resource.resource_plugin \
    import ResourcePlugin

from enthought.pyface.image_resource \
    import ImageResource

from enthought.pyface.api \
    import error, confirm, NO

from enthought.pyface.timer.api \
    import do_later

# Local imports:
from repository \
    import Repository

from repository_tree_editor \
    import repository_tree_editor, FileNode, RepositoryNode, DirectoryNode, \
           RepositoryRootNode

#-------------------------------------------------------------------------------
#  Constants:
#-------------------------------------------------------------------------------

# The location of the image files used:
image_location = dirname( __file__ )

# No directory specified message:
no_directory = ('---  (Please select the repository directory to store the '
                'item in)')

#-------------------------------------------------------------------------------
#  'DummySelection' class
#-------------------------------------------------------------------------------

class DummySelection ( HasPrivateTraits ):

    #---------------------------------------------------------------------------
    #  Traits view definitions:
    #---------------------------------------------------------------------------

    view = View(
               VGroup(
                   Label( 'Select an item in the tree view\n'
                          'to display its preview here.' ),
                   label       = 'Preview',
                   show_border = True
               ),
               resizable = True
           )

# Dummy a reusable instance:
dummy_selection = DummySelection()

#-------------------------------------------------------------------------------
#  'RepositoryHandler' class:
#-------------------------------------------------------------------------------

class RepositoryHandler ( Handler ):

    #---------------------------------------------------------------------------
    #  Trait definitions:
    #---------------------------------------------------------------------------

    # The info object associated with the UI:
    info = Instance( UIInfo )

    # The repository being imported from:
    repository = Instance( Repository )

    # The list of valid types (i.e. resource type ids) that can be imported:
    types = List( Str )

    # The resource types corresponding to the list of resource type ids:
    resource_types = List( ResourceType )

    # The name of the resource type view to be used for browsing the current
    # selected repository object:
    view = Str

    # The title to display in the import/export dialog:
    title = Str

    # The currently selected tree node:
    selection_node = Any

    # The currently selected repository object (if any):
    selection = Any( dummy_selection )

    # The parent window for the dialog:
    parent = Any

    # The root node of the repository tree view:
    root_node = Instance( RepositoryNode )

    # Should 'locked' root node be shown?
    show_locked = true

    #--- Toolbar buttons -------------------------------------------------------

    # Add a new repository root:
    add_root = ToolbarButton(
        image = ImageResource( 'add_root',
                               search_path = [ image_location ] ),
    )

    # Create a new folder:
    create_folder = ToolbarButton(
        image = ImageResource( 'create_folder',
                               search_path = [ image_location ] ),
    )

    # Delete the currently selected item:
    delete_item = ToolbarButton(
        image = ImageResource( 'delete_item',
                               search_path = [ image_location ] ),
    )

    #---------------------------------------------------------------------------
    #  Methods:
    #---------------------------------------------------------------------------
    
    #---------------------------------------------------------------------------
    #  Informs the handler what the UIInfo object for a View will be:  
    #---------------------------------------------------------------------------

    def init_info ( self, info ):
        self.info = info

    #---------------------------------------------------------------------------
    #  Initializes the controls of a user interface:
    #---------------------------------------------------------------------------

    def init ( self, info ):
        """ Initializes the controls of a user interface.
        """
        info.add_root.enabled      = True
        info.create_folder.enabled = info.delete_item.enabled = False

        return True

    #---------------------------------------------------------------------------
    #  Sets the root node of the repository tree:
    #---------------------------------------------------------------------------

    def set_root_node ( self ):
        """ Sets the root node of the repository tree.
        """
        self.root_node = self.selection_node = \
            RepositoryNode( show_locked = self.show_locked ).set(
                            repository  = self.repository,
                            handler     = self )

    #---------------------------------------------------------------------------
    #  Gets a specified View object (Handler override):
    #---------------------------------------------------------------------------

    def trait_view_for ( self, info, view, object, object_name, trait_name ):
        """ Gets a specified View object.
        """
        for rt in self.resource_types:
            if rt.is_type_for( object ):
                klass = rt.views.get( self.view )
                if klass is not None:
                    handler = klass()
                    return handler.trait_view().set( handler = handler )
                break

        return super( RepositoryHandler, self ).trait_view_for( info,
                                         view, object, object_name, trait_name )

    #---------------------------------------------------------------------------
    #  Handles the user selecting a node in the repository tree view:
    #---------------------------------------------------------------------------

    def on_select ( self, object ):
        """ Handles the user selecting a node in the repository tree view.
        """
        self.selection_node = object

        info = self.info
        if info.initialized:
            info.add_root.enabled = isinstance( object, RepositoryNode )
            if isinstance( object, RepositoryRootNode ):
                info.create_folder.enabled = ((not object.root.locked) and 
                                              access( object.path, W_OK ))
                if isinstance( object, DirectoryNode ):
                    info.delete_item.enabled = (info.create_folder.enabled and
                                                object.tno_can_delete_me())
                else:
                    info.delete_item.enabled = ((not object.root.locked) and
                                                object.tno_can_delete_me())
            else:
                info.create_folder.enabled = False
                info.delete_item.enabled   = (isinstance( object, FileNode ) and
                                              (not object.root.locked) and
                                              access( object.path, W_OK ))

    #---------------------------------------------------------------------------
    #  Handles the 'add_root' button being clicked:
    #---------------------------------------------------------------------------

    def _add_root_changed ( self ):
        """ Handles the 'add_root' button being clicked.
        """
        root_node = RepositoryRootNode()
        if root_node.edit_traits( parent = self.parent,
                                  kind   = 'livemodal' ).result:
            self.selection_node.roots.append( root_node )

    #---------------------------------------------------------------------------
    #  Handles the 'create_folder' button being clicked:
    #---------------------------------------------------------------------------

    def _create_folder_changed ( self ):
        """ Handles the 'create_folder' button being clicked.
        """
        dir_node = DirectoryNode()
        if dir_node.edit_traits( parent = self.parent,
                                 kind   = 'livemodal' ).result:
            self.selection_node.children.append( dir_node )

    #---------------------------------------------------------------------------
    #  Handles the 'delete_item' button being clicked:
    #---------------------------------------------------------------------------

    def _delete_item_changed ( self ):
        """ Handles the 'delete_item' button being clicked.
        """
        item = self.selection_node
        if item.tno_confirm_delete():
            if isinstance( item, ( DirectoryNode, FileNode ) ):
                item.delete()
            else:
                self.root_node.roots.remove( item )

    #---------------------------------------------------------------------------
    #  Handles the 'repository' trait being changed:
    #---------------------------------------------------------------------------

    def _repository_changed ( self, old, new ):
        """ Handles the 'repository' trait being changed.
        """
        if old is not None:
            old.on_trait_change( self._repository_modified, 'modified',
                                 remove = True )
        if new is not None:
            new.on_trait_change( self._repository_modified, 'modified' )

    #---------------------------------------------------------------------------
    #  Handles the associated repository being modified:
    #---------------------------------------------------------------------------

    def _repository_modified ( self ):
        """ Handles the associated repository being modified.
        """
        do_later( self.set_root_node )

#-------------------------------------------------------------------------------
#  'RepositoryImportHandler' class:
#-------------------------------------------------------------------------------

class RepositoryImportHandler ( RepositoryHandler ):

    #---------------------------------------------------------------------------
    #  Trait definitions:
    #---------------------------------------------------------------------------

    # Returns True when the 'import' button should be enabled:
    import_enabled = Property

    #---------------------------------------------------------------------------
    #  Methods:
    #---------------------------------------------------------------------------

    def process ( self, id ): 
        """ Process a request to display a repository import dialog. Returns
            None or the object that the user selected.
        """
        # Initialize the set of resource types we can import:
        self.set_resource_types()
        self.set_root_node()

        content = [ VGroup(
                        HFlow(
                            Item( 'add_root@',
                                  tooltip = 'Add a new repository root' ),
                            Item( 'create_folder@',
                                  tooltip = 'Create a new repository folder' ),
                            Item( 'delete_item@',
                                  tooltip = 'Delete the selection' ),
                            show_labels = False
                        ),
                        Item( 'root_node',
                              show_label = False,
                              style      = 'custom',
                              editor     = repository_tree_editor )
                    ) ]
        width = 0.25                                        
        if self.view != '':
            content.append( Item( 'selection',
                                  show_label = False,
                                  id         = 'selection',
                                  editor     = InstanceEditor(),
                                  style      = 'custom',
                                  resizable  = True ) )
            width = 0.50
        view = View(
                   HSplit( id = 'splitter', *content ),
                   title     = self.title,
                   buttons   = [ Action(
                                     name         = 'Import',
                                     enabled_when = 'import_enabled' ),
                                 'Cancel',
                                 'Help', ],
                   help_id   = 'enlib|HID_Import_Item_Dlg',
                   id        = id,
                   kind      = 'livemodal',
                   resizable = True,
                   width     = width,
                   height    = 0.5 )
        if self.edit_traits( view = view, parent = self.parent ).result:
            return self.selection
        return None

    #---------------------------------------------------------------------------
    #  Sets the 'resource_types' trait to the resource types corresponding
    #  to the set of resource type ids specified by 'types':
    #---------------------------------------------------------------------------

    def set_resource_types ( self ):
        """ Sets the 'resource_types' trait to the resource types corresponding
            to the set of resource type ids specified by 'types'.
        """    
        rm = self.repository.application.get_service(
                                             ResourcePlugin.IRESOURCE_MANAGER )
        self.resource_types = [ rm.lookup( id ) for id in self.types ]

    #---------------------------------------------------------------------------
    #  Handles the user clicking the 'Import' button:
    #---------------------------------------------------------------------------

    def _import_clicked ( self, info ):
        """ Handles the user clicking the 'Import' button.
        """
        info.ui.dispose( True )

    #---------------------------------------------------------------------------
    #  Handles the user selecting a node in the repository tree view:
    #---------------------------------------------------------------------------

    def on_select ( self, object ):
        """ Handles the user selecting a node in the repository tree view.
        """
        super( RepositoryImportHandler, self ).on_select( object )

        if isinstance( object, FileNode ):
            try:
                self.selection = object.object
                return
            except:
                error( self.parent, "Could not load '%s'" % 
                                    splitext( basename( object.path ) )[0] )

        self.selection = dummy_selection

#-- Property Implementations ---------------------------------------------------

    def _get_import_enabled ( self ):
        return (self.selection is not dummy_selection)

#-------------------------------------------------------------------------------
#  'RepositoryExportHandler' class:
#-------------------------------------------------------------------------------

class RepositoryExportHandler ( RepositoryHandler ):

    #---------------------------------------------------------------------------
    #  Trait definitions:
    #---------------------------------------------------------------------------

    # The object to be exported:
    object = Any

    # The currently selected path for exporting:
    path = Str( no_directory )

    # The name of the object in the file system (minus path and extension)
    file_name = Str

    # True when the 'Export' button should be enabled:
    export_enabled = Property

    # Should 'locked' root node be shown (override):
    show_locked = False

    #---------------------------------------------------------------------------
    #  Methods:
    #---------------------------------------------------------------------------

    def process ( self, id ):
        """ Process a request to display a repository export dialog. Returns
            True if the object was exported successfully; and False otherwise.
        """
        # Initialize the set of resource types we can import:
        self.set_resource_types()
        self.set_root_node()

        content = [ VGroup(
                        HFlow(
                             Item( 'add_root@',
                                    tooltip = 'Add a new repository root' ),
                             Item( 'create_folder@',
                                    tooltip = 'Create a new repository folder'),
                             Item( 'delete_item@',
                                    tooltip = 'Delete the selection' ),
                             show_labels = False
                        ),
                        Item( 'root_node',
                              show_label = False,
                              style      = 'custom', 
                              editor     = repository_tree_editor )
                    ) ]
        width = 0.25                                        
        if self.view != '':
            content.append( Item( 'object',
                                  show_label = False,
                                  id         = 'selection',
                                  editor     = InstanceEditor(),
                                  style      = 'custom' ) )
            width = 0.50
        view = View( 
                   VGroup( 
                       HSplit( id = 'splitter', *content ),
                       Item( 'path', label = 'Directory', style = 'readonly' ),
                       Item( 'file_name' ),
                   ),
                   title     = self.title,
                   buttons   = [ Action( name         = 'Export', 
                                         enabled_when = 'export_enabled' ),
                                 'Cancel' ],
                   id        = id,
                   kind      = 'livemodal',
                   resizable = True,
                   width     = width,
                   height    = 0.5 )
        return self.edit_traits( view = view, parent = self.parent ).result

    #---------------------------------------------------------------------------
    #  Sets the 'resource_types' trait to the resource type corresponding
    #  to the object being exported:
    #---------------------------------------------------------------------------

    def set_resource_types ( self ):
        """ Sets the 'resource_types' trait to the resource type corresponding
            to the object being exported.
        """    
        rm = self.repository.application.get_service(
                                             ResourcePlugin.IRESOURCE_MANAGER )
        rt = rm.get_type_of( self.object )
        self.resource_types = [ rt ]
        self.types = [ rt.id ]

    #---------------------------------------------------------------------------
    #  Handles the user clicking the 'Export' button:
    #---------------------------------------------------------------------------

    def _export_clicked ( self, info ):
        """ Handles the user clicking the 'Export' button.
        """
        if hasattr(self.object, 'name') and self.object.name == "":
            self.object.name = self.file_name
            
        # Generate and validate the selected file name for the object:
        path      = join( self.path, self.file_name )
        rt        = self.resource_types[0]
        full_path = path + rt.serializer.ext
        if isfile( full_path ):
            if confirm( self.parent,
                        "'%s' already exists.\nDo you wish to replace it?" %
                        self.file_name, 'Confirm Export' ) == NO:
                return
        elif isdir( full_path ):
            error( self.parent, ("Cannot export to '%s'.\nA directory with "
            "that name already exists.") % (self.file_name + rt.serializer.ext))
            return

        # Save the object to the specified file:
        try:
            rt.serializer.save( path, self.object )
            self.repository.modified = True
        except:
            from traceback import print_exc
            print_exc()
            error( self.parent, "Could not save '%s'" % self.file_name )
            return

        # Close the dialog successfully:
        info.ui.dispose( True )

    #---------------------------------------------------------------------------
    #  Handles the user selecting a node in the repository tree view:
    #---------------------------------------------------------------------------

    def on_select ( self, object ):
        """ Handles the user selecting a node in the repository tree view.
        """
        super( RepositoryExportHandler, self ).on_select( object )

        if isinstance( object, RepositoryRootNode ):
            path = object.path
            if not access( path, W_OK ):
                path = ''
            self.path = path

        elif isinstance( object, FileNode ):
            path, file_name = split( object.path )
            if not access( path, W_OK ):
                path = ''
            self.path      = path
            self.file_name = splitext( file_name )[0]

#-- Property Implementations ---------------------------------------------------

    def _get_export_enabled ( self ):
        return ((self.path != no_directory) and (self.file_name != ''))


Generated by  Doxygen 1.6.0   Back to index