"""
     qtgui/MGMainWindow.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     Copyright (C) 2009-2011 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,QtOpenGL
import tempfile
from global_definitions import *
import functools
import sys,os
import shutil
import math
import time
import guiUtils,mgWidgets,MGSimpleDialog 
import utils
import pygl_coord
import mmdb2 as mmdb

def getSuffixes(chomp):
  suffixes = []
  if chomp.find('.')<0:
    return suffixes
  while chomp:
    newchomp = chomp[chomp.find('.')+1:]
    suffixes.append(newchomp)
    if newchomp.find('.')<0:
      break
    chomp = newchomp
  return suffixes

def applyAdvancedPrefs():
  DISPLAYTABLE().update(all=1)

def createAdvancedParamsManager():
  import services
  import MGMainWindow
  pm = services.ParamsManager ( 
          name="advanced_options",
          apply_action = applyAdvancedPrefs,
          title='Advanced',
          help = '_has_no_help_',
          gui=['display_table_header','dockable_display_table','iconized_display_table','super_compact_display_table','other_header','developer_mode','spacer','restart_label'],
      default = { 'developer_mode' : 0, 'dockable_display_table' : 1, 'iconized_display_table' : 0, 'super_compact_display_table' : 0},
      definition = {
             'display_table_header' : dict(type=str, label='<b>Display Table options</b>', style='label'),
             'other_header' : dict(type=str, label='<b>Other options</b>', style='label'),
             'spacer' : dict(type=str, size=170, style='spacer'),
             'dockable_display_table' : dict(type=str, label='Dock display table (*)',style='checkbox'),
             'iconized_display_table' : dict(type=str, label='Use icons in display table',style='checkbox'),
             'super_compact_display_table' : dict(type=str, label='Super-compact when docked (*)',style='checkbox'),
             'restart_label' : dict(type=str, label='* <i>Requires program restart</i>', style='label'),
             'developer_mode' : dict(type=str, label='Enable development features (*)',style='checkbox')
                } )

  return pm

def createRecentreParamsManager():
  import services
  import MGMainWindow
  pm = services.ParamsManager ( 
          name="centre_mode",
          title='Recentre method',
          help = '_has_no_help_',
          gui=['centre_method'],
      default = { 'centre_method' : MGMainWindow.MGMainWindow.CENTRE_MODE_EXTENTS },
      definition = {
             'centre_method' : dict(type=str, label='Recenter method',style='combobox',alias = [MGMainWindow.MGMainWindow.CENTRE_MODE_EXTENTS,MGMainWindow.MGMainWindow.CENTRE_MODE_COORDS,MGMainWindow.MGMainWindow.CENTRE_MODE_MASS],menu= ['Extents Box','Centre of Coordinates','Centre of Mass'])
                } )

  return pm
     
"""
import opengl
class GLWidget(QtOpenGL.QGLWidget):
  def __init__(self,parent=None,share=None,fmt=None):
    if fmt:
      QtOpenGL.QGLWidget.__init__(self,fmt,parent,share)
    else:
      QtOpenGL.QGLWidget.__init__(self,parent)
    self.viewsize = 100.0;
    self.NEAR = 0.01
    self.FAR = 1000
    self.obj = None
    self.lastPos = QtCore.QPoint()
    self.mouseDownPos = QtCore.QPoint()
    self.quat = pygl_coord.Quat(0.0,0.0,0.0,0)
    self.RADIUS = 60.
    self.rpos = (0,0,0)
    self.slab_enabled = False
    self.slab_width = 10.
    self.slab_offset = 0.
    self.clip_cap = False
    self.customClipPlanes = []
    self.fog_enabled = False
    self.fog_strength = 1.
    self.fog_near = self.NEAR
    self.fog_far = self.FAR
    self.ambientOcclusionZNear  = 100.0
    self.ambientOcclusionZFar   = 150.0
    self.ambientOcclusionRadius = 15.0
    self.ambientOcclusionBias   = 0.3
    self.ambientOcclusionScale  = 1.0
    self.show_axes = 0
    self.show_scale = 0
    self.shaders_on = 0
    self.vertexShader = ''
    self.fragmentShader = ''
    self.show_fps = False
    import mmdb2 as mmdb
    import SimpleObject
    mmdb.InitMatType()
    molHnd = mmdb.Manager()
    molHnd.SetFlag(mmdb.MMDBF_AllowDuplChainID)
    molHnd.ReadCoorFile("/richelieu/stuart/ccp4-jhbuild-distutils/1sva_1.mmol")
    self.obj = SimpleObject.SimpleObject(molHnd)
    self.nframes = 0
    self.previous_frames = 0
    self.previous_time = time.time()
    self.current_fps_text = "0"


  def setPosition(self,axes):
      pass
    
  def setZoom(self,axes):
      pass
    
  def setQuat(self,axes):
      pass
    
  def setMouseBindings(self,axes):
      pass
    
  def getAxes(self):
      return self.show_axes
    
  def setShowScale(self,show):
      pass
    
  def getShowScale(self):
      return 0
    
  def rebuildAllDisplayObjects(self):
      pass

  def setAmbientOcclusionState(self,state):
      pass

  def setOutlineState(self,state):
      pass

  def setShadowState(self,state=None,foo=False):
      pass
  def transparency(self):
      return False

  def setAxes(self,axes):
      pass
    
  def getAxes(self):
      return self.show_axes
    
  def setShowScale(self,show):
      pass
    
  def getShowScale(self):
      return 0
    
  def rebuildAllDisplayObjects(self):
      pass

  def setAmbientOcclusionState(self,state):
      pass

  def setOutlineState(self,state):
      pass

  def setShadowState(self,state=None,foo=False):
      pass

  def setShaderState(self,state=None):
      pass

  def setBackground(self,r,g,b):
      pass

  def getBackground(self):
      return [1.0,1.0,1.0]

  def setAmbientOcclusionPrefs(self,lights=None):
      pass

  def setLights(self,lights=None):
      pass

  def calculateShadowExtents(self):
      return 200.

  def getStereo(self):
      return False

  def handleZoom(self,dx,dy):
    factor = 1. - dy/50.
    self.RADIUS = self.RADIUS * factor
    if self.RADIUS < 1: self.RADIUS = 1

  def mousePressEvent(self, event):
    self.lastPos = QtCore.QPoint(event.pos())
    self.mouseDownPos = QtCore.QPoint(event.pos())

  def mouseMoveEvent(self,event):
    diff = QtCore.QPoint(event.pos()) - self.lastPos
    dx = event.x() - self.lastPos.x()
    dy = event.y() - self.lastPos.y()
    if (dx==0 and abs(dy)<2) or (abs(dy)<2 and dx==0): return
    button = int(event.buttons())
    if button == QtCore.Qt.MidButton:
      self.handleZoom(dx,dy)
    if button == QtCore.Qt.LeftButton:
      rotQ = pygl_coord.Quat(dy,dx,0,0)
      self.quat.postMult(rotQ)
    self.updateGL()
    self.lastPos = QtCore.QPoint(event.pos())

  def resizeGL(self,w,h):
    if h == 0:
      h = 1
    if w == 0:
      w = 1
    ratio = 1.0*w / h
    opengl.glMatrixMode(opengl.GL_PROJECTION);
    opengl.glLoadIdentity();
    opengl.glViewport(0, 0, w, h);
    opengl.glOrtho(-self.viewsize*ratio,self.viewsize*ratio,-self.viewsize,self.viewsize,self.NEAR,self.FAR);
    opengl.glMatrixMode(opengl.GL_MODELVIEW)

  def paintGL(self):
    opengl.glLoadIdentity();
    opengl.glTranslatef(0,0,-600);
    opengl.glScalef(60.0/float(self.RADIUS),60.0/float(self.RADIUS),60.0/float(self.RADIUS))
    glrotmat = self.quat.getInvMatrix().to_dp()
    opengl.glMultMatrixd(glrotmat)
    opengl.delcdp(glrotmat)

    self.qglClearColor(QtGui.QColor(QtCore.Qt.white))
    opengl.glClear(opengl.GL_COLOR_BUFFER_BIT | opengl.GL_DEPTH_BUFFER_BIT)
    opengl.glDisable(opengl.GL_LIGHTING);
    opengl.glEnableClientState(opengl.GL_VERTEX_ARRAY)
    opengl.glEnableClientState(opengl.GL_COLOR_ARRAY)

    if hasattr(self,"obj") and hasattr(self.obj,"draw") and callable(self.obj.draw):
      self.obj.draw()

    if True:
        message = ""
	if True:
          self.nframes = self.nframes + 1
          t = time.time()
          if t - self.previous_time > 1:
            fps  = (self.nframes-self.previous_frames)/( time.time()-self.previous_time)
            fps_text = ( "%4.0f" ) % fps
            self.previous_frames = self.nframes
            self.previous_time = t
            message = message + "framerate:"+fps_text+" "
            self.current_fps_text = fps_text
          else:
            message = message + "framerate:"+self.current_fps_text+" "
          print message
