class DeleteMolecule(MVCommand):
    """Command to delete a molecule from the MoleculeViewer
    \nPackage : Pmv
    \nModule  : deleteCommands
    \nClass   : DeleteMolecule
    \nCommand : deleteMolecule
    \nSynopsis:\n
        None<---deleteMol(nodes, **kw)
    \nRequired Arguments:\n
        nodes --- TreeNodeSet holding the current selection
           It resets the undo stack automatically.\n
    """
    
    def onAddCmdToViewer(self):
        self.vf._deletedLevels = []
        if  not self.vf.commands.has_key('select'):
            self.vf.loadCommand("selectionCommands", "select", "Pmv",
                                topCommand=0)
        if  not self.vf.commands.has_key('clearSelection'):
            self.vf.loadCommand("selectionCommands", "clearSelection", "Pmv",
                                topCommand=0)

    def onAddObjectToViewer(self, obj):
        if hasattr(self, 'chooser')\
               and self.chooser is not None \
               and self.form.root.winfo_exists():        
            w = self.chooser.form.descr.entryByName['Molecule']['widget']
            molParser = obj.parser
            molStr = molParser.getMoleculeInformation()
            w.add((obj.name, molStr))
 
           
    def deleteMolecule_cb(self):
        """called each time the 'Delete Molecule' button is pressed"""
        mols = self.chooser.getMolSet()
        if mols is not None and len(mols):
            if self.vf.undoCmdStack == []:
                self.doitWrapper(mols, redraw=0)
                
            else:
            
                text = """WARNING: This command cannot be undone.
                if you choose to continue the undo list will be reset.
                The hide Button will make the molecule disappear without
                resetting the Undo list. Do you want to continue?""" 
                if not hasattr(self, 'idf'): 
                    self.idf = InputFormDescr(title="WARNING")
                    self.idf.append({'widgetType':Tkinter.Label,
                                'wcfg':{'text':text},
                                'gridcfg':{'columnspan':3,'sticky':'w'}})

                    self.idf.append({'name': 'Continue Button',
                                'widgetType':Tkinter.Button,
                                'wcfg':{'text':'CONTINUE',
                                        'command':self.continue_cb},
                                'gridcfg':{'sticky':'we'}})

                    self.idf.append({'name': 'Cancel Button',
                                'widgetType':Tkinter.Button,
                                'wcfg':{'text':'CANCEL',
                                        'command':self.cancel_cb},
                                'gridcfg':{'row':-1,'sticky':'we'}})

                    self.idf.append({'name': 'Hide Button',
                                'widgetType':Tkinter.Button,
                                'wcfg':{'text':'HIDE',
                                        'command':self.hide_cb},
                                'gridcfg':{'row':-1,'sticky':'we'}})
                form = self.vf.getUserInput(self.idf, okcancel=0)
                self.form.root.protocol('WM_DELETE_WINDOW',self.cancel_cb)
                

    def hide_cb(self):
        if hasattr(self, 'chooser'):
            if self.chooser.ipf.form is not None:
                mols = self.chooser.getMolSet()
                self.vf.showMolecules(mols.name, negate=1, topCommand=0)
                self.chooser.done_cb()
            self.idf.form.destroy()
            


    def continue_cb(self):
        if hasattr(self, 'chooser'):
            if self.chooser.ipf.form is not None:
                mols = self.chooser.getMolSet()
                self.vf.resetUndo(topCommand=0)
                self.doitWrapper(mols, redraw=0)
            self.idf.form.destroy()


    def cancel_cb(self):
        self.idf.form.destroy()
        
    def guiCallback(self):
        if len(self.vf.Mols) == 0: return
        self.chooser = MoleculeChooser(self.vf,mode = 'extended',
                                       title='Choose Molecules to delete' )
        self.chooser.ipf.append({'name':'Delete Button',
                                 'widgetType':Tkinter.Button,
                                 'text':'Delete Molecule',
                                 'wcfg':{'bd':6},
                                 'gridcfg':{'sticky':Tkinter.E+Tkinter.W},
                                 'command': self.deleteMolecule_cb})
        self.form = self.chooser.go(modal=0, blocking=0)


    def deleteMol(self, mol):
        """ Function to delete all the references to each elements of a
        molecule and then these elements and the molecule to free the
        memory space."""

        #  Call the removeObject function for all the command having an
        # onRemoveMol function
        self.vf.removeObject(mol)

        # Maybe do that in moleculeViewer ???
        # also need to clean up selector.selection:
        nodes = self.vf.getSelection()
        mol.__class__._numberOfDeletedNodes = 0
        node = mol
        while len(node.children):
            node = node.children

        # Initialize the variable _numberOfDeletedNodes at 0
        node[0].__class__._numberOfDeletedNodes = 0
        sslevels = [Coil, Helix, Strand, Turn]
        # Initialize the variable _numberOfDeletedNodes for each secondary
        # structure to 0.
        for sl in sslevels:
            # Initialize the variable _numberOfDeletedNodes at 0
            sl._numberOfDeletedNodes = 0

        # but only change selection if there is any
        if nodes is not None and len(nodes)>0:
            setClass = nodes.__class__
            thisMolNodes = setClass(nodes.get(lambda x, mol=mol: x.top==mol))
            #only change selection if this molecule has any nodes in it
            if len(thisMolNodes)>0:
                nodes = nodes-thisMolNodes
                self.vf.clearSelection(topCommand=0)
                if nodes is not None:
                    self.vf.select(nodes)
                    #self.vf.selector.select(nodes)

        if hasattr(self, 'chooser') and self.form.root.winfo_exists():
            # update the listChooser
            lc = self.chooser.ipf.entryByName['Molecule']['widget']
            lc.remove(mol.name)
            #lc.clearComments()

        #check for any possible reference in self.vf.GUI.VIEWER.lastPick
        if self.vf.hasGui and self.vf.GUI.VIEWER.lastPick:
            for key in self.vf.GUI.VIEWER.lastPick.hits.keys():
                if hasattr(key,'mol'):
                    if mol==key.mol:
                        del self.vf.GUI.VIEWER.lastPick.hits[key]

        # Remove the atoms of the molecule you are deleting from the
        # the AtomSet self.vf.allAtoms
        self.vf.allAtoms = self.vf.allAtoms - mol.allAtoms
        # Delete all the reference to the atoms you want to delete
        if hasattr(mol.allAtoms, 'bonds'):
            bnds = mol.allAtoms.bonds[0]
            for b in bnds:
                b.__dict__.clear()
                del(b)
        mol.allAtoms.__dict__.clear()
        del mol.allAtoms

        if self.vf.hasGui and hasattr(mol, 'geomContainer'):
            for g in mol.geomContainer.geoms.values():
                if hasattr(g, 'mol'):
                    delattr(g, 'mol')

            mol.geomContainer.geoms.clear()
            mol.geomContainer.atoms.clear()
            delattr(mol.geomContainer, 'mol')
            del mol.geomContainer

        if hasattr(mol, 'atmNum'):
            mol.atmNum.clear()
            del mol.atmNum

        if hasattr(mol, 'childByName'):
            mol.childByName.clear()
            del mol.childByName

        if hasattr(mol, 'parser') and hasattr(mol.parser, 'mol'):
            delattr(mol.parser,'mol')
            del mol.parser

        # delete molecule from Vision, if Vision is running
        if self.vf.visionAPI:
            self.vf.visionAPI.remove(mol)

        if len(mol.children):
            deletedLevels = mol.deleteSubTree()
        else:
            deletedLevels = []
        # then delete all the refences to the molecule
        del mol.top
        # Then delete the molecule
        deletedLevels.insert(0, mol.__class__)

        mol.__dict__.clear()
        del mol
        self.vf._deletedLevels = deletedLevels

        if len(self.vf.Mols) == 0 and hasattr(self, 'chooser') \
                and self.form.root.winfo_exists():
            self.chooser.done_cb()


    def getFreeMemoryInformation(self):
        """Store how many TreeNodes have been actually free'ed during the
        last delete operation in a dictionary"""

        memoryInformation = {}
        #print 'self.vf._deletedLevels=', self.vf._deletedLevels
        for d in self.vf._deletedLevels:
            #print 'checking ', d, ' for deletedNodes'
            memoryInformation[d.__name__] = d._numberOfDeletedNodes
        sslevels = [Coil, Helix, Strand, Turn]
