"""
     qtgui/modelUtils.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2009 University of York, CCLRC
     Copyright (C) 2009-2010 University of York
     Copyright (C) 2012 STFC

     This library is free software: you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public License
     version 3, modified in accordance with the provisions of the 
     license to address the requirements of UK law.
 
     You should have received a copy of the modified GNU Lesser General 
     Public License along with this library.  If not, copies may be 
     downloaded from http://www.ccp4.ac.uk/ccp4license.php
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU Lesser General Public License for more details.
"""

from PyQt4 import QtGui,QtCore
from global_definitions import *
import guiUtils
import MGSimpleDialog,mgWidgets
import model
import functools


#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class ModelSecStrEditor(MGSimpleDialog.MGSimpleDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

#-------------------------------------------------------------------
  def __init__(self,parent,MolData=''):
#-------------------------------------------------------------------
    MGSimpleDialog.MGSimpleDialog.__init__(self,parent)
    self.MolData = MolData
    #print "ModelColourEditor.__init__ MolData",self.MolData,self.parent
    self.setWindowTitle('Edit secondary structure for '+MolData)
    layout = QtGui.QVBoxLayout()

    widget = QtGui.QLabel('Override automatic secondary structure assignment',self)
    layout.addWidget(widget)
    
    #edit_frame =  QtGui.QFrame()
    #edit_frame.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
    #edit_layout = QtGui.QVBoxLayout()
    
   
    self.exFrame =  mgWidgets.extendingFrame(self,widget=ModelSecStrLine,ifClose=1,ifClear=1,width=0)
    self.exFrame.show()
    layout.addWidget(self.exFrame)
    #edit_frame.setLayout(edit_layout)

    #layout.addWidget(edit_frame)
    self.setLayout(layout)

    self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.apply)
    self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close)

    self.connect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu)

    self.loadFromModelInfo()




#----------------------------------------------------------------------
  def loadFromModelInfo(self):
#----------------------------------------------------------------------
    
    status,data = MODELINFO().get_info( set=self.MolData,info= 'edit_secstr')
    #print 'ModelSecStrEditor from MODELINFO',status,data
    if not status and data.has_key('secstr') and data.has_key('selection_command'):
      self.setParams(selection_command=data['selection_command'],secstr=data['secstr'])


#----------------------------------------------------------------------
  def apply(self):
#----------------------------------------------------------------------
    params = self.getParams()
    if params.has_key('selection_command') and params['selection_command']:
      secstr= []
      for item in params['secstr']:
        secstr.append(model.MolData.secstr_alias[model.MolData.secstr_menu.index(item)])
      #print 'ModelSecStrEditor.apply',secstr
      MODELINFO().add_info(set=self.MolData,info='edit_secstr',key='secstr',value=secstr)
      MODELINFO().add_info(set=self.MolData,info='edit_secstr',key='selection_command',value=params['selection_command'])

      target = data(self.MolData)
      if target:
        target.apply_edit_secstr(apply=1)
        target.redraw_all_objects()
        UPDATEDISPLAY()
        
#----------------------------------------------------------------------
  def atomPickMenu(self,pickevent=None):
#----------------------------------------------------------------------
    #print 'ModelSecStrEditor.atomPickMenu',pickevent
    if not self.isVisible(): return
    dobj = pickevent.getDataObj()
    menu = pickevent.getContextMenu()
    if not dobj or not menu or (not dobj.name == self.MolData): return
    name = str(self.objectName())
    guiUtils.populateMenu(self,menu,[['Set secondary structure for this',name+'range_2',name+'residue',name+'range_1']],self.getActionDef,info = { 'pickevent' : pickevent } )

#----------------------------------------------------------------------
  def getActionDef(self,name,**info):
#----------------------------------------------------------------------
    #print "ModelColourEditor.getActionDef",name,info
    name = name[len(str(self.objectName())):]
    pickevent=info.get('pickevent','')
    if not pickevent: return

    args = [name,pickevent.getLabel(format='full')]
    if name == 'residue':
      return dict ( text = 'Residue',
                    tip = 'Colour the selected residue',
                    slot = [self.editPickedResidue,args],
                    deleteLater = 1,
            )
    if name == 'range_1':
      return dict ( text = 'Start range',
                    tip = 'Select first residue in a range',
                    slot = [self.editPickedResidue,args],
                    deleteLater = 1,
            )
    if name == 'range_2':
      if not hasattr(self,'pickedRangeStart'): return {}
      return dict ( text = 'Range from '+self.pickedRangeStart,
                    tip = 'Select end residue in a range',
                    slot = [self.editPickedResidue,args],
                    deleteLater = 1,
            )
    else:
      return {}
    

#----------------------------------------------------------------------
  def editPickedResidue(self,args=[]):
#----------------------------------------------------------------------
    #print "ModelSecstrEditor.editPickedResidue",args
    name,atom_id = args
    if ['residue','range_1'].count(name):
      selection= data(self.MolData).convertAtomID (out = 'residue', atomID =atom_id )     
    elif name == 'range_2':
      res2 = data(self.MolData).convertAtomID (out = 'residue', atomID =atom_id )
      selection = data(self.MolData).interpretRanges(self.pickedRangeStart,atom_id)[1]
      del self.pickedRangeStart
    #print "editPickedAtom selection",selection
        
    if name == 'range_1':
      self.pickedRangeStart = selection
      return
    else:
      self.exFrame.addLine()
      self.exFrame.setParams(params = { 'selection_command': [ selection] }, index=self.exFrame.getNofLines()-1)


  def getParams(self):
    params = self.exFrame.getParams({'selection_command':[],'secstr':[]})
    #print 'ModelSecStrEditor.getParams',params
    return params

  def setParams(self,params={},**kw):
    params.update(kw)
    #print 'ModelSecStrEditor.setParams',params
    if params.has_key('selection_command') and params.has_key('secstr'):
      secstr= []
      for item in params['secstr']:
        if model.MolData.secstr_alias.count(item):      
          secstr.append(model.MolData.secstr_menu[model.MolData.secstr_alias.index(item)])
        else:
          secstr.append(item)
      params['secstr'] = secstr

      self.exFrame.setParams(params)