"""

class MoviePresQuestion(QtGui.QDialog):
  def __init__(self,parent=None):
    QtGui.QDialog. __init__(self,parent)
    layout = QtGui.QGridLayout(self)
    label = QtGui.QLabel(self)
    label.setText(self.tr("Open this file as"))
    layout.addWidget(label)
    self.combo = QtGui.QComboBox(self)
    self.combo.addItems(["Movie","Presentation","Animation"])
    layout.addWidget(self.combo,0,1)
    buttonbox = QtGui.QDialogButtonBox(self)
    button = buttonbox.addButton(QtGui.QDialogButtonBox.Ok)
    cancel = buttonbox.addButton(QtGui.QDialogButtonBox.Cancel)
    layout.addWidget(buttonbox)
    self.connect(button,QtCore.SIGNAL("clicked(bool)"),self.Done)
    self.connect(cancel,QtCore.SIGNAL("clicked(bool)"),functools.partial(self.done,-1))
    self.setLayout(layout)

  def Done(self):
    self.done(self.combo.currentIndex())

class GLView:
  def __init__(self,quat=None,pos=[],scale=0.0,glWidget=None):
    if glWidget:
      self.getFromGLWidget(glWidget)
    else:
      self.pos = pos
      self.quat = quat
      self.scale = scale
  def Quat(self): return self.quat
  def Position(self): return self.pos
  def Scale(self): return self.scale
  
  def getFromGLWidget(self,glWidget):
    self.quat = pygl_coord.Quat()
    self.quat.Setdval(glWidget.quat.Getdval())
    self.pos = []
    self.pos.extend([glWidget.rpos[0],glWidget.rpos[1],glWidget.rpos[2]])
    import copy
    self.scale = copy.deepcopy(glWidget.RADIUS)

    for item in ['fog_enabled','fog_strength','fog_near','fog_far','slab_enabled','slab_width','slab_offset','clip_cap','customClipPlanes']:
      setattr(self,item,getattr(glWidget,item))
    
  def setGLWidget(self,glWidget):
    quat = pygl_coord.Quat()
    quat.Setdval(self.quat.Getdval())
    glWidget.setQuat(quat)
    glWidget.setPosition(self.pos)
    glWidget.setZoom(self.scale)
    
    for item in ['fog_enabled','fog_strength','fog_near','fog_far','slab_enabled','slab_width','slab_offset','clip_cap','customClipPlanes']:
      setattr(glWidget,item,getattr(self,item))

  
class MGMainWindowCore:

    plugins = []
    CENTRE_MODE_EXTENTS = 0
    CENTRE_MODE_COORDS = 1
    CENTRE_MODE_MASS = 2
    centre_mode = CENTRE_MODE_EXTENTS

    def show(self): pass
    def hide(self): pass

    def __init__(self, parent=None,application=None,gui_params={},stereoFormatAvailable=False):
        self.downloadThreads = []
        self.customDownloadFilterTypes = []
        self.defaultObjBodyVisibility = 'open_all'

    def addCustomDownloadFilterType(self,filter):
        if not filter in self.customDownloadFilterTypes:
          self.customDownloadFilterTypes.append(filter)

    def applyStereoPrefs(self):
	try:
		params =  PM("stereo_prefs").getparams()
		if params.has_key('stereo_mode'):
			if params['stereo_mode'] == 0:
				self.stereo_mode = 'SHEAR'
			else:
				self.stereo_mode = 'ROTATION'
		else:
			self.stereo_mode = 'SHEAR'
		if params.has_key('shear_sep'):
			self.stereo_shear_separation = float(params['shear_sep'])
		else:
			self.stereo_shear_separation = 0.1

		if params.has_key('rot_sep'):
			self.stereo_rotation_angle = float(params['rot_sep'])
		else:
			self.stereo_rotation_angle = 6.0
	except:
		print "Exception!"
		exc_type, exc_value,exc_tb = sys.exc_info()[:3]
		print exc_type
		print exc_value
		self.stereo_mode = 'SHEAR'
		self.stereo_shear_separation = 0.1
		self.stereo_rotation_angle = 6.0

	self.setStereoMatrices()
  
    """
    def findWidgetPosition(self,findWidget):
	for i in range(self.box_layout.count()):
		item = self.box_layout.itemAt(i)
		if item.widget() is findWidget:
			return self.box_layout.getItemPosition(i)
	return None	
    """

    def removeGLDisplayObject(self,mod):
        #print "MGMainWindow.removeGLDisplayObject", mod
        self.glWidget.removeDisplayObject(mod,1)
        for widget in self.glWidgets:
		if widget is not self.glWidget:
			widget.SetGO(self.glWidget.go,1)

    def rebuildGLDisplayObject(self,mod):
        # This probably ought loop over all the GLWidgets we want to draw the same thing.
        for widget in self.glWidgets:
          widget.rebuildDisplayObject(mod,1)

    def setGLSize(self,size=None,width=0,height=0,restore=0,save=0):
        # This probably ought loop over all the GLWidgets we want to draw the same thing.
        if restore and self.savedGLSize:
          #self.glWidget.setViewsize(self.savedGLSize)
          self.glWidget.resize(self.savedGLSize[0],self.savedGLSize[1])
        if save:
          #self.savedGLSize = self.glWidget.size()
          self.savedGLSize = (self.glWidget.width(),self.glWidget.height())
        if size:
          #self.glWidget.setViewsize(size)
          self.glWidget.resize(size.width(),size.height())
        elif width and height:
          #self.glWidget.setViewsize(QtCore.QSize(width,height))
          self.glWidget.resize(width,height)
          
          
    def addGLDisplayObject(self,mod):
        # This probably ought loop over all the GLWidgets we want to draw the same thing.
        self.glWidget.addDisplayObject(mod,1)
        for widget in self.glWidgets:
		if widget is not self.glWidget:
			widget.SetGO(self.glWidget.go,1)

    def updateGLWindows(self):
        for widget in self.glWidgets:
          widget.makeCurrent()
          widget.updateGL()

    def clearLabels(self):
      PICKLABEL().clear_labels(0)
      self.updateGLWindows()
      
#---------------------------------------------------------------------------            
    def getParams(self):
#---------------------------------------------------------------------------            
      params = {}
      params['background_colour'] = self.glWidget.getBackground()
      params['show_axes'] = self.glWidget.getAxes()
      params['show_scale'] = self.glWidget.getShowScale()
      params['main_toolbar']=self.toolbar.getParams()
      params['centre_mode']=self.centre_mode
      params['defaultObjBodyVisibility']=self.defaultObjBodyVisibility
      
      pars = {}
      for item in ['rollspeed','rockspeed','rockangle','rollorientation']:
        pars[item] = getattr(self,item)                   
      params['rockParams']= pars
      
      # last directory accessed by file browser is saved but not
      # currently used on restart
      params['last_directory'] = mgWidgets.MGFileDialog.last_directory

       #print "MGMainWindow.getParams",params
      return params
      
    
#---------------------------------------------------------------------------            
    def setParams(self,params):
#---------------------------------------------------------------------------
      #print "MGMainWindow.setParams",params
      if params.has_key('background_colour'):
        for widget in self.glWidgets:
          r,g,b=params['background_colour']
          widget.setBackground(r,g,b)
      if params.has_key('show_axes'):
        for widget in self.glWidgets:
          widget.setAxes(params['show_axes'])
      if params.has_key('show_scale'):
        for widget in self.glWidgets:
          widget.setShowScale(params['show_scale'])
      if params.has_key('centre_mode'):
         self.centre_mode = params['centre_mode']
      if params.has_key('defaultObjBodyVisibility'):
         self.defaultObjBodyVisibility = params['defaultObjBodyVisibility']


    def checkIfStereoAvailable(self):
        return 0 # This function is broken
        fmt = QtOpenGL.QGLFormat()
        fmt.setStereo (1);
        ctx = QtOpenGL.QGLContext(fmt,pd)
        if ctx.create():
           return 1
        else:
           return 0
       
    def openCloseAllObjects(self,mode):
      import displayTable	 
      self.defaultObjBodyVisibility = mode
      if mode == 'open_all':
        for obj in DISPLAYTABLE().findChildren(displayTable.GDataObj):
          if not obj.isOpen():
            obj.toggleBodyVisibility(updateWidth=0)
      elif mode == 'close_all':
        for obj in DISPLAYTABLE().findChildren(displayTable.GDataObj):
          if obj.isOpen():
            obj.toggleBodyVisibility(updateWidth=0)
      self.wMGDisplayTable.updateWidth()

    def getActionDef(self,name,**info):
      # This will work for picking any object that
      # is properly handled by PickEvent
      if name =='pickInfo':        
        pickevent = info.get('pickevent',None)
        if not pickevent or not pickevent.getDataObj(): return dict()     
        dobj = DISPLAYTABLE().getDataObj(pickevent.getDataObj().name)
        #print 'getActionDef pickInfo dobj',dobj
        if not dobj:  return dict()
        return dict(
            text = 'Info about '+pickevent.getLabel(),
            tip = 'More information '+pickevent.getLabel(),
            signal = 'triggered()',
            slot = [dobj.pickInfo,pickevent],
            deleteLater = 1
            )
      if name =='centreOnAtom':
        pickevent = info.get('pickevent',None)
        if pickevent:
          return dict(
            text = 'Centre on '+pickevent.getLabel(),
            tip = 'Centre on atom '+pickevent.getLabel(),
            signal = 'triggered()',
            slot = [self.centreOn,pickevent.getPickPosition()],
            deleteLater = 1,
            )
      elif self.actionDefinitions.has_key(name):
          return self.actionDefinitions[name]
      else:
        return dict()

    def initializeActionDefinitions(self):
      import opengl
      import ccp4iGui
      self.actionDefinitions = {}

# Loading data

      self.actionDefinitions['download'] = dict (
        text = 'Download coordinates..',
        icon = 'download',
        tip = 'Download coordinate,map data from server',
        signal = 'triggered()',
        slot = self.handleDownload
      )

      self.actionDefinitions['open'] = dict (
        text = 'Open..',
        shortcut = QtGui.QKeySequence.Open,
        icon = 'fileopen',
        tip = 'Open coordinate,map,vector or image file',
        signal = 'triggered()',
        slot = self.handleOpen
      )

      self.actionDefinitions['open_presentation'] = dict (
        text = 'Open presentation',
        tip = 'Open directory to edit or show presentation',
        signal = 'triggered()',
        slot = guiUtils.partial(self.handlePresentation,'open_presentation'),
      )
      self.actionDefinitions['zip_presentation'] = dict (
        text = 'Open zipped presentation',
        icon = 'open_presentation',
        tip = 'UNcompress zip and open directory to edit or show presentation',
        signal = 'triggered()',
        slot = guiUtils.partial(self.handlePresentation,'zip_presentation'),
      )
      
      self.actionDefinitions['new_presentation'] = dict (
        text = 'New presentation',
        tip = 'Create directory to save presentation',
        signal = 'triggered()',
        slot = guiUtils.partial(self.handlePresentation,'new_presentation'),
      )

      self.actionDefinitions['file_viewer'] = dict (
        text = 'File viewer',
        tip = 'View text, image or movie files',
        signal = 'triggered()',
        slot = self.handleFileViewer
      )
      
      self.actionDefinitions['superpose'] = dict (
        text = 'Superpose models',
        tip = 'Automatic and manual model superposition',
        signal = 'triggered()',
        slot = self.handleSuperpose
      )
      
      self.actionDefinitions['transparency'] = dict (
        text = 'Transparency..',
        tip = 'Set display object(s) transparent',
        signal = 'triggered()',
        slot = guiUtils.partial(self.openTransparency),
      )

      self.actionDefinitions['setup_animation'] = dict (
        text = 'Setup animation',
        tip = 'Define the alternating scenes for an animation',
        signal = 'triggered()',
        slot = guiUtils.partial(self.openAnimation,'setup'),
      )
      
      def a(): return self.handleAnimationGui('animate_on')
      def e(): return self.handleAnimationGui('animate_enabled')
      
      self.actionDefinitions['animate'] = dict (
        text = 'Run animation',
        tip = 'Switch animation on/off',
        signal = 'triggered()',
        slot = guiUtils.partial(self.handleAnimationGui,'animate'),
        enabled = e,
        checkable = 1,
        checked = a
      )
      
      self.actionDefinitions['open_movie'] = dict (
        text = 'Open movie',
        tip = 'Open directory to edit or show movie',
        signal = 'triggered()',
        slot = guiUtils.partial(self.handlePresentation,'open_movie'),
      )
      
      self.actionDefinitions['new_movie'] = dict (
        text = 'New movie',
        tip = 'Create directory to save movie',
        signal = 'triggered()',
        slot = guiUtils.partial(self.handlePresentation,'new_movie'),
      )

      self.actionDefinitions['restore_status_from_file'] = dict (
        text = 'Restore..',
        shortcut = '',
        icon = 'restore',
        tip = 'Restore status',
        signal = 'triggered()',
        slot = self.handleRestore
      )
      
      self.actionDefinitions['save_status_to_file'] = dict (
        text = 'Save status to file..',
        shortcut = 'Shift+Ctrl+S',
        icon = 'save_status',
        tip = 'Save the current program status',
        signal = 'triggered()',
        slot = self.handleSaveStatus
      )

      self.actionDefinitions['save_default_status'] = dict (
        text = 'Save as default status..',
        shortcut = QtGui.QKeySequence.Save,
        icon = 'save_status',
        tip = 'Save the current program status to the default status file',
        signal = 'triggered()',
        slot = HISTORY().save_program_status
      )

# Saving to files

      self.actionDefinitions['print'] = dict (
        text = 'Print screen',
        shortcut = QtGui.QKeySequence.Print,
        tip = 'Print screen',
        signal = 'triggered()',
        slot = self.handlePrint
      )


      self.actionDefinitions['screenshot'] = dict (
        text = 'Screenshot',
        icon = 'camera',
        tip = 'Make image from current display',
        signal = 'triggered()',
        slot = self.screenshotGUI,
        checkable = 0,
        initialise = ''
      )

      self.actionDefinitions['tutorial_data'] = dict (
          text = 'Get tutorial data',
          icon = 'tutorial',
          tip = 'Copy data for tutorial to your own directory',
          slot = self.copyTutorialData
       )
      
      self.actionDefinitions['exit'] = dict (
        text = 'Exit',
        shortcut = 'Ctrl+Q',
        icon = 'exit',
        tip = 'Exit program',
        signal = 'triggered()',
        slot = self.handleExit,
        checkable = 0,
        initialise = ''
      )

  # Edit tools
      self.actionDefinitions['paste'] = dict (
        text = 'Paste',
        shortcut = QtGui.QKeySequence.Paste,
        icon = '',
        tip = 'Paste',
        signal = 'triggered()',
        slot = self.handlePaste,
        checkable = 0,
        initialise = ''
      )
      self.actionDefinitions['collapse_all'] = dict (
        text = 'Minimize all',
        slot = guiUtils.partial(self.openCloseAllObjects,'close_all')
      )
      self.actionDefinitions['show_all'] = dict (
        text = 'Maximize all',
        slot = guiUtils.partial(self.openCloseAllObjects,'open_all')
      )
      self.actionDefinitions['all_data_hide'] = dict (
        text = 'Hide',
        slot = guiUtils.partial(self.handleAllDataAction,'all_data_hide')
      )
      self.actionDefinitions['all_data_show'] = dict (
        text = 'Show',
        slot =  guiUtils.partial(self.handleAllDataAction,'all_data_show')
      )
      self.actionDefinitions['all_disp_labels'] = dict (
        text = 'Hide labels',
        slot =  guiUtils.partial(self.handleAllDataAction,'all_disp_labels')
      )
      self.actionDefinitions['all_disp_flashing'] = dict (
        text = 'Stop flashing',
        slot =  guiUtils.partial(self.handleAllDataAction,'all_disp_flashing')
      )
      self.actionDefinitions['all_disp_transparency'] = dict (
        text = 'Undo transparency',
        slot =  guiUtils.partial(self.handleAllDataAction,'all_disp_transparency')
      )
      
      self.actionDefinitions['all_data_close'] = dict (
        text = 'Close all data',
        slot = guiUtils.partial(self.handleAllDataAction,'all_data_close')
      )
      
      self.actionDefinitions['picture_wizard'] = dict (
        text = 'Picture Wizard',
        slot = guiUtils.partial(self.handleAllDataAction,'all_data_picture_wizard')
      )
      
      self.actionDefinitions['ccp4i_aliases'] = dict (
        text = 'CCP4i projects and aliases',
        tip = 'Add or change project and directory aliases as used in CCP4i',
        slot = ccp4iGui.openGui
      )

      self.actionDefinitions['preferences'] = dict (
        text = 'Preferences..',
        icon = 'preferences',
        tip = 'Program preferences',
        signal = 'triggered()',
        slot = self.handlePreferences,
        checkable = 0,
        initialise = ''
      )
    
  # View tools

      self.actionDefinitions['view_forward'] = dict (
        text = 'View redo',
        tip = 'Undo revert view',
        shortcut = QtGui.QKeySequence.Forward,
        slot = self.viewForward
      )
      
      self.actionDefinitions['view_back'] = dict (
        text = 'View undo',
        shortcut =  QtGui.QKeySequence.Back,
        tip = 'Revert view',
        slot = self.viewBack
      )

      self.actionDefinitions['view_from_left'] = dict (
          text = 'Left',
          tip = 'Rotate to view from left',
          slot = guiUtils.partial(self.viewFrom,'left')
      )
      self.actionDefinitions['view_from_right'] = dict (
          text = 'right',
          tip = 'Rotate to view from right',
          slot = guiUtils.partial(self.viewFrom,'right')
      )

      self.actionDefinitions['view_from_top'] = dict (
          text = 'top',
          tip = 'Rotate to view from top',
          slot = guiUtils.partial(self.viewFrom,'top')
      )

      self.actionDefinitions['view_from_bottom'] = dict (
          text = 'bottom',
          tip = 'Rotate to view from bottom',
          slot = guiUtils.partial(self.viewFrom,'bottom')
      )

      self.actionDefinitions['view_from_back-x'] = dict (
          text = 'back (about x)',
          tip = 'Rotate to view from back',
          slot = guiUtils.partial(self.viewFrom,'back-x')
      )

      self.actionDefinitions['view_from_back-y'] = dict (
          text = 'back (about y)',
          tip = 'Rotate to view from back',
          slot = guiUtils.partial(self.viewFrom,'back-y')
      )

      self.actionDefinitions['copyclipboard'] = dict (
        text = 'Copy to clipboard',
        shortcut = 'Ctrl+C',
        tip = 'Copy graphics window image to clipboard',
        signal = 'triggered()',
        slot = self.handleCopyClipboard
      )

      self.actionDefinitions['recentre'] = dict (
        text = 'Recentre',
        shortcut = 'Ctrl+E',
        tip = 'Recentre view to show all visible objects',
        signal = 'triggered()',
        slot = self.handleRecentre
      )
       
      self.actionDefinitions['centreOn'] = dict (
        text = 'Find, centre on..',
        shortcut = QtGui.QKeySequence.Find,
        tip = 'Centre on selected atom(s) or residue(s)',
        signal = 'triggered()',
        slot = self.handleCentreOn,
        checkable = 0,
      )
      self.actionDefinitions['clearLabels'] = dict (
        text = 'Clear picked labels',
        shortcut = '',
        icon = '',
        tip = 'Delete all labels on picked atoms',
        slot = self.clearLabels 
      )

      def a(): return len(self.glWidgets)==2
      self.actionDefinitions['sideBySide'] = dict (
        text = 'Side by side stereo',
        shortcut = '',
        icon = '',
        tip = 'Side by side stereo',
        signal = 'triggered()',
        group = 'screenSplit',
        slot = self.handleScreenSplit,
        checkable = 1,
        checked =  a
      )

      def a(): return len(self.glWidgets)==1
      self.actionDefinitions['singleView'] = dict (
        text = 'Single view',
        shortcut = '',
        icon = '',
        tip = 'Normal view',
        signal = 'triggered()',
        group = 'screenSplit',
        slot = self.handleScreenSplit,
        checkable = 1,
        checked =  a
      )

      def a(): return len(self.glWidgets)==3
      self.actionDefinitions['threeView'] = dict (
        text = 'Three way view',
        shortcut = '',
        icon = '',
        tip = 'Three way orthogonal view',
        signal = 'triggered()',
        group = 'screenSplit',
        slot = self.handleScreenSplit,
        checkable = 1,
        checked = a 
      )
      
      def a(): return len(self.glWidgets)==2
      self.actionDefinitions['toolbar_sideBySide'] = dict (
        text = 'Side by side stereo',
        shortcut = '',
        icon = '',
        tip = 'Side by side stereo',
        signal = 'triggered()',
        slot =  guiUtils.partial(self.toggleScreenSplit,'sideBySide'),
        checkable = 1,
        checked =  a
      )

      def a(): return len(self.glWidgets)==3
      self.actionDefinitions['toolbar_threeView'] = dict (
        text = 'Three way view',
        shortcut = '',
        icon = '',
        tip = 'Three way orthogonal view',
        signal = 'triggered()',
        slot =  guiUtils.partial(self.toggleScreenSplit,'threeView'),
        checkable = 1,
        checked = a
      )

      self.actionDefinitions['window_size'] = dict (
          text = 'Window size..',
          shortcut = '',
          tip = 'Set the window size',
          icon = '',
          slot = self.handleWindowSize,
        )

      def a(): return self.rockroll == 1
      self.actionDefinitions['roll_view'] = dict (
          text = 'Roll view',
          shortcut = '',
          tip = 'Rotate view continuously',
          icon = '',
          checkable = 1,
          checked = a,
          slot =  guiUtils.partial(self.toggleRockRoll,1)
        )
        
      def a(): return self.rockroll == 2
      self.actionDefinitions['rock_view'] = dict (
          text = 'Rock view',
          shortcut = '',
          tip = 'Rock view continuously',
          icon = '',
          checkable = 1,
          checked = a,
          slot = guiUtils.partial(self.toggleRockRoll,2)
      )
      self.actionDefinitions['rock_details'] = dict (
          text = 'Details..',
          shortcut = '',
          tip = 'Rock and roll details',
          icon = '',
          slot = self.rockAndRoll
      )

  # Help tools
  
      self.actionDefinitions['help'] = dict (
        text = 'Help..',
        shortcut = '',
        icon = 'help',
        tip = 'Program documentation',
        signal = 'triggered()',
        slot = self.handleHelp,
        checkable = 0,
      )
      
      self.actionDefinitions['about'] = dict (
        text = 'About..',
        shortcut = '',
        tip = 'About CCP4mg',
        signal = 'triggered()',
        slot = self.handleAbout,
        checkable = 0,
        initialise = ''
      )
    
      self.actionDefinitions['unclose'] = dict (
        text = 'Graphics Window',
        shortcut = '',
        icon = '',
        tip = 'Graphics Window',
        signal = 'triggered()',
        slot = self.UnClose,
        checkable = 0,
        initialise = ''
      )

      self.actionDefinitions['create_legend'] = dict (
        text = 'Legend',
        shortcut = '',
        tip = 'Create a 2D text legend object',
        slot = guiUtils.partial(self.createObject,'legend')
      )
   
      self.actionDefinitions['create_crystal'] = dict (
        text = 'Crystal',
        shortcut = '',
        tip = 'Create a crystal object',
        slot = guiUtils.partial(self.createObject,'crystal')
      )
      self.actionDefinitions['create_vectors'] = dict (
        text = 'Vectors',
        shortcut = '',
        tip = 'Create a vector object',
        slot = guiUtils.partial(self.createObject,'vectors'),
      )
       

      # Display menu

      self.actionDefinitions['display_back'] = dict (
          text = 'Undo',
          shortcut = QtGui.QKeySequence.Undo,
          tip = 'Revert status of displayed objects',
          slot = guiUtils.partial(self.restoreDisplay,-1)
          )
      
      self.actionDefinitions['display_forward'] = dict (
          text = 'Redo',
          shortcut =  QtGui.QKeySequence.Redo,
          tip = 'Undo revert status of displayed objects',
          slot = guiUtils.partial(self.restoreDisplay,1)
          )

      def a(): return self.glWidgets[0].show_axes
      self.actionDefinitions['show_axes'] = dict (
            text = 'Axes',
            tip = 'Show coordinate system axes in the main window',
            shortcut = '',
            checkable = 1,
            checked = a,
            slot = self.toggleAxes )

      def a(): return self.glWidgets[0].show_scale
      self.actionDefinitions['show_scale'] = dict (
            text = 'Scale',
            tip = 'Show coordinate system scale in the main window',
            shortcut = '',
            checkable = 1,
            checked = a,
            slot = self.toggleShowScale )
       
      def a(): return self.glWidgets[0].getStereo() and not self.glWidgets[0].getDoZalmanStereo()
      def stereoAvailable(): 
	      	return True # TEST SJM 15/02/2011
		return self.stereoFormatAvailable
      self.actionDefinitions['stereo_on'] = dict (
            text = 'Hardware Stereo',
            tip = 'Turn hardware stereo on/off',
            checkable = 1,
            enabled = stereoAvailable,
            checked = a,
            slot = self.toggleStereo )
      def a(): return self.glWidgets[0].getStereo() and self.glWidgets[0].getDoZalmanStereo()
      self.actionDefinitions['zalman_stereo_on'] = dict (
            text = 'Zalman Stereo',
            tip = 'Turn line-by line polarized stereo on/off',
            checkable = 1,
            enabled = 1,
            checked = a,
            slot = self.toggleZalmanStereo )

      self.actionDefinitions['fullscreen'] = dict (
            text = 'Fullscreen',
            tip = 'Turn fullscreen on/off',
            shortcut = 'Ctrl+B',
            checkable = 1,
            enabled = 1,
            checked = 0,
            slot = self.toggleFullscreen )

      def a(): return self.glWidgets[0].show_fps
      self.actionDefinitions['framerate'] = dict (
            text = 'Show framerate',
            tip = 'Show framerate in status bar',
            checkable = 1,
            enabled = 1,
            checked = a,
            slot = self.toggleFramerate )

      self.actionDefinitions['zoom_display'] = dict (
            text = 'Show/change zoom',
            tip = 'Show/change zoom factor in status bar',
            checkable = 1,
            enabled = 1,
            checked = 0,
            slot = self.toggleZoomDisplay )

      def a(): return self.glWidgets[0].format().sampleBuffers()
      self.actionDefinitions['fsaa_on'] = dict (
             text = 'Solid smoothing',
             tip = 'Use antialiasing to reduce jagged edges of solid objects',
             checkable = 1,
             checked = a,
             slot = self.toggleFSAA )

      def a(): return self.glWidgets[0].fog_enabled
      self.actionDefinitions['fog_on'] = dict (
            text = 'Depth cue fog',
            tip = 'Fog out distant objects',
            shortcut = 'Ctrl+W',
            checkable = 1,
            checked = a,
            slot = self.toggleFog )
       
      def a(): return self.glWidgets[0].slab_enabled
      self.actionDefinitions['slab_on'] = dict (
            text = 'Clip front/back',
            tip = 'Clip front and rear of view',
            shortcut = 'Ctrl+L',
            checkable = 1,
            checked =  a,
            slot = self.toggleSlab )
            
      """
      self.actionDefinitions['toggle_toolbar'] = dict (
            text = 'Toolbar',
            shortcut = '',
            tip = 'Show/hide toolbar',
            action = self.toolbar.toggleViewAction() )
      """
      import slabAndFog
      self.actionDefinitions['slab_n_fog'] = dict (
            shortcut = '',
            text = 'Clip and fog details..',
            tip = 'Control depth clipping and fog out distant objects',
            slot = slabAndFog.slabAndFog )
      
      self.actionDefinitions['background_black'] = dict (
            shortcut = '',
           text = 'Black',
           slot = guiUtils.partial(self.setBackgroundColour,'black') )
           
      self.actionDefinitions['background_white'] = dict (
            shortcut = '',
           text = 'White',
           slot = guiUtils.partial(self.setBackgroundColour,'white') )
           
      self.actionDefinitions['background_other'] = dict (
            shortcut = '',
           text = 'Select other..',
           slot = guiUtils.partial(self.setBackgroundColour,'other') )

      light_menu = { 'light_shiny' : 'Shiny',
                     'light_soft' : 'Soft',
                     'light_shaded' : 'Shaded',
                     'light_shadows_top_right' : 'Ray-trace shadows' }
      for item in ['light_shiny','light_soft','light_shaded','light_shadows_top_right']:
        self.actionDefinitions[item] = dict (
          text = light_menu[item],
          tip = 'Reset the lighting',
          slot = guiUtils.partial(self.setLighting,item) )
        

    def removeMenuDefinition(self,name,defn,menu,force=0):
        self.actionDefinitions[name] = defn
        if self.menuDefinitions.has_key(menu):
		if self.menuDefinitions[menu].count(name)>0:
			idx = self.menuDefinitions[menu].index(name)
			if idx >=0 :
           			self.menuDefinitions[menu].pop(idx)
	   			#self.drawMenu(menu)
        else:
           if self.menuDefinitions.has_key("Tools"):
		if self.menuDefinitions["Tools"].count(name)>0:
			idx =  self.menuDefinitions["Tools"].index(name)
			if idx >=0 :
           			self.menuDefinitions["Tools"].pop(idx)
	     			#self.drawMenu('Tools')

    def addMenuDefinition(self,name,defn,menu,force=0,submenu=None,draw_menu=True):
        if force or not self.actionDefinitions.has_key(name):
          self.actionDefinitions[name] = defn
        if defn.has_key("icon_path"):
           action = guiUtils.createAction(name,self,icon_path=defn["icon_path"])
        else:
          action = guiUtils.createAction(name,self)
        if self.menuDefinitions.has_key(menu):
           if submenu:
		try:
			for it in self.menuDefinitions[menu]:
				if type(it) == list:
					if len(it)>0 and it[0]==submenu:
           					idx = it.count(name)
						if idx==0: 
							it.append(name)
	   						if draw_menu: self.drawMenu(menu)
		except:
           		idx = self.menuDefinitions["Tools"].count(name)
			if idx == 0: self.menuDefinitions["Tools"].append(name)
			if draw_menu: self.drawMenu('Tools')
           else:
           	idx = self.menuDefinitions[menu].count(name)
	        if idx == 0: self.menuDefinitions[menu].append(name)
	   	if draw_menu: self.drawMenu(menu)
        else:
           if self.menuDefinitions.has_key("Tools"):
           	idx = self.menuDefinitions["Tools"].count(name)
		if idx == 0: self.menuDefinitions["Tools"].append(name)
		if draw_menu: self.drawMenu('Tools')
        return action

    def initializeMenuDefinitions(self):
        import sys
        self.menuDefinitions =  {}
        # Definition of popup screen context menu
        self.menuDefinitions['context'] =  ['recentre','centreOnAtom','pickInfo']

        # Definition of sub-sections of File menu and File menu
        self.menuDefinitions['_file_download'] = ['download']
        self.menuDefinitions['_file_open'] = ['open',self.recentFilesList,'_file_download','restore_status_from_file',['Edit/show presentation','new_presentation','open_presentation','zip_presentation']]
        self.menuDefinitions['_file_close'] = ['all_data_close']
        self.menuDefinitions['_file_create'] = [['Create object','create_legend','create_crystal','create_vectors']]
        self.menuDefinitions['_tutorial'] = ['tutorial_data']
        self.menuDefinitions['_file_save'] =  [ 'save_status_to_file','save_default_status','screenshot','print']         
        #self.menuDefinitions['File'] =  ['_file_open','_file_create','sep','_tutorial','sep','_file_save']
        self.menuDefinitions['File'] =  ['_file_open','sep','_file_close','sep','_tutorial','sep','_file_save']
        
        if sys.platform != 'darwin': 
        	#self.menuDefinitions['Edit'] =  ['copyclipboard','paste',['For all data','all_data_hide','all_data_show'],['For all display objects','all_disp_labels','all_disp_flashing','all_disp_transparency'],'preferences']
        	self.menuDefinitions['Edit'] =  ['copyclipboard','paste','sep','display_back','display_forward','sep','preferences']
	else:
        	#self.menuDefinitions['Edit'] =  ['paste',['For all data','all_data_hide','all_data_show'],['For all display objects','all_disp_labels','all_disp_flashing','all_disp_transparency']]
        	self.menuDefinitions['Edit'] =  ['copyclipboard','paste','sep','display_back','display_forward']
       
        self.menuDefinitions['_view_orientation'] = [['View history','view_back','view_forward'],'recentre','centreOn',['View from','view_from_left','view_from_right','view_from_bottom','view_from_top','view_from_back-x','view_from_back-y']]
        self.menuDefinitions['_view_applications'] = [['Rock and roll','roll_view','rock_view','rock_details']]
        self.menuDefinitions['View'] =  ['_view_orientation','sep',['Split screen','singleView','sideBySide','threeView'],'sep','_view_applications']

        self.menuDefinitions['_display_onoff'] = ['toggle_toolbar','fog_on','slab_on','slab_n_fog','show_axes','show_scale']
        self.menuDefinitions['_display_applications'] = [['Animate display','animate','setup_animation']]
        self.menuDefinitions['Display'] =  ['clearLabels','sep','_display_onoff','sep',['Background colour','background_black','background_white','background_other'],'stereo_on','zalman_stereo_on','fsaa_on','sep','_display_applications','fullscreen','sep','framerate','zoom_display']
        self.menuDefinitions['Windows'] =  []
        self.menuDefinitions['Tools'] =  []
        self.menuDefinitions['Applications'] =  ['file_viewer','superpose',['Movie editor','open_movie','new_movie'],'picture_wizard']
        if sys.platform != 'darwin': 
        	self.menuDefinitions['Help'] =  ['help','about']
	else:
        	self.menuDefinitions['Help'] =  ['help']

        # Definition of toolbar
        self.menuDefinitions['main_toolbar_supported'] =  ['open','download','save_status_to_file','screenshot','all_data_close','preferences','view_back','view_forward','recentre','centreOn','rock_view','roll_view','display_back','display_forward','clearLabels','fog_on','slab_on','slab_n_fog','show_axes','show_scale','background_black','background_white','stereo_on','superpose','open_movie','picture_wizard']
        self.menuDefinitions['main_toolbar_default'] =  ['open','download','save_status_to_file','screenshot','view_back','view_forward','display_back','display_forward','recentre','centreOn','clearLabels','fog_on','slab_on','superpose','open_movie','preferences']

        if sys.platform != 'darwin': 
		self.menuDefinitions['File'].extend(['sep','exit'])
        if sys.platform == 'darwin': 
		self.menuDefinitions['_dummy'] = ['about','preferences','exit']

    def getGuiDef(self,name='',pickevent=None):

      if name == 'menus':
        if sys.platform == 'darwin': 
           return [['File','&File','aboutToShow'], ['Edit','&Edit'],['View','&View','aboutToShow'], ['Display','&Display','aboutToShow'],['Applications','&Applications','aboutToShow'],['Windows','&Windows','aboutToShow'],['Tools','&Tools','aboutToShow'],['Help','&Help'],['_dummy','_dummy']]
        else:
           return [['File','&File','aboutToShow'], ['Edit','&Edit'],['View','&View','aboutToShow'], ['Display','&Display','aboutToShow'],['Applications','&Applications','aboutToShow'],['Windows','&Windows','aboutToShow'],['Tools','&Tools','aboutToShow'],['Help','&Help']]
      else:
        defn = []
        defn.extend(self.getGuiDef0(name))
        return defn

    def getGuiDef0(self,name=''):
      if not self.menuDefinitions.has_key( name): return []
      defn = []
      for item in self.menuDefinitions[name]:
          if item[0] == '_' and self.menuDefinitions.has_key(item):
            defn.extend(self.getGuiDef0(item))
          else:
            defn.append(item)
      return defn
      
    def PositionChanged(self,args=None):
        if args:
           widget = args
	self.statusBar().showMessage("Origin: %s %s %s" % (widget.rpos[0],widget.rpos[1],widget.rpos[2]))
        for glwidget in self.glWidgets:
           if glwidget is not widget:
             glwidget.SetOrigin(widget.rpos,1)

    def MousePress(self,args=None):
        event = args[0]
        widget = args[1]
        #print event.pos().x(), event.pos().y()
        #print widget

    def ZoomChanged(self,args=None):
        if args:
           widget = args
        for glwidget in self.glWidgets:
           if glwidget is not widget:
             glwidget.RADIUS = widget.RADIUS
             glwidget.updateGL()

    def QuatChanged(self,args=None):
        if args:
           widget = args
        for glwidget in self.glWidgets:
           if glwidget is not widget:
             glwidget.quat = widget.quat
             glwidget.updateGL()

    def toggleScreenSplit(self,mode):
      '''
      Handle the toolbar buttons which are not in an QActionGroup
      Check the appropriate button in the group to force required action
      current = self.findChild(QtGui.QActionGroup,'screenSplit').checkedAction().objectName()
      if mode == current:
        # Trying to switch off stereo/three way - reset to single
        self.findChild(QtGui.QAction,'singleView').setChecked(1)
      else:
        self.findChild(QtGui.QAction,mode).setChecked(1)
      '''
      self.handleScreenSplit()
        
    def handleScreenSplit(self):
      new = self.findChild(QtGui.QActionGroup,'screenSplit').checkedAction().objectName()
      # Do we need to close any exisiting views?
      if len(self.glWidgets) == 3:
        if new == 'threeView':
          return
        else:
          self.handleThreeWayView()
      elif len(self.glWidgets) == 2:
        if new == 'sideBySide':
          return
        else:
          self.handleSideBySide()
      #print "closed views",len(self.glWidgets)
      # Should be back at single view now - do we need to open
      # new views?
      if new == 'threeView':
        self.handleThreeWayView()
      elif new == 'sideBySide':
        self.handleSideBySide()

      self.toggleAxes()

      action = self.findChild(QtGui.QAction,'toolbar_sideBySide') ## ?? Why separate actions for toolbar?
      if action: action.setChecked(len(self.glWidgets)==2)
      action = self.findChild(QtGui.QAction,'toolbar_threeView')
      if action: action.setChecked(len(self.glWidgets)==3)

    def handleThreeWayView(self):
        if len(self.glWidgets)==3:
          while len(self.glWidgets)>1:
            glwidget = self.glWidgets.pop()
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("ShadowStateChanged"),glwidget.setShadowState)
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("AmbientOcclusionStateChanged"),glwidget.setAmbientOcclusionState)
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("ShaderStateChanged"),glwidget.setShaderState)
            glwidget.SetGO([],0)
            glwidget.close()
            self.box_layout.removeWidget(glwidget)
            glwidget.deleteLater()
        else:
          if len(self.glWidgets)>0:
           while len(self.glWidgets)>1:
            glwidget = self.glWidgets.pop()
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("ShadowStateChanged"),glwidget.setShadowState)
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("AmbientOcclusionStateChanged"),glwidget.setAmbientOcclusionState)
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("ShaderStateChanged"),glwidget.setShaderState)
            glwidget.SetGO([],0)
            glwidget.close()
            self.box_layout.removeWidget(glwidget)
            glwidget.deleteLater()
          import MGGLWidget
          y_glWidget = MGGLWidget.MGGLWidget(self,self.glWidget,format=self.glWidget.format())
          y_glWidget.setStereo(self.glWidget.getStereo())
          y_glWidget.setDoZalmanStereo(self.glWidget.getDoZalmanStereo())
          self.glWidgets.append(y_glWidget)
          self.box_layout.addWidget(y_glWidget,0,1)
          for item in ['RADIUS','quat','fog_enabled','fog_strength','fog_near','fog_far','slab_enabled','slab_width','slab_offset','clip_cap','customClipPlanes']:
            setattr(y_glWidget,item,getattr(self.glWidgets[0],item))
          r,g,b = self.glWidgets[0].getBackground()
          y_glWidget.setBackground(r,g,b)
          y_glWidget.setDoubleClickHandler(self.pickEventRecentre)
          y_glWidget.setLeftClickHandler(self.labelPickedObject)
          y_glWidget.setContextMenuHandler(self.contextMenuHandler)
          self.connect(y_glWidget,QtCore.SIGNAL("QuatChanged"),self.QuatChanged)
          self.connect(y_glWidget,QtCore.SIGNAL("ZoomChanged"),self.ZoomChanged)
          self.connect(y_glWidget,QtCore.SIGNAL("PositionChanged"),self.PositionChanged)
          self.connect(y_glWidget,QtCore.SIGNAL("ViewChanged"),self.GLLeftMouseReleased)
          self.connect(y_glWidget,QtCore.SIGNAL("TransformObject"),self.MGDisplayTable.handleObjectMoving)
          y_glWidget.extra_quat = pygl_coord.Quat(1.0,0.0,0.0,1,90)
          y_glWidget.setExtraMatrix(None)
          y_glWidget.updateGL()
          if self.glWidget.go: 
            y_glWidget.SetGO(self.glWidget.go,1)
            y_glWidget.SetOrigin(self.glWidget.rpos,1)
          x_glWidget = MGGLWidget.MGGLWidget(self,self.glWidget,format=self.glWidget.format())
          x_glWidget.setStereo(self.glWidget.getStereo())
          x_glWidget.setDoZalmanStereo(self.glWidget.getDoZalmanStereo())
          self.glWidgets.append(x_glWidget)
          self.box_layout.addWidget(x_glWidget,1,0)
          for item in ['RADIUS','quat','fog_enabled','fog_strength','fog_near','fog_far','slab_enabled','slab_width','slab_offset','clip_cap','customClipPlanes']:
            setattr(x_glWidget,item,getattr(self.glWidgets[0],item))
          r,g,b = self.glWidgets[0].getBackground()
          x_glWidget.setBackground(r,g,b)
          x_glWidget.setDoubleClickHandler(self.pickEventRecentre)
          x_glWidget.setLeftClickHandler(self.labelPickedObject)
          x_glWidget.setContextMenuHandler(self.contextMenuHandler)
          self.connect(x_glWidget,QtCore.SIGNAL("QuatChanged"),self.QuatChanged)
          self.connect(x_glWidget,QtCore.SIGNAL("ZoomChanged"),self.ZoomChanged)
          self.connect(x_glWidget,QtCore.SIGNAL("PositionChanged"),self.PositionChanged)
          self.connect(x_glWidget,QtCore.SIGNAL("ViewChanged"),self.GLLeftMouseReleased)
          self.connect(x_glWidget,QtCore.SIGNAL("TransformObject"),self.MGDisplayTable.handleObjectMoving)

          for mapdisp in get_dispobj(object_type=['MapDisp']):
            if hasattr(mapdisp,'graphmod') and mapdisp.graphmod:
              y_glWidget.connect(y_glWidget,QtCore.SIGNAL("PositionChanged"),mapdisp.graphmod.handleGLWidgetChangePostion)
              x_glWidget.connect(x_glWidget,QtCore.SIGNAL("PositionChanged"),mapdisp.graphmod.handleGLWidgetChangePostion)


          x_glWidget.updateGL()
          if self.glWidget.go: 
            x_glWidget.SetGO(self.glWidget.go,1)
            x_glWidget.SetOrigin(self.glWidget.rpos,1)
          x_glWidget.extra_quat = pygl_coord.Quat(0.0,1.0,0.0,1,-90)
          x_glWidget.setExtraMatrix(None)
          self.applyGLLighting()
          # We more or less must, load shaders here into main GL widget, any other way is going to be
          # too complicated.
          if not hasattr(self.glWidgets[0],"circleShader"):
            # We are protecting with try, but the module should be available. (I think Shaders should be core, not plugin.)
            try:
              oldState = self.glWidgets[0].getShaderState()
              import Shaders
              Shaders.handleShaders({"use_shaders":1})
              self.glWidgets[0].setShaderState(oldState)
            except:
              pass
          x_glWidget.copyShaders(self.glWidgets[0])
          y_glWidget.copyShaders(self.glWidgets[0])
          self.connect(self.glWidgets[0],QtCore.SIGNAL("ShadowStateChanged"),x_glWidget.setShadowState)
          self.connect(self.glWidgets[0],QtCore.SIGNAL("ShadowStateChanged"),y_glWidget.setShadowState)
          self.connect(self.glWidgets[0],QtCore.SIGNAL("AmbientOcclusionStateChanged"),x_glWidget.setAmbientOcclusionState)
          self.connect(self.glWidgets[0],QtCore.SIGNAL("AmbientOcclusionStateChanged"),y_glWidget.setAmbientOcclusionState)
          self.connect(self.glWidgets[0],QtCore.SIGNAL("ShaderStateChanged"),x_glWidget.setShaderState)
          self.connect(self.glWidgets[0],QtCore.SIGNAL("ShaderStateChanged"),y_glWidget.setShaderState)

    def handleSideBySide(self):
        if len(self.glWidgets)==2:
          while len(self.glWidgets)>1:
            glwidget = self.glWidgets.pop()
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("ShadowStateChanged"),glwidget.setShadowState)
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("AmbientOcclusionStateChanged"),glwidget.setAmbientOcclusionState)
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("ShaderStateChanged"),glwidget.setShaderState)
            glwidget.SetGO([],0)
            glwidget.close()
            self.box_layout.removeWidget(glwidget)
            glwidget.deleteLater()
          self.glWidgets[0].extra_quat = pygl_coord.Quat(0.0,0.0,0.0,0)
          self.glWidgets[0].setExtraMatrix(None)
        else:
          if len(self.glWidgets)>0:
           while len(self.glWidgets)>1:
            glwidget = self.glWidgets.pop()
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("ShadowStateChanged"),glwidget.setShadowState)
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("AmbientOcclusionStateChanged"),glwidget.setAmbientOcclusionState)
            self.disconnect(self.glWidgets[0],QtCore.SIGNAL("ShaderStateChanged"),glwidget.setShaderState)
            glwidget.SetGO([],0)
            glwidget.close()
            self.box_layout.removeWidget(glwidget)
            glwidget.deleteLater()
          import MGGLWidget
          sideStereo_glWidget = MGGLWidget.MGGLWidget(self,self.glWidget,format=self.glWidget.format())
          sideStereo_glWidget.setStereo(self.glWidget.getStereo())
          sideStereo_glWidget.setDoZalmanStereo(self.glWidget.getDoZalmanStereo())
          self.glWidgets.append(sideStereo_glWidget)
          self.box_layout.addWidget(sideStereo_glWidget,0,1)
          for item in ['RADIUS','quat','fog_enabled','fog_strength','fog_near','fog_far','slab_enabled','slab_width','slab_offset','clip_cap','customClipPlanes']:
            setattr(sideStereo_glWidget,item,getattr(self.glWidgets[0],item))
          r,g,b = self.glWidgets[0].getBackground()
          sideStereo_glWidget.setBackground(r,g,b)
          sideStereo_glWidget.setDoubleClickHandler(self.pickEventRecentre)
          sideStereo_glWidget.setLeftClickHandler(self.labelPickedObject)
          sideStereo_glWidget.setContextMenuHandler(self.contextMenuHandler)
          self.connect(sideStereo_glWidget,QtCore.SIGNAL("QuatChanged"),self.QuatChanged)
          self.connect(sideStereo_glWidget,QtCore.SIGNAL("ZoomChanged"),self.ZoomChanged)
          self.connect(sideStereo_glWidget,QtCore.SIGNAL("PositionChanged"),self.PositionChanged)
          self.connect(sideStereo_glWidget,QtCore.SIGNAL("ViewChanged"),self.GLLeftMouseReleased)
          self.connect(sideStereo_glWidget,QtCore.SIGNAL("TransformObject"),self.MGDisplayTable.handleObjectMoving)

          for mapdisp in get_dispobj(object_type=['MapDisp']):
            if hasattr(mapdisp,'graphmod') and mapdisp.graphmod:
              sideStereo_glWidget.connect(sideStereo_glWidget,QtCore.SIGNAL("PositionChanged"),mapdisp.graphmod.handleGLWidgetChangePostion)
 
          
          sideStereo_glWidget.updateGL()
          if self.glWidget.go: 
            sideStereo_glWidget.SetGO(self.glWidget.go,1)
            sideStereo_glWidget.SetOrigin(self.glWidget.rpos,1)

          self.setStereoMatrices()

          self.applyGLLighting()
          # We more or less must, load shaders here into main GL widget, any other way is going to be
          # too complicated.
          if not hasattr(self.glWidgets[0],"circleShader"):
            # We are protecting with try, but the module should be available. (I think Shaders should be core, not plugin.)
            try:
              oldState = self.glWidgets[0].getShaderState()
              import Shaders
              Shaders.handleShaders({"use_shaders":1})
              self.glWidgets[0].setShaderState(oldState)
            except:
              pass
          sideStereo_glWidget.copyShaders(self.glWidgets[0])
          self.connect(self.glWidgets[0],QtCore.SIGNAL("ShadowStateChanged"),sideStereo_glWidget.setShadowState)
          self.connect(self.glWidgets[0],QtCore.SIGNAL("AmbientOcclusionStateChanged"),sideStereo_glWidget.setAmbientOcclusionState)
          self.connect(self.glWidgets[0],QtCore.SIGNAL("ShaderStateChanged"),sideStereo_glWidget.setShaderState)

    def setStereoMatrices(self):
          if len(self.glWidgets)!=2: return

          if self.stereo_mode == 'SHEAR':
            shear_plus  = pygl_coord.matrix(4,4,[1,0,0,0,
                                             0,1,0,0,
                                             self.stereo_shear_separation,0,1,0,
                                             0,0,0,1])
            shear_minus = pygl_coord.matrix(4,4,[1,0,0,0,
                                             0,1,0,0,
                                             -self.stereo_shear_separation,0,1,0,
                                             0,0,0,1])

            matp = shear_plus.to_dp()
            matm = shear_minus.to_dp()
            self.glWidgets[0].setExtraMatrix(matp)
            self.glWidgets[1].setExtraMatrix(matm)
            self.glWidgets[0].extra_quat = pygl_coord.Quat(0.0,1.0,0.0,1,0.0)
            self.glWidgets[1].extra_quat = pygl_coord.Quat(0.0,1.0,0.0,1,0.0)
          else:
            self.glWidgets[0].setExtraMatrix(None)
            self.glWidgets[1].setExtraMatrix(None)
            self.glWidgets[0].extra_quat = pygl_coord.Quat(0.0,1.0,0.0,1,0.5*self.stereo_rotation_angle)
            self.glWidgets[1].extra_quat = pygl_coord.Quat(0.0,1.0,0.0,1,-0.5*self.stereo_rotation_angle)
	  self.glWidgets[0].updateGL()
	  self.glWidgets[1].updateGL()

    def labelPickedObject(self,pickevent):
      #print "labelPickedObject",pickevent
      if pickevent.getPickedAtoms():
        ret = PICKLABEL().addLabel(pickevent)
        #print 'MGMainWindow.labelPickedObject',ret
        if ret:
          import rebuild
          #rebuild.UpdateDisplay(target=pickevent.getDispObj(),controllingWidget=self)
          rebuild.UpdateDisplay()
        MGAPPLICATION().clipboard().setText(pickevent.getLabel(format='full'))
      #self.lastPickEvent = pickevent
      del pickevent
      
    def getLastPickEvent(self):
      return getattr(self,'lastPickEvent',None)
        
    def pickEventRecentre(self,pickevent):
      # Centre on picked atoms - check that atoms have been picked
      atoms = pickevent.getPickedAtoms()
      if atoms:
        pos = pickevent.getPickPosition()
        if pos:
          for glwidget in self.glWidgets: glwidget.centreOn(pos)

    def contextMenuHandler(self,pickevent):

        menu = pickevent.getContextMenu()
        if not menu:
            print "not menu!"
            del pickevent
            return
        menu.clear()

        # Add actions for the MGWindow class
        menudef = self.getGuiDef('context',pickevent=pickevent)
        if menudef:
          guiUtils.populateMenu(self,menu,menudef,self.getActionDef,info = { 'pickevent' : pickevent } )

        # Add actions for the picked dataobj and dispobj
        dispobj_menudef = []
        dataobj_menudef = []
        gui_disp = pickevent.getGuiObject()
        #print "MGMainWindow.contextMenuHandler guiobj",gui_disp
        if gui_disp:
          dispobj_menudef = gui_disp.getGuiDef('context',pickevent=pickevent)
        pick_dataobj = pickevent.getDataObj()
        if pick_dataobj:
          gui_data = self.MGDisplayTable.getDataObj(pick_dataobj.name)
          if gui_data:    
            dataobj_menudef = gui_data.getGuiDef('context',pickevent=pickevent)
        #print "menudef",dispobj_menudef,dataobj_menudef
          
        if dataobj_menudef:
            dataobj_menudef.insert(0,'sep')
            guiUtils.populateMenu(gui_data,menu,dataobj_menudef,gui_data.getActionDef,info = { 'pickevent' : pickevent } )
        if dispobj_menudef:
            dispobj_menudef.insert(0,'sep')
            guiUtils.populateMenu(gui_disp,menu,dispobj_menudef,gui_disp.getActionDef,info = { 'pickevent' : pickevent } )
            
        #Give open applications a chance to add to menu
        self.emit(QtCore.SIGNAL('atomContextMenu'),pickevent)

	"""
        # The stuff for QWhatsThis
        menu.addSeparator()
        whatsthis = menu.addAction(self.tr("What's this?"))
        self.connect(whatsthis,QtCore.SIGNAL("triggered(bool)"),functools.partial(QtGui.QWhatsThis.showText,self.mapToGlobal(pickevent.pos()),self.tr("The main graphics window.")))
	"""
      
        del pickevent

        
    def handleAllDataAction(self,action):
      # This method is necessary 'cos on program startup the
      # menubar is defined before the display table so DISPLAYTABLE()
      # is undefined.
      if action == 'all_data_show':
        DISPLAYTABLE().showAllDataObj(1)
      elif action == 'all_data_hide':
        DISPLAYTABLE().showAllDataObj(0)      
      elif action == 'all_disp_labels':
        for obj in get_dispobj():
          label = getattr(obj,'label',None)
          if label: label.setparams(label_select='label_no')
        import rebuild
        rebuild.UpdateDisplay()      
      elif action == 'all_disp_flashing':
        for obj in get_dispobj():
          obj.set_flashing(0)
      elif action == 'all_disp_transparency':
        for obj in get_dispobj():
          obj.set_opacity(1.0)
        import rebuild
        rebuild.UpdateDisplay()
      elif action =='all_data_close':
        rv = QtGui.QMessageBox.question(None, "Close data",
                            "Close all files?",
                            QtGui.QMessageBox.Ok,QtGui.QMessageBox.Cancel)
        if rv == QtGui.QMessageBox.Ok:
          doSideBySide = False
          doThreeWayView = False
          if len(self.glWidgets) == 2:
             self.handleSideBySide()
             doSideBySide = True
          elif len(self.glWidgets) == 3:
             self.handleThreeWayView()
             doThreeWayView = True
          DISPLAYTABLE().deleteAllDataObj()
          if doSideBySide:
             self.handleSideBySide()
          elif doThreeWayView:
             self.handleThreeWayView()
      elif action == 'all_data_picture_wizard':
        import pictureWizardGui
        pictureWizardGui.pictureWizardGui(parent=self,moldata_name='ALL')

    def createPreferencesWindows(self):
        import mgPreferences
        self.wPreferences = mgPreferences.preferencesBrowser(self)

    def showPrefsPane(self,paneText):
        if not self.wPreferences:
            self.createPreferencesWindows()
        self.wPreferences.show()
        self.wPreferences.raise_()
        items = self.wPreferences.tree.findItems(self.tr("Plugins preferences"),QtCore.Qt.MatchContains)
        if len(items)>0:
           items[0].setExpanded(True)
           for i in range(items[0].childCount()):
              if items[0].child(i).text(0) == self.tr(paneText):
                 self.wPreferences.tree.setCurrentItem(items[0].child(i))
                 break
                    
    def handlePreferences(self):
      if not self.wPreferences:
	self.createPreferencesWindows()
      self.wPreferences.show()
      self.wPreferences.raise_()
      
    def screenshotGUI(self):
     import screenshot
     screenShotGui= screenshot.screenShotGUI(self)
     screenShotGui.exec_()
        
    def handleExit(self):
      #print "MGMainWindow.handleExit"; sys.stdout.flush()
      QtGui.QApplication.instance().quit()
  
    def removeFileTypeFilter(self,filter):
       while self.extra_filters.count(filter)>0:
         self.extra_filters.pop(self.extra_filters.index(filter))

    def addFileTypeFilter(self,filter):
       if not filter in self.extra_filters:
         self.extra_filters.append(filter)

    def defaultFileTypeHandler(self,args):
      print "Don't know what to do with file",args
      return 1

    def getSaveFileTypeHandlerByFullName(self,fn):
      for key,val in self.extra_save_handlers.items():
         if fn.endswith(key):
           return val
      return self.defaultFileTypeHandler

    def directoryHandlers(self,fname):
      for dirHandler in self.directory_handlers:
        try:
          return dirHandler(fname)
        except:
          pass
      print "No directory handler for", fname
      QtGui.QMessageBox.warning(self,"Unknown directory/folder type","Directory/folder "+fname+" is not a recognised CCP4MG input.")
      return None

    def getFileTypeHandler(self,filter):
      if self.extra_handlers.has_key(filter.lower()):
        return self.extra_handlers[filter.lower()] 
      else:
        return self.defaultFileTypeHandler
      
    def addFileTypeHandler(self,filter,handler):
      self.extra_handlers[filter] = handler

    def addSaveFileTypeHandler(self,filter,handler):
      self.extra_save_handlers[filter] = handler
      
    def handlePrint(self):
      printer = QtGui.QPrinter()
      pd = QtGui.QPrintDialog(printer)
      pdret = pd.exec_()
      if pdret == QtGui.QDialog.Accepted:
        import screenshot
        rv = screenshot.makePDF(printer)

    def handleDownload(self):
      import downloadPdb
      download =  self.findChild(downloadPdb.downloadPdb)
      if download:
        download.resetSelection()
        download.show()
      else:
        download_open = downloadPdb.downloadPdb(parent=self)
        download_open.show()

    def handleOpen(self):
        gui_open = guiOpen(parent=self)
        if hasattr(self,'extra_filters'):
          gui_open.addFilters(self.extra_filters)
        self.connect(gui_open,QtCore.SIGNAL('filesSelected'),self.openFile)
        gui_open.exec_()

    def handleFileViewer(self):
      viewer =  FILEVIEWER()
      viewer.show()
      viewer.raise_()
      """
      if not hasattr(self,'viewer'):
        import mgFileViewer
        self.viewer = mgFileViewer.mgFileViewer(self)
      self.viewer.show()
      self.viewer.raise_()
      """
      
    def handleSuperpose(self):
      if not hasattr(self,'superpose'):
        import superposeGui
        self.superpose = superposeGui.superposeWindow(self)
      else:
        self.superpose.UnClose()
      self.superpose.show()
      
    def openTransparency(self):
      
      if not hasattr(self,'transparencyGui') or not self.transparencyGui:
        import TransparencyDialog
        self.transparencyGui = TransparencyDialog.TransparencyDialog(self)
      self.transparencyGui.UnClose()

    def openAnimation(self,mode):
      
      if not hasattr(self,'animationGui') or not self.animationGui:
        import animationGui
        self.animationGui = animationGui.animationGui(self)
      self.animationGui.show()
      self.animationGui.raise_()

    def handleAnimationGui(self,mode):
      if mode == 'animate_enabled':
        if not hasattr(self,'animationGui') or not self.animationGui or \
                                        self.animationGui.numberOfFrames(selected=1)<2:
          return 0
        else:
          return 1
      elif mode == 'animate_on':
        if not hasattr(self,'animationGui') or not self.animationGui:
          return 0
        else:
          return self.animationGui.presentation.animation_on
      elif mode == 'animate':
        if not hasattr(self,'animationGui') or not self.animationGui: return
        widget = self.findChild(QtGui.QAction,'animate')
        if widget:
          self.animationGui.presentation.animate(widget.isChecked())

    def handlePresentation(self,mode='open_presentation'):
      import string
      mode,application= string.split(mode,'_')
      gui_open = guiOpenPresentation(parent=self,mode=mode,application=application)
      self.connect(gui_open,QtCore.SIGNAL('filesSelected'),self.openPresentation)
      gui_open.exec_()

    def openPresentation(self,file='',application='presentation',**kw):
      #print "openPresentation",file,application
      if not file.endswith(".ccp4mg_presentation") and not file.endswith(".ccp4mg_presentation.zip") :
          file = file+".ccp4mg_presentation"

      # Open the application (from python/ui)
      import presentation,mgPresentation
      p = presentation.open_presentation(file)
      #print "openPresentation p,open guis",p,self.findChildren(mgPresentation.mgPresentation)

      # Is there a gui to this presentation already open?
      if not p: return
      
      for gui in self.findChildren(mgPresentation.mgPresentation):
        if gui.presentation == p:
          gui.show()
          return

      # Close the selection gui (do this before opening movie gui or mac puts movie
      # beneath main window
      for item in self.findChildren(guiOpenPresentation):
        item.close()
       
      # Create gui for this presentation
      if os.path.exists(os.path.join(file,"PRESENTATION_TYPE")):
        try:
          os.unlink(os.path.join(file,"PRESENTATION_TYPE"))
        except:
          exc_type, exc_value,exc_tb = sys.exc_info()[:3]
          print "Do not seem to have write permission on presentation directory",file
          sys.stderr.write(str(exc_type)+'\n')
          sys.stderr.write(str(exc_value)+'\n')

      if application == 'movie':
        import movieGui
        gui = movieGui.movieGui(self,presentation=p)
        if not os.path.exists(os.path.join(file,"PRESENTATION_TYPE")): # It *should* have been deleted above.
          ptf = open(os.path.join(file,"PRESENTATION_TYPE"),"wb")
          ptf.write("movie\n")
          ptf.close()
      elif application == 'animation':
        import animationGui
        gui = animationGui.animationGui(self,presentation=p)
        if not os.path.exists(os.path.join(file,"PRESENTATION_TYPE")):
          ptf = open(os.path.join(file,"PRESENTATION_TYPE"),"wb")
          ptf.write("animation\n")
          ptf.close()
      else:
        gui = mgPresentation.mgPresentation(self,presentation=p)
        if os.path.isdir(file):
          if not os.path.exists(os.path.join(file,"PRESENTATION_TYPE")):
            ptf = open(os.path.join(file,"PRESENTATION_TYPE"),"wb")
            ptf.write("presentation\n")
            ptf.close()
        elif file.endswith(".zip") and os.path.exists(file[:-4]):
          if not os.path.exists(os.path.join(file[:-4],"PRESENTATION_TYPE")):
            ptf = open(os.path.join(file[:-4],"PRESENTATION_TYPE"),"wb")
            ptf.write("presentation\n")
            ptf.close()
          
      gui.show()
          

    def createObject(self,object_type = ''):
      
      #print "createObject",object_type
      if object_type == 'legend':
        import Legend
        legend = Legend.Legend(parent=GL2DMANAGER(),name='Legend')
        self.MGDisplayTable.addDispObj(object_type='Legend',name=legend.name,parent_name = GL2DMANAGER().name)
        import rebuild
        rebuild.UpdateDisplay()
      elif object_type == 'crystal':
        import Crystal
        xtl = CRYSTALMANAGER().add_object()
        self.MGDisplayTable.addDispObj(object_type='Crystal',name=xtl.name)

      elif object_type == 'vectors':
        import VectorsDispobj
        dobj = VectorsDispobj.VectorsData()
        disp = VectorsDispobj.VectorsDispobj(parent=dobj.name,visible=1)
        gui_obj = self.MGDisplayTable.addDataObj(object_type='VectorsData',name=dobj.name)
        gui_obj.editVector()

        
        
#-------------------------------------------------------------------
    def openFile(self,file='',drawing_style='',use_current_style=0,show_wizard_choices=0,filter='',pasteAtCursor=False,setDefaultDirectory=True,mgpic_file='',customResCIFFiles={}):
#-------------------------------------------------------------------
       if setDefaultDirectory:
          #print "set directory to",os.path.dirname(file)
          mgWidgets.MGFileDialog.last_directory = os.path.dirname(file)
       # This should be calling functions from appropariate data modules!!
       import rebuild,MGGLImage
        
       if not os.path.exists(file): return 2
       ext = os.path.splitext(file)[1][1:].lower()
       extgz = None
       if ext == 'gz':
          ext2 = os.path.splitext(os.path.splitext(file)[0])[1]
          if ext2 != '':
             extgz = (ext2 + '.' + ext)[1:].lower()

       '''
       dir_alias = CCP4DATABASE().aliasForDir(os.path.split(file)[0])
       if dir_alias:
         file_list_def = [dir_alias,os.path.split(file)[1],file]
       else:
         file_list_def = ['FULLPATH',file,file]
       print 'openFile ccp4 alias',file,dir_alias,file_list_def
       '''

       if file.endswith('.ccp4mg_presentation.zip'):
         self.openPresentation(file,"presentation")
         return
       if file.endswith('.ccp4mg_presentation'):
         if os.path.exists(os.path.join(file,"PRESENTATION_TYPE")):
           ptf = open(os.path.join(file,"PRESENTATION_TYPE"))
           pres_type = ptf.read().strip()
           ptf.close()
           if pres_type in ["movie","presentation","animation"]:
             idx = ["movie","presentation","animation"].index(pres_type)
             self.openPresentation(file,["movie","presentation","animation"][idx])
             return
         print "Maybe a presentation, animation or movie ...."
         dialog = MoviePresQuestion(self)
         dialog.setWindowTitle("Open presentation/movie/animation")
         rt = dialog.exec_()
         if rt>-1 and rt < 3:
           self.openPresentation(file,["movie","presentation","animation"][rt])
         return
       if file.endswith('.mgpic.py') or file.endswith('.pkl'):
         self.loadStatusFile(file,restore_status=1,restore_view=1)
         return

       nvis = 0
       if ext in ['map']:
          theDataobjs = get_dataobj(object_type='MolData')
          nvis = 0
          for obj in theDataobjs:
            if hasattr(obj,"visible"):
              if obj.visible:
                for dispobj in obj.get_dispobj('MolDisp'):
                    if hasattr(dispobj,"visible"):
                      if dispobj.visible:
                        nvis = nvis + 1
          mapdispobjs = get_dispobj(object_type =['MapDisp'])
          for dispobj in mapdispobjs:
            if hasattr(dispobj.parent,"is_em_map") and dispobj.parent.is_em_map and dispobj.visible and dispobj.parent.visible:
              nvis = nvis + 1

       if ext in ['ent','brk','pdb','cif'] or extgz in ['ent.gz','brk.gz','pdb.gz','cif.gz']:
          if extgz:
             file = utils.gunzipToNamedFile(file)

          if (not drawing_style and not mgpic_file) and use_current_style:
             drawing_style = PICTUREWIZARD().default_drawing_style    

          if not show_wizard_choices and not mgpic_file:
            # Test if this drawing_style absolutely requires user input (if so will return show_wizard_choices = 1)
            show_wizard_choices,choices = PICTUREWIZARD().read_mgpic_file_choices(drawing_style=drawing_style)
          #print "openFile drawing_style",show_wizard_choices,drawing_style
          theDataobjs = get_dataobj(object_type='MolData')
          nvis = 0
          for obj in theDataobjs:
            if hasattr(obj,"visible"):
              if obj.visible:
                for dispobj in obj.get_dispobj('MolDisp'):
                    if hasattr(dispobj,"visible"):
                      if dispobj.visible:
                        nvis = nvis + 1
          mapdispobjs = get_dispobj(object_type =['MapDisp'])
          for dispobj in mapdispobjs:
            if hasattr(dispobj.parent,"is_em_map") and dispobj.parent.is_em_map and dispobj.visible and dispobj.parent.visible:
              nvis = nvis + 1
          
          import model
          rv,m = model.openpdbfile( file,customResCIFFiles=customResCIFFiles )
          print "openpdbfile ret",rv,m
          if rv and rv != model.MolData.NO_ATOMS_IN_CIF_FILE:
            print "Error opening file",file
            return 1
          
          if rv == model.MolData.NO_ATOMS_IN_CIF_FILE and (file.lower().endswith('.cif') or file.lower().endswith('.cif.gz')):
            print "This is not a coordinate cif file, maybe a reflection list?"
            # Is it supported by a plugin?
            suffix = file[file.rfind('.')+1:]
            handler = MAINWINDOW().getFileTypeHandler(suffix)
            #print "openFile handler",handler
            return handler(file)

          self.addToRecentList(file)
          if show_wizard_choices:
            import pictureWizardGui
            gui = pictureWizardGui.pictureWizardGui(MAINWINDOW(),drawing_style=drawing_style,moldata_name=m.name,recentreIfOnlyOne=True)
          else:  
            m.applyDrawingStyle(drawing_style=drawing_style,mgpic_file=mgpic_file)
             
          DISPLAYTABLE().emit(QtCore.SIGNAL("applyWizard"))
          m_gui = DISPLAYTABLE().addDataObj(object_type='MolData',name=m.name,label=m.name_label)
          if hasattr(m_gui,"toggleBodyVisibility") and self.defaultObjBodyVisibility != "open_all":
            m_gui.toggleBodyVisibility(updateWidth=0)
          DISPLAYTABLE().emit(QtCore.SIGNAL("finishedApplyWizard"))
          rebuild.UpdateDisplay()
          #print "MGMainWindow.openFile nvis",nvis
          if nvis == 0:
             MAINWINDOW().handleRecentre(glide=0)
             selection = 'all'
             rv = m.parse_selection(command=selection)
             if rv[0] == 0 and rv[1] > 0:
               selHnd = rv[1]

               tmp = pygl_coord.doublea(1)
               rtde =  tmp.frompointer(mmdb.realtype_to_double(m.molHnd.Extent(selHnd)))
               mine,maxe = (rtde[0],rtde[1],rtde[2]),(rtde[3],rtde[4],rtde[5])
               mide = ((mine[0]+maxe[0])/2.,(mine[1]+maxe[1])/2.,(mine[2]+maxe[2])/2.)
               theSize = max(abs(mine[0]-maxe[0]),abs(mine[1]-maxe[1]),abs(mine[2]-maxe[2]))
               if hasattr(self,"glWidget"):
                 self.glWidget.setZoom(theSize*2.5*1.25)


       elif ['map'].count(ext) or ['map.gz'].count(extgz):
         if extgz:
           file = utils.gunzipToNamedFile(file)
         import map
         m = map.MapData(filename=file,filetype='MAP')
         emMap = False
         if QtGui.QMessageBox.question(self,"EM or Xtal map","Is this an EM map?",buttons=QtGui.QMessageBox.Yes|QtGui.QMessageBox.No) == QtGui.QMessageBox.Yes:
           print "EM map!!"
           emMap = True
         m.loaddata(emMap=emMap)
         m.create_contours()
         m_gui = DISPLAYTABLE().addDataObj(object_type='MapData',name=m.name,label=m.name_label)
         xtl = CRYSTALMANAGER().add_object()
         xtl.set_source(m.name)
         DISPLAYTABLE().addDispObj(parent_name=CRYSTALMANAGER().name,object_type='Crystal',name=xtl.name)
         rebuild.UpdateDisplay()
         self.addToRecentList(file)
         if nvis == 0:
            MAINWINDOW().handleRecentre(glide=0)
            radius = m.clipper_map.GetMaxDim()
            self.glWidget.setZoom(radius*2.5*1.25)

       elif  ['vector'].count(ext):
         # Assume it is a vector file for now
         import VectorsDispobj
         m = VectorsDispobj.openvectorfile(file)
         if m:
           m_gui = DISPLAYTABLE().addDataObj(object_type='VectorsData',name=m.name,label=m.name_label)  
           rebuild.UpdateDisplay()
           
       elif MGGLImage.supportedReadFormats().count(ext) and ext != "svg":
           if pasteAtCursor:
             xfrac,yfrac = self.getGLWidgetFractionalCursorPosition()
             m = MGGLImage.Image(filename = str(file),parent=GL2DMANAGER(),params={"x":xfrac,"y":yfrac})
           else:
             m = MGGLImage.Image(filename = str(file),parent=GL2DMANAGER())
           if m.isValid:
             m_gui =  DISPLAYTABLE().addDispObj(object_type='Image',name=m.name,parent_name ='Legends&Images')
             rebuild.UpdateDisplay()
           
       elif os.path.isdir(file):
         return self.directoryHandlers(file)
       elif file.find('.') > -1:
         # Is it supported by a plugin?
         suffixes = getSuffixes(file)
         for suffix in suffixes:
           handler = MAINWINDOW().getFileTypeHandler(suffix)
           if not handler == self.defaultFileTypeHandler:
              break
         #print "openFile handler",handler
         return handler(file)

       else:
         # Nothing matched..
           return 1
         
       return 0

    def addToRecentList(self,f):
      settings = QtCore.QSettings("CCP4","CCP4MG")
      recentFiles = settings.value("recentFileList").toStringList()
      if not f in recentFiles:
        recentFiles.prepend(f)
      recentFiles = recentFiles[:5]
      settings.setValue("recentFileList",QtCore.QVariant(recentFiles))
      settings.sync()
      self.setupRecentList()

    def setupRecentList(self):
      settings = QtCore.QSettings("CCP4","CCP4MG")
      recentFiles = settings.value("recentFileList").toStringList()
      recentFiles = list(set(list(recentFiles)))
      recentFiles = sorted(recentFiles)
      self.recentFilesList = ['Recent files']
      for fnew in recentFiles:
         bn = os.path.basename(str(fnew.toUtf8()))
         if os.path.isfile(str(fnew.toUtf8())) is False:
           continue
	 if sys.platform != "win32":
           import uuid
           uuid._uuid_generate_time = None
           uuid._uuid_generate_random = None

           uuid_str = uuid.uuid4().get_hex()
	 else:
           import msilib
           uuid_str = msilib.gen_uuid().strip('{').strip('}').replace('-','')

         self.actionDefinitions[uuid_str] = dict (text=str(fnew.toUtf8()),shortcut = '',signal = 'triggered()',slot = functools.partial(self.openFile,str(fnew.toUtf8()),use_current_style=1,show_wizard_choices=0))
         self.recentFilesList.append(uuid_str)
      #self.menuDefinitions['_file_open'] = ['open',self.recentFilesList,'_file_download','restore_status_from_file',['Edit/show presentation','new_presentation','open_presentation','zip_presentation']]
      self.menuDefinitions['_file_open'] = ['open',self.recentFilesList,'_file_download',['Edit/show presentation','new_presentation','open_presentation','zip_presentation']]
             
#-------------------------------------------------------------------
    def saveStatusFile(self,file='',saved_status=None):
#-------------------------------------------------------------------
      if not file: return
      ext = os.path.splitext(file)[1][1:]

      # This almost certainly should be elsewhere, I guess. Probably should 
      # emit a signal here and have this in a slot.
      #
      # Make sure we save vectors somewhere when we save status.
      vecs = get_dataobj(object_type='VectorsData')
      ccp4mg_dir = utils.get_CCP4MG()
      if sys.platform != "win32":
        import uuid
        uuid._uuid_generate_time = None
        uuid._uuid_generate_random = None
        uuid_str = uuid.uuid4().get_hex()
      else:
        import msilib
        uuid_str = msilib.gen_uuid().strip('{').strip('}').replace('-','')
      newDir = os.path.join(ccp4mg_dir,uuid_str)
      ivec = 0
      for vec in vecs:
        if hasattr(vec,"filename") and vec.filename and len(vec.filename)>2 and vec.filename[0] and vec.filename[1] and vec.filename[2]:
          print vec.filename
          vec.save_file(vec.filename[2])
        else:
          print "vectors have no filename!"
          try:
            os.makedirs(newDir)
          except:
            pass
          newFName = os.path.join(newDir,"Vectors_"+str(ivec)+".vector")
          print "Trying to save",newFName
          vec.save_file(newFName)
          """
          try:
            newFName = os.path.join(newDir,"Vectors_"+str(ivec)+".vector")
            print "Trying to save",newFName
            vec.savefile(newFName)
          except:
            pass
          """
        ivec = ivec + 1

      if ext == 'pkl':
        if saved_status:
          rv = HISTORY().write_pickle_file(filename=file,status=saved_status)
          if rv:
            QtGui.QMessageBox.warning(self,'Error saving status file','Error writing file '+file)
        else:
          HISTORY().save_status(filename=file)
      elif file.endswith('.mgpic.py'):
        PICTUREDEFINITION().save_picture_definition(filename=file)
      else:
        handler = MAINWINDOW().getSaveFileTypeHandlerByFullName(file)
        handler(file)

#-------------------------------------------------------------------
    def loadStatusFile(self,file='',status={},restore_status=-1,restore_view=-1,remove=-1):
#-------------------------------------------------------------------
      #if remove<0: remove = int(self.remove.isChecked())

      if os.path.splitext(file)[1] == '.pkl':
        print 'loadStatusFile',file,restore_status,restore_view
        rv = HISTORY().get_status_data_files(filename=file)
        if rv[0]<0:
          QtGui.QMessageBox.warning(self,'Error reading status file',rv[1])
          return
        elif rv[0]:
          hints = [utils.get_HOME()]
          if file:
            hints.append(os.path.split(file)[0])
          nLost,objList,fileDef,nFound = HISTORY().get_status_data_files(file,hints)
          if nLost == nFound:
            status_new =  HISTORY().edit_status_data_files(file,1,objList,fileDef)
            if restore_status:
              DISPLAYTABLE().deleteAllDataObj()
            exclude_list = []
            if not restore_view: exclude_list = ['view']
            rv3 = HISTORY().restore_status(restore_data=1,filename='',status=status_new,exclude_list=exclude_list)
            if restore_status:
              DISPLAYTABLE().loadAllDataObj()
              import rebuild
              rebuild.UpdateDisplay()
            DISPLAYTABLE().update(all=1) # Stops a wierd bug whereby first name label is blank.
            return
          import statusGui
          lostGui = statusGui.lostFilesGui(self,file)
          rv2 = lostGui.exec_()
          if rv2 == QtGui.QDialog.Accepted:
            objList,fileDefn = lostGui.getFiles()
            status_new =  HISTORY().edit_status_data_files(file,1,objList,fileDefn)
            if restore_status:
              DISPLAYTABLE().deleteAllDataObj()
            exclude_list = []
            if not restore_view: exclude_list = ['view']
            rv3 = HISTORY().restore_status(restore_data=1,filename='',status=status_new,exclude_list=exclude_list)
            if restore_status:
              DISPLAYTABLE().loadAllDataObj()
              import rebuild
              rebuild.UpdateDisplay()
              theDataobjs = get_dataobj(object_type='MolData')
              for theDO in theDataobjs:
                if hasattr(theDO,"filename"):
                  theName = os.path.basename(os.path.splitext(theDO.filename[2])[0])
                  if theName:
                    gdo = DISPLAYTABLE().getDataObj(theDO.name)
                    theDO.renameuniquename(theName,theDO.name)
                    gdo.updateLabel() 
              DISPLAYTABLE().update(all=1) # Stops a wierd bug whereby first name label is blank.
              retval = QtGui.QMessageBox.question(self,
                    'Save status file',                              
                    'Save the status with new data file names?\n',
                     QtGui.QMessageBox.Save|QtGui.QMessageBox.Cancel)
              if retval == QtGui.QMessageBox.Cancel: return
                
              saveGui = statusGui.guiSaveStatus(self)
              title = 'Save updated status from file: '+os.path.split(file)[1]
              saveGui.setWindowTitle(title)
              saveGui.fileDialog.selectFile(file)
              self.connect(saveGui,QtCore.SIGNAL('filesSelected'),self.saveStatusFile)
              rv4 = saveGui.exec_()
            return
          else:
            return
        
      if restore_status:
        DISPLAYTABLE().deleteAllDataObj()
	self.emit(QtCore.SIGNAL("RestoringFile"))
    
      if os.path.splitext(file)[1] == '.pkl' or status:
        if restore_status:
           exclude_list = []
           if not restore_view: exclude_list = ['view']
           rv = HISTORY().restore_status(restore_data=1,filename=file,status=status,exclude_list=exclude_list)
        elif restore_view:
           rv = HISTORY().restore_view(filename=file,status=status)
           if rv == 1:
             QtGui.QMessageBox.warning(self,'Error reading status file','Error reading '+file)
             return
           elif rv == 2:
             QtGui.QMessageBox.warning(self,'Error reading status file','No data in file '+file)
             return
      elif os.path.splitext(file)[1] == '.py':
        PICTUREDEFINITION().restore_picture_definition(filename=file,keep_current=1)
      else:
        self.openFile(file,use_current_style=1)
        return

      if restore_status:
        DISPLAYTABLE().loadAllDataObj()
        import rebuild
        rebuild.UpdateDisplay()
	self.emit(QtCore.SIGNAL("RestoredFile"))
     
    def handleRestore(self):
     import statusGui
     gui_open = statusGui.guiRestore(parent=self)
     self.connect(gui_open,QtCore.SIGNAL('filesSelected'),self.loadStatusFile)
     gui_open.exec_()
       
    def handleSaveStatus(self):
     import statusGui
     gui_open = statusGui.guiSaveStatus(parent=self)
     self.connect(gui_open,QtCore.SIGNAL('filesSelected'),self.saveStatusFile)
     gui_open.exec_()


    def handleCopyClipboard(self):
      import screenshot
      print "copy"
      QtGui.QApplication.instance().clipboard().clear()
      import MGApplication
      app = MGApplication.QtApp()
      fw = app.focusWidget()
      if hasattr(fw,"hasSelectedText") and callable(fw.hasSelectedText) and fw.hasSelectedText() and hasattr(fw,"selectedText") and callable(fw.selectedText):
        QtGui.QApplication.instance().clipboard().setText(fw.selectedText())
        return
      size = [self.glWidget.size().width(),self.glWidget.size().height()]
      dpi=72
      pm = PM("screenshot_preferences")
      tfile = tempfile.NamedTemporaryFile(suffix=".png",prefix="ccp4mg"+str(os.getpid()),delete=False)
      name = tfile.name
      tfile.close()
      os.unlink(name)
      if sys.platform == "darwin" and QtOpenGL.QGLFramebufferObject.hasOpenGLFramebufferObjects():
        print "Using FBOs"
        rv = screenshot.makeScreenshot(filename=name,size=size,dpi=dpi,use_pbuffer=True)
      else:
        rv = screenshot.makeScreenshot(filename=name,size=size,dpi=dpi)
      pix = QtGui.QPixmap(name)
      QtGui.QApplication.instance().clipboard().setPixmap(pix)

    def handleRecentre(self,glide=1,**args):
       # Note that we are *not* looping over widgets!
       # This is because default slot for PositionChanged signal
       # is to move others. This behaviour will change.
 
       try:
        self.centre_mode = PM('centre_mode').getparams()['centre_method']
       except:
        self.centre_mode = self.CENTRE_MODE_EXTENTS

       total_mass = 0.0 
       total_maxe = [-1e+7,-1e+7,-1e+7]
       total_mine = [1e+7,1e+7,1e+7]
       for widget in self.glWidgets[0:1]:
         origins = pygl_coord.CartesianVector()
         dispobjs = get_dispobj(object_type =['MolDisp'])

         mapdispobjs = get_dispobj(object_type =['MapDisp'])
         for dispobj in mapdispobjs:
           if hasattr(dispobj.parent,"is_em_map") and dispobj.parent.is_em_map and dispobj.visible and dispobj.parent.visible:
             map_orig_cart = dispobj.parent.clipper_map.GetOrigin()
             map_orig = (map_orig_cart.get_x(),map_orig_cart.get_y(),map_orig_cart.get_z())
             radius = dispobj.parent.clipper_map.GetMaxDim()
             if self.centre_mode != self.CENTRE_MODE_EXTENTS:
               if self.centre_mode == self.CENTRE_MODE_COORDS:
                 mass = 1.0 # FIXME - we could have a sensible approximation here, based on size.
                 total_mass = total_mass + mass
               elif self.centre_mode == self.CENTRE_MODE_MASS:
                 mass = 1.0 # FIXME - we could have a sensible approximation here, based on size.
                 total_mass = total_mass + mass
               else:
                 return # In case self.centre_mode is junk value.
               origins.append(map_orig_cart*mass)
             if self.centre_mode == self.CENTRE_MODE_EXTENTS:
               mine_c = map_orig_cart - pygl_coord.Cartesian(radius,radius,radius)
               maxe_c = map_orig_cart + pygl_coord.Cartesian(radius,radius,radius)
               maxe = (maxe_c.get_x(), maxe_c.get_y(), maxe_c.get_z())
               mine = (mine_c.get_x(), mine_c.get_y(), mine_c.get_z())
               if (mine[0]) < total_mine[0]: total_mine[0] = mine[0]
               if (mine[1]) < total_mine[1]: total_mine[1] = mine[1]
               if (mine[2]) < total_mine[2]: total_mine[2] = mine[2]
               if (maxe[0]) > total_maxe[0]: total_maxe[0] = maxe[0]
               if (maxe[1]) > total_maxe[1]: total_maxe[1] = maxe[1]
               if (maxe[2]) > total_maxe[2]: total_maxe[2] = maxe[2]
             
         for dispobj in dispobjs:
		if hasattr(dispobj,"visible") and hasattr(dispobj,"parent") and hasattr(dispobj.parent,"visible") and dispobj.visible and dispobj.parent.visible:
			if hasattr(dispobj,"SelHandle") and hasattr(dispobj.SelHandle,"getSelHnd") and callable(dispobj.SelHandle.getSelHnd) and hasattr(dispobj.parent,"molHnd") and hasattr(dispobj.parent.molHnd,"CentreOfMass") and callable(dispobj.parent.molHnd.CentreOfMass): # Overly careful?
				if self.centre_mode != self.CENTRE_MODE_EXTENTS:
					if self.centre_mode == self.CENTRE_MODE_COORDS:
						rtd =  mmdb.realtype_to_double(dispobj.parent.molHnd.CentreOfCoordinates(dispobj.SelHandle.getSelHnd()))
						mass = dispobj.parent.molHnd.NumberOfAtoms(dispobj.SelHandle.getSelHnd())
					elif self.centre_mode == self.CENTRE_MODE_MASS:
						rtd =  mmdb.realtype_to_double(dispobj.parent.molHnd.CentreOfMass(dispobj.SelHandle.getSelHnd()))
						mass = dispobj.parent.molHnd.Mass(dispobj.SelHandle.getSelHnd())
					else:
						return # In case self.centre_mode is junk value.
					total_mass = total_mass + mass
					cart = pygl_coord.Cartesian(rtd) * mass
					origins.append(cart)
				if self.centre_mode == self.CENTRE_MODE_EXTENTS:
					tmp = pygl_coord.doublea(1)
					rtde =  tmp.frompointer(mmdb.realtype_to_double(dispobj.parent.molHnd.Extent(dispobj.SelHandle.getSelHnd())))
					mine,maxe = (rtde[0],rtde[1],rtde[2]),(rtde[3],rtde[4],rtde[5])
					if hasattr(dispobj,"doBiomolecule") and dispobj.doBiomolecule and hasattr(dispobj.parent,"molHnd"):
						matrices = dispobj.parent.molHnd.GetBiomoleculeAsMatrices(0,1);
						mide = ((mine[0]+maxe[0])/2.,(mine[1]+maxe[1])/2.,(mine[2]+maxe[2])/2.)
						for mat in matrices:
							midet = mat * pygl_coord.Cartesian(mide)
							if (midet.get_x()) < total_mine[0]: total_mine[0] = midet.get_x()
							if (midet.get_y()) < total_mine[1]: total_mine[1] = midet.get_y()
							if (midet.get_z()) < total_mine[2]: total_mine[2] = midet.get_z()
							if (midet.get_x()) > total_maxe[0]: total_maxe[0] = midet.get_x()
							if (midet.get_y()) > total_maxe[1]: total_maxe[1] = midet.get_y()
							if (midet.get_z()) > total_maxe[2]: total_maxe[2] = midet.get_z()
					else:
						if (mine[0]) < total_mine[0]: total_mine[0] = mine[0]
						if (mine[1]) < total_mine[1]: total_mine[1] = mine[1]
						if (mine[2]) < total_mine[2]: total_mine[2] = mine[2]
						if (maxe[0]) > total_maxe[0]: total_maxe[0] = maxe[0]
						if (maxe[1]) > total_maxe[1]: total_maxe[1] = maxe[1]
						if (maxe[2]) > total_maxe[2]: total_maxe[2] = maxe[2]

	 if self.centre_mode == self.CENTRE_MODE_EXTENTS:
	 	mide = ((total_mine[0]+total_maxe[0])/2.,(total_mine[1]+total_maxe[1])/2.,(total_mine[2]+total_maxe[2])/2.)
         	widget.centreOn(mide,glide=glide)
	 	return

	 if len(origins)>0:
	   total_o = pygl_coord.Cartesian(0,0,0)
	   for o in origins:
	     total_o = total_o + o
           mid =  total_o/float(total_mass)
           widget.centreOn([mid.get_x(), mid.get_y(), mid.get_z()],glide=glide)
         

#-------------------------------------------------------------------
    def handleCentreOn(self):
#-------------------------------------------------------------------
      gui = self.findChild(guiCentreOn)
      if gui:
        print "CentreOn gui already open"
        gui.show()
      else:
        MolData_list = get_dataobj(object_type = 'MolData')
        if MolData_list:
          gui = guiCentreOn(parent=self)
        else:
          print "No loaded PDB"


#-------------------------------------------------------------------
    def centreOn(self,position=[],molHnd=None,selHnd=-1):
#-------------------------------------------------------------------
      import mmdb2 as mmdb
      import mmut

      #print "centreOn position",position,molHnd

      if position:
        xx,yy,zz = position
      else:
        selindexp = pygl_coord.intp()
        SelAtoms = mmdb.newPPCAtom()
        #nSelAtoms = molHnd.GetSelIndex (selHnd,SelAtoms)
        SelAtoms = mmut.GetAtomSelIndex(molHnd,selHnd,selindexp)
        nSelAtoms = selindexp.value()
        if nSelAtoms <= 0: return
        #print nSelAtoms; sys.stdout.flush()
        xx = 0.0
        yy = 0.0
        zz = 0.0
        for n in range(0,nSelAtoms):
          pAtom = mmdb.getPCAtom(SelAtoms,n)
          xx = xx + pAtom.x
          yy = yy + pAtom.y
          zz = zz + pAtom.z
        xx = xx/nSelAtoms
        yy = yy/nSelAtoms
        zz = zz/nSelAtoms
      #print "centreOn xx,yy,zz",xx,yy,zz
      #new_centre = pygl_coord.CartesianPtr([xx,yy,zz])
      self.glWidget.centreOn([xx,yy,zz])

          
    def dragEnterEvent(self, event):
      event.accept()

    def dragMoveEvent(self, event):
      event.accept()

    def DealWithOpenFileEvent(self,file):
       self.openFile(str(file.toAscii()),use_current_style=1)
       '''
       rc = self.pdb.load_file(str(file.toAscii()))
       go = ''
       if not rc:
         go = DrawConnectivity(self.pdb.Connectivity,self.pdb.molHnd,self.pdb.selHnd,self.pdb.nSelAtoms)
         if go: self.glWidget.SetGO(go,1)
       '''
       
    def getGLWidgetFractionalCursorPosition(self):
        widgetPos = self.glWidget.mapFromGlobal(QtGui.QCursor.pos())
        widgetSize = self.glWidget.size()
        xfrac = float(widgetPos.x())/widgetSize.width()
        yfrac = 1.0-float(widgetPos.y())/widgetSize.height()
        if xfrac >=1 or xfrac <0 or yfrac >=1 or yfrac < 0:
          xfrac = 0
          yfrac = 0
        xfrac = min(0.9, xfrac)
        yfrac = min(0.9, yfrac)
        return xfrac,yfrac

    def DealWithMimeData(self,mimeData,pasteAtCursor=False):
        if mimeData.hasImage():
          ccp4mg_dir = utils.get_CCP4MG()
          if ccp4mg_dir != "":
            tfile = tempfile.NamedTemporaryFile(suffix=".png",prefix="ccp4mg"+str(os.getpid()),delete=False,dir=ccp4mg_dir)
          else:
            tfile = tempfile.NamedTemporaryFile(suffix=".png",prefix="ccp4mg"+str(os.getpid()),delete=False)
          name = tfile.name
          tfile.close()
          os.unlink(name)
          image = QtGui.QImage(mimeData.imageData())
          image.save(name)
          rv = self.openFile(name,use_current_style=1,pasteAtCursor=pasteAtCursor)
          print "Save clipboard image to",name

        if mimeData.hasText() and not mimeData.hasUrls():
          import Legend
          if pasteAtCursor:
            xfrac,yfrac = self.getGLWidgetFractionalCursorPosition()
            legend = Legend.Legend(parent=GL2DMANAGER(),name='Legend',params={"x":xfrac,"y":yfrac})
          else:
            legend = Legend.Legend(parent=GL2DMANAGER(),name='Legend')
          self.MGDisplayTable.addDispObj(object_type='Legend',name=legend.name,parent_name = GL2DMANAGER().name)
          legend.set_text("<p>"+str(mimeData.text().toUtf8()).replace("\n","</p><p>")+"</p>")
          import rebuild
          rebuild.UpdateDisplay()
      
	rv = 0
	for url in mimeData.urls():
		self.DealWithUrl(url,pasteAtCursor=pasteAtCursor)
	return rv
    
    def DealWithUrl(self,url=None,pasteAtCursor=False):
      print url
      def downloaded(fname=None,dlfname=None):
         if not dlfname:
            return
         def handler(dlfname=None,fname=None):
             shutil.copy2(dlfname,fname)
             self.openFile(fname,use_current_style=1)
         filters = ["Model coordinate files (*.pdb *.cif *.ent *.brk *.pdb.gz *.cif.gz *.ent.gz *.brk.gz)"]
         filters.extend(self.customDownloadFilterTypes)
         fd = mgWidgets.MGSaveFileDialog(self,filters=filters, defaultFileName=fname)
         fd.setWindowTitle("Save "+fname)
         self.connect(fd,QtCore.SIGNAL('save'),guiUtils.partialWithSignal(handler,dlfname))
         self.connect(fd,QtCore.SIGNAL('save'),fd.close)
         fd.setModal(True)
         fd.show()
      if str(url.scheme())=='file':
          rv = self.openFile(str(url.toLocalFile().toUtf8()),use_current_style=1,pasteAtCursor=pasteAtCursor,setDefaultDirectory=True)
      else:
          import downloadPdb, UtilityThread
          dpdb = downloadPdb.downloadPdbCore()
          self.connect(dpdb,QtCore.SIGNAL("DownloadFinished"),guiUtils.partialWithSignal(downloaded,os.path.basename(str(url.path()))))
          downloadThread = UtilityThread.UtilityThread(functools.partial(dpdb.downloadMain,str(url.toString())))
          self.downloadThreads.append(downloadThread)
          self.connect(downloadThread,QtCore.SIGNAL("finished()"),functools.partial(self.downloadThreads.remove,downloadThread))
          downloadThread.start()

    def handleHelp(self):
      HELPBROWSER().loadMgHelp('index.html')
      
    def openPDF(self,f):
      QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(f))

    def getHelpBrowser(self):
         
      # Presently this is called from global_definitions.HELPBROWSER
      # to create one instance of MGBrowserWindow to show help text
      if not hasattr(self,'helpGui'):
        import MGWebBrowser
        self.helpGui = MGWebBrowser.MGBrowserWindow()
	self.connect(self.helpGui,QtCore.SIGNAL("CustomMimeTypeRequested"),self.DealWithUrl)
        self.helpGui.setCustomMimeTypes(["pdb","mtz","ent","zip","pdf"])
        self.addFileTypeHandler("pdf",self.openPDF)
        self.helpGuiD = MGSimpleDialog.MGSimpleDockDialog(defaultDockArea=QtCore.Qt.RightDockWidgetArea,tabify=False)
        self.helpGuiD.dockWidget.setWidget(self.helpGui)
        self.helpGuiD.dockWidget.setWindowTitle('CCP4mg Browser')
        # Set this slightly offset from main window - otherwise usually totally obscures main window
        #self.helpGui.move( self.x()+10, self.y()-10)
      self.helpGui.show()
      self.helpGuiD.UnClose()
      return self.helpGui

    def handleAbout(self):
      if hasattr(self,'about'):
        if self.about:
          self.about.UnClose()
        return
      import HelpAboutDialog
      self.about = HelpAboutDialog.HelpAboutDialog(parent=self)

    def handlePaste(self):
      import MGApplication
      app = MGApplication.QtApp()
      clipboard = app.clipboard()
      self.DealWithMimeData(clipboard.mimeData(),pasteAtCursor=True)

    def dropEvent(self, event):
      rv = self.DealWithMimeData(event.mimeData())
      if not rv:
        event.setDropAction(QtCore.Qt.IgnoreAction)
        event.accept()
      else:
        event.ignore()
        
    def toggleAxes(self):
      state = int(self.findChild(QtGui.QAction,'show_axes').isChecked())
      for widget in self.glWidgets: widget.setAxes(state)
      self.updateGLWindows()

    def toggleShowScale(self):
      state = int(self.findChild(QtGui.QAction,'show_scale').isChecked())
      for iwidget,widget in zip(range(len(self.glWidgets)),self.glWidgets):
       if iwidget == 0:
        widget.setShowScale(state)
      self.updateGLWindows()
       
    def toggleFramerate(self):
       state = int(self.findChild(QtGui.QAction,'framerate').isChecked())
       self.glWidget.show_fps = state
       
    def handleZoomSpinChanged(self,val):
       self.glWidget.RADIUS = val*60.
       self.glWidget.updateGL()
       self.ZoomChanged(self.glWidget)

    def handleZoomChanged(self):
       self.zoom_spin.blockSignals(True)
       self.zoom_spin.setValue(self.glWidget.RADIUS/60.)
       self.zoom_spin.blockSignals(False)

    def toggleZoomDisplay(self):
       state = int(self.findChild(QtGui.QAction,'zoom_display').isChecked())
       if not hasattr(self,"zoom_spin_all"):
          self.zoom_spin = QtGui.QDoubleSpinBox()
          self.zoom_spin.setMinimum(0.01)
          self.zoom_spin.setMaximum(100000)
          self.zoom_spin.setSingleStep(0.1)
          self.connect(self.glWidget,QtCore.SIGNAL("ZoomChanged"),self.handleZoomChanged)
          self.zoom_spin.setValue(self.glWidget.RADIUS/60.)
          self.connect(self.zoom_spin,QtCore.SIGNAL("valueChanged(double)"),self.handleZoomSpinChanged)
          self.zoom_spin_all = QtGui.QWidget()
          layout = QtGui.QHBoxLayout()
          self.zoom_spin_all.setContentsMargins(0,0,0,0)
          layout.setContentsMargins(0,0,0,0)
          zoom_label = QtGui.QLabel(self.tr("Zoom:"))
          layout.addWidget(zoom_label)
          layout.addWidget(self.zoom_spin)
          self.zoom_spin_all.setLayout(layout)
       if state:
          self.statusBar().addPermanentWidget(self.zoom_spin_all)
          self.zoom_spin_all.show()
       else:
          self.statusBar().removeWidget(self.zoom_spin_all)
       
    def toggleFSAA(self):
       state = int(self.findChild(QtGui.QAction,'stereo_on').isChecked())
       import MGGLWidget
       fmt = MGGLWidget.getMaxSampleBuffersFormat()
       fmt.setStereo(state);
       fmt.setSampleBuffers(int(self.findChild(QtGui.QAction,'fsaa_on').isChecked()))
       self.setGLWidgetFormats(fmt,stereoState=state)
       for dispobj in get_dispobj(): dispobj.set_redraw_text()
       UPDATEDISPLAY()

    def toggleFullscreen(self):
      state = int(self.findChild(QtGui.QAction,'fullscreen').isChecked())
      if not state:
         self.setWindowState(self.windowState()&~QtCore.Qt.WindowFullScreen)
         self.toolbar.show()
         self.statusBar().show()
      else:
         self.setWindowState(self.windowState()|QtCore.Qt.WindowFullScreen)
         self.toolbar.hide()
         self.statusBar().hide()

    def toggleZalmanStereo(self):
      state = int(self.findChild(QtGui.QAction,'zalman_stereo_on').isChecked())
      for widget in self.glWidgets: 
        widget.setDoZalmanStereo(state)
        widget.setStereo(state)
        widget.updateGL()

    def toggleStereo(self):
      state = int(self.findChild(QtGui.QAction,'stereo_on').isChecked())
      import MGGLWidget
      fmt = MGGLWidget.getMaxSampleBuffersFormat()
      fmt.setStereo(state);
      fmt.setSampleBuffers(int(self.findChild(QtGui.QAction,'fsaa_on').isChecked()))
      self.setGLWidgetFormats(fmt,stereoState=state)
      for dispobj in get_dispobj(): dispobj.set_redraw_text()
      UPDATEDISPLAY()

    def setGLWidgetFormats(self,fmt,stereoState=False,doZalmanStereo=False):
      import MGGLWidget
      newWidgets = []
      i=0
      positions = []
      for widget in self.glWidgets: 
        self.disconnect(widget,QtCore.SIGNAL("TransformObject"),self.MGDisplayTable.handleObjectMoving)
        newWidget = MGGLWidget.MGGLWidget(self,self.glWidget,format=fmt)
        if widget.go: 
          newWidget.SetGO(widget.go,1)
        newWidget.SetOrigin(widget.rpos,1)
        newWidget.RADIUS = widget.RADIUS
        newWidget.quat = widget.quat
        newWidget.show_axes = widget.show_axes
        newWidget.extra_quat = widget.extra_quat
        newWidget.setExtraMatrix(widget.getExtraMatrix())
	r,g,b = widget.getBackground()
	newWidget.setBackground(r,g,b)
        newWidget.setDoubleClickHandler(self.pickEventRecentre)
        newWidget.setLeftClickHandler(self.labelPickedObject)
        newWidget.setContextMenuHandler(self.contextMenuHandler)
        newWidget.setStereo(stereoState)
        newWidget.setDoZalmanStereo(doZalmanStereo)
        self.connect(newWidget,QtCore.SIGNAL("QuatChanged"),self.QuatChanged)
        self.connect(newWidget,QtCore.SIGNAL("ZoomChanged"),self.ZoomChanged)
        self.connect(newWidget,QtCore.SIGNAL("PositionChanged"),self.PositionChanged)
        self.connect(newWidget,QtCore.SIGNAL("ViewChanged"),self.GLLeftMouseReleased)
        self.connect(newWidget,QtCore.SIGNAL("TransformObject"),self.MGDisplayTable.handleObjectMoving)
        newWidgets.append(newWidget)
        positions.append(self.box_layout.getItemPosition(i))
        newWidget.copyShaders(self.glWidgets[0])
        i = i + 1
      while len(self.glWidgets)>0:
        glwidget = self.glWidgets.pop()
        glwidget.updateGL()
        glwidget.close()
        glwidget.removeMouseBindings()
        self.box_layout.removeWidget(glwidget)
        """
        # There is a problem here, lots of bound methods...
        import gc
        gc.collect()
        refs = gc.get_referrers(glwidget)
        for ref in refs:
          print ref
          print 
        """
        del glwidget
      self.glWidgets = newWidgets
      self.glWidget = newWidgets[0]
      i = 0
      for widget in self.glWidgets: 
        self.box_layout.addWidget(widget,positions[i][0],positions[i][1],positions[i][2],positions[i][3])
        widget.reInitializeTextPrims()
        widget.rebuildAllDisplayObjects(1)
        widget.updateGL()
        self.connect(widget,QtCore.SIGNAL("TransformObject"),self.MGDisplayTable.handleObjectMoving)
        i = i + 1

      self.applyGLLighting()

    def toggleFog(self):
      state = int(self.findChild(QtGui.QAction,'fog_on').isChecked())
      for widget in self.glWidgets: widget.setFog(state)
      self.updateGLWindows()
      
    def toggleSlab(self):
      state = int(self.findChild(QtGui.QAction,'slab_on').isChecked())
      for widget in self.glWidgets: widget.setSlab(state)
      self.updateGLWindows()

    def setBackgroundColour(self,mode=''):
       #print "setBackgroundColour mode",mode
       if mode == 'other':
         import mgWidgets
         self.backgroundGui = mgWidgets.mgColourBrowser(selected_colour='white')
         self.connect(self.backgroundGui,QtCore.SIGNAL("ColourSelected"),self.setBackgroundColour)
         self.backgroundGui.setAttribute(QtCore.Qt.WA_DeleteOnClose)
       else:
         rgb = MGCOLOUR().RGB255(mode)
         for widget in self.glWidgets:
            widget.setBackground(rgb[0],rgb[1],rgb[2])
         for dispobj in get_dispobj(): dispobj.set_redraw_text()
         UPDATEDISPLAY()

    def setLighting(self,style):
      import LightingGui
      style = style[6:]
      print 'MGMainWindow.setLighting',style
      params = LightingGui.CUSTOM_STYLE_DEFINITIONS.get(style,{})
      self.setLightParams(params)
            
    def handleWindowSize(self):
      window = QtGui.QDialog(self)

      window.setWindowTitle('Main window size')
      window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
      layout = QtGui.QHBoxLayout()

      label =  QtGui.QLabel('Window height')
      layout.addWidget(label)
      height = QtGui.QSpinBox(self)
      height.setObjectName('window_height')
      height.setRange(0,5000)
      layout.addWidget(height)
      label = QtGui.QLabel('width')
      layout.addWidget(label)
      width = QtGui.QSpinBox(self)
      width.setObjectName('window_width')
      width.setRange(0,5000)
      layout.addWidget(width)
      window.setLayout(layout)

    
      self.connect(height,QtCore.SIGNAL('valueChanged(int)'),self.setWindowHeight)
      self.connect(width,QtCore.SIGNAL('valueChanged(int)'),self.setWindowWidth)
      self.setWindowSizeGui()
      window.show()
      
    def setWindowSizeGui(self):
      height = self.findChild(QtGui.QSpinBox,'window_height')
      if height: height.setValue(self.glWidgets[0].size().height())
      width = self.findChild(QtGui.QSpinBox,'window_width')
      if width: width.setValue(self.glWidgets[0].size().width())

    def setWindowHeight(self,height):
      #print "setWindowHeight",height
      for widget in self.glWidgets:
        widget.resize(height,widget.size().width())
      
    def setWindowWidth(self,width):
      #print "setWindowWidth",width
      for widget in self.glWidgets:
        widget.resize(width,widget.size().height())
  

    '''

    def setLanguage(self, action=None):
        lang = action.text()
        translator = QtCore.QTranslator()
        if lang == "English":
          translator.load(":/pyqtmg_en")
          app.installTranslator(translator)
          print "Load English"
        elif lang == "Latin":
          translator.load(":/pyqtmg_la")
          app.installTranslator(translator)
          print "Load Latin"
        else:
          print "unknown language"
    '''
    def checkIfZalmanStereo(self):
		try:
			import MonitorInfo
			mons = MonitorInfo.getMonitorNames()
			for m in mons:
				if m.find('ZM-M220') >-1:
					return True
		except:
			return False
		return False

    def drawMenu(self,menuName=''):
      # Redraw the main window menu on every 'aboutToShow
      # populateMenu will update checked/enabled status of action

      menuWidget=self.findChild(QtGui.QMenu,menuName)
      if not menuWidget:
        #print "ERROR drawing menu",menuName
        return
      menuWidget.clear()
      menudef = self.getGuiDef(menuName)
      guiUtils.populateMenu(self,menuWidget,menudef,self.getActionDef)
      self.toolbar.updateToolBar()

      

    def initialiseAnimation(self):
      # Set up one mechanism to handle animation/movies etc
      # Applications should use addAnimationHandler/removeAnimationHandler
      # to register their handler that will be called by default every 1ms
      self.animation_timer = QtCore.QTimer(self)
      self.animation_timer.setInterval(100)
      self.connect(self.animation_timer,QtCore.SIGNAL('timeout()'),self.handle_animation)
      self.animation_handlers = {}


    def addAnimationHandler(self,name='',handler=''):
      # Give a name (that can be used in error message to user)
      # and a handler
      #print 'addAnimationHandler',name
      self.animation_handlers[name] = handler
      if not self.animation_timer.isActive():
        self.animation_timer.start()

    def removeAnimationHandler(self,name=''):
      #print 'removeAnimationHandler',name
      if self.animation_handlers.has_key(name):
        del self.animation_handlers[name]
        if not self.animation_handlers and self.animation_timer.isActive():
          #print 'removeAnimationHandler stopping'
          self.animation_timer.stop()
        return 0
      else:
        return 1

    def handle_animation(self,trap_errors=0):

      redraw = 0
      if self.animation_handlers:
        for name,handler in self.animation_handlers.items():
          if trap_errors:
            try:
              handler()
              #redraw = 1
            except:
              print "Error in animation_handler for application",name
          else:
            handler()
            #redraw = 1
        if redraw:
          import rebuild
          rebuild.UpdateDisplay()

    def setAnimationInterval(self,delay):
      if delay>=0 and delay<= 10000 and delay != self.animation_timer.interval():
          self.animation_timer.setInterval(delay)

    def animationInterval(self):
      return int(self.animation_timer.interval())

    def setGLLights(self,lights):
		self.lights = lights
		self.applyGLLighting()

    def applyGLLighting(self):
	for widget in self.glWidgets:
		widget.setLights(self.lights)
	self.emit(QtCore.SIGNAL("LightingChanged"))

    def initialiseGLWidgets(self,rockParams={}):
        import MGGLWidget
        """
        fmt = MGGLWidget.getMaxSampleBuffersFormat()
        self.glWidget = GLWidget(fmt=fmt,parent=self)
        self.glWidgets = [ self.glWidget ]
        
        """
        fmt = MGGLWidget.getMaxSampleBuffersFormat()
        self.glWidget = MGGLWidget.MGGLWidget(format=fmt,parent=self)
        self.glWidgets = [ self.glWidget ]

        self.connect(self.glWidget,QtCore.SIGNAL("QuatChanged"),self.QuatChanged)
        self.connect(self.glWidget,QtCore.SIGNAL("ZoomChanged"),self.ZoomChanged)
        self.connect(self.glWidget,QtCore.SIGNAL("PositionChanged"),self.PositionChanged)
        #self.connect(self.glWidget,QtCore.SIGNAL("MousePress"),self.MousePress)        
        self.glWidget.setMouseBindings(self.mouseBindings())
        
        self.glWidget.setContextMenuHandler(self.contextMenuHandler)
        self.glWidget.setDoubleClickHandler(self.pickEventRecentre)
        self.glWidget.setLeftClickHandler(self.labelPickedObject)

        self.rockroll = 0
        self.rockcounter = -1

        self.rockspeed = rockParams.get('rockspeed',0.5)
        self.rollspeed = rockParams.get('rollspeed',0.5)
        self.rollorientation = rockParams.get('rollorientation','y')
        self.rockangle = rockParams.get('rockangle',20)
        
        self.roll_timer = QtCore.QTimer(self)
        self.connect(self.roll_timer,QtCore.SIGNAL('timeout()'),self.roll_handler)
        self.savedGLSize = None
        
    def roll_handler(self):

      if not self.glWidgets or len(self.glWidgets)==3: return
      if self.rockroll == 1:
        # Rolling
        if self.rollorientation == 'y':
          rotQ = pygl_coord.Quat(0,self.rollspeed,0,0)
        elif self.rollorientation == 'x':
          rotQ = pygl_coord.Quat(self.rollspeed,0,0,0)
      else:
        # Rocking
        nsteps=float(int(self.rockangle/self.rockspeed)) # steps/quarter cycle
        self.rockcounter = self.rockcounter+1
        if self.rockcounter>nsteps*4: self.rockcounter=0
        if self.rockcounter>=nsteps*2:
          speed = float(self.rockcounter-(nsteps*3))/nsteps *self.rockspeed*2
        else:
          speed = float(nsteps-self.rockcounter)/nsteps *self.rockspeed*2
        #print "rock", self.rockcounter,speed
        if self.rollorientation == 'y':
          rotQ = pygl_coord.Quat(0,speed,0,0)
        elif self.rollorientation == 'x':  
          rotQ = pygl_coord.Quat(speed,0,0,0)

      self.glWidgets[0].quat.postMult(rotQ)
      self.glWidgets[0].updateGL()

      if len(self.glWidgets) == 2:       
        self.glWidgets[1].quat.postMult(rotQ)
        self.glWidgets[1].updateGL()
      elif len(self.glWidgets) == 3:
        pass

    def toggleRockRoll(self,mode):
      '''
      mode == 1 : toggle roll
      mode == 2: toggle rock
      '''

      if mode == self.rockroll:
        # ** Ideally should put view back to original orientation
        # but this could get v. complicated if user is changing view
        self.rockroll = 0
      else:
        self.rockroll = mode
      
        
      if self.rockroll:
        self.roll_timer.start(1)
      else:
        self.roll_timer.stop()
        self.rockcounter = -1

      # Update the GUI
      self.findChild(QtGui.QAction,'roll_view').setChecked(self.rockroll==1)
      self.findChild(QtGui.QAction,'rock_view').setChecked(self.rockroll==2)
      gui = self.findChild(rockAndRollGUI)
      if gui: gui.setParams(rockroll=self.rockroll)

    def rockAndRoll(self):
      gui = self.findChild(rockAndRollGUI)
      if not gui:
        gui = rockAndRollGUI(self)

      pars = {}
      for key in ['rockroll','rockspeed','rollspeed','rockangle','rollorientation']:
        pars[key] = getattr(self,key)
      gui.setParams( pars )
      
      self.connect(gui,QtCore.SIGNAL('changed'),self.handleRockAndRoll)

      gui.show()
      gui.raise_()

    def handleRockAndRoll(self):
      gui = self.findChild(rockAndRollGUI)
      if not gui: return
      params = gui.getParams()
      for key in ['rockroll','rockspeed','rollspeed','rockangle','rollorientation']:
        setattr(self,key,params.get(key))
        
      self.findChild(QtGui.QAction,'roll_view').setChecked(self.rockroll==1)
      self.findChild(QtGui.QAction,'rock_view').setChecked(self.rockroll==2)

      if self.rockroll:
        self.roll_timer.start(1)
      else:
        self.roll_timer.stop()
        self.rockcounter = -1


    def GLLeftMouseReleased(self,arg=None):
	if self.autoSavePosition < len(self.autoSaveView)-1:
	  del self.autoSaveView[self.autoSavePosition+1:]
	self.autoSaveView.append(GLView(glWidget=self.glWidget))
	self.autoSavePosition = len(self.autoSaveView)-1
        self.setViewActionsEnabled()


    def initialiseAutoSaveView(self):
        self.autoSaveView = []
	self.autoSavePosition = 0
	self.autoSaveView.append(GLView(glWidget=self.glWidget))
        self.forwardAction = guiUtils.createAction('view_forward',self)
        self.backAction = guiUtils.createAction('view_back',self)
        self.connect(self.glWidget,QtCore.SIGNAL("ViewChanged"),self.GLLeftMouseReleased)
        self.setViewActionsEnabled()


    def viewForward(self,arg=None):
	if self.autoSavePosition < len(self.autoSaveView)-1:
	  self.autoSavePosition = self.autoSavePosition + 1
          self.autoSaveView[self.autoSavePosition].setGLWidget(self.glWidget)
          self.setViewActionsEnabled()

    def viewBack(self,arg=None):
	if self.autoSavePosition > 0:
	  self.autoSavePosition = self.autoSavePosition - 1
          self.autoSaveView[self.autoSavePosition].setGLWidget(self.glWidget)
          self.setViewActionsEnabled()

    def setViewActionsEnabled(self):
	if len(self.autoSaveView)>0 and self.autoSavePosition < len(self.autoSaveView)-1:
          self.forwardAction.setEnabled(True)
	else:
          self.forwardAction.setEnabled(False)
	if len(self.autoSaveView)>0 and self.autoSavePosition >0:
          self.backAction.setEnabled(True)
	else:
          self.backAction.setEnabled(False)

          

    def restoreDisplay(self,increment):
      HISTORY().autoRestore(increment)
      # edit_list is list [ object_name, object_type, add/delete/update]
      #print "restoreDisplay edit_list",edit_list
      doSideBySide = False
      doThreeWayView = False
      if len(self.glWidgets) == 2:
         self.handleSideBySide()
         doSideBySide = True
      elif len(self.glWidgets) == 3:
         self.handleThreeWayView()
         doThreeWayView = True
      import rebuild
      rebuild.UpdateDisplay(auto_save=0)
      self.updateGLWindows()      
      self.setDisplayActionsEnabled()
      self.MGDisplayTable.update()

      # Add the PMs
      for item in HISTORY().update_gui:
        if item[0] == 'update_PM':
          widget = self.findChild(QtGui.QWidget,item[1])
          #print "MGMainWindow.restoreDisplay",item,widget
          if widget:  widget.setParams(PM(item[1]).getparams())
        elif item[0] == 'delete_PM':         
          widget = self.findChild(QtGui.QWidget,item[1])
          #print "MGMainWindow.restoreDisplay",item,widget
          if widget:  widget.window().close()
              
      HISTORY().update_gui = []
      if doSideBySide:
         self.handleSideBySide()
      elif doThreeWayView:
         self.handleThreeWayView()

      

    def viewFrom(self,view_from=''):
      rotate_x = 0.0
      rotate_y = 0.0
      rotate_z = 0.0
      if view_from == 'left':
        rotate_y = 90.0
      elif view_from == 'right':
        rotate_y = -90.0
      elif view_from == 'top':
        rotate_x = 90.0
      elif view_from == 'bottom':
        rotate_x = -90.0
      elif view_from == 'back-x':
        rotate_x = 180.0
      elif view_from == 'back-y':
        rotate_y = 180.0


      # But this is interesting applied to 3-way view
      # ?? Just disable the gui
      # No, no, no !!!! Rotate self.glWidget and let signals do the rest.
      if len(self.glWidgets) == 3: return
      for widget in self.glWidgets:
        widget.setRotation ( rotate_x,rotate_y,rotate_z)

      self.updateGLWindows()
      self.GLLeftMouseReleased()
 
    def addGraphicsWindowShortcut(self):
        app = QtGui.QApplication.instance()
        if app:
          #print "Calling allWidgets 3"
          widgets = app.allWidgets()
          for widget in widgets:
             if widget != self and hasattr(widget,'isWindow') and callable(widget.isWindow) and widget.isWindow():
                graphicsWindowShortcut = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+G"),widget)
                self.connect(graphicsWindowShortcut,QtCore.SIGNAL('activated()'),self.UnClose)

    def closeEvent(self,event):
        app = QtGui.QApplication.instance()
        if app:
          #print "Calling allWidgets 4"
          widgets = app.allWidgets()
          for widget in widgets:
             if widget != self and hasattr(widget,'isWindow') and callable(widget.isWindow) and widget.isWindow() and hasattr(widget,'isHidden') and callable(widget.isHidden) :
               if not widget.isHidden():
                  event.ignore()
                  self.hide()
                  return

        event.accept()

    def UnClose(self):
        self.show()
        self.raise_()



    def mouseBindings(self):

      if not hasattr(self,'mouse_bindings'):
        import MouseBindings
        self.mouse_bindings = {}
        self.mouse_bindings.update(MouseBindings.DEFAULT)
        
      return self.mouse_bindings


    def setMouseBindings(self,params):
      self.mouse_bindings = {}
      self.mouse_bindings.update(params)
      #print "MGMainWindow.setMouseBindings",self.mouse_bindings
      for widget in self.glWidgets:
        widget.setMouseBindings(self.mouse_bindings)

#-------------------------------------------------------------------
    def hideWindows(self,open=0,all_systems=0):
#-------------------------------------------------------------------
      import MGApplication,sys

      if (not all_systems) and ['darwin'].count(sys.platform): return
      
      app = MGApplication.QtApp()
      glWidget = self.glWidget

      if open:
        if not  hasattr(self,'hiddenWindows'): return
        # Restore windows
        for widget in self.hiddenWindows:
           widget.show()
        del self.hiddenWindows
      else:
        # Close all possible obscuring widgets
        widgets = self.findChildren(QtGui.QDialog,"")
        #print "screenshot",self,widgets
        if not hasattr(self,'hiddenWindows'): self.hiddenWindows = []
        for widget in widgets:
          if (not [glWidget,self].count(widget)) and \
          hasattr(widget,'isHidden') and callable(widget.isHidden) and \
          hasattr(widget,'setVisible') and callable(widget.setVisible) and \
          hasattr(widget,'isWindow') and callable(widget.isWindow) and widget.isWindow() and \
          (not isinstance(widget,QtGui.QProgressDialog)):
            if not widget.isHidden():
              widget.setVisible(False)
              app.sendPostedEvents()
              app.processEvents(QtCore.QEventLoop.AllEvents)
              app.flush()
              if not hasattr(self,'hiddenWindows'): self.hiddenWindows = []
              self.hiddenWindows.append(widget)
        for repeat in range(0,2):
          app.sendPostedEvents()
          app.processEvents(QtCore.QEventLoop.AllEvents)
          app.flush()
        import time
        time.sleep(2) # Oh, dear. And we still can't be sure what window manager has done.
 

#---------------------------------------------------------------------------
    def getViewParams(self):
#---------------------------------------------------------------------------            
      if not self.glWidget: return {}
      params = {}
      qPtr = self.glWidget.quat.Getdval()
      tmp = pygl_coord.doublea(1)
      quatp = tmp.frompointer(qPtr)
      params['quat']= []
      for ii in range(0,4):params['quat'].append(quatp[ii])
      params['pos'] = []
      for ii in range(0,3): params['pos'].append(self.glWidget.rpos[ii])
      params['scale'] = self.glWidget.RADIUS

      for item in ['fog_enabled','fog_strength','fog_near','fog_far','slab_enabled','slab_width','slab_offset','clip_cap','customClipPlanes']:
        params[item]=getattr(self.glWidget,item)

      params['transparency'] = self.glWidget.transparency()

      return params


#---------------------------------------------------------------------------            
    def setViewParams(self,params={}):
#---------------------------------------------------------------------------            
      if not self.glWidgets: return
      #print "MAINWINDOW setViewParams glWidgets",self.glWidgets,'params',params
      if params.has_key('orientation'): 
        if type(params['orientation'])==dict and params['orientation'].has_key('molData') and params['orientation'].has_key('selection'):
          dataobjs = get_dataobj(object_type ='MolData',name=str(params['orientation']['molData']).replace('-','_'))
          if len(dataobjs)>0:
              dataobj = dataobjs[0]
              selection = params['orientation']['selection']
              rv = dataobj.parse_selection(command=selection)
              if rv[0] == 0 and rv[1] > 0:
                selHnd = rv[1]
                pca = dataobj.molHnd.GetPrincipalComponents(selHnd)
                xcart = pygl_coord.Cartesian(1,0,0)
                minpca = pygl_coord.Cartesian(pca[1].get_x(),pca[1].get_y(),pca[1].get_z())
                maxpca = pygl_coord.Cartesian(pca[0].get_x(),pca[0].get_y(),pca[0].get_z())
                print "minpca"; minpca.Print(); print
                print "maxpca"; maxpca.Print(); print
                angle = math.acos(pygl_coord.Cartesian.DotProduct(maxpca,xcart))*180/math.pi
                print "first angle", angle, pygl_coord.Cartesian.DotProduct(maxpca,xcart)
                if pygl_coord.Cartesian.DotProduct(maxpca,xcart)>0:
                  angle -= 180 
                if abs(angle)>1e-8:
                  axis = pygl_coord.Cartesian.CrossProduct(maxpca,xcart)
                  axis.normalize()
                  quat = pygl_coord.Quat(axis.get_x(),axis.get_y(),axis.get_z(),1,angle)
                  dvals = quat.dvals()
                  params['quat'] = [dvals[0], dvals[1], dvals[2], dvals[3]]
                  mat = quat.getMatrix()
                  screeny = pygl_coord.Cartesian(0,1,0)
                  minpca = mat*minpca
                  angle = math.acos(pygl_coord.Cartesian.DotProduct(minpca,screeny))*180/math.pi
                  if abs(angle)>1e-8:
                    print "second angle", angle, pygl_coord.Cartesian.DotProduct(minpca,screeny)
                    axis = pygl_coord.Cartesian(1,0,0)
                    if pygl_coord.Cartesian.DotProduct(minpca,screeny)>0:
                      angle -= 180 
                    quat2 = pygl_coord.Quat(axis.get_x(),axis.get_y(),axis.get_z(),1,angle)
                    quat.postMult(quat2)
                    dvals = quat.dvals()
                    params['quat'] = [dvals[0], dvals[1], dvals[2], dvals[3]]
                else:
                  params['quat'] = [1,0,0,0]
              else:
                params['quat'] = [1,0,0,0]
          else:
            params['quat'] = [1,0,0,0]

        else:
          params['quat'] = params['orientation']

      if params.has_key('RADIUS'): params['scale'] = params['RADIUS']
      

      theSize = None
      if params.has_key('centre_MolData'):
        dataobjs = get_dataobj(object_type ='MolData',name=str(params['centre_MolData']).replace('-','_'))
        if len(dataobjs)>0:
          dataobj = dataobjs[0]

          if params.has_key('centre_selection'):
             selection = params['centre_selection']
          else:
             selection = 'all'

          rv = dataobj.parse_selection(command=selection)
          if rv[0] == 0 and rv[1] > 0:
            selHnd = rv[1]

            tmp = pygl_coord.doublea(1)
            rtde =  tmp.frompointer(mmdb.realtype_to_double(dataobj.molHnd.Extent(selHnd)))
            mine,maxe = (rtde[0],rtde[1],rtde[2]),(rtde[3],rtde[4],rtde[5])
            mide = ((mine[0]+maxe[0])/2.,(mine[1]+maxe[1])/2.,(mine[2]+maxe[2])/2.)
            theSize = max(abs(mine[0]-maxe[0]),abs(mine[1]-maxe[1]),abs(mine[2]-maxe[2]))
            
            if hasattr(self,"glWidget"):
               self.glWidget.centreOn(mide,glide=0)

      elif params.has_key('pos'):
        pass
      elif params.has_key('centre_xyz'):
        params['pos'] = params['centre_xyz']
      elif params.has_key('rpos'):
        params['pos'] = params['rpos']
      
      if params.has_key('quat'):
        qPtr = pygl_coord.doublea(4)
        quat = pygl_coord.Quat()
        for ii in range(0,4):qPtr[ii]=params['quat'][ii]
        quat.Setdval(qPtr)
        for glWidget in self.glWidgets:
          glWidget.setQuat(quat)

      for glWidget in self.glWidgets:
        if params.has_key('pos'): glWidget.setPosition(params['pos'])

        if params.has_key('zoom'):
           try:
             zoom = float(params['zoom'])
             if zoom>1e-6:
               glWidget.setZoom(1./zoom*60)
           except:
             pass

        if params.has_key('scale'):
           if type(params['scale']) == str and 'ang' in params['scale']:
             try:
                sc = params['scale'].split()[0]
                scf = float(sc)
                # 2.5 is the factor which turns angstroms into CCP4MG's bizarre arbs.
                glWidget.setZoom(scf*2.5)
             except:
                pass
              
           elif params['scale'] == 'auto':
             if theSize:
                # 2.5 is the factor which turns angstroms into CCP4MG's bizarre arbs.
                # 1.25 is a fudge factor, which gives a reasonable viewsize.
               glWidget.setZoom(theSize*2.5*1.25)
             else:
               glWidget.setZoom(60)
           elif params['scale'] == 'auto_contacts':
             if theSize:
               import symmetry
               dum = pygl_coord.Cartesian()
               point = pygl_coord.Cartesian(glWidget.rpos[0],glWidget.rpos[1],glWidget.rpos[2])
               symmetry = symmetry.Symmetry(dataobj.molHnd,selHnd,point,dum,dum,dum,dum,0,0,0,0,50,1)
               symmSize = symmetry.ExtentSize()
               if symmSize > theSize:
                 glWidget.setZoom(symmSize*2.5)
               else:
                 glWidget.setZoom(theSize*2.5*2)
             else:
               glWidget.setZoom(60)
           elif params['scale']>1e-6:
             glWidget.setZoom(params['scale'])

        for item in ['fog_enabled','fog_strength','fog_near','fog_far','slab_enabled','slab_width','slab_offset','clip_cap','customClipPlanes']:
          if params.has_key(item):
            setattr(glWidget,item,params[item])

#---------------------------------------------------------------------------            
    def getLightParams(self):
#---------------------------------------------------------------------------                  
      params = {}
      params['nLights'] = len(self.lights)
      ii = -1
      for lightobj in self.lights:
        ii = ii+1
        params[ii] = {}
        for item in ['position','ambient','specular','diffuse','on']:
          params[ii][item] = getattr(lightobj,item)  

      #print "getViewParams",params
      return params

#---------------------------------------------------------------------------                  
    def setLightParams(self,params):
#---------------------------------------------------------------------------                  
      
      """
      print "Setting light params"
      for key,val in params.items():
        print key,val
      """

      nLights = params.get('nLights',0)
      #if not nLights: return

      import opengl,Light
      self.lights = []
      for ii in range(nLights):
        lightName=getattr(opengl,"GL_LIGHT"+str(ii),'')
        if lightName:
          light = Light.Light(lightName,params[ii]['position'],params[ii]['ambient'],params[ii]['specular'],params[ii]['diffuse'])
          if params[ii]['on']: light.turn_on()
          self.lights.append(light)
          
      self.applyGLLighting()
      
#---------------------------------------------------------------------------            
    def copyTutorialData(self):
#---------------------------------------------------------------------------            
      text = utils.copyTutorialData()
      QtGui.QMessageBox.warning(self,'Copying tutorial data',text)

#-------------------------------------------------------------------
    def loadPlugins(self):
#-------------------------------------------------------------------
      import loadPlugins
      self.plugins = loadPlugins.loadPlugins()

class MGMainWindowSimple(QtCore.QObject,MGMainWindowCore):

    def setDisplayActionsEnabled(self):
	pass

    def initialiseAutoSaveDisplay(self):
	pass

#-------------------------------------------------------------------
    def openFile(self,file='',drawing_style='',use_current_style=0,show_wizard_choices=0,filter=''):
#-------------------------------------------------------------------
       # This should be calling functions from appropariate data modules!!
       import rebuild,MGGLImage
        
       if not os.path.exists(file): return 2
       ext = os.path.splitext(file)[1][1:].lower()
       extgz = None
       if ext == 'gz':
          ext2 = os.path.splitext(os.path.splitext(file)[0])[1]
          if ext2 != '':
             extgz = (ext2 + '.' + ext)[1:].lower()

       '''
       dir_alias = CCP4DATABASE().aliasForDir(os.path.split(file)[0])
       if dir_alias:
         file_list_def = [dir_alias,os.path.split(file)[1],file]
       else:
         file_list_def = ['FULLPATH',file,file]
       print 'openFile ccp4 alias',file,dir_alias,file_list_def
       '''

       if ext in ['ent','brk','pdb','cif'] or extgz in ['ent.gz','brk.gz','pdb.gz','cif.gz']:
          if extgz:
             file = utils.gunzipToNamedFile(file)

          if (not drawing_style) and use_current_style:
             drawing_style = PICTUREWIZARD().default_drawing_style    

          if not show_wizard_choices:
            # Test if this drawing_style absolutely requires user input (if so will return show_wizard_choices = 1)
            show_wizard_choices,choices = PICTUREWIZARD().read_mgpic_file_choices(drawing_style=drawing_style)
          #print "openFile drawing_style",show_wizard_choices,drawing_style
          ndispobj = len(get_dispobj())
          import model
          rv,m = model.openpdbfile( file )
          print "openpdbfile ret",rv,m
          if rv:
            print "Error opening file",file
            return 0
          m.applyDrawingStyle(drawing_style=drawing_style)
             
          rebuild.UpdateDisplay()
          #print "MGMainWindow.openFile ndispobj",ndispobj
          if ndispobj == 0: MAINWINDOW().handleRecentre(glide=0)
            
       elif ['map'].count(ext) or ['map.gz'].count(extgz):
         if extgz:
           file = utils.gunzipToNamedFile(file)
         import map
         m = map.MapData(filename=file,filetype='MAP')
         m.loaddata()
         m.create_contours()
         xtl = CRYSTALMANAGER().add_object()
         xtl.set_source(m.name)
         rebuild.UpdateDisplay()

       elif  ['vector'].count(ext):
         # Assume it is a vector file for now
         import VectorsDispobj
         m = VectorsDispobj.openvectorfile(file)
         if m:
           rebuild.UpdateDisplay()
           
       elif MGGLImage.supportedReadFormats().count(ext) and ext != "svg":
           m = MGGLImage.Image(filename = str(file),parent=GL2DMANAGER())
           if m.isValid:
             rebuild.UpdateDisplay()
           
       elif file.find('.') > -1:
         # Is it supported by a plugin?
         suffixes = getSuffixes(file)
         for suffix in suffixes:
           handler = MAINWINDOW().getFileTypeHandler(suffix)
           if not handler == self.defaultFileTypeHandler:
              break
         #print "openFile handler",handler
         return handler(file)

       else:
         # Nothing matched..
           return 0
         
       return m

    def deleteAllDataObj(self):
      dellist = []
      for dataobj in get_dataobj():
        if not (hasattr(dataobj,'master_application') and dataobj.master_application):
          dellist.append(dataobj)
    
      for dataobj in dellist:
        dataobj.delete()
        if hasattr(dataobj,"close"):
          dataobj.close()

    def deleteDataObj(self,name):
       target = get_dataobj(name=name)
       #print "deleteDataObj",name,target
       if target:
         # Are there any other objects that should be deleted
         # along with this one (eg Crystal gets deleted with map)
         dependents = target[0].getDependentsForDeletion()
         #print 'displayTable deleteDataObj dependents',dependents
         target[0].delete()
         if dependents:
           # In principle there could be a recursion here.
           for dep in dependents:
             dep_target = get_dataobj(name=dep)
             if dep_target:
               dep_target[0].delete()
             else:
               dep_target = get_dispobj(name=dep)
               if dep_target:
                 dep_target.delete()
   
    def initialiseGLWidgets(self,rockParams={}):
        import MGGLWidget
        if sys.argv.count('-osmesa'):
           import MGGLWidgetOSMesa
           self.glWidget = MGGLWidgetOSMesa.MGGLWidgetOSMesa()
           self.glWidgets = [ self.glWidget ]
           return
        self.glWidget = MGGLWidget.MGGLWidgetSimple()
        self.glWidgets = [ self.glWidget ]

    def __init__(self, parent=None,application=None,gui_params={},stereoFormatAvailable=False):
        QtCore.QObject.__init__(self, parent)
        MGMainWindowCore.__init__(self, parent,application,gui_params,stereoFormatAvailable)
        self.extra_handlers = {}
        self.extra_filters = []
        self.initialiseGLWidgets()   

class MGMainWindow(QtGui.QMainWindow,MGMainWindowCore):

    def setDisplayActionsEnabled(self):
      nS = len(HISTORY().autoSavedStatus)
      nP = HISTORY().autoSavedPosition
      #print "setDisplayActionsEnabled",nS,nP
      self.displayForwardAction.setEnabled(nS>0 and nP<(nS-1))
      self.displayBackAction.setEnabled(nS>0 and nP>0)
    
    def initialiseAutoSaveDisplay(self):
        
      self.displayForwardAction =  guiUtils.createAction('display_forward',self)
      self.displayBackAction =  guiUtils.createAction('display_back',self)
      self.setDisplayActionsEnabled()

    def __init__(self, parent=None,application=None,gui_params={},stereoFormatAvailable=False,dockedDT=False,super_compact=False):
        QtGui.QMainWindow.__init__(self, parent)
        MGMainWindowCore.__init__(self, parent,application,gui_params,stereoFormatAvailable)
        import MGApplication
        MGApplication._mainWindow = self
	self.stereoFormatAvailable = stereoFormatAvailable

        #self.setDockOptions(QtGui.QMainWindow.ForceTabbedDocks)
        #print "MainWindow gui_params",gui_params

        self.recentFilesList = ['Recent files']

        self.extra_handlers = {}
        self.directory_handlers = []
        self.extra_save_handlers = {}
        self.extra_filters = []

        #self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        self.application = application

        self.setAcceptDrops(1)
        #print "1"; sys.stdout.flush()
        icon_file=os.path.join(os.environ["CCP4MG"],"ccp4mg_icon.png")
        icon = QtGui.QIcon(QtGui.QPixmap(icon_file))
        self.setWindowIcon(icon)
	import version
	version_string = self.tr("CCP4MG version ") + QtCore.QString(version.ccp4mg_version)
        self.setWindowTitle(version_string)
        #print "2"; sys.stdout.flush()

        self.box_layout = QtGui.QGridLayout()
        self.box_layout.setSpacing(0)
        self.box_layout.setContentsMargins(0,0,0,0)
        
        self.lights = []
        import Light
        import opengl
        position = (0.0, 0.0, 60.0)
        ambient = (0.0, 0.0, 0.0)
        specular = (1.0, 1.0, 1.0)
        diffuse = (1.0, 1.0, 1.0)
        light0 = Light.Light(opengl.GL_LIGHT0,position,ambient,specular,diffuse)
        light0.turn_on()
        self.lights.append(light0)

        self.initialiseGLWidgets(rockParams=gui_params.get('rockParams',{}))
        
        null_widget = QtGui.QWidget()
        null_widget.setLayout(self.box_layout)

        self.setCentralWidget(null_widget)

        if sys.platform != "win32":
          self.box_layout.addWidget(self.glWidget,0,0)

        #print "2.1"; sys.stdout.flush()

        #init_ccp4mg_resources()
        #print "2.2"; sys.stdout.flush()

        mainLayout = self.layout()
        #print "3"; sys.stdout.flush()

	statusBar = self.statusBar()
	statusBar.showMessage("")
        
        self.menuDefinitions =  {}
        self.actionDefinitions = {}
        self.initializeActionDefinitions()
        self.initializeMenuDefinitions()
        self.initialiseAutoSaveView()
        self.initialiseAutoSaveDisplay()

        import MGToolBar
        self.toolbar = MGToolBar.MGToolBar(self,title=self.tr("Toolbar"),params=gui_params.get('main_toolbar',{}),default_actions = self.getGuiDef('main_toolbar_default'),supported_actions= self.getGuiDef('main_toolbar_supported'))

        self.toolbar.setObjectName("Main Toolbar")
        self.addToolBar(self.toolbar)
        self.actionDefinitions['toggle_toolbar'] = dict (
            text = 'Toolbar',
            icon = 'toolbar',
            shortcut = '',
            tip = 'Show/hide toolbar',
            action = self.toolbar.toggleViewAction() )

        import re
        for item in  self.getGuiDef('menus'):
          menudef = self.getGuiDef(item[0])
          menuWidget = self.menuBar().addMenu(item[1])
          menuWidget.setObjectName(item[0])
          if item.count('aboutToShow'):
            self.drawMenu(item[0])
            self.connect(menuWidget,QtCore.SIGNAL("aboutToShow()"),guiUtils.partial(self.drawMenu,item[0]))
          else:
            self.drawMenu(item[0])


        import displayTable	 
        if dockedDT:
          self.MGDisplayTable = displayTable.MGDisplayTable(docked=True,super_compact=super_compact)	 
          self.wMGDisplayTable = displayTable.DispWindowDock(self,MGDisplayTable=self.MGDisplayTable)	 
        else:
          self.MGDisplayTable = displayTable.MGDisplayTable(self)	 
          self.wMGDisplayTable = displayTable.DispWindowNoDock(self,MGDisplayTable=self.MGDisplayTable)	 
        #self.wMGDisplayTable.show()
        self.connect(self.glWidget,QtCore.SIGNAL("TransformObject"),self.MGDisplayTable.handleObjectMoving)
        self.connect(self.MGDisplayTable,QtCore.SIGNAL("DisplayTableChanged"),self.glWidget.calculateShadowExtents)

        # Initialise wPreferences - but don't draw until required
        self.wPreferences = None

        self.addGraphicsWindowShortcut()
	self.menuDefinitions["Windows"].append("unclose")
        self.initialiseAnimation()
        import annotationGui
        self.autoAnnotate = annotationGui.autoAnnotate()

        doneLighting = False
        if sys.platform == "win32":
          self.glWidget.makeCurrent() # Is this generally safe?
          if opengl.glGetString(opengl.GL_VENDOR).strip().find('Intel')>-1 \
            and opengl.glGetString(opengl.GL_RENDERER).strip().find('Intel Cantiga')>-1 \
            and opengl.glGetString(opengl.GL_VERSION).strip().find('2.0.0')>-1:
            # We have a strange driver which needs to do lighting now or it crashes later.
            self.applyGLLighting()
            doneLighting = True

        import JobControl
        self.jobControl = JobControl.JobControl(self)
        if sys.platform == "win32":
          self.box_layout.addWidget(self.glWidget,0,0)

        """
        if not doneLighting:
          self.applyGLLighting()
        """

	self.applyStereoPrefs()
        self.setupRecentList()

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

    def addFilters(self,filters):
      self.filedialog.addFilters(filters)
      
    def addFilter(self,filter):
      self.filedialog.addFilter(filter)
      
    def filters(self):
      return self.filedialog.filters(filters)
      
    def setNameFilters(self,filters):
      self.filedialog.setNameFilters(filters)

    def __init__(self,parent=None):
      QtGui.QDialog.__init__(self,parent)
      self.setObjectName('guiOpen')
      #print 'guiOpen.__init__'
      self.setWindowTitle(self.tr("Open file(s)"))
      layout = QtGui.QVBoxLayout()

      wiz_layout =  QtGui.QHBoxLayout()
      import pictureWizardGui
      self.drawingStyle = pictureWizardGui.drawingStyleGui(self)
      wiz_layout.addWidget(self.drawingStyle)
      wiz_group = QtGui.QGroupBox('Picture wizard',self)
      wiz_group_layout =  QtGui.QVBoxLayout()
      widget = QtGui.QRadioButton('Automatic picture setup',self)
      wiz_group_layout.addWidget(widget)
      self.show_wizard_choices =  QtGui.QRadioButton('Open picture wizard choices',self)
      wiz_group_layout.addWidget(self.show_wizard_choices)
      wiz_group.setLayout(wiz_group_layout)
      self.show_wizard_choices.setChecked(PICTUREWIZARD().show_wizard_choices)
      widget.setChecked(1-PICTUREWIZARD().show_wizard_choices)
      self.connect(self.show_wizard_choices,QtCore.SIGNAL('toggled(bool)'),self.update_show_wizard_choices)
      wiz_layout.addWidget(wiz_group)
      wiz_layout.addStretch(5)
      layout.addLayout(wiz_layout)

      filedialog = mgWidgets.MGFileDialog(self,editAlias=0)
      layout.addWidget(filedialog)
      self.filedialog = filedialog.getFileDialog()

      self.filedialog.setFileMode(self.filedialog.ExistingFiles)
      self.connect(self.filedialog, QtCore.SIGNAL('filesSelected (const QStringList&)'), self.handleSelection)

      filter_list = ["Model coordinate files (*.pdb *.cif *.ent *.brk *.pdb.gz *.cif.gz *.ent.gz *.brk.gz)",
                     "CCP4 map files (*.map *.map.gz)",
                     "CCP4 experimental data files (*.mtz)",
                     "Zipped Presentations (*.ccp4mg_presentation.zip)",
                     "Status files (*.mgpic.py *.pkl)",
                     "CCP4mg vector file (*.vector)" ]
      
      # Add the image formats 
      import platform
      platter = platform.platform()
      # For some reason, the correct code fails on (some) 64-bit Ubuntus.
      formats = QtGui.QImageWriter.supportedImageFormats()
      """
      if False and ('Ubuntu' in platter or 'debian-squeeze-sid' in platter) and 'x86_64' in platter:
        formats = QtGui.QImageWriter.supportedImageFormats()
      else:
        import image_info
        formats = image_info.image_info.GetSupportedWriteFormats()
      """
      image_exts = '('
      for format in formats:
        if str(format).upper()!=str(format):
          image_exts = image_exts + '*.'+format+' '
      image_exts= image_exts[0:-1] + ')'
      filter_list.append('Image files '+image_exts)

      self.filedialog.setNameFilters(filter_list)

      self.setLayout(layout)

      children = self.filedialog.findChildren(QtGui.QPushButton,"")
      for child in children:
        if child.text() == self.tr("&Open"):
          child.clicked.disconnect()
          child.clicked.connect(self.openClicked)

      self.tree = self.filedialog.findChild(QtGui.QTreeView)

    def openClicked(self):
      inds = self.tree.selectionModel().selectedIndexes()
      files = []
      for i in inds:
        if i.column() == 0:
          files.append(os.path.join(unicode(self.filedialog.directory().absolutePath().toUtf8(),'utf-8'),unicode(i.data().toString())))
      self.filedialog.emit(QtCore.SIGNAL('filesSelected (const QStringList&)'),QtCore.QStringList(files))
      self.done(0)
      
#-------------------------------------------------------------------
    def handleSelection(self,selectedFiles):
#-------------------------------------------------------------------
      filter = str(self.filedialog.selectedFilter())
      for item in selectedFiles:
        f = str(item.toUtf8())
        self.emit(QtCore.SIGNAL('filesSelected'),f,self.drawingStyle.getStyle(),0,self.show_wizard_choices.isChecked(),filter)
      self.close()

#-------------------------------------------------------------------
    def update_show_wizard_choices(self,state):
#-------------------------------------------------------------------
      #print 'update_show_wizard_choices',state
      PICTUREWIZARD().show_wizard_choices= int(state)

#-------------------------------------------------------------------
    def getFileName(self):
#-------------------------------------------------------------------
        if len(self.filedialog.selectedFiles()) > 0:
          if not os.path.isdir(self.filedialog.selectedFiles()[0]):
            return self.filedialog.selectedFiles()[0]
        return None

#-------------------------------------------------------------------
    def useWizard(self):
#-------------------------------------------------------------------
        return self.wizard_radio.isChecked()


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


    def __init__(self,parent=None,mode='open',application='presentation'):
      super(guiOpenPresentation,self).__init__(parent)
      self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
      self.setObjectName('dialogPresentation')
      self.setApp(application)
      layout = QtGui.QVBoxLayout()
       

      filedialog = mgWidgets.MGFileDialog(self)
      layout.addWidget(filedialog)
      self.filedialog = filedialog.getFileDialog()

      if mode == 'zip':
        filter_list = [self.tr("Zipped presentation directory (*.ccp4mg_presentation.zip)")]
      else:
        filter_list = [self.tr("Presentation directory (*.ccp4mg_presentation)")]
        if mode == 'open':
          self.filedialog.setFileMode(self.filedialog.DirectoryOnly)
        else:
          self.filedialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
        #self.filedialog.setDirectory(proj_dir)
          children = self.filedialog.findChildren(QtGui.QPushButton,"")
          for child in children:
            if child.text() == self.tr("&Save"):
              child.setText(self.tr("&Create"))
              self.connect(child, QtCore.SIGNAL('pressed()'),self.saveFile)
    
      self.filedialog.setNameFilters(filter_list)

      #self.setSidebar()        
          
      self.setLayout(layout)
      self.connect(self.filedialog, QtCore.SIGNAL('filesSelected (const QStringList&)'), self.handleSelection)

#-------------------------------------------------------------------
    def setApp(self,application):
#-------------------------------------------------------------------
      self.setWindowTitle("Open "+application+" directory")
      self.application = application

#-------------------------------------------------------------------
    def getFileName(self):
#-------------------------------------------------------------------
        if len(self.filedialog.selectedFiles()) > 0:
          if not os.path.isdir(self.filedialog.selectedFiles()[0]):
            return self.filedialog.selectedFiles()[0]
        return None


#-------------------------------------------------------------------
    def handleSelection(self,selectedFiles):
#-------------------------------------------------------------------
      #print "handleSelection drawing_style",self.drawingStyle.getStyle()
      #filter = str(self.filedialog.selectedFilter())
      #print "openGui.handleSelection filter",filter
      for item in selectedFiles:
        f = str(item.toUtf8())
        self.emit(QtCore.SIGNAL('filesSelected'),f,self.application)
      self.close()

#-------------------------------------------------------------------
    def saveFile(self):
#-------------------------------------------------------------------
      file = self.filedialog.selectedFiles()
      if not file: return
      self.parent().openPresentation(str(file[0].toUtf8()),mode='new',application=self.application)
      

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

    
  def __init__(self,parent=None):
    #print "guiCentreOn",parent
    
    QtGui.QDialog.__init__(self,parent)

    self.setWindowTitle(self.tr("Find, centre on.."))
    master_layout = QtGui.QVBoxLayout()
    
    layout = QtGui.QHBoxLayout()
    seleLabel =   QtGui.QLabel(self.tr('Find'),self)
    import mgWidgets
    self.selectionCombo = mgWidgets.mgSelectionCombo(self,multi=1)
    self.connect(self.selectionCombo, QtCore.SIGNAL('changed'),self.handleCentreOnButton)
    for item in [seleLabel, self.selectionCombo]:
      layout.addWidget(item)
    master_layout.addLayout(layout)

    layout = QtGui.QHBoxLayout()
    self.createDispobj = QtGui.QCheckBox('Show atoms if not visible',self)
    self.createDispobj.setChecked(1)
    layout.addWidget(self.createDispobj)
    master_layout.addLayout(layout)
    
    buttonBox = QtGui.QDialogButtonBox(self)
    buttonBox.setOrientation(QtCore.Qt.Horizontal)
    button = buttonBox.addButton('Centre on',QtGui.QDialogButtonBox.ApplyRole)
    self.connect(button, QtCore.SIGNAL('clicked()'), self.handleCentreOnButton)
    master_layout.addWidget(buttonBox)
    
    self.setLayout(master_layout)

    self.show()


#-------------------------------------------------------------------
  def handleCentreOnButton(self):
#-------------------------------------------------------------------
    molobj = self.selectionCombo.getCurrentDataObj()
    selected = self.selectionCombo.text()
    #print "selected",molobj,selected
    ret = molobj.parse_selection(command=selected)
    if ret[0]!=0: return
    self.parent().centreOn(molHnd=molobj.molHnd,selHnd=ret[1])

    # label first atom in selection
    atm_ptr=molobj.interpretAtomID(mol=molobj,selHnd=ret[1])
    if atm_ptr:
      dispobj = molobj.findDispobjContainingAtom(atm_ptr=atm_ptr)
      #print 'handleCentreOnButton',atm_ptr,dispobj
      
      if not dispobj and self.createDispobj.isChecked():
        dispobj = molobj.add_object(visible=1,object_type='MolDisp',selparams={'select':'cid','cid':selected},styleparams={'style_mode':'CYLINDERS'})
        DISPLAYTABLE().addDispObj(molobj.name,object_type='MolDisp',name=dispobj.name)
        import rebuild
        rebuild.UpdateDisplay()
        
      if dispobj:
        obj = DISPLAYTABLE().getDispObj(dispobj.name)
        if obj: obj.set_visibility(1)
        rv = PICKLABEL().addLabel(atm_ptr=atm_ptr,dispobj=dispobj)
        if rv: 
          import rebuild
          rebuild.UpdateDisplay()
    molobj.molHnd.DeleteSelection(ret[1])


    



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

  
#-------------------------------------------------------------------
    def __init__(self,parent):
#-------------------------------------------------------------------
        QtGui.QDialog.__init__(self,parent)
        self.setWindowTitle('Rock and roll')
        self.setObjectName('rock_n_roll')

        layout = QtGui.QVBoxLayout()

        group = QtGui.QButtonGroup(self)
        group.setObjectName('rockroll')
        
        line_layout = QtGui.QHBoxLayout()
        widget = QtGui.QRadioButton('Roll',self)
        widget.setObjectName('roll_on')
        group.addButton(widget)
        self.connect(widget,QtCore.SIGNAL('clicked()'),self.apply)
        line_layout.addWidget(widget)
        widget = QtGui.QLabel('speed')
        line_layout.addWidget(widget)
        widget = mgWidgets.mgSlider(QtCore.Qt.Horizontal,self)
        widget.setRange(-5.0,5.0)
        widget.setObjectName('rollspeed')
        self.connect(widget,QtCore.SIGNAL("valueChanged(double)"),self.apply)
        line_layout.addWidget(widget)
        line_layout.addStretch()
        layout.addLayout(line_layout)

        line_layout = QtGui.QHBoxLayout()
        widget = QtGui.QRadioButton('Rock',self)
        widget.setObjectName('rock_on')
        group.addButton(widget)
        self.connect(widget,QtCore.SIGNAL('clicked()'),self.apply)
        line_layout.addStretch()
        line_layout.addWidget(widget)
        widget = QtGui.QLabel('speed')
        line_layout.addWidget(widget)
        widget = mgWidgets.mgSlider(QtCore.Qt.Horizontal,self)
        widget.setRange(0.1,5.0)
        widget.setObjectName('rockspeed')
        self.connect(widget,QtCore.SIGNAL("valueChanged(double)"),self.apply)
        line_layout.addWidget(widget)
        widget = QtGui.QLabel('angle')
        widget.setToolTip('Maximum rock angle')
        line_layout.addWidget(widget)
        widget = mgWidgets.mgSlider(QtCore.Qt.Horizontal,self)
        widget.setRange(0,90)
        widget.setObjectName('rockangle')
        self.connect(widget,QtCore.SIGNAL("valueChanged(double)"),self.apply)
        line_layout.addWidget(widget)
        layout.addLayout(line_layout)
        
        widget = QtGui.QRadioButton('No motion',self)
        widget.setObjectName('norockroll')
        self.connect(widget,QtCore.SIGNAL('clicked()'),self.apply)
        layout.addWidget(widget)
        group.addButton(widget)

        line_layout = QtGui.QHBoxLayout()
        group = QtGui.QButtonGroup(self)
        
        widget = QtGui.QLabel('Rock and roll axis:')
        line_layout.addWidget(widget)
        widget = QtGui.QRadioButton('vertical',self)
        widget.setObjectName('roll_vertical')
        group.addButton(widget)
        self.connect(widget,QtCore.SIGNAL('clicked()'),self.apply)
        line_layout.addWidget(widget)
        widget = QtGui.QRadioButton('horizontal',self)
        widget.setObjectName('roll_horizontal')
        group.addButton(widget)
        self.connect(widget,QtCore.SIGNAL('clicked()'),self.apply)
        line_layout.addWidget(widget)
        line_layout.addStretch()
        layout.addLayout(line_layout)
        
        self.setLayout(layout)

#-------------------------------------------------------------------
    def apply(self):
#-------------------------------------------------------------------
      self.emit(QtCore.SIGNAL("changed"))


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

      params.update(kw)
      rr = params.get('rockroll',-1)
      if rr==0:
        self.findChild(QtGui.QRadioButton,'norockroll').setChecked(1)
      elif rr==1:
        self.findChild(QtGui.QRadioButton,'roll_on').setChecked(1)
      elif rr==2:
        self.findChild(QtGui.QRadioButton,'rock_on').setChecked(1)

      for key in ['rockspeed','rollspeed','rockangle']:
        if params.has_key(key):
          self.findChild(mgWidgets.mgSlider,key).setValue(params[key])

      orientation = params.get('rollorientation','')
      if orientation:
        self.findChild(QtGui.QRadioButton,'roll_horizontal').setChecked(orientation=='x')
        self.findChild(QtGui.QRadioButton,'roll_vertical').setChecked(orientation=='y')

#-------------------------------------------------------------------
    def getParams(self):
#-------------------------------------------------------------------
      pars = {}
      mode = self.findChild(QtGui.QButtonGroup,'rockroll').checkedButton().objectName()
      if mode == 'rock_on':
        imode = 2
      elif mode == 'roll_on':
        imode = 1
      else:
        imode =0
      pars['rockroll'] = imode

      if self.findChild(QtGui.QRadioButton,'roll_horizontal').isChecked():
        pars['rollorientation']='x'
      else:
        pars['rollorientation']='y'

      for key in ['rollspeed','rockspeed','rockangle']:
        pars[key] = self.findChild(mgWidgets.mgSlider,key).value()

      #print "rockAndRollGUI pars",pars
      return pars