##          geomslevels = [IndexedPolylines, IndexedPolygons]
        # Have to loop on the known secondarystructure because our
        # Data structure doesn't support multiple children and parents.
        for sl in sslevels:
            if sl._numberOfDeletedNodes!=0:
                memoryInformation[sl.__name__] = sl._numberOfDeletedNodes

##          for sg in geomslevels:
##              if sl._numberOfDeletedNodes!=0:
##                  memoryInformation[sl.__name__] = sl._numberOfDeletedNodes
                
        return memoryInformation


    def doit(self, nodes):
        #if called with no selection, just return
        molecules, nodeSets = self.vf.getNodesByMolecule(nodes)
        for mol in molecules: self.deleteMol(mol)


    def __call__(self, nodes, **kw):
        """None <- deleteMol(nodes, **kw)
        \nnodes: TreeNodeSet holding the current selection.
        \nIt resets the undo stack automatically.
        """
        if type(nodes) is types.StringType:
            self.nodeLogString = "'"+nodes+"'"
        
        self.vf.resetUndo(topCommand=0)
        apply ( self.doitWrapper, (nodes,), kw )
예제 #2
0
class DeleteMolecule(MVCommand):
    """Command to delete a molecule from the MoleculeViewer
    \nPackage : Pmv
    \nModule  :
    deleteCommands
    \nClass   : DeleteMolecule
    \nCommand : deleteMolecule
    \nSynopsis:\n
        None<---deleteMol(nodes, **kw)
    \nRequired Arguments:\n
        nodes --- TreeNodeSet holding the current selection
           It resets the undo stack automatically.\n
    """
    def onAddCmdToViewer(self):
        self.vf._deletedLevels = []
        if not self.vf.commands.has_key('select'):
            self.vf.loadCommand("selectionCommands",
                                "select",
                                "Pmv",
                                topCommand=0)
        if not self.vf.commands.has_key('clearSelection'):
            self.vf.loadCommand("selectionCommands",
                                "clearSelection",
                                "Pmv",
                                topCommand=0)

    def onAddObjectToViewer(self, obj):
        if hasattr(self, 'chooser')\
               and self.chooser is not None \
               and self.form.root.winfo_exists():
            w = self.chooser.form.descr.entryByName['Molecule']['widget']
            molParser = obj.parser
            molStr = molParser.getMoleculeInformation()
            w.add((obj.name, molStr))

    def deleteMolecule_cb(self):
        """called each time the 'Delete Molecule' button is pressed"""
        mols = self.chooser.getMolSet()
        if mols is not None and len(mols):
            if self.vf.undoCmdStack == []:
                undoable = self.undoableVar.get()
                for mol in mols:
                    self.doitWrapper(mol, redraw=0, undoable=undoable)
            else:
                self.continue_cb()

    def hide_cb(self):
        if hasattr(self, 'chooser'):
            if self.chooser.ipf.form is not None:
                mols = self.chooser.getMolSet()
                self.vf.showMolecules(mols.name, negate=1, topCommand=0)
                self.chooser.done_cb()
            self.idf.form.destroy()

    def continue_cb(self):
        if hasattr(self, 'chooser'):
            if self.chooser.ipf.form is not None:
                mols = self.chooser.getMolSet()
                undoable = self.undoableVar.get()
                if not undoable:
                    self.vf.resetUndo(topCommand=0)
                for mol in mols:
                    self.doitWrapper(mol, redraw=0, undoable=undoable)
            #self.idf.form.destroy()

    def cancel_cb(self):
        self.idf.form.destroy()

    def guiCallback(self):
        if len(self.vf.Mols) == 0: return
        self.chooser = MoleculeChooser(self.vf,
                                       mode='extended',
                                       title='Choose Molecules to delete')

        self.undoableVar = Tkinter.IntVar()
        self.undoableVar.set(1)
        self.chooser.ipf.append({
            'name': 'Undo',
            'widgetType': Tkinter.Checkbutton,
            'wcfg': {
                'text': ' Undoable Delete',
                'variable': self.undoableVar
            },
            'gridcfg': {
                'sticky': Tkinter.E + Tkinter.W
            }
        })

        self.chooser.ipf.append({
            'name': 'Delete Button',
            'widgetType': Tkinter.Button,
            'text': 'Delete Molecule',
            'wcfg': {
                'bd': 6
            },
            'gridcfg': {
                'sticky': Tkinter.E + Tkinter.W
            },
            'command': self.deleteMolecule_cb
        })
        self.form = self.chooser.go(modal=0, blocking=0)

    def deleteMol(self, mol, undoable=False):
        """ Function to delete all the references to each elements of a
        molecule and then these elements and the molecule to free the
        memory space."""

        #  Call the removeObject function for all the command having an
        # onRemoveMol function
        self.vf.removeObject(mol, undoable=undoable)

        # Maybe do that in moleculeViewer ???
        # also need to clean up selector.selection:
        nodes = self.vf.getSelection()
        mol.__class__._numberOfDeletedNodes = 0
        node = mol
        while len(node.children):
            node = node.children

        # Initialize the variable _numberOfDeletedNodes at 0
        node[0].__class__._numberOfDeletedNodes = 0
        sslevels = [Coil, Helix, Strand, Turn]
        # Initialize the variable _numberOfDeletedNodes for each secondary
        # structure to 0.
        for sl in sslevels:
            # Initialize the variable _numberOfDeletedNodes at 0
            sl._numberOfDeletedNodes = 0

        # but only change selection if there is any
        if nodes is not None and len(nodes) > 0:
            setClass = nodes.__class__
            thisMolNodes = setClass(nodes.get(lambda x, mol=mol: x.top == mol))
            #only change selection if this molecule has any nodes in it
            if len(thisMolNodes) > 0:
                nodes = nodes - thisMolNodes
                self.vf.clearSelection(topCommand=0)
                if nodes is not None:
                    self.vf.select(nodes)
                    #self.vf.selector.select(nodes)

        if hasattr(self, 'chooser') and self.form.root.winfo_exists():
            # update the listChooser
            lc = self.chooser.ipf.entryByName['Molecule']['widget']
            lc.remove(mol.name)
            #lc.clearComments()

        #check for any possible reference in self.vf.GUI.VIEWER.lastPick
        if self.vf.hasGui and self.vf.GUI.VIEWER.lastPick:
            for key in self.vf.GUI.VIEWER.lastPick.hits.keys():
                if hasattr(key, 'mol'):
                    if mol == key.mol:
                        del self.vf.GUI.VIEWER.lastPick.hits[key]

        # Remove the atoms of the molecule you are deleting from the
        # the AtomSet self.vf.allAtoms
        self.vf.allAtoms = self.vf.allAtoms - mol.allAtoms

        if not undoable:
            # Delete all the reference to the atoms you want to delete
            if hasattr(mol.allAtoms, 'bonds'):
                bnds = mol.allAtoms.bonds[0]
                for b in bnds:
                    b.__dict__.clear()
                    del (b)

            mol.allAtoms.__dict__.clear()
            del mol.allAtoms

            if self.vf.hasGui and hasattr(mol, 'geomContainer'):
                for g in mol.geomContainer.geoms.values():
                    if hasattr(g, 'mol'):
                        delattr(g, 'mol')

                mol.geomContainer.geoms.clear()
                mol.geomContainer.atoms.clear()
                delattr(mol.geomContainer, 'mol')
                del mol.geomContainer

            if hasattr(mol, 'atmNum'):
                mol.atmNum.clear()
                del mol.atmNum

            if hasattr(mol, 'childByName'):
                mol.childByName.clear()
                del mol.childByName

            if hasattr(mol, 'parser') and hasattr(mol.parser, 'mol'):
                delattr(mol.parser, 'mol')
                del mol.parser

        # delete molecule from Vision, if Vision is running
        if self.vf.visionAPI:
            self.vf.visionAPI.remove(mol)

        if not undoable:
            if len(mol.children):
                deletedLevels = mol.deleteSubTree()
            else:
                deletedLevels = []
            # then delete all the refences to the molecule
            del mol.top
            # Then delete the molecule
            deletedLevels.insert(0, mol.__class__)

            mol.__dict__.clear()
            del mol

            self.vf._deletedLevels = deletedLevels

        if len(self.vf.Mols) == 0 and hasattr(self, 'chooser') \
                and self.form.root.winfo_exists():
            self.chooser.done_cb()

    def getFreeMemoryInformation(self):
        """Store how many TreeNodes have been actually free'ed during the
        last delete operation in a dictionary"""

        memoryInformation = {}
        #print 'self.vf._deletedLevels=', self.vf._deletedLevels
        for d in self.vf._deletedLevels:
            #print 'checking ', d, ' for deletedNodes'
            memoryInformation[d.__name__] = d._numberOfDeletedNodes
        sslevels = [Coil, Helix, Strand, Turn]
        ##          geomslevels = [IndexedPolylines, IndexedPolygons]
        # Have to loop on the known secondarystructure because our
        # Data structure doesn't support multiple children and parents.
        for sl in sslevels:
            if sl._numberOfDeletedNodes != 0:
                memoryInformation[sl.__name__] = sl._numberOfDeletedNodes