#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
class ModelSecStrLine(QtGui.QWidget):
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------

  def __init__(self,parent=None):

    QtGui.QWidget.__init__(self,parent)
    #print "ColourBlendLine parent",parent,parent.parent()
    
    layout = QtGui.QHBoxLayout()
    layout.setContentsMargins(0,0,0,0)
    layout.setSpacing(0)
    
    abstractModel = data(self.window().MolData).treeModel
    self.seleCombo = mgWidgets.mgSelectionCombo(self,abstractModel,modelGroups=['peptide'],selectionWidgets=[])
    self.seleCombo.setToolTip('Select residue or range of residues')
    self.seleCombo.setObjectName('selection_command')
    layout.addWidget(self.seleCombo)

    # There must be better way of doing this!
    self.secstrCombo = QtGui.QComboBox(self)
    for item in model.MolData.secstr_menu:
      self.secstrCombo.addItem(item)
    self.secstrCombo.setToolTip('Secondary structure assignment for residue(s)')
    self.secstrCombo.setObjectName('secstr')
    layout.addWidget(self.secstrCombo)
   
    self.setLayout(layout)

#-----------------------------------------------------------------------
  def setDefault(self):
#-----------------------------------------------------------------------
    self.seleCombo.clear()
    self.secstrCombo.setCurrentIndex(0)

'''
#-----------------------------------------------------------------------
  def getParams(self):
#-----------------------------------------------------------------------
    pars = {}
    pars['secstr'] = model.MolData.secstr_alias[self.secstrCombo.currentIndex()]
    pars['selection_command'] = self.seleCombo.text()
    return pars
  
#-----------------------------------------------------------------------
  def setParams(self,params={},**kw):
#-----------------------------------------------------------------------
    params.update(kw)
    print 'ModelSecStrLine.setParams',params
    if params.has_key('secstr'):
      if model.MolData.secstr_alias.count(params['secstr']):      
        self.secstrCombo.setCurrentIndex(model.MolData.secstr_alias.index(params['secstr']))
      elif model.MolData.secstr_menu.count(params['secstr']):      
        self.secstrCombo.setCurrentIndex(model.MolData.secstr_menu.index(params['secstr']))
    if params.has_key('selection_command'): self.seleCombo.setText(params['selection_command'])
    
 ''' 

class editCIFFilesGui(MGSimpleDialog.MGSimpleDialog):
  def __init__(self,parent=None,MolData=''):
    MGSimpleDialog.MGSimpleDialog.__init__(self,parent)
    self.MolData_name = MolData
    self.setWindowTitle('Edit residue types for '+self.MolData_name)
    self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    layout = QtGui.QVBoxLayout()

    layout.addWidget(QtGui.QLabel('For residue types not recognised by the monomer library enter the name',self))
    layout.addWidget(QtGui.QLabel('of residue and the cif file that goes with it.',self))

    self.exFrame = mgWidgets.extendingFrame(self,widget=editCIFFilesLine,ifClose=1,width=0)
    layout.addWidget(self.exFrame)

    self.setLayout(layout)

    self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply)
    self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close)

    self.loadData()

  def Apply(self):
    params = self.getParams()
    target = data(self.MolData_name)
    if target and hasattr(target,"setCustomResCIFFiles"):
      target.setCustomResCIFFiles(params)
      target.GetMolBonds()
      target.redraw_all_objects()

  def getParams(self):
    params = self.exFrame.getParams({'resname':[],'dict':[]})
    p = {}
    for key,val in zip(params['resname'],params['dict']):
      p[key] = val
    return p
    
  def loadData(self):
    target = data(self.MolData_name)
    if target:
      keys = []
      vals = []
      for key,val in target.customResCIFFiles.items():
        keys.append(key)
        vals.append(val)
      params = {}
      params['resname'] = keys
      params['dict'] = vals
      self.exFrame.setParams(params)

class editCIFFilesLine(QtGui.QWidget):
  def __init__(self,parent):
    QtGui.QWidget.__init__(self,parent)
    layout = QtGui.QHBoxLayout()
    layout.setContentsMargins(0,0,0,0)
    layout.setSpacing(0)

    widget = QtGui.QLineEdit(self)
    widget.setToolTip('Residue name (usually 3-letter code)')
    widget.setObjectName('resname')
    layout.addWidget(widget)

    ciffilewidget = QtGui.QLineEdit(self)
    ciffilewidget.setToolTip('CIF dictionary file')
    ciffilewidget.setObjectName('dict')
    layout.addWidget(ciffilewidget)

    widget = QtGui.QPushButton("Browse",self)
    widget.setAutoDefault(False)
    widget.setToolTip('Pick a CIF dictionary file on your computer')
    layout.addWidget(widget)
    def getFile(dum=True):
      w = QtGui.QFileDialog()
      w.setFileMode(QtGui.QFileDialog.ExistingFile)
      w.setOption(QtGui.QFileDialog.DontUseNativeDialog,True)
      f = w.exec_()
      if f:
        ciffilewidget.setText(w.selectedFiles()[0])
    widget.clicked.connect(getFile)

    self.setLayout(layout)

  def setDefault(self):
    self.findChild(QtGui.QWidget,'resname').setText('')
    self.findChild(QtGui.QWidget,'dict').setText('')

#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class editRestypesGui(MGSimpleDialog.MGSimpleDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent=None,MolData=''):
    
    MGSimpleDialog.MGSimpleDialog.__init__(self,parent)

    self.MolData_name = MolData

    self.setWindowTitle('Edit residue types for '+self.MolData_name)
    self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    layout = QtGui.QVBoxLayout()

    layout.addWidget(QtGui.QLabel('For residue types not recognised by the monomer library enter the name',self))
    layout.addWidget(QtGui.QLabel('of residue and either the equivalent library name and/or the residue type',self))

    self.exFrame = mgWidgets.extendingFrame(self,widget=editRestypesLine,ifClose=1,width=0)
    self.exFrame.show()
    layout.addWidget(self.exFrame)

    self.setLayout(layout)

    self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply)
    self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close)

    self.loadData()


#-------------------------------------------------------------------
  def Apply(self):
#-------------------------------------------------------------------
      params = self.getParams()
      
      # Set up selection_protocols dictionary with items for the
      # 'standard' residue types
      # sel_prot[type]['ORDER'] is a list for each residue type (eg protein/monomer/etc) of
      # of the residue names (eg 'ALA'/'NAD') that are that type
      sel_prot = {}
        
      # Load sel_prot with the residue type info from the GUI
      for ii in range(len(params['resname'])):
        if not sel_prot.has_key(params['restype'][ii]): sel_prot[params['restype'][ii]]= { 'ORDER' : [] }
        if not sel_prot[params['restype'][ii]]['ORDER'].count(params['resname'][ii]):
          sel_prot[params['restype'][ii]]['ORDER'].append(params['resname'][ii])
      #print 'editRestypesGui.Apply',sel_prot
      # For each 'standard' type either add or delete from ModelInfo
      # dependent on whether there is an info in the sel_prot item
      for type in model.MolData.restype_alias:
        if sel_prot.has_key(type):
          ret = MODELINFO().add_info(set=self.MolData_name, 
                           info='selection_protocols',key=type,value=sel_prot[type])
        else:
          MODELINFO().delete_info(set=self.MolData_name,
                                    info='selection_protocols',key=type)

      # Clear out any saved residue aliases
      MODELINFO().delete_info(set=self.MolData_name,info='residue_aliases',key='*')
      # Save the residue name alias info
      for ii in range(len(params['resname'])):
        if params['resname'][ii] and params['alias'][ii]:
          ret = MODELINFO().add_info(set=self.MolData_name,info='residue_aliases',
                                     key=params['resname'][ii],value=params['alias'][ii])

      
      MODELINFO().save(set=self.MolData_name)
      target = data(self.MolData_name)
      if target:
        target.updateCustomResTypes()
        target.analyse_restypes()
        target.GetMolBonds()
        target.redraw_all_objects()
        UPDATEDISPLAY()

      
#-------------------------------------------------------------------
  def loadData(self):
#-------------------------------------------------------------------
    import types
    restype_type = []
    restype_res = []
    restype_alias = []
    
    #Get the residue name aliases
    status,alias= MODELINFO().get_info(set=self.MolData_name,info='residue_aliases')
    #print "status,alias",status,alias
    if not status:
        for key,value in alias.items():
          restype_res.append(key)
          restype_alias.append(value)
          restype_type.append('')

    
    status,sel_prot= MODELINFO().get_info(set=self.MolData_name,info='selection_protocols')
    #print 'editRestypesGui.loadData',self.MolData_name,status,sel_prot
    for type in model.MolData.restype_alias:
      if sel_prot.has_key(type) and sel_prot[type].has_key('ORDER'):
        for item in sel_prot[type]['ORDER']:
          if restype_res.count(item):
            ii = restype_res.index(item)
            restype_type[ii] = type
          else:
            restype_type.append(type)
            restype_res.append(item)
            restype_alias.append('')

    #print 'editRestypesGui.loadData',restype_res,restype_alias,restype_type
    self.setParams( { 'resname' : restype_res,
                      'alias' : restype_alias,
                      'restype' : restype_type } )

    

#-------------------------------------------------------------------
  def getParams(self):
#-------------------------------------------------------------------
    params = self.exFrame.getParams({'resname':[],'alias':[],'restype':[]})
    restype = []
    for item in params['restype']:
      if model.MolData.restype_menu.count(item):      
          restype.append(model.MolData.restype_alias[model.MolData.restype_menu.index(item)])
      else:
          restype.append(item)
    params['restype'] = restype

    #print 'editRestypesGui.getParams',params
    return params

#-------------------------------------------------------------------
  def setParams(self,params={},**kw):
#-------------------------------------------------------------------
    params.update(kw)
    #print 'editRestypesGui.setParams',params
    for item in ['resname','alias','restype']:
      if not params.has_key(item): return
      
    restype = []
    for item in params['restype']:
      if model.MolData.restype_alias.count(item):      
          restype.append(model.MolData.restype_menu[model.MolData.restype_alias.index(item)])
      else:
          restype.append(item)
    params['restype'] = restype

    self.exFrame.setParams(params)


#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class editRestypesLine(QtGui.QWidget):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent):
    QtGui.QWidget.__init__(self,parent)

    layout = QtGui.QHBoxLayout()
    layout.setContentsMargins(0,0,0,0)
    layout.setSpacing(0)

    widget = QtGui.QLineEdit(self)
    widget.setToolTip('Residue name (usually 3-letter code)')
    widget.setObjectName('resname')
    layout.addWidget(widget)

    widget = QtGui.QLineEdit(self)
    widget.setToolTip('Alternative residue name used in the monomer library')
    widget.setObjectName('alias')
    layout.addWidget(widget)

    widget = QtGui.QComboBox(self)
    widget.setToolTip('Assign residue to chemical type to help atom selection')
    widget.setObjectName('restype')
    for item in model.MolData.restype_menu:
      widget.addItem(item)
    layout.addWidget(widget)

    self.setLayout(layout)

  def setDefault(self):
    self.findChild(QtGui.QWidget,'resname').setText('')
    self.findChild(QtGui.QWidget,'alias').setText('')
    self.findChild(QtGui.QWidget,'restype').setCurrentIndex(0)
    
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class editBondsGui(MGSimpleDialog.MGSimpleDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent=None,MolData=''):
    
    MGSimpleDialog.MGSimpleDialog.__init__(self,parent)

    self.MolData_name = MolData

    self.setWindowTitle('Edit bonds for '+self.MolData_name)
    layout = QtGui.QVBoxLayout()

    layout.addWidget(QtGui.QLabel('Add or remove bonds in the structure',self))

    self.exFrame = mgWidgets.extendingFrame(self,widget=editBondsLine,ifClose=1,width=0)
    self.exFrame.show()
    layout.addWidget(self.exFrame)

    self.setLayout(layout)

    self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply)
    self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close)
    self.connect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu)

    self.loadData()


#-------------------------------------------------------------------
  def Apply(self):