##          for sg in geomslevels:
##              if sl._numberOfDeletedNodes!=0:
##                  memoryInformation[sl.__name__] = sl._numberOfDeletedNodes

        return memoryInformation

    def doit(self, nodes, undoable=False):
        #if called with no selection, just return
        molecules, nodeSets = self.vf.getNodesByMolecule(nodes)
        event = BeforeDeleteMoleculesEvent(molecules)
        self.vf.dispatchEvent(event)
        for mol in molecules:
            self.deleteMol(mol, undoable)
        if self.vf.hasGui:
            self.vf.GUI.VIEWER.SetCurrentObject(self.vf.GUI.VIEWER.rootObject)
        if not undoable:
            self.vf.resetUndo(topCommand=0)

    def __call__(self, nodes, undoable=False, **kw):
        """None <- deleteMol(nodes, **kw)
        \nnodes: TreeNodeSet holding the current selection.
        """
        if type(nodes) is types.StringType:
            self.nodeLogString = "'" + nodes + "'"
        kw['undoable'] = undoable
        self.doitWrapper(*(nodes, ), **kw)

    def setupUndoBefore(self, molecule, undoable=False):
        if undoable:
            if type(molecule) is types.StringType:
                molecules, nodeSets = self.vf.getNodesByMolecule(molecule)
                if not len(molecules): return
                molecule = molecules[0]
            molecule.code = self.vf.getStateCodeForMolecule(molecule)
            self.addUndoCall([molecule], {}, self.name)

    def undo(self):
        """Undo for DeleteMolecule:
        We use self.vf.getStateCodeForMolecule from setupUndoBefore to restore the state of the molecule.
        """
        mol = self.undoStack.pop()
        mol = mol[0][0]
        self.vf.addMolecule(mol)
        exec(mol.code, {'self': self.vf})