#-------------------------------------------------------------------
      params = self.getParams()
      edit_bonds = []
      for i in range(len(params['first_atom'])):
        if params['first_atom'][i] and params['second_atom'][i]:
            edit_bonds.append([params['first_atom'][i],params['second_atom'][i],params['action'][i]])
            
      MODELINFO().add_info(set=self.MolData_name,info='edit_bonds',key='edit_bonds',value=edit_bonds)
      #print "editBondsGui",edit_bonds
      data(self.MolData_name).apply_edit_bonds()

      import rebuild
      rebuild.UpdateDisplay()

#-------------------------------------------------------------------
  def Close(self):
#-------------------------------------------------------------------
    self.disconnect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu)
    MGSimpleDialog.MGSimpleDialog.Close(self)
      
#-------------------------------------------------------------------
  def loadData(self):
#-------------------------------------------------------------------
    first_atom = []
    second_atom = []
    action = []

    status,edit_bonds = MODELINFO().get_info( 
        set=self.MolData_name,info= 'edit_bonds',key='edit_bonds')
    if edit_bonds.has_key('edit_bonds'):
      for item in edit_bonds['edit_bonds']:
        first_atom.append(item[0])
        second_atom.append(item[1])
        action.append(item[2])

    self.setParams( { 'first_atom' : first_atom,
                      'second_atom' : second_atom,
                      'action' : action } )

    

#-------------------------------------------------------------------
  def getParams(self):
#-------------------------------------------------------------------
    params = self.exFrame.getParams({'first_atom':[],'second_atom':[],'action':[]})
  
    return params

#-------------------------------------------------------------------
  def setParams(self,params={},**kw):
#-------------------------------------------------------------------
    params.update(kw)
    self.exFrame.setParams(params)

#----------------------------------------------------------------------
  def atomPickMenu(self,pickevent=None):
#----------------------------------------------------------------------
    dobj = pickevent.getDataObj()
    if not self.isVisible() or not dobj or not dobj.name == self.MolData_name: return
    menu = pickevent.getContextMenu()
    if not menu: return
    name = str(self.objectName())
    guiUtils.populateMenu(self,menu,[['Add/delete bond',name+'atom_2',name+'atom_1']],self.getActionDef,info = { 'pickevent' : pickevent } )

#----------------------------------------------------------------------
  def getActionDef(self,name,**info):
#----------------------------------------------------------------------
    #print "ModelColourEditor.getActionDef",name,info
    name = name[len(str(self.objectName())):]
    pickevent=info.get('pickevent','')
    if not pickevent: return

    args = [name,pickevent.getLabel(format='full')]
    if name == 'atom_1':
      return dict ( text = 'First atom',
                    tip = 'Select first atom in bond',
                    slot = [self.handlePickedAtom,args],
                    deleteLater = 1,
            )
    if name == 'atom_2':
      if not hasattr(self,'firstPickedAtom'): return {}
      return dict ( text = 'Bond from '+self.firstPickedAtom,
                    tip = 'Select second atom for bond',
                    slot = [self.handlePickedAtom,args],
                    deleteLater = 1,
            )
    else:
      return {}
    
#----------------------------------------------------------------------
  def handlePickedAtom(self,args=[]):
#----------------------------------------------------------------------
    #print "ModelColourEditor.colourPickedAtom",args
    name,atom_id = args
    if ['atom_1'].count(name):
      self.firstPickedAtom = atom_id
    elif name == 'atom_2':
      self.exFrame.addLine()
      self.exFrame.setParams(params = { 'first_atom': [self.firstPickedAtom ],
                                        'second_atom' : [ atom_id ] },
                             index=self.exFrame.getNofLines()-1)
      del self.firstPickedAtom
      self.Apply()

#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class editBondsLine(QtGui.QWidget):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent):
    QtGui.QWidget.__init__(self,parent)

    layout = QtGui.QHBoxLayout()
    layout.setContentsMargins(0,0,0,0)
    layout.setSpacing(0)

    widget = QtGui.QComboBox(self)
    widget.setToolTip('Add or delete bond')
    widget.setObjectName('action')
    for item in ['add', 'delete']:
      widget.addItem(item)
    layout.addWidget(widget)

    widget = mgWidgets.mgAtomPicker(self,MolData_name=self.window().MolData_name)
    widget.setToolTip('First atom of bond')
    widget.setObjectName('first_atom')
    layout.addWidget(widget)

    widget = mgWidgets.mgAtomPicker(self,MolData_name=self.window().MolData_name)
    widget.setToolTip('Second atom of bond')
    widget.setObjectName('second_atom')
    layout.addWidget(widget)
  
    self.setLayout(layout)

  def setDefault(self):
     self.findChild(QtGui.QWidget,'first_atom').reset()
     self.findChild(QtGui.QWidget,'second_atom').reset()
     self.findChild(QtGui.QWidget,'action').setCurrentIndex(0)


#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class editLinksGui(MGSimpleDialog.MGSimpleDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent=None,MolData=''):
    
    MGSimpleDialog.MGSimpleDialog.__init__(self,parent)

    self.MolData_name = MolData

    self.setWindowTitle('Edit links for '+self.MolData_name)
    layout = QtGui.QVBoxLayout()

    layout.addWidget(QtGui.QLabel('Define intra-residue links',self))

    self.exFrame = mgWidgets.extendingFrame(self,widget=editLinksLine,ifClose=1,width=0)
    self.exFrame.show()
    layout.addWidget(self.exFrame)

    self.setLayout(layout)

    self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply)
    self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close)
    #self.connect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu)

    self.loadData()


#-------------------------------------------------------------------
  def Apply(self):
#-------------------------------------------------------------------
      params = self.getParams()
      edit_links = []
      for i in range(len(params['first_atom'])):
        if params['first_atom'][i] and params['second_atom'][i] and \
           params['first_res'][i] and params['second_res'][i] :
            edit_links.append([ params['first_res'][i],params['first_atom'][i],params['second_res'][i],params['second_atom'][i]])
            
      MODELINFO().add_info(set=self.MolData_name,info='edit_links',key='edit_links',value=edit_links)
      #print "editBondsGui",edit_bonds
      data(self.MolData_name).apply_edit_links()

      import rebuild
      rebuild.UpdateDisplay()

#-------------------------------------------------------------------
  def Close(self):
#-------------------------------------------------------------------
    #self.disconnect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu)
    MGSimpleDialog.MGSimpleDialog.Close(self)
      
#-------------------------------------------------------------------
  def loadData(self):
#-------------------------------------------------------------------
    first_atom = []
    second_atom = []
    first_res = []
    second_res = []

    status,edit_links = MODELINFO().get_info( 
        set=self.MolData_name,info= 'edit_links',key='edit_links')
    if edit_links.has_key('edit_links'):
      for item in edit_links['edit_links']:
        first_res.append(item[0])
        first_atom.append(item[1])
        second_res.append(item[2])
        second_atom.append(item[3])
        

    self.setParams( { 'first_atom' : first_atom,
                      'second_atom' : second_atom,
                      'first_res' : first_res,
                      'second_res' : second_res } )

    

#-------------------------------------------------------------------
  def getParams(self):
#-------------------------------------------------------------------
    params = self.exFrame.getParams({'first_atom':[],'second_atom':[],
                                     'first_res':[],'second_res':[]})
  
    return params

#-------------------------------------------------------------------
  def setParams(self,params={},**kw):
#-------------------------------------------------------------------
    params.update(kw)
    self.exFrame.setParams(params)



#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class editLinksLine(QtGui.QWidget):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent):
    QtGui.QWidget.__init__(self,parent)

    layout = QtGui.QHBoxLayout()
    layout.setContentsMargins(0,0,0,0)
    layout.setSpacing(0)

    widget = QtGui.QLineEdit(self)
    widget.setToolTip('Add first residue name (usually 3-letter code) ')
    widget.setObjectName('first_res')
    layout.addWidget(widget)

    widget = QtGui.QLineEdit(self)
    widget.setToolTip('Add first atom name')
    widget.setObjectName('first_atom')
    layout.addWidget(widget)
    
    widget = QtGui.QLineEdit(self)
    widget.setToolTip('Add second residue name (usually 3-letter code) ')
    widget.setObjectName('second_res')
    layout.addWidget(widget)

    widget = QtGui.QLineEdit(self)
    widget.setToolTip('Add second atom name')
    widget.setObjectName('second_atom')
    layout.addWidget(widget)

    self.setLayout(layout)

  def setDefault(self):
     self.findChild(QtGui.QWidget,'first_atom').setText('')
     self.findChild(QtGui.QWidget,'second_atom').setText('')
     self.findChild(QtGui.QWidget,'first_res').setText('')
     self.findChild(QtGui.QWidget,'second_res').setText('')

#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class SymmetryMatesGui(MGSimpleDialog.MGSimpleDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  

  def __init__(self,parent=None,MolData=''):
    
    MGSimpleDialog.MGSimpleDialog.__init__(self,parent)

    self.MolData_name = MolData

    self.setWindowTitle('Show symmetry mates for '+self.MolData_name)
    self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    layout = QtGui.QVBoxLayout()
    layout.setContentsMargins(2,2,2,2)
    layout.setSpacing(2)
    
    frame =  QtGui.QFrame()
    frame.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
    frame_layout = QtGui.QVBoxLayout()
    
    frame_layout.addWidget(QtGui.QLabel('Automatic search for symmetry mates contacting the model',self))
    line_layout = QtGui.QHBoxLayout()
    #line_layout.addWidget(QtGui.QLabel('Search over',self))
    #self.nCells = QtGui.QComboBox(self)
    #for item in ['1','2','3','4']: self.nCells.addItem(item)
    #line_layout.addWidget(self.nCells)
    line_layout.addWidget(QtGui.QLabel('Search for symmetry mates within',self))
    self.radius = QtGui.QDoubleSpinBox(self)
    self.radius.setRange(0.5,10.0)
    self.radius.setSingleStep(0.5)
    line_layout.addWidget(self.radius)
    line_layout.addWidget(QtGui.QLabel('A of',self))
    frame_layout.addLayout(line_layout)

    line_layout = QtGui.QHBoxLayout()
    line_layout.addWidget(QtGui.QLabel('Contact area of model',self))
    abstractModel = data(self.MolData_name).treeModel
    self.seleCombo = mgWidgets.mgSelectionCombo(self,abstractModel,selectionWidgets=[])
    self.seleCombo.setToolTip('Optionally select limited contact area of model')
    line_layout.addWidget(self.seleCombo)
    frame_layout.addLayout(line_layout)

    line_layout = QtGui.QHBoxLayout()
    line_layout.addStretch(5)
    widget = QtGui.QPushButton('Search for contacting symmetry mates',self)
    widget.setAutoDefault(0)
    self.connect(widget,QtCore.SIGNAL('clicked()'),self.autoSearch)
    line_layout.addWidget(widget)
    frame_layout.addLayout(line_layout)

    frame.setLayout(frame_layout)
    layout.addWidget(frame)


    MolDisp_selection_menu = data(self.MolData_name).model_symmetry.MolDisp_selection_menu
    frame =  QtGui.QFrame()
    frame.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
    frame_layout = QtGui.QVBoxLayout()
    line_layout = QtGui.QHBoxLayout()
    self.MolDisp_visible = QtGui.QCheckBox('Show',self)
    line_layout.addWidget(self.MolDisp_visible)
    self.MolDisp_selection = QtGui.QComboBox(self)
    for item in MolDisp_selection_menu: self.MolDisp_selection.addItem(item)
    line_layout.addWidget(self.MolDisp_selection)
    line_layout.addWidget(QtGui.QLabel('of symmetry mates in separate display object',self))
    line_layout.addStretch(5)
    frame_layout.addLayout(line_layout)
    frame.setLayout(frame_layout)
    layout.addWidget(frame)

    self.MolDisp_visible.setChecked(data(self.MolData_name).model_symmetry.MolDisp_visible)
    sele = data(self.MolData_name).model_symmetry.MolDisp_selection
    if MolDisp_selection_menu.count(sele):
      self.MolDisp_selection.setCurrentIndex(MolDisp_selection_menu.index(sele))
    self.connect(self.MolDisp_visible,QtCore.SIGNAL('toggled(bool)'),self.handleMolDisp)
    self.connect(self.MolDisp_selection,QtCore.SIGNAL('currentIndexChanged(int)'),self.handleMolDisp)

    layout.addWidget(QtGui.QLabel('Enter transformations',self))
    self.exFrame = mgWidgets.extendingFrame(self,widget=symmetryMatesLine,ifClose=1,ifClear=1,width=0)
    self.connect(self.exFrame,QtCore.SIGNAL('cleared'),functools.partial(self.Apply,"clear"))
    self.connect(self.exFrame,QtCore.SIGNAL('lineAdded(int)'),self.handleNewLine)
    self.exFrame.show()
    layout.addWidget(self.exFrame)

    self.setLayout(layout)

    self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply)
    self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.Close)
    
    self.radius.setValue(5.0)
    #self.nCells.setCurrentIndex(self.nCells.findText('2'))
    self.seleCombo.setText('all')

    self.loadData()
    self.connect(self.parent(),QtCore.SIGNAL('symmetryMatesChanged'),self.loadData)
    self.connect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu)


#-------------------------------------------------------------------
  def atomPickMenu(self,pickevent):
#-------------------------------------------------------------------
    if not self.isVisible(): return
    dobj = pickevent.getDataObj()
    menu = pickevent.getContextMenu()
    atomlist = pickevent.getPickedAtoms()
    #print 'SymmetryMatesGui.atomPickMenu',dobj,atomlist,menu,dobj.name
    if not dobj or not menu or not atomlist  or (not dobj.name == self.MolData_name): return
    
    # Is pick of an atom in symmetry mate model?
    model = atomlist[0].GetModelNum()
    model_symmetry = data(self.MolData_name).model_symmetry
    if not model_symmetry or model < model_symmetry.firstSymModel: return
    symop = model_symmetry.modelSymop(model)
    
    name = str(self.objectName())
    guiUtils.populateMenu(self,menu,[['For symmetry mate '+symop,name+'delete',name+'hide']],self.getActionDef,info = { 'pickevent' : pickevent } )

#-------------------------------------------------------------------
  def getActionDef(self,name,**info):
#-------------------------------------------------------------------
    name = name[len(str(self.objectName())):]
    pickevent=info.get('pickevent','')
    if not pickevent: return
    atomlist = pickevent.getPickedAtoms()
    model = atomlist[0].GetModelNum()
    args = [model]
    if name == 'delete':
      return dict ( text = 'Delete',
                    tip = 'Delete the symmetry mate',
                    slot = [self.deleteSymmMate,args],
                    deleteLater = 1 )
    if name == 'hide':
      return dict ( text = 'Hide',
                    tip = 'Hide the symmetry mate',
                    slot = [self.hideSymmMate,args],
                    deleteLater = 1 )

#-------------------------------------------------------------------
  def deleteSymmMate(self,args):
#-------------------------------------------------------------------
    model = args[0]
    params = self.exFrame.getParams(params={'model_num':[]})
    if params['model_num'].count(model):
      self.exFrame.deleteLine(line=params['model_num'].index(model))
      self.Apply()
      
#-------------------------------------------------------------------
  def hideSymmMate(self,args):
#-------------------------------------------------------------------
    model = args[0]
    params = self.exFrame.getParams(params={'model_num':[]})
    if params['model_num'].count(model):
      sym_widget = self.exFrame.getLine(params['model_num'].index(model))
      sym_widget.visible.setChecked(0)
      sym_widget.handleVisibility()
      
#-------------------------------------------------------------------
  def autoSearch(self):
#-------------------------------------------------------------------
    import string
    selection = self.seleCombo.text()
    if string.strip(selection) == '': selection = 'all'
    radius = self.radius.value()
    #xtl_limit = int(self.nCells.currentText())
    xtl_limit = 2
    sym_obj = data(self.MolData_name).model_symmetry
    sym_obj.delete_MolDisp()
    sym_obj.setSymmetryMates([])
    models = sym_obj.get_symmetry_models()
    print "This should be empty",models
    rv = sym_obj.findSymmetryNeighbours(selection=selection,radius=radius,xtl_limit=xtl_limit)
    #print 'SymmetryMatesGui.autoSearch',rv
    if not rv[0]:
      sym_obj.setSymmetryMates(rv[1])
      sym_obj.showSymmetryMates()
      self.redraw()
      
      params = data(self.MolData_name).model_symmetry.getGuiParams()
      #print 'autoSearch params',params
      self.setParams( params )

#-------------------------------------------------------------------
  def Apply(self,args=None):
#-------------------------------------------------------------------
    params = self.getParams()
    sym_obj = data(self.MolData_name).model_symmetry
    molData = data(self.MolData_name)
    for obj in get_dispobj(object_type='MolDisp'):
      obj.clearPickedAtoms()
    sym_obj.setGuiParams(params,append=0)
    if args != "clear":
      sym_obj.showSymmetryMates()
    else:
      sym_obj.delete_MolDisp()
    models = sym_obj.get_symmetry_models()
    print models
    if models: self.exFrame.setParams( { 'model_num' : models,
                                         'visible' : sym_obj.symmetry_visible,
                                         'colour' :sym_obj.symmetry_colours } )
    self.redraw()

#-------------------------------------------------------------------
  def Close(self):
#-------------------------------------------------------------------
    #data(self.MolData_name).model_symmetry.hideSymmetryMates()
    MGSimpleDialog.MGSimpleDialog.Close(self)

#-------------------------------------------------------------------
  def handleNewLine(self,index):
#-------------------------------------------------------------------
    widget = self.exFrame.getLine(index)
    #print 'handleNewLine',index,widget
    widget.colour.set_colour(data(self.MolData_name).model_symmetry.nextColour())


#-------------------------------------------------------------------
  def handleMolDisp(self,**kw):
#-------------------------------------------------------------------
    #print 'handleMolDisp',kw
    target = data(self.MolData_name)
    if not target: return
    redraw = target.model_symmetry.setMolDisp(visible = int(self.MolDisp_visible.isChecked()),
                                        selection = str(self.MolDisp_selection.currentText()) )

    if redraw: UPDATEDISPLAY(controllingWidget=self)
    
#-------------------------------------------------------------------
  def loadData(self):
#-------------------------------------------------------------------
    params = data(self.MolData_name).model_symmetry.getGuiParams()
    #print 'SymmetryMatesGui.loadData',params
    self.setParams( params )

#-------------------------------------------------------------------
  def redraw(self):
#-------------------------------------------------------------------
    sym_obj = data(self.MolData_name).model_symmetry   
    import rebuild
    rebuild.UpdateDisplay(controllingWidget=self)
    self.emit(QtCore.SIGNAL('nofModelsChanged'))

#-------------------------------------------------------------------
  def getParams(self):
#-------------------------------------------------------------------
    params = self.exFrame.getParams({'symop':[],'tran_a':[],'tran_b':[], 'tran_c': [],
                                     'visible' : [], 'colour' : [] }) 
    return params

#-------------------------------------------------------------------
  def setParams(self,params={},**kw):
#-------------------------------------------------------------------
    params.update(kw)
    self.exFrame.blockSignals(True)
    self.exFrame.setParams(params)
    self.exFrame.blockSignals(False)

    


#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class symmetryMatesLine(mgWidgets.frameLine):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  TRAN_MENU = ['-5','-4','-3','-2','-1','0','1','2','3','4','5']
  
  def __init__(self,parent):
    #QtGui.QWidget.__init__(self,parent)
    mgWidgets.frameLine.__init__(self,parent)

    target = data(self.window().MolData_name)
    if not target: return

    layout = QtGui.QHBoxLayout()
    layout.setContentsMargins(0,0,0,0)
    layout.setSpacing(0)

    self.model_num = QtGui.QLabel('/1',self)
    layout.addWidget(self.model_num)
    self.model_num.setObjectName('model_num')
    self.model_num.setToolTip('Model number for use in atom selection')

    layout.addWidget( QtGui.QLabel(' ',self))
    
    self.symop = QtGui.QComboBox(self)
    self.symop.setObjectName('symop')
    self.symop.setToolTip('Symmetry operation')
    for item in target.model_symmetry.symops_titles: self.symop.addItem(item)
    self.connect(self.symop,QtCore.SIGNAL('currentIndexChanged(int)'),self.updateSymid)
    layout.addWidget(self.symop)
    
    for dirn in ['a','b','c']:
      name = 'tran_'+dirn
      widget = QtGui.QComboBox(self)
      widget.setObjectName(name)
      setattr(self,name,widget)
      widget.setToolTip('Unit cell translation in '+dirn+' direction')
      for item in symmetryMatesLine.TRAN_MENU:
        widget.addItem(item)
      widget.setCurrentIndex(5)
      self.connect(widget,QtCore.SIGNAL('currentIndexChanged(int)'),self.updateSymid)
      layout.addWidget(widget)

    layout.addStretch(1)
    self.symid =  QtGui.QLabel('1_555',self)
    layout.addWidget(self.symid)
    layout.addStretch(1)
    self.symid.setToolTip('Symmetry id which can be used in atom selection')

    self.visible = QtGui.QCheckBox(self)
    self.visible.setToolTip("Model shown the 'symmetry' display object")
    self.visible.setChecked(1)
    self.visible.setObjectName('visible')
    self.connect(self.visible,QtCore.SIGNAL('toggled(bool)'),self.handleVisibility)
    layout.addWidget(self.visible)

    
    self.colour = mgWidgets.mgColourCombo(self)
    self.colour.setObjectName('colour')
    self.colour.setToolTip("Colour of model in the 'symmetry' object")
    self.connect(self.colour,QtCore.SIGNAL('currentIndexChanged(const QString)'),self.handleColour)
    layout.addWidget(self.colour)

    self.setLayout(layout)

#-------------------------------------------------------------------
  def setDefault(self):
#-------------------------------------------------------------------
     self.symop.setCurrentIndex(0)
     for dirn in ['a','b','c']:
       widget = getattr(self,'tran_',dirn)
       widget.setCurrentIndex(widget.findText('0'))

     self.visible.setChecked(1)
     #self.colour.setCurrentIndex(0)

#-------------------------------------------------------------------
  def getParams(self):
#-------------------------------------------------------------------
    pars = { 'model_num' : int(str(self.model_num.text())[1:]),
             'symop' : str(self.symop.currentText()),
             'tran_a' : str(self.tran_a.currentText()),
             'tran_b' : str(self.tran_b.currentText()),
             'tran_c' : str(self.tran_c.currentText()),
             'visible' : int(self.visible.isChecked()),
             'colour' : self.colour.get_colour() }
    #print 'symmetryMatesLine.getParams',pars
    return pars

#-------------------------------------------------------------------
  def setParams(self,params):
#-------------------------------------------------------------------
    #print 'symmetryMatesLine setParams',params
    
    symop = params.get('symop','')
    if symop: self.symop.setCurrentIndex(self.symop.findText(symop))
    model_num = params.get('model_num','')
    if model_num: self.model_num.setText(model_num)
    for dirn in ['a','b','c']:
      tran = str(params.get('tran_'+dirn,''))
      if tran and symmetryMatesLine.TRAN_MENU.count(tran):
        widget = getattr(self,'tran_'+dirn)
        widget.setCurrentIndex(symmetryMatesLine.TRAN_MENU.index(tran))

    if params.has_key('visible'): self.visible.setChecked(params['visible'])
    if params.has_key('colour'): self.colour.set_colour(params['colour'])

#-------------------------------------------------------------------
  def updateSymid(self,junk):
#-------------------------------------------------------------------
    idx = str(self.symop.currentIndex()+1)+'_'+ \
         str(int(self.tran_a.currentText())+5) + \
         str(int(self.tran_b.currentText())+5) + \
         str(int(self.tran_c.currentText())+5)

    self.symid.setText(idx)


#-------------------------------------------------------------------
  def handleVisibility(self,state=-1):
#-------------------------------------------------------------------
    target = data(self.window().MolData_name)
    #print 'symmetryMatesLine.handleVisibility',target,state
    if not target: return
    model = int(str(self.model_num.text()).strip('/'))
    target.model_symmetry.setVisibility(model,int(self.visible.isChecked()))
    target.model_symmetry.select_MolDisp()
    UPDATEDISPLAY(controllingWidget=self)

#-------------------------------------------------------------------
  def handleColour(self,colour):
#-------------------------------------------------------------------
    target = data(self.window().MolData_name)
    #print 'symmetryMatesLine.handleVisibility',target,state
    if not target: return
    model = int(str(self.model_num.text()).strip('/'))
    target.model_symmetry.setColour(model,self.colour.get_colour())
    target.model_symmetry.colour_MolDisp()
    UPDATEDISPLAY(controllingWidget=self)

    
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class DispObjTree( QtGui.QTreeWidget ):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------

#----------------------------------------------------------------------
  def __init__(self,parent=None,dataobj_list=[],object_types=['MolDisp'],exclude=[]):
#----------------------------------------------------------------------
     QtGui.QTreeWidget.__init__(self,parent)
     self.headerItem().setHidden(1)
     self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
     self.object_types = object_types
     self.exclude = exclude
     self.dataobj_list = dataobj_list
     self.populate()
     self.connect(DISPLAYTABLE(),QtCore.SIGNAL("DisplayTableChanged"),self.populate)

#----------------------------------------------------------------------
  def populate(self):
#----------------------------------------------------------------------
        
    root = self.invisibleRootItem()
    status = {}
    if root and self.invisibleRootItem().childCount():
      for i in range(0,self.invisibleRootItem().childCount()):
        item = root.child(i)
        status[str(item.text(0))] = item.isExpanded()
    #print "populate status",status
    self.clear()
    self.disp_list = []

    if self.dataobj_list:
      dataobj_list = []
      for item in self.dataobj_list: dataobj_list.append(data(name=item))
    else:
      dataobj_list =  get_dataobj(object_type='MolData')
    #print ' DispObjTree.populate',self.dataobj_list,dataobj_list

    for object_type in self.object_types:
      for dataobj in dataobj_list:
        top =  QtGui.QTreeWidgetItem ( [dataobj.name] )
        top.setText(0,dataobj.name)
        top.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.ShowIndicator)
        #print "ModelInfoTree.populate top",set
        self.addTopLevelItem(top)
        dispobj_list = dataobj.get_dispobj(object_type=object_type)
        for item in dispobj_list:
          if not self.exclude.count(item.name):
            line = QtGui.QTreeWidgetItem ([item.get_selection_label()] )
            top.addChild(line)
            line.setToolTip(0,item.name)
        if status.has_key(top):
          top.setExpanded(status[top])
        else:
          top.setExpanded(1)       


#----------------------------------------------------------------------
  def getCurrentDispObj(self):
#----------------------------------------------------------------------
      item = self.currentItem()
      #print 'DispObjTree.getCurrentDispObj',item
      if not item or not item.parent(): return ''
      return str(item.toolTip(0))



#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class AsDispObjGui(QtGui.QDialog):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------

  def __init__(self,parent=None,dataobj_list=[],exclude=[],object_types=['MolData']):
    QtGui.QDialog.__init__(self,parent)
    layout = QtGui.QVBoxLayout()

    self.tree = DispObjTree(dataobj_list=dataobj_list,exclude=exclude,object_types=object_types)
    layout.addWidget(self.tree )

    buttons = QtGui.QDialogButtonBox(self)
    but = buttons.addButton('OK',QtGui.QDialogButtonBox.AcceptRole)
    self.connect(but,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.emitApply,1))
    self.connect(but,QtCore.SIGNAL('clicked()'),self.close)
    but = buttons.addButton('Apply',QtGui.QDialogButtonBox.ApplyRole)
    self.connect(but,QtCore.SIGNAL('clicked()'),self.emitApply)
    but = buttons.addButton('Close',QtGui.QDialogButtonBox.RejectRole)
    self.connect(but,QtCore.SIGNAL('clicked()'),self.close)
    layout.addWidget(buttons )

    self.setLayout(layout)

    return

  def emitApply(self,close=0):
    self.emit(QtCore.SIGNAL('apply'),(QtCore.QVariant(self.objectName()),QtCore.QVariant(self.getCurrentDispObj())))
    if close: self.close()

  def populate(self):
    self.tree.populate()

  def getCurrentDispObj(self):
     return self.tree.getCurrentDispObj()

#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class AsDataObjGui(QtGui.QDialog):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
  def __init__(self,parent=None,exclude_list=[],object_type='MolData'):
    QtGui.QDialog.__init__(self,parent)
    layout = QtGui.QVBoxLayout()

    line = QtGui.QHBoxLayout()
    self.clear = QtGui.QCheckBox('Clear existing display objects',self)
    self.clear.setChecked(1)
    line.addWidget(self.clear)
    layout.addLayout(line)

    self.dataCombo = mgWidgets.mgDataObjCombo(object_type=object_type)
    if exclude_list: self.dataCombo.setExcludeDataObjList(exclude_list)
    layout.addWidget(self.dataCombo )

    buttons = QtGui.QDialogButtonBox(self)
    but = buttons.addButton('OK',QtGui.QDialogButtonBox.AcceptRole)
    self.connect(but,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.emitApply,1))
    self.connect(but,QtCore.SIGNAL('clicked()'),self.close)
    but = buttons.addButton('Apply',QtGui.QDialogButtonBox.ApplyRole)
    self.connect(but,QtCore.SIGNAL('clicked()'),self.emitApply)
    but = buttons.addButton('Close',QtGui.QDialogButtonBox.RejectRole)
    self.connect(but,QtCore.SIGNAL('clicked()'),self.close)
    layout.addWidget(buttons )

    self.setLayout(layout)

    return

  def emitApply(self,close=0):
    if close: self.close()
    if self.getCurrentDataObj():
      self.emit(QtCore.SIGNAL('apply'),(QtCore.QVariant(self.objectName()),QtCore.QVariant(self.getCurrentDataObj().name),QtCore.QVariant(self.clear.isChecked())))

  def populate(self):
    self.dataCombo.populateMenu()

  def getCurrentDataObj(self):
     return self.dataCombo.getCurrentDataObj()
