"""
qtgui/mgWidgets.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.
"""
import sys
import os
from PyQt4 import QtGui,QtCore
import sip
import guiUtils
import global_definitions
import ColourBrowser
import MGSimpleDialog
import copy
from mgSliders import *
import mgapp
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class mgLineEdit(QtGui.QLineEdit):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# This class is just a kludge to intercept the return key press which
# in many dialog boxes activates default button
def __init__(self,parent=None):
QtGui.QLineEdit.__init__(self,parent)
def keyPressEvent(self,event=None):
#print 'mgLineEdit.keyPressEvent',event,event.key()
if event.key() == QtCore.Qt.Key_Return:
#print 'mgLineEdit emmit apply'
self.emit(QtCore.SIGNAL('apply'))
else:
QtGui.QLineEdit.keyPressEvent(self,event)
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class mgCidValidator(QtGui.QValidator):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def __init__(self,parent=None,mode='atom'):
QtGui.QValidator.__init__(self,parent)
self.mode = mode
self.useMMDB = 1
self.selHnd = -1
self.MolData_name = ''
'''
def __del__(self):
print 'mgCidValidator.__del__'
if self.useMMDB:
dobj.molHnd.DeleteSelection(self.selHnd)
QtGui.QValidator.__del__(self)
'''
def deleteSelHnd(self):
if not self.MolData_name or self.selHnd<0: return
dobj = data(self.MolData_name)
if dobj: dobj.molHnd.DeleteSelection(self.selHnd)
self.MolData_name = ''
self.selHnd = -1
def createSelHnd(self):
self.MolData_name = self.parent.MolData_name
dobj = self.parent().getDataobj()
self.selHnd = dobj.molHnd.NewSelection()
#----------------------------------------------------------------------
def validate(self,text='',pos=0):
#----------------------------------------------------------------------
import string
import pygl_coord
selindexp = pygl_coord.intp()
#print 'mgCidValidator.validate',text,self.parent().getDataobj()
text = string.strip(str(text))
if not text: return (QtGui.QValidator.Intermediate,pos)
dobj = self.parent().getDataobj()
if not dobj: return (QtGui.QValidator.Intermediate,pos)
if self.useMMDB:
import mmdb2 as mmdb
self.selHnd = dobj.molHnd.NewSelection()
if self.selHnd<0: self.createSelHnd()
if self.mode == 'atom':
selAtoms = mmdb.newPPCAtom()
dobj.molHnd.Select(self.selHnd,mmdb.STYPE_ATOM,text,mmdb.SKEY_NEW)
#nHits = dobj.molHnd.GetSelIndex(self.selHnd,selAtoms)
selAtoms = mmut.GetAtomSelIndex(dobj.molHnd,self.selHnd,selindexp)
nHits = selindexp.value()
elif self.mode == 'residue':
selRes = mmdb.newPPCResidue()
dobj.molHnd.Select(self.selHnd,mmdb.STYPE_RESIDUE,text,mmdb.SKEY_NEW)
#nHits = dobj.molHnd.GetSelIndex(self.selHnd,selRes)
selRes = mmut.GetResidueSelIndex(dobj.molHnd,self.selHnd,selindexp)
nHits = selindexp.value()
dobj.molHnd.DeleteSelection(self.selHnd)
if nHits == 1:
return (QtGui.QValidator.Acceptable,pos)
else:
return (QtGui.QValidator.Intermediate,pos)
else:
splitText = string.split(text,'/')
return (QtGui.QValidator.Acceptable,pos)
#----------------------------------------------------------------------
def fixup(self,text=''):
#----------------------------------------------------------------------
print 'mgCidValidator.fixup',text
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class mgSelectionCombo(QtGui.QFrame):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
pendingColour = QtCore.Qt.lightGray
regularColour = ''
def __init__(self,parent=None,abstractModel=None,modelGroups=['ligands','metal','peptide','nucleic','nucleotide','water','solute','nglycosylation','oglycosylation'],multi=0,selectionWidgets=[],highlightPending=0):
super(mgSelectionCombo,self).__init__(parent)
if not mgSelectionCombo.regularColour:
mgSelectionCombo.regularColour = self.palette().color(QtGui.QPalette.Normal,QtGui.QPalette.Button)
self.treeView = None
self.dataViewWindow = None
self.seleDialog = None
self.seleWidget = None
self.highlightPending = highlightPending
self.lastLineText = ''
self.selParams = {}
self.seleWidgetMode = ''
self.modelGroups = modelGroups
self.setFrameStyle(QtGui.QFrame.Panel|QtGui.QFrame.Plain)
margin = 0
layout = QtGui.QHBoxLayout()
layout.setContentsMargins(margin,margin,margin,margin)
layout.setSpacing(0)
if multi:
self.dataobjCombo = mgDataObjCombo(object_type='MolData',parent=self)
layout.addWidget(self.dataobjCombo)
else:
self.dataobjCombo = None
self.lineEdit = mgLineEdit(self)
#self.lineEdit = mgLineEdit(self)
ht = self.lineEdit.height()
self.lineEdit.setMinimumWidth(200)
wid = 200 + 2*ht
if selectionWidgets: wid = wid + ht
self.setMinimumWidth(wid)
layout.addWidget(self.lineEdit,5)
import guiUtils
icon = QtGui.QIcon(guiUtils.loadPixmap('seleTree','disptab'))
self.iconButton = QtGui.QToolButton(self)
self.iconButton.setPopupMode(QtGui.QToolButton.InstantPopup)
self.iconButton.setIcon(icon)
self.iconButton.setMaximumSize(QtCore.QSize(ht-2,ht-2))
self.iconButton.setToolTip('Open selection browser')
layout.addWidget(self.iconButton)
icon = QtGui.QIcon(guiUtils.loadPixmap('gtk-clear','disptab'))
self.clearButton = QtGui.QToolButton(self)
self.clearButton.setIcon(icon)
self.clearButton.setMaximumSize(QtCore.QSize(ht-2,ht-2))
self.clearButton.setToolTip('Clear selection')
layout.addWidget(self.clearButton)
if selectionWidgets:
icon = QtGui.QIcon(guiUtils.loadPixmap('lasso'))
self.seleButton = QtGui.QToolButton(self)
self.seleButton.setIcon(icon)
self.seleButton.setMaximumSize(QtCore.QSize(ht-2,ht-2))
self.seleButton.setToolTip('Open selection widgets')
#print 'mgSelectionCombo selectionWidgets',selectionWidgets
menu = QtGui.QMenu(self)
guiUtils.populateMenu(self,menu,selectionWidgets,default_icon='')
self.seleButton.setMenu(menu)
self.seleButton.setPopupMode(QtGui.QToolButton.InstantPopup)
layout.addWidget(self.seleButton)
self.setLayout(layout)
if not mgSelectionCombo.regularColour:
mgSelectionCombo.regularColour = self.lineEdit.palette().color( QtGui.QPalette.Base)
self.abstractModel = None
self.setAbstractModel(abstractModel=abstractModel)
if multi:
self.connect(self.dataobjCombo,QtCore.SIGNAL('currentIndexChanged(int)'), self.setAbstractModel)
self.connect (self.clearButton,QtCore.SIGNAL("released()"),self.clear)
self.connect(self.iconButton,QtCore.SIGNAL("released()"),self.toggleDataView)
self.connect(self.iconButton,QtCore.SIGNAL("pressed()"),self.returnPressed)
self.connect(self.lineEdit,QtCore.SIGNAL("apply"),self.returnPressed)
if self.highlightPending:
self.connect(self.lineEdit,QtCore.SIGNAL("textEdited(const QString)"),self.updateTextHighlight)
#----------------------------------------------------------------------
def toggleDataView(self):
#----------------------------------------------------------------------
#print "in toggleDataView"
geom = self.lineEdit.geometry().bottomLeft()
pos = self.mapToGlobal( self.lineEdit.geometry().bottomLeft() )
#print "mgSelectionCombo.toggleDataView",geom.x(),geom.y(),pos.x(),pos.y()
xx = pos.x()
yy = pos.y()
wid = self.lineEdit.width()
#print pos,xx,yy,wid
if not self.dataViewWindow:
self.dataViewWindow = QtGui.QDialog(self,QtCore.Qt.Popup)
#self.dataViewWindow = QtGui.QDialog(self)
layout = QtGui.QGridLayout()
layout.setContentsMargins(0,0,0,0)
import mgTreeView
self.treeView = mgTreeView.mgTreeView(self,self.abstractModel)
self.treeView.setExpandsOnDoubleClick(0)
self.treeView.loadGroups(self.modelGroups)
layout.addWidget(self.treeView,0,0,1,1)
self.dataViewWindow.setLayout(layout)
#self.connect(self.treeView,QtCore.SIGNAL('doubleClicked(QModelIndex)'),self.handleDoubleClick)
self.dataViewWindow.show()
self.dataViewWindow.setGeometry(xx,yy,wid,300)
self.updateTreeView()
self.connect(self.treeView,QtCore.SIGNAL('changed'),self.updateLineEdit)
elif self.dataViewWindow.isHidden():
self.dataViewWindow.show()
self.dataViewWindow.setGeometry(xx,yy,wid,300)
#self.updateTreeView()
else:
self.dataViewWindow.hide()
#----------------------------------------------------------------------
def returnPressed(self):
#----------------------------------------------------------------------
#print "returnPressed"
self.updateTreeView()
self.lastLineText = self.text()
self.updateTextHighlight()
self.emit(QtCore.SIGNAL("changed"))
#----------------------------------------------------------------------
def updateTextHighlight(self,text=''):
#----------------------------------------------------------------------
if not self.highlightPending: return
palette = self.lineEdit.palette()
#print 'updateTextHighlight',self.lastLineText,'*',self.text(),'*'
if self.text() != self.lastLineText:
self.lastLineText = self.text()
palette.setColor( QtGui.QPalette.Base, mgSelectionCombo.pendingColour )
#print 'updateTextHighlight pending'
else:
palette.setColor( QtGui.QPalette.Base, mgSelectionCombo.regularColour )
self.lastLineText = self.text()
#print 'updateTextHighlight regular'
self.lineEdit.setPalette(palette)
#----------------------------------------------------------------------
def updateLineEdit(self):
#----------------------------------------------------------------------
selected = self.treeView.selectedIndexes()
#print "mgSelectionCombo.updateLineEdit selected",selected
ret = self.abstractModel.interpretTreeSelection(selected,returnCommand=1)
if not ret[0]:
self.setText(ret[1])
self.emit(QtCore.SIGNAL("changed"))
#----------------------------------------------------------------------
def text(self):
#----------------------------------------------------------------------
return str(self.lineEdit.text())
#----------------------------------------------------------------------
def setText(self,text):
#----------------------------------------------------------------------
self.lineEdit.setText(text)
self.lastLineText = text
self.updateTextHighlight()
#----------------------------------------------------------------------
def getParams(self):
#----------------------------------------------------------------------
if self.seleWidget: self.selParams.update(self.seleWidget.getParams())
return self.selParams
#----------------------------------------------------------------------
def setParams(self,params={},**kw):
#----------------------------------------------------------------------
params.update(kw)
self.selParams.update(params)
if self.seleWidget: self.seleWidget.setParams(self.selParams)
if self.selParams.has_key('selection'): self.setText(self.selParams['selection'])
#----------------------------------------------------------------------
def updateTreeView(self):
#----------------------------------------------------------------------
if self.treeView:
sele_text = str(self.lineEdit.text())
#Test if this is a named selection (eg all/peptide)
rv = self.treeView.setGroupSelection(sele_text)
if not rv: return
# Make sure command will actually parse
molobj = self.getCurrentDataObj()
rv = molobj.parse_selection(command=sele_text)
#print "mgSelectionCombo.updateTreeView rv",rv
# Update tree view
if not rv[0]:
#self.disconnect(self.treeView,QtCore.SIGNAL('changed'),self.updateLineEdit)
self.treeView.blockSignals(True)
self.treeView.clearSelection()
self.treeView.loadMMDBSelection(rv[1])
molobj.molHnd.DeleteSelection(rv[1])
#self.connect(self.treeView,QtCore.SIGNAL('changed'),self.updateLineEdit)
self.treeView.blockSignals(False)
#----------------------------------------------------------------------
def clear(self):
#----------------------------------------------------------------------
#print "mgSelectionCombo.clear",self.treeView
if self.treeView:
#self.disconnect(self.treeView,QtCore.SIGNAL('changed'),self.updateLineEdit)
self.treeView.blockSignals(True)
self.treeView.clearSelection()
#print "mgSelectionCombo from treeView.clearSelection"
self.setText('')
if self.treeView:
#self.connect(self.treeView,QtCore.SIGNAL('changed'),self.updateLineEdit)
self.treeView.blockSignals(False)
self.emit(QtCore.SIGNAL("changed"))
#------------------------------------------------------------------------
def setAbstractModel(self,index=-1,abstractModel=''):
#------------------------------------------------------------------------
'''
Set the abstract model - beware used as slot and receives index from
comboBox
'''
if abstractModel:
if abstractModel == self.abstractModel: return
self.abstractModel = abstractModel
elif self.dataobjCombo:
dobj = self.dataobjCombo.getCurrentDataObj()
if dobj and hasattr(dobj,'treeModel'):
if dobj.treeModel == self.abstractModel: return
self.abstractModel = dobj.treeModel
else:
return
self.dataViewWindow = None
self.setText('')
#----------------------------------------------------------------------
def handleDoubleClick(self):
#----------------------------------------------------------------------
#print "emit doubleClick"
self.emit(QtCore.SIGNAL("doubleClicked()"))
self.dataViewWindow.hide()
#----------------------------------------------------------------------
def getCurrentDataObj(self):
#----------------------------------------------------------------------
if self.dataobjCombo:
return self.dataobjCombo.getCurrentDataObj()
else:
return self.abstractModel.MolDataObj
#----------------------------------------------------------------------
def setCurrentDataObj(self,MolData=''):
#----------------------------------------------------------------------
if self.dataobjCombo:
self.dataobjCombo.setCurrentDataObj(MolData)
#----------------------------------------------------------------------
def getActionDef(self,name):
#----------------------------------------------------------------------
if name == 'neighb':
return dict (
text = 'Neighbourhood..',
icon = '',
tip = 'Select atoms/residues around central atom(s)',
signal = 'triggered()',
slot = guiUtils.partial(self.openSelectionWidget,name)
)
if name == 'buried':
return dict (
text = 'Buried area..',
icon = '',
tip = 'Select atoms/residues buried by another set of atoms',
signal = 'triggered()',
slot = guiUtils.partial(self.openSelectionWidget,name)
)
if name == 'secStr':
return dict (
text = 'Secondary structure..',
icon = '',
tip = 'Select secondary structure elements',
signal = 'triggered()',
slot = guiUtils.partial(self.openSelectionWidget,name)
)
if name == 'resType':
return dict (
text = 'Residue types..',
icon = '',
tip = 'Select residue types',
signal = 'triggered()',
slot = guiUtils.partial(self.openSelectionWidget,name)
)
if name == 'chains':
return dict (
text = 'Chains..',
icon = '',
tip = 'Select whole chains',
signal = 'triggered()',
slot = guiUtils.partial(self.openSelectionWidget,name)
)
if name == 'property':
return dict (
text = 'Property..',
icon = '',
tip = 'Select by the value of atom property',
signal = 'triggered()',
slot = guiUtils.partial(self.openSelectionWidget,name)
)
if name == 'namedSelection':
return dict (
text = 'Save/restore selection..',
icon = '',
tip = 'Save or restore a selection',
signal = 'triggered()',
slot = guiUtils.partial(self.openSelectionWidget,name)
)
return {}
#----------------------------------------------------------------------
def openSelectionWidget(self,name):
#----------------------------------------------------------------------
import selectionBrowser
if self.seleWidget:
if self.seleWidgetMode == name:
self.seleDialog.show()
self.seleDialog.raise_()
return
else:
self.selParams.update(self.seleWidget.getParams())
self.seleWidget.close()
#self.seleWidget.deleteLater()
self.seleWidget=None
self.seleWidgetMode = ''
if self.seleDialog:
#self.seleDialog.deleteLater()
self.seleDialog.close()
self.seleDialog = QtGui.QDialog(self)
layout = QtGui.QVBoxLayout()
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
if name == 'neighb':
self.seleDialog.setWindowTitle('Select neighbourhood for '+self.getCurrentDataObj().name_label)
self.seleWidget = selectionBrowser.neighbGui(self.seleDialog,self.getCurrentDataObj().name_label )
self.seleWidget.setParams()
self.connect(self.seleWidget,QtCore.SIGNAL('accepted()'),guiUtils.partial(self.updateFromTabWidget,'neighb'))
if name == 'buried':
self.seleDialog.setWindowTitle('Select buried area for '+self.getCurrentDataObj().name_label)
self.seleWidget = selectionBrowser.buriedGui(self.seleDialog,self.getCurrentDataObj().name_label )
self.seleWidget.setParams()
self.connect(self.seleWidget,QtCore.SIGNAL('accepted()'),guiUtils.partial(self.updateFromTabWidget,'buried'))
elif name == 'namedSelection':
self.seleDialog.setWindowTitle('Save/restore selection for '+self.getCurrentDataObj().name_label)
self.seleWidget = selectionBrowser.namedSelectionGui(self.seleDialog,self.getCurrentDataObj().name_label,delete=0 )
self.connect(self.seleWidget,QtCore.SIGNAL('save'),self.saveNamedSelection)
self.connect(self.seleWidget,QtCore.SIGNAL('restore'),self.restoreNamedSelection)
elif name == 'secStr':
self.seleDialog.setWindowTitle('Select secondary structure for '+self.getCurrentDataObj().name_label)
self.seleWidget = selectionBrowser.secStrGui(self.seleDialog,self.getCurrentDataObj().name_label )
self.seleWidget.setGeometry(0,0,selectionBrowser.tabWidth,selectionBrowser.tabHeight)
self.seleDialog.setFixedHeight(selectionBrowser.tabHeight+20)
self.seleDialog.setFixedWidth(selectionBrowser.tabWidth+20)
self.connect(self.seleWidget,QtCore.SIGNAL('accepted()'),guiUtils.partial(self.updateFromTabWidget,'secStr'))
elif name == 'property':
self.seleDialog.setWindowTitle('Select by property for '+self.getCurrentDataObj().name_label)
self.seleWidget = selectionBrowser.propertyGui(self.seleDialog,self.getCurrentDataObj().name_label )
self.connect(self.seleWidget,QtCore.SIGNAL('accepted()'),guiUtils.partial(self.updateFromTabWidget,'property'))
elif name == 'resType':
self.seleDialog.setWindowTitle('Select by residue type for '+self.getCurrentDataObj().name_label)
self.seleWidget = selectionBrowser.resTypeGui(self.seleDialog,self.getCurrentDataObj().name_label )
self.seleWidget.setGeometry(0,0,selectionBrowser.tabWidth,selectionBrowser.tabHeight)
self.seleDialog.setFixedHeight(selectionBrowser.tabHeight+20)
self.seleDialog.setFixedWidth(selectionBrowser.tabWidth+20)
self.connect(self.seleWidget,QtCore.SIGNAL('accepted()'),guiUtils.partial(self.updateFromTabWidget,'resType'))
elif name == 'chains':
self.seleDialog.setWindowTitle('Select chains for '+self.getCurrentDataObj().name_label)
self.seleWidget = selectionBrowser.chainsGui(self.seleDialog,self.getCurrentDataObj().name_label )
self.seleWidget.setGeometry(0,0,selectionBrowser.tabWidth,selectionBrowser.tabHeight)
self.seleDialog.setFixedHeight(selectionBrowser.tabHeight+20)
self.seleDialog.setFixedWidth(selectionBrowser.tabWidth+20)
self.connect(self.seleWidget,QtCore.SIGNAL('accepted()'),guiUtils.partial(self.updateFromTabWidget,'chains'))
#print "openSelectionWidget name",name
if name != 'namedSelection' and self.seleWidget: self.seleWidget.setParams(self.selParams)
layout.addWidget(self.seleWidget)
self.seleDialog.setLayout(layout)
self.seleWidget.show()
self.seleDialog.show()
self.seleWidgetMode = name
#---------------------------------------------------------------------------
def restoreNamedSelection(self):
#---------------------------------------------------------------------------
set,name = self.seleWidget.getSelection()
if name:
import model_selection
SelHandle = model_selection.SelHandle(self.getCurrentDataObj().name)
SelHandle.restoreSelection(name)
#print "restoreNamedSelection command",SelHandle.getCommand()
self.setText(SelHandle.getCommand())
del SelHandle
self.updateTreeView()
self.emit(QtCore.SIGNAL("changed"))
#---------------------------------------------------------------------------
def saveNamedSelection(self):
#---------------------------------------------------------------------------
pars = self.seleWidget.getSaveParams()
name = pars.get('name','')
if name:
save_mode = pars.get('save_mode','this')
import model_selection
SelHandle = model_selection.SelHandle(self.getCurrentDataObj().name)
#print "saveNamedSelection command",self.text()
SelHandle.setCommand(self.text())
SelHandle.saveSelection (name=name,save_mode=save_mode,overwrite=1)
del SelHandle
DISPLAYTABLE().getDataObj(self.getCurrentDataObj().name).handleSavedSelection(save_mode)
#self.seleWidget.populateList()
#----------------------------------------------------------------------
def updateFromTabWidget(self,mode=''):
#----------------------------------------------------------------------
# Update browser based on input to one of the tab widgets
# First get the widget to return its selection in the
# form of a SelHandle
widgetSelHandle = self.seleWidget.getSelHandle()
if not widgetSelHandle: return
#print "updateFromTabWidget command",widgetSelHandle.getCommand()
self.setText(widgetSelHandle.getCommand())
del widgetSelHandle
self.updateTreeView()
self.emit(QtCore.SIGNAL("changed"))
if self.seleDialog:
self.seleDialog.close()
return 0
#----------------------------------------------------------------------
def close(self):
#----------------------------------------------------------------------
if self.seleDialog:
self.seleDialog.close()
#self.seleDilog.deleteLater()
self.seleDialog = None
QtGui.QFrame.close(self)
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#class mgDataObjCombo(QtGui.QComboBox,dataobj.Dependency):
class mgDataObjCombo(QtGui.QComboBox):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def __init__(self,object_type='',default='',null='',parent=None):
# default should be a name_label for the model
super(mgDataObjCombo,self).__init__(parent)
# Maintain list of data objects that are excluded
self.exclude_list = []
self.null = null
#dataobj.Dependency.__init__(self)
self.object_type = object_type
self.setEditable(0)
self.populateMenu(default=default)
#import model
#if object_type == 'MolData':
# self.add_dependency(model.MolData,['create'],[self.populateMenu])
self.connect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('addDataObj'),self.resetMenu)
self.connect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('deleteDataObj'),self.resetMenu)
self.connect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('loadAllDataObj'),self.resetMenu)
self.connect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('update'),self.resetMenu)
self.connect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('update_labels'),self.resetMenu)
#----------------------------------------------------------------------
def disconnectGlobalSignals(self):
#----------------------------------------------------------------------
self.disconnect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('addDataObj'),self.resetMenu)
self.disconnect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('deleteDataObj'),self.resetMenu)
self.disconnect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('loadAllDataObj'),self.resetMenu)
self.disconnect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('update'),self.resetMenu)
self.disconnect(global_definitions.DISPLAYTABLE(),QtCore.SIGNAL('update_labels'),self.resetMenu)
#----------------------------------------------------------------------
def resetMenu(self):
#----------------------------------------------------------------------
#print 'mgDataObjCombo.resetMenu'
self.blockSignals(1)
current = self.getCurrentDataObj()
if current:
default = current.name
else:
default = ''
self.emit(QtCore.SIGNAL('currentDataObjDeleted()'))
self.populateMenu(default = default)
self.blockSignals(0)
#----------------------------------------------------------------------
def populateMenu(self,default='',attributes=[],**keywords):
#----------------------------------------------------------------------
#print "mgDataObjCombo populateMenu",default
self.clear()
if self.null: self.addItem(self.null,QtCore.QVariant(self.null))
obj_list = global_definitions.get_dataobj(object_type = self.object_type)
#print "mgDataObjCombo.populateMenu obj_list",obj_list
if obj_list:
for obj in obj_list:
if not self.exclude_list.count(obj.name):
self.addItem(obj.name_label,QtCore.QVariant(obj.name))
elif self.null:
# make sure ther is a 'blank' option in case user deletes all objects
self.addItem(self.null,QtCore.QVariant(self.null))
# Set up dependencies
#self.add_dependency(obj,['delete','rename'],[self.populateMenu])
default_index = 0
if default:
default_obj = global_definitions.get_dataobj(name=default)
if default_obj and len(default_obj)>0 and obj_list.count(default_obj[0]):
default_index = obj_list.index(default_obj[0])
if self.null: default_index = default_index + 1
self.setCurrentIndex(default_index)
elif len(obj_list) == 1 and self.null:
default_index = 1
self.setCurrentIndex(default_index)
#print "currentIndex",self.currentIndex()
## **********delete the dependencies!!!
#----------------------------------------------------------------------
def setCurrentDataObj(self,name):
#----------------------------------------------------------------------
for n in range(0,self.count()):
if str(self.itemData(n).toString())==name:
self.setCurrentIndex(n)
break
#----------------------------------------------------------------------
def getCurrentDataObj(self):
#----------------------------------------------------------------------
if self.currentIndex()<0:
return None
else:
# * beware the text is the DataObj.name_label which is not necessarilly
# unique - check the userData for the DataObj.name
name = str(self.itemData(self.currentIndex()).toString())
obj_list = global_definitions.get_dataobj(name = name)
#print 'getCurrentDataObj',name,obj_list
if obj_list:
return obj_list[0]
else:
return None
def setExcludeDataObjList(self,excluded=[]):
self.exclude_list = excluded
self.resetMenu()
def getExcludeDataObjList(self):
return self.exclude_list
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class MGOpenFileDialog(QtGui.QDialog):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def __init__(self,parent=None,title='Open file',filters=[],defaultSuffix='',defaultFileName=''):
QtGui.QDialog.__init__(self,parent)
self.setWindowTitle(self.tr(title))
layout = QtGui.QGridLayout()
filed = MGFileDialog(self)
self.fileDialog = filed.getFileDialog()
self.fileDialog.setNameFilters(filters)
selectedFilter = str(self.fileDialog.selectedNameFilter().toAscii())
needDefaultSuffix = False
if selectedFilter.find('(')>-1 and selectedFilter.find(')')>selectedFilter.find('('):
splitFilters = selectedFilter[selectedFilter.find('(')+1:selectedFilter.find(')')].strip().split(' ')
if (len(splitFilters) == 1 and splitFilters[0]=='*.*') or (len(splitFilters) > 0 and splitFilters[0]=='*.*') or len(splitFilters) > 1:
needDefaultSuffix = True
if defaultSuffix and ((len(self.fileDialog.filters())==1 and str((self.fileDialog.filters()[0]).toAscii()).find(self.tr('All Files'))>-1)) or (len(self.fileDialog.filters()))==0:
self.fileDialog.setDefaultSuffix(defaultSuffix)
if defaultFileName: self.fileDialog.selectFile(defaultFileName)
self.connect(self.fileDialog, QtCore.SIGNAL('rejected()'),self.close)
children = self.fileDialog.findChildren(QtGui.QPushButton,"")
for child in children:
if child.text() == self.tr("&Open"):
self.connect(child, QtCore.SIGNAL('pressed()'),self.openFile)
layout.addWidget(filed)
self.setLayout(layout)
def openFile(self):
files = self.fileDialog.selectedFiles()
if files:
self.emit(QtCore.SIGNAL('open'),str(files[0].toUtf8()))
self.close()
def getFilename(self):
files = self.fileDialog.selectedFiles()
if files:
return str(files[0].toUtf8())
else:
return ''
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class MGSaveFileDialog(QtGui.QDialog):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def exec_(self):
QtGui.QDialog.exec_(self)
def __init__(self,parent=None,title='Save to file',filters=[],defaultSuffix='',defaultFileName=''):
QtGui.QDialog.__init__(self,parent)
self.setWindowTitle(self.tr(title))
layout = QtGui.QGridLayout()
filed = MGFileDialog(self)
self.fileDialog = filed.getFileDialog()
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
self.fileDialog.setConfirmOverwrite(False)
self.fileDialog.setNameFilters(filters)
selectedFilter = str(self.fileDialog.selectedNameFilter().toAscii())
needDefaultSuffix = False
if selectedFilter.find('(')>-1 and selectedFilter.find(')')>selectedFilter.find('('):
splitFilters = selectedFilter[selectedFilter.find('(')+1:selectedFilter.find(')')].strip().split(' ')
if (len(splitFilters) == 1 and splitFilters[0]=='*.*') or (len(splitFilters) > 0 and splitFilters[0]=='*.*') or len(splitFilters) > 1:
needDefaultSuffix = True
if defaultSuffix and (((len(self.fileDialog.filters())==1 and str((self.fileDialog.filters()[0]).toAscii()).find(self.tr('All Files'))>-1)) or (len(self.fileDialog.filters()))==0 or needDefaultSuffix):
self.fileDialog.setDefaultSuffix(defaultSuffix)
if defaultFileName: self.fileDialog.selectFile(defaultFileName)
self.connect(self.fileDialog, QtCore.SIGNAL('rejected()'),self.close)
children = self.fileDialog.findChildren(QtGui.QPushButton,"")
for child in children:
if child.text() == self.tr("&Save"):
self.connect(child, QtCore.SIGNAL('pressed()'),self.save)
layout.addWidget(filed)
self.setLayout(layout)
self.connect(self.fileDialog, QtCore.SIGNAL('filesSelected(const QStringList&)'),self.saveSelected)
self.defaultSuffix = defaultSuffix
def setDefaultFileName(self,defaultFileName):
self.fileDialog.selectFile(defaultFileName)
def saveSelected(self,files=None):
if files:
self.emit(QtCore.SIGNAL('save'),str(files[0].toUtf8()))
self.close()
def save(self):
files = self.fileDialog.selectedFiles()
theFile = str(files[0].toUtf8())
if files:
if files[0].count('.') == 0:
selectedFilter = str(self.fileDialog.selectedNameFilter().toAscii())
if selectedFilter.find('(')>-1 and selectedFilter.find(')')>selectedFilter.find('('):
splitFilters = selectedFilter[selectedFilter.find('(')+1:selectedFilter.find(')')].strip().split(' ')
if (len(splitFilters) == 1 and splitFilters[0]=='*.*') or (len(splitFilters) > 0 and splitFilters[0]=='*.*') or len(splitFilters) > 1:
useSuffix = self.defaultSuffix
useSuffix = useSuffix[useSuffix.find('.'):]
theFile = theFile + useSuffix
elif len(splitFilters) == 1:
useSuffix = splitFilters[0]
useSuffix = useSuffix[useSuffix.find('.'):]
theFile = theFile + useSuffix
self.emit(QtCore.SIGNAL('save'),theFile)
self.close()
def getFilename(self):
files = self.fileDialog.selectedFiles()
if files:
return str(files[0].toUtf8())
else:
return ''
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class MGFileDialog(QtGui.QWidget):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
last_directory = ''
def event(self,event=None):
if event.type()==QtCore.QEvent.WhatsThisClicked:
import global_definitions
global_definitions. HELPBROWSER().loadMgHelp(file=str(event.href()))
return QtGui.QWidget.event(self,event)
def __init__(self,parent=None,editAlias=0):
QtGui.QWidget.__init__(self,parent)
self.setWhatsThis(self.tr("A file dialog for opening data files supported by ccp4mg with a wizard to select drawing styles of molecular structure more help"))
layout = QtGui.QVBoxLayout()
ccp4_dirs,ccp4_aliases = global_definitions.CCP4DATABASE().getProjectsList()
if len(ccp4_dirs)>0 or len(ccp4_aliases)>0:
layout0 = QtGui.QHBoxLayout()
self.ccp4i_combo = QtGui.QComboBox()
self.load_ccp4i_combo()
ccp4i_label1 = QtGui.QLabel()
ccp4i_label1.setText("Look in ccp4 project or aliased directory:")
if editAlias:
ccp4i_button = QtGui.QPushButton('Edit aliases',self)
ccp4i_label2 = QtGui.QLabel(" or ...")
layout0.addWidget(ccp4i_label1)
layout0.addWidget(self.ccp4i_combo)
if editAlias: layout0.addWidget(ccp4i_button)
layout0.addWidget(ccp4i_label2)
layout0.addStretch()
layout.addLayout(layout0)
self.connect(self.ccp4i_combo,QtCore.SIGNAL("activated(const QString&)"),self.ccp4iDirectoryChanged)
if editAlias: self.connect(ccp4i_button,QtCore.SIGNAL("clicked()"),self.editAlias)
self.connect(global_definitions.CCP4DATABASE(),QtCore.SIGNAL('directoriesChanged'),self.load_ccp4i_combo)
self.filedialog = MGFileDialog0(parent)
self.filedialog.setObjectName('fileDialog')
layout.addWidget( self.filedialog)
if len(ccp4_dirs)>0:
self.connect( self.filedialog, QtCore.SIGNAL('directoryEntered(QString)'),self.update_ccp4i_combo)
self.setLayout(layout)
# Set keyboard focus to text input widget
self.filedialog.findChildren(QtGui.QLineEdit)[0].setFocus(QtCore.Qt.ActiveWindowFocusReason)
if MGFileDialog.last_directory:
#print "setting last_directory",MGFileDialog.last_directory
self.filedialog.setDirectory(MGFileDialog.last_directory)
if len(ccp4_dirs)>0 or len(ccp4_aliases)>0:
self.update_ccp4i_combo(self.filedialog.directory().path())
def load_ccp4i_combo(self):
self.ccp4i_combo.clear()
self.ccp4i_combo.addItem(' -Projects- ')
ccp4_dirs,ccp4_aliases = global_definitions.CCP4DATABASE().getProjectsList()
print ccp4_dirs,ccp4_aliases
for project in ccp4_dirs:
#self.ccp4i_combo.addItem(project)
self.ccp4i_combo.addItem(unicode(project,'utf-8'))
self.ccp4i_combo.addItem(' -Aliases- ')
for project in ccp4_aliases: self.ccp4i_combo.addItem(project)
def ccp4iDirectoryChanged(self,alias):
path = global_definitions.CCP4DATABASE().get_project_dir(str(alias.toUtf8()))
if path:
self.filedialog.setDirectory(unicode(path,'utf-8'))
MGFileDialog.last_directory = path
def getFileDialog(self):
return self.filedialog
def setSidebar(self):
url_list = self.filedialog.sidebarUrls ()
#print "in setSidebar",url_list
for item in url_list:
#print "side bar",item.path(),item.port(),'*',item.host()
pass
#self.filedialog.setSidebarUrls(side)
#for path in ['/work/stuart']:
# url = QtCore.QUrl("file://"+path)
# url_list.append(url)
self.filedialog.setSidebarUrls(url_list )
def update_ccp4i_combo(self,directory):
MGFileDialog.last_directory = directory
proj = global_definitions.CCP4DATABASE().aliasForDir(str(directory.toUtf8()))
if proj:
indx = self.ccp4i_combo.findText(unicode(proj,'utf-8'))
if indx>=0:
self.ccp4i_combo.setCurrentIndex(indx)
return
self.ccp4i_combo.setCurrentIndex(0)
def editAlias(self):
import ccp4iGui
ccp4iGui.ccp4iAliasGui(self)
def setLabelText(self,mode,text):
self.filedialog.setLabelText(mode,text)
def selectFile(self,file):
#print 'MGFileDialog.selectFile',file
self.filedialog.selectFile(file)
class IconProvider(QtGui.QFileIconProvider):
def __init__(self):
QtGui.QFileIconProvider.__init__(self)
self._filters = {}
self._icon_cache = {}
def setIconForFilter(self,icon,filter):
self._filters[icon] = filter
def setIconsForFilters(self,filters):
self._filters = filters
def icon(self,info):
if info and hasattr(info,'filePath'):
for k in self._filters:
for f in self._filters[k]:
if repr(info.filePath()).endswith(f):
if not self._icon_cache.has_key(k):
self._icon_cache[k] = QtGui.QIcon(k)
return self._icon_cache[k]
return QtGui.QFileIconProvider.icon(self,info)
class ProxyModel(QtGui.QSortFilterProxyModel):
def __init__(self,parent=None):
QtGui.QSortFilterProxyModel.__init__(self,parent)
def filterAcceptsRow(self, sourceRow, sourceParent):
if sourceParent.row() == -1 or sourceParent.column():
return True
index0 = self.sourceModel().index(sourceRow, 0, sourceParent);
if self.sourceModel().isDir(index0):
return True
for f in self.sourceModel().nameFilters():
if str(self.sourceModel().fileName(index0).toUpper()).endswith(str(f).lstrip('*').upper()):
return True
return False
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class MGFileDialog0(QtGui.QFileDialog):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# Reimplement to stop widget closing immediately a file is selected
def addFilters(self,filters_in):
filters = self.filters()
for filter in filters_in:
filters.append(filter)
self.setNameFilters(filters)
def addFilter(self,filter):
filters = self.filters()
filters.append(filter)
self.setNameFilters(filters)
def setNameFilters(self,filters,all=1):
import types
self.suffix_lookup = {}
all_filters = "All files ("
new_filters = []
for filt in filters:
#print "setNameFilters filt",filt
if isinstance(filt,types.ListType):
self.suffix_lookup[filt[0]] = filt[1]
filter = str(filt[0])
else:
filter = str(filt)
if len(filter)>11 and filter[:11] == 'All files (' and (filter).rfind(')') > 0:
pass
else:
new_filters.append(filter)
left_par = filter.rfind('(')
right_par = filter.rfind(')')
if left_par > -1 and right_par > 0 and right_par > left_par:
if (filter[left_par+1:right_par]).find('*')>-1:
all_filters = all_filters + " " + filter[left_par+1:right_par]
else:
all_filters = all_filters + " " + filter
else:
all_filters = all_filters + " " + filter
all_filters = all_filters + " )"
total_filters = new_filters
# Put all_filters at end of list when saving file and
# at beginning when reading file
if all:
if self.acceptMode() == QtGui.QFileDialog.AcceptSave:
total_filters.append(all_filters)
else:
total_filters.insert(0,all_filters)
QtGui.QFileDialog.setNameFilters(self,total_filters)
if self.suffix_lookup:
self.setSuffix(filters[0][0])
self.connect(self,QtCore.SIGNAL('filterSelected(QString)'),self.setSuffix)
def checkMounts(self,**args):
try:
import subprocess
import signal
signal.siginterrupt(signal.SIGCHLD,False)
except:
pass
mounts = []
try:
syscmd = "/sbin/mount"
p = subprocess.Popen([syscmd],stdout=subprocess.PIPE)
output = p.communicate()[0].split('\n')
except:
return
for o in output:
if o and o.find('/dev/disk')==0:
t = o[o.find(' ')+1:]
t2 = t[t.find(' ')+1:]
mounts.append(t2[:t2.find('(')-1])
if mounts != self._old_mounts:
#print "CHANGE!!", mounts
urls = self.sidebarUrls()
newUrls = []
_urls = []
for url in urls:
if url.host() == "" and url.port() == -1:
path = str(url.toLocalFile().toAscii())
if path == '': path = '/'
if path.find('/Volumes') == 0:
if path in mounts:
newUrls.append(url)
_urls.append(path)
else:
newUrls.append(url)
_urls.append(path)
for m in mounts:
if m != '/':
if not m in _urls:
newUrls.append(QtCore.QUrl.fromLocalFile(m))
_urls.append(path)
self.setSidebarUrls(newUrls)
self._old_mounts = mounts
def checkMountsNew(self,**args):
fd = self
sb = fd.sidebarUrls()
for url in sb[:]:
path = str(url.toLocalFile().toAscii())
if path.find('/Volumes') == 0:
if not os.path.exists(path):
sb.remove(url)
# Clear everything
fd.setSidebarUrls([])
for loc in [QtGui.QDesktopServices.HomeLocation,QtGui.QDesktopServices.DesktopLocation,QtGui.QDesktopServices.DocumentsLocation]:
path = QtGui.QDesktopServices.storageLocation(loc)
url = QtCore.QUrl.fromLocalFile(path)
if not url in sb:
sb.append(url)
# The following will hopefully be replaced by QStorageInfo in Qt5.
if sys.platform == "darwin":
for v in os.listdir('/Volumes'):
url = QtCore.QUrl.fromLocalFile(os.path.join("/Volumes/",v))
if not url in sb:
sb.append(url)
"""
# This would probably be good on windows
roots = QtCore.QDir.drives()
for r in roots:
print r.filePath()
"""
# Add "My Computer"
computer = QtCore.QUrl.fromLocalFile('')
if not computer in sb:
sb.insert(0,computer)
fd.setSidebarUrls(sb)
def __init__(self,parent=None):
QtGui.QFileDialog.__init__(self,parent)
self.setSizeGripEnabled(0)
"""
if sys.platform == "darwin": # We will need to implement the low level stuff for other oses.
self.fstimer = QtCore.QTimer();
self.connect(self.fstimer, QtCore.SIGNAL("timeout()"), self.checkMounts);
self.fstimer.start(2000);
self._old_mounts = []
self.checkMounts()
"""
self.checkMountsNew()
#self.show()
"""
pm = ProxyModel()
self.setProxyModel(pm)
iconProvider = IconProvider()
iconProvider.setIconsForFilters({
os.path.join(os.environ["CCP4MG"],'qticons','dispobj','MolData.png'):['.pdb','.pdb.gz','.ent','.ent.gz','.brk','.brk.gz'],
os.path.join(os.environ["CCP4MG"],'qticons','dispobj','MapData.png'):['.map','mtz'],
os.path.join(os.environ["CCP4MG"],'qticons','dispobj','VectorsData.svg'):['.vector']
})
self.setIconProvider(iconProvider)
"""
def close(self):
pass
def done(self,mode):
pass
def reject(self):
#print "MGFileDialog reject",self.parent(),self.window()
if self.window():
self.window().close()
else:
self.close()
def setSuffix(self,filter):
filter = str(filter)
#print "setSuffix",filter
if self.suffix_lookup.has_key(filter):
self.setDefaultSuffix(self.suffix_lookup[filter])
def selectFile(self,file):
#print 'MGFileDialog0.selectFile',file
#QFileDialog.selectFile does not work for selecting non-existing files
# as you would want in Save mode - so try this kludge
if self.fileMode() == QtGui.QFileDialog.ExistingFile:
widget = self.findChild(QtGui.QLineEdit,'fileNameEdit')
#print 'MGFileDialog0.selectFile widget',widget
if widget: widget.setText(file)
else:
QtGui.QFileDialog.selectFile(self,file)
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
class mgGroupSelector(QtGui.QWidget):
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
def __init__(self,parent=None,groups=[],items=[],reMatch=0,closeButton=0,
height=200,width=400):
super(mgGroupSelector,self).__init__(parent)
self.groupOrder = []
self.groupSelection = {}
self.itemOrder = []
self.itemText = {}
self.reMatch = reMatch
self.closeButton = closeButton
self.widgetHeight = height
self.widgetWidth = width
self.addItems(items)
self.addGroups(groups)
self.draw()
#-----------------------------------------------------------------------
def addItems(self,items=[]):
#-----------------------------------------------------------------------
import types
for it in items:
if len(it) >= 2 and isinstance(it[0],types.StringType) and isinstance(it[1],types.StringType):
self.itemOrder.append(it[0])
self.itemText[it[0]] = it[1]
#print "addItems",self.itemOrder
#-----------------------------------------------------------------------
def addGroups(self,groups=[]):
#-----------------------------------------------------------------------
import types
for gp in groups:
if len(gp) >= 2 and isinstance(gp[0],types.StringType) and isinstance(gp[1],types.ListType):
self.groupOrder.append(gp[0])
self.groupSelection[gp[0]] = gp[1]
elif len(gp) == 1:
self.groupOrder.append(gp[0])
#-----------------------------------------------------------------------
def select(self,group='',state=1):
#-----------------------------------------------------------------------
#print "select group",group,self.itemOrder
if group:
if group == 'all':
for item in self.itemOrder:
but = self.itemList.findChild(QtGui.QCheckBox,item)
if but: but.setChecked(1)
elif group == 'clear':
for item in self.itemOrder:
but = self.itemList.findChild(QtGui.QCheckBox,item)
if but: but.setChecked(0)
elif self.groupSelection.has_key(group):
if self.reMatch:
for item in self.groupSelection[group]:
#print "searching for",item
but_list = self.itemList.findChildren(QtGui.QCheckBox,item)
#print "but_list",but_list
for but in but_list: but.setChecked(state)
else:
for item in self.groupSelection[group]:
but = self.itemList.findChild(QtGui.QCheckBox,item)
if but: but.setChecked(state)
#-----------------------------------------------------------------------
def draw(self):
#-----------------------------------------------------------------------
# Scrolled list of items with checkboxes on left side
self.listArea = QtGui.QScrollArea(self)
margin = 0
layout0 = QtGui.QHBoxLayout()
self.listArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
#self.listArea.setFixedHeight(self.widgetHeight)
#self.listArea.setMinimumWidth(self.widgetWidth-220)
self.itemList = QtGui.QWidget()
layout = QtGui.QVBoxLayout()
layout.setContentsMargins(margin,margin,margin,margin)
layout.setSpacing(margin)
for item in self.itemOrder:
cb = QtGui.QCheckBox(self.itemText[item].strip(),self)
cb.setObjectName(item)
layout.addWidget(cb)
self.itemList.setLayout(layout)
self.listArea.setWidget(self.itemList)
layout0.addWidget(self.listArea)
if self.groupOrder:
self.custom_box = QtGui.QWidget()
layout = QtGui.QVBoxLayout()
layout.setContentsMargins(margin,margin,margin,margin)
layout.setSpacing(margin)
layout.addStretch(5)
for gp in self.groupOrder:
w = QtGui.QPushButton(gp,self)
w.setObjectName(gp)
layout.addWidget(w)
self.connect(w,QtCore.SIGNAL('released()'),guiUtils.partial(self.select,gp))
self.custom_box.setLayout(layout)
layout0.addWidget(self.custom_box)
rbox = QtGui.QWidget()
layout = QtGui.QVBoxLayout()
layout.setContentsMargins(margin,margin,margin,margin)
layout.setSpacing(margin)
clear = QtGui.QPushButton('Clear',self)
clear.setContentsMargins(margin,margin,margin,margin)
layout.addWidget(clear)
self.connect(clear,QtCore.SIGNAL('released()'),guiUtils.partial(self.select,'clear'))
all = QtGui.QPushButton('Select all',self)
all.setContentsMargins(margin,margin,margin,margin)
layout.addWidget(all)
self.connect(all,QtCore.SIGNAL('released()'),guiUtils.partial(self.select,'all'))
layout.addStretch(5)
apply = QtGui.QPushButton('Apply',self)
layout.addWidget(apply)
self.connect(apply,QtCore.SIGNAL('released()'),self.apply)
if self.closeButton:
close = QtGui.QPushButton('Close',self)
layout.addWidget(close)
self.connect(apply,QtCore.SIGNAL('released()'),self.close)
rbox.setLayout(layout)
layout0.addSpacing(5)
layout0.addWidget(rbox)
self.setLayout(layout0)
#-----------------------------------------------------------------------
def apply(self):
#-----------------------------------------------------------------------
self.emit(QtCore.SIGNAL("accepted()"))
#-----------------------------------------------------------------------
def getSelection(self):
#-----------------------------------------------------------------------
sele_list = []
for item in self.itemOrder:
but = self.itemList.findChild(QtGui.QCheckBox,item)
if but and but.isChecked(): sele_list.append(item)
return sele_list
#-----------------------------------------------------------------------
def setSelection(self,selectedList=[]):
#-----------------------------------------------------------------------
# Input a list of selected items
# Also set items not in that list to unchecked
for item in self.itemOrder:
but = self.itemList.findChild(QtGui.QCheckBox,item)
if but: but.setChecked(selectedList.count(item))
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class extendingFrame(QtGui.QWidget):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
LINE_HEIGHT = 32
#-------------------------------------------------------------------
def __init__(self,parent=None,widget='',nLines=1,ifApply=1,
ifEditable=1,ifClose=0,ifClear=0,ifSave=0,height=200,width=400):
#-------------------------------------------------------------------
QtGui.QWidget.__init__(self,parent)
margin = 0
self.widgetClass = widget
self.lineHeight = extendingFrame.LINE_HEIGHT
self.ifClear = ifClear
self.ifEditable = ifEditable
self.ifAddLine = ifEditable
self.ifSave = ifSave
self.widgetHeight = height
if width:
self.widgetWidth = width
else:
tmp_widget = self.widgetClass(self.parent())
tmp_widget.setAttribute(QtCore.Qt.WA_DeleteOnClose)
tmp_widget.show()
self.widgetWidth = tmp_widget.width() + extendingFrame.LINE_HEIGHT + 5
#print 'extendingFrame widgetWidth',self.widgetWidth
tmp_widget.close()
# Buttons
buttonLayout = QtGui.QHBoxLayout()
buttonLayout.addStretch()
if ifApply:
apply_button = QtGui.QPushButton('Apply')
apply_button.setObjectName('applyButton')
apply_button.setFocusPolicy(QtCore.Qt.ClickFocus)
apply_button.setAutoDefault(0)
buttonLayout.addWidget(apply_button)
self.connect(apply_button,QtCore.SIGNAL('released()'),guiUtils.partial(self.emit,QtCore.SIGNAL('accepted()')))
if ifSave:
save_button = QtGui.QPushButton('Save')
save_button.setObjectName('saveButton')
save_button.setAutoDefault(0)
buttonLayout.addWidget(save_button)
self.connect(save_button,QtCore.SIGNAL('released()'),guiUtils.partial(self.emit,QtCore.SIGNAL('save')))
if self.ifClear:
clear_button = QtGui.QPushButton('Clear')
clear_button.setObjectName('clearButton')
clear_button.setAutoDefault(0)
clear_button.setFocusPolicy(QtCore.Qt.ClickFocus)
buttonLayout.addWidget(clear_button)
if self.ifAddLine:
add_button = QtGui.QPushButton('Add line')
add_button.setObjectName('addButton')
add_button.setAutoDefault(0)
add_button.setFocusPolicy(QtCore.Qt.ClickFocus)
buttonLayout.addWidget(add_button)
if ifClose:
close_button = QtGui.QPushButton('Close')
close_button.setObjectName('closeButton')
close_button.setAutoDefault(0)
buttonLayout.addWidget(close_button)
self.connect(close_button,QtCore.SIGNAL('released()'),guiUtils.partial(self.emit,QtCore.SIGNAL('close()')))
# Body in which sub-widgets will be drawn
self.scroll_frame = QtGui.QFrame(self)
#if self.widgetHeight>0: self.scroll_frame.setFixedHeight(self.widgetHeight-40)
scroll_layout = QtGui.QGridLayout()
scroll_layout.setSpacing(0)
scroll_layout.setContentsMargins(0,0,0,0)
scroll = QtGui.QScrollArea(self)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
#scroll.setFixedWidth(self.widgetWidth+scroll.verticalScrollBar().height())
#if self.widgetHeight>0: scroll.setFixedHeight(self.widgetHeight-40-2*margin)
scroll_layout.addWidget(scroll,0,0,1,1)
self.scroll_frame.setLayout(scroll_layout)
self.body = QtGui.QWidget(self)
self.body.setFixedWidth(self.widgetWidth-10)
body_layout = QtGui.QVBoxLayout()
body_layout.setSpacing(0)
body_layout.setContentsMargins(0,0,0,0)
self.body.setLayout(body_layout)
scroll.setWidget(self.body)
v_layout = QtGui.QVBoxLayout()
v_layout.setSpacing(margin)
v_layout.setContentsMargins(margin,margin,margin,margin)
v_layout.addWidget(self.scroll_frame)
v_layout.addLayout(buttonLayout)
self.setLayout(v_layout)
if self.ifAddLine:
self.connect(add_button,QtCore.SIGNAL('clicked()'),self.addLine)
if self.ifClear:
self.connect(clear_button,QtCore.SIGNAL('released()'),self.clear)
self.setNofLines(nLines)
#-------------------------------------------------------------------
def clear(self):
#-------------------------------------------------------------------
self.setNofLines(0)
self.emit(QtCore.SIGNAL('cleared'))
#-------------------------------------------------------------------
def setNofLines(self,nLines):
#-------------------------------------------------------------------
# Add or delete lines to get to NLines
curNLines = self.body.layout().count()
#print 'exFrame.setNofLines',curNLines,nLines
if nLines == curNLines:
return
elif nLines > curNLines:
for ii in range(curNLines,nLines):
self.addLine()
elif nLines < curNLines and nLines>=0:
for ii in range(curNLines,nLines,-1):
#print 'exFrame.setNofLines deleteLine',ii-1
self.deleteLine(line=ii-1)
#-------------------------------------------------------------------
def getNofLines(self):
#-------------------------------------------------------------------
return self.body.layout().count()
#-------------------------------------------------------------------
def getLine(self,index):
#-------------------------------------------------------------------
item = self.body.layout().itemAt(index)
if not item:
return None
else:
return item.widget().child
#-------------------------------------------------------------------
def setWidget(self,widget):
#-------------------------------------------------------------------
self.widgetClass = widget
#-------------------------------------------------------------------
def addLine(self,index=-1):
#-------------------------------------------------------------------
widget = self.widgetClass(self.parent())
line = extendingFrameLine(parent=self,child=widget,ifEditable=self.ifEditable)
line.show()
self.body.layout().insertWidget(index,line)
self.setBodyHeight()
if index<0: index = self.body.layout().count()-1
self.emit(QtCore.SIGNAL('lineAdded(int)'),index)
#-------------------------------------------------------------------
def setBodyHeight(self):
#-------------------------------------------------------------------
nLines = self.body.layout().count()
#print "setBodyHeight",nLines
if self.lineHeight<0:
widget = self.widgetClass()
self.lineHeight = self.widgetClass().height()+6
#print "lineHeight", self.lineHeight
self.body.setMinimumHeight( self.lineHeight * nLines)
self.body.setMaximumHeight( self.lineHeight * nLines)
self.body.updateGeometry()
#-------------------------------------------------------------------
def deleteLine(self,widget=None,line=-1):
#-------------------------------------------------------------------
#print "deleteLine",line,widget
if line>=0:
item = self.body.layout().itemAt(line)
#print 'exFrame deleteLine item',item,item.widget()
if item:
# Beware have seen crashes with the two following
# lines in reversed order (close after removeWidget)
item.widget().close()
self.body.layout().removeWidget(item.widget())
self.setBodyHeight()
self.emit(QtCore.SIGNAL('lineDeleted'))
elif widget:
ii = self.body.layout().indexOf(widget)
if ii>=0:
widget.close()
self.body.layout().removeWidget(widget)
self.setBodyHeight()
self.emit(QtCore.SIGNAL('lineDeleted'))
#-------------------------------------------------------------------
def insertLine(self,args):
#-------------------------------------------------------------------
widget = args[0]
mode = args[1]
#print "insertLine",widget,mode
ii = self.body.layout().indexOf(widget)
if ii>=0:
if mode == 'below': ii = ii +1
self.addLine(index=ii)
#-------------------------------------------------------------------
def getParams(self,params={},index=-1):
#-------------------------------------------------------------------
keyList = params.keys()
if index<0:
first = 0
last = self.body.layout().count()
else:
first = index
last = index + 1
for line in range(first,last):
item = self.body.layout().itemAt(line)
if item:
lineWidget = item.widget().child
try:
pars = lineWidget.getParams()
for key in keyList:
params[key].append(pars.get(key,''))
except:
for key in keyList:
widget = lineWidget.findChild(QtGui.QWidget,key)
value = ''
if widget:
if isinstance(widget,QtGui.QComboBox):
value = str(widget.itemData(widget.currentIndex()).toString())
if not value: value = str(widget.currentText())
elif isinstance(widget,QtGui.QLabel):
value = str(widget.text())
elif isinstance(widget,QtGui.QLineEdit):
value = str(widget.text())
elif isinstance(widget,QtGui.QAbstractButton):
value = int(widget.isChecked())
elif isinstance(widget,mgSelectionCombo):
value = str(widget.text())
elif isinstance(widget,mgColourCombo):
value = str(widget.get_colour())
elif isinstance(widget,mgAtomPicker):
value = str(widget.selection())
elif isinstance(widget,QtGui.QDoubleSpinBox):
value = float(widget.value())
elif isinstance(widget,QtGui.QSpinBox):
value = int(widget.value())
params[key].append(value)
#print "exframe.getParams",params
return params
#----------------------------------------------------------------
def setParams(self,params,index=0):
#----------------------------------------------------------------
# Beware - do not assume that all items in params are
# in our widget
# index in the first line in the extending frame that the params
# should be assigned to
keyList = params.keys()
#print "exframe.setParams",params,keyList
# This will be tricky without an instance of the line
# so create one if one does not exist
if self.body.layout().count() == 0: self.addLine()
lineWidget = self.body.layout().itemAt(0).widget()
# Need find at least one item in keyList that is definitely in the line
widget = None
ii = -1
while not widget and ii=0: widget.setCurrentIndex(ic)
elif isinstance(widget,QtGui.QLineEdit):
widget.setText(str(params[key][jj]))
elif isinstance(widget,QtGui.QLabel):
widget.setText(str(params[key][jj]))
elif isinstance(widget,QtGui.QAbstractButton):
widget.setChecked(params[key][jj])
elif isinstance(widget,mgSelectionCombo):
widget.setText(params[key][jj])
elif isinstance(widget,mgColourCombo):
widget.set_colour(params[key][jj])
elif isinstance(widget,mgAtomPicker):
widget.setSelection(atomName=params[key][jj])
elif isinstance(widget,QtGui.QDoubleSpinBox):
widget.setValue(float(params[key][jj]))
elif isinstance(widget,QtGui.QSpinBox):
widget.setValue(int(params[key][jj]))
else:
# If cant find widget in this line then wont find
# one in any subsequent lines
break
return nL
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class extendingFrameLine(QtGui.QWidget):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
iconPixmap = None
def __init__(self,parent=None,child=None,ifEditable=1):
QtGui.QWidget.__init__(self,parent)
self.child = child
layout = QtGui.QHBoxLayout()
margin = 0
layout.setSpacing(margin)
layout.setContentsMargins(margin,margin,margin,margin)
if child:
layout.addWidget(child)
#ht = child.height()
if not extendingFrameLine.iconPixmap:
extendingFrameLine.iconPixmap = guiUtils.loadPixmap(name='extendingFrameLine',group='actions')
if ifEditable:
icon = QtGui.QIcon(extendingFrameLine.iconPixmap)
iconButton = QtGui.QToolButton(self)
iconButton.setPopupMode(QtGui.QToolButton.InstantPopup)
iconButton.setIcon(icon)
iconButton.setMaximumSize(QtCore.QSize(extendingFrame.LINE_HEIGHT-4,extendingFrame.LINE_HEIGHT-4))
iconButton.setToolTip('Add or delete a row')
iconMenu = QtGui.QMenu(self)
deleteAction = QtGui.QAction('Delete',parent)
self.connect(deleteAction,QtCore.SIGNAL('triggered()'),guiUtils.partial(parent.deleteLine,self))
iconMenu.addAction(deleteAction)
aboveAction = QtGui.QAction('Insert above',parent)
self.connect(aboveAction,QtCore.SIGNAL('triggered()'),guiUtils.partial(parent.insertLine,[self,'above']))
iconMenu.addAction(aboveAction)
belowAction = QtGui.QAction('Insert below',parent)
self.connect(belowAction,QtCore.SIGNAL('triggered()'),guiUtils.partial(parent.insertLine,[self,'below']))
iconMenu.addAction(belowAction)
resetAction = QtGui.QAction('Reset',parent)
self.connect(resetAction,QtCore.SIGNAL('triggered()'),self.child.setDefault)
iconMenu.addAction(resetAction)
iconButton.setMenu(iconMenu)
layout.addWidget(iconButton)
self.setLayout(layout)
class frameLine(QtGui.QWidget):
def __init__(self,parent=None):
QtGui.QWidget.__init__(self,parent)
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class mgColourCombo( QtGui.QComboBox ):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def __init__(self,parent=None,colour='black',browser=0):
#----------------------------------------------------------------------
QtGui.QComboBox.__init__(self,parent)
self.ifBrowser= browser
self.loadColours()
self.old_colour = colour
self.set_colour(colour)
self.connect(ColourBrowserManager(),QtCore.SIGNAL('coloursChanged'),self.loadColours)
if self.ifBrowser:
self.connect(self,QtCore.SIGNAL('currentIndexChanged(const QString)'),self.handleIndexChanged)
#print 'mgColourCombo.init',self,self.old_colour
#----------------------------------------------------------------------
def loadColours(self):
#----------------------------------------------------------------------
#print 'mgColourCombo.loadColours'
current_colour = self.currentText()
self.blockSignals(1)
self.clear()
for col in global_definitions.MGCOLOUR().colourlist():
colour = global_definitions.MGCOLOUR().RGB255(col)
qcol = QtGui.QColor(colour[0],colour[1],colour[2])
pixmap = QtGui.QPixmap(20,10)
pixmap.fill(qcol)
icon = QtGui.QIcon(pixmap)
self.addItem(icon,col)
idx = self.findText(current_colour)
if idx>=0: self.setCurrentIndex(idx)
if self.ifBrowser: self.addItem('Colour browser')
self.blockSignals(0)
#----------------------------------------------------------------------
def handleIndexChanged(self,label):
#----------------------------------------------------------------------
#print 'mgColourCombo.handleIndexChanged',label,self.old_colour
if label == 'Colour browser':
idx = global_definitions.MGCOLOUR().index(self.old_colour)
if idx>=0: self.setCurrentIndex( idx )
if not hasattr(self,'browser'):
self.browser = mgColourBrowser(self)
self.connect(self.browser,QtCore.SIGNAL('ColourSelected'),self.handleBrowser)
else:
self.browser.show()
#----------------------------------------------------------------------
def handleBrowser(self,col):
#----------------------------------------------------------------------
#print 'mgColourCombo.handleBrowser',col
self.loadColours()
self.set_colour(col)
#----------------------------------------------------------------------
def set_colour(self,col):
#----------------------------------------------------------------------
#print 'colourCombo.set_colour',col; sys.stdout.flush()
#self.blockSignals(1)
if col == 'Colour browser':
idx = self.findText(self.old_colour)
if idx>=0: self.setCurrentIndex( idx )
else:
idx = self.findText(col)
if idx>=0:
self.setCurrentIndex( idx )
self.old_colour = col
#self.blockSignals(0)
#print 'colourCombo.set_colour',col,idx; sys.stdout.flush()
#----------------------------------------------------------------------
def get_colour(self):
#----------------------------------------------------------------------
return str(self.currentText())
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class mgAtomPicker(QtGui.QFrame):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def textChanged0(self):
txt = str(self.textBox.text())
#print 'mgAtomPicker.textChanged0',txt
return self.textChanged(txt)
def textChanged(self,text=''):
self.blockComboSignals(1)
text = (str(text)).strip()
model,chain,residue,residue2,atom = self.getDataobj().splitAtomID(text,res_range=1)
#print 'mgAtomPicker.textChanged',self.mode,model,chain,residue,residue2,atom
if self.showModelCombo:
match = self.modelCombo.findText(QtCore.QString(model),QtCore.Qt.MatchExactly)
#print 'modelCombo match',model,match
if match>=0: self.modelCombo.setCurrentIndex(match)
if not chain and self.blankOption:
self.chainCombo.setCurrentIndex(0)
else:
match = self.chainCombo.findText(chain,QtCore.Qt.MatchExactly)
#print 'mgAtomPicker.textChanged chainCombo match',chain,'*',match
if match>=0:
self.chainCombo.setCurrentIndex(match)
self.chainChanged(match,updateText=0)
if not residue and self.blankOption:
self.residueCombo.setCurrentIndex(0)
else:
match = self.residueCombo.findText(residue,QtCore.Qt.MatchExactly)
if match<0: match = self.residueCombo.findText(residue+'(',QtCore.Qt.MatchStartsWith)
#print 'residueCombo match',residue,match
if match>=0:
self.residueCombo.setCurrentIndex(match)
self.residueChanged(match,updateText=0)
if self.mode == 'atom':
if not atom and self.blankOption:
self.atomCombo.setCurrentIndex(0)
else:
match = self.atomCombo.findText(atom,QtCore.Qt.MatchExactly)
#print 'atomCombo match',atom,match
if match>=0:
self.atomCombo.setCurrentIndex(match)
else:
pass #print "atom:--"+atom+"-- not found"
elif self.mode == 'range':
if residue2:
match = self.rangeCombo.findText(residue2,QtCore.Qt.MatchExactly)
if match<0: match = self.rangeCombo.findText(residue2+'(',QtCore.Qt.MatchStartsWith)
#print 'residueCombo match',residue,match
if match>=0: self.rangeCombo.setCurrentIndex(match)
else:
self.rangeCombo.setCurrentIndex(0)
self.blockComboSignals(0)
dobj = self.getDataobj()
if not self.signalBlocked and (dobj.name,model,chain,residue,residue2,atom) != self.lastEmitSelection:
self.emit(QtCore.SIGNAL("AtomChanged"),(dobj.name,model,chain,residue,residue2,atom))
self.lastEmitSelection = (dobj.name,model,chain,residue,residue2,atom)
def atomChanged(self,iatom,updateText=1):
if iatom < 0: return
if self.showDataCombo and self.dataCombo.count()==0: return
if self.showModelCombo and self.modelCombo.count()==0: return
if self.chainCombo.count()==0: return
if self.residueCombo.count()==0: return
dobj = self.getDataobj()
imodel = self.getModelNumber()
ichain = self.chainCombo.currentIndex()
iresidue = self.residueCombo.currentIndex()
changed = False
if self.showDataCombo and dobj.name != self.dataName:
self.dataName = dobj.name
changed = True
if imodel != self.imodel:
self.imodel = imodel
changed = True
if ichain != self.ichain:
self.ichain = ichain
changed = True
if iresidue != self.iresidue:
self.iresidue = iresidue
changed = True
if iatom != self.iatom:
self.iatom = iatom
changed = True
if changed:
#print dataName+"/"+str(imodel)+"/"+str(ichain)+"/"+str(iresidue)+"/"+str(iatom)
if updateText:self.updateTextBox()
def rangeChanged(self,ires,updateText=1):
#print 'rangeChanged',ires
if updateText: self.updateTextBox()
def updateTextBox(self):
dobj = self.getDataobj()
imodel = self.getModelNumber()
ichain = self.chainCombo.currentIndex()-self.blankOption
iresidue = self.residueCombo.currentIndex()-self.blankOption
iresidue2 = -1
#print 'updateTextBox',self.signalBlocked,imodel,ichain,iresidue
iatom = -1
text = ''
if self.showModelCombo and imodel>0: text = '/'+str(imodel)
if ichain>=0:
chainID = dobj.molHnd.GetModel(imodel).GetChain(ichain).GetChainID()
if text:
text = text + "/"+str(chainID)+ "/"
elif len(chainID)>0:
text = str(chainID)+ "/"
else:
text = '// /'
pRes = dobj.molHnd.GetModel(imodel).GetChain(ichain).GetResidue(iresidue)
if pRes:
text = text +str(pRes.GetSeqNum())
if self.mode == 'atom':
iatom = self.atomCombo.currentIndex()-self.blankOption
if iatom>=0:
theAtom = pRes.GetAtom(iatom)
atomID = theAtom.GetAtomName()
text = text +'/' + (atomID).strip()
altLoc = theAtom.GetAltLoc().strip()
if altLoc:
text = text + ':' + altLoc
elif self.mode == 'range':
irange = self.rangeCombo.currentIndex()-self.blankOption
if irange>=0:
resNo2 = dobj.molHnd.GetModel(imodel).GetChain(ichain).GetResidue(irange).GetSeqNum()
if irange>iresidue:
text = text +'-'+str(resNo2)
elif iresidue>irange:
text = "/"+str(imodel)+"/"+str(chainID)+"/"+str(resNo2)+'-'+str(pRes.GetSeqNum())
iresidue2 = resNo2
self.textBox.blockSignals(1)
self.textBox.setText(text)
self.textBox.blockSignals(0)
if not self.signalBlocked:
if self.lastEmitSelection != (dobj.name,imodel,ichain,iresidue,iresidue2,iatom):
self.emit(QtCore.SIGNAL("AtomChanged"),(dobj.name,imodel,ichain,iresidue,iresidue2,iatom))
self.lastEmitSelection = (dobj.name,imodel,ichain,iresidue,iresidue2,iatom)
def reset(self):
if self.showDataCombo: self.dataCombo.setCurrentIndex(0)
if self.showModelCombo: self.modelCombo.setCurrentIndex(0)
self.chainCombo.setCurrentIndex(0)
self.residueCombo.setCurrentIndex(0)
self.rangeCombo.setCurrentIndex(0)
def blockSignals(self,mode):
self.signalBlocked = mode
def blockComboSignals(self,mode):
if self.showDataCombo: self.dataCombo.blockSignals(mode)
if self.showModelCombo: self.modelCombo.blockSignals(mode)
self.chainCombo.blockSignals(mode)
self.residueCombo.blockSignals(mode)
if self.rangeCombo: self.rangeCombo.blockSignals(mode)
self.atomCombo.blockSignals(mode)
def setSelection(self,modelName='',atomName='',MolData=None,pAtom=None):
#print 'mgAtomPicker setSelection atomName',atomName
if MolData:
dobj = MolData
modelName = dobj.name
elif modelName:
dobj = global_definitions.data(modelName)
else:
dobj = self.getDataobj()
if not dobj: return
if pAtom: atomName = pAtom.GetAtomID()
#print 'mgAtomPicker setSelection',dobj,atomName
if dobj and self.showDataCombo and self.dataCombo.findText(modelName,QtCore.Qt.MatchExactly)>-1:
self.dataCombo.setCurrentIndex(self.dataCombo.findText(modelName,QtCore.Qt.MatchExactly))
self.textBox.blockSignals(1)
self.textBox.setText(atomName)
self.textBox.blockSignals(0)
self.textChanged(atomName)
'''
full_id = dobj.splitAtomID(atomName,res_range=1)
print 'mgAtomPicker setSelection atomName',atomName,full_id
if self.showModelCombo:
if full_id[0]:
iModel = self.modelCombo.findText(full_id[0])
if iModel>= 0:
self.modelCombo.setCurrentIndex(iModel)
iChain = self.chainCombo.findText(full_id[1])
if iChain>=0:
self.chainCombo.setCurrentIndex(iChain)
iRes = self.residueCombo.findText(full_id[2])
if iRes<0: iRes = self.residueCombo.findText(full_id[2]+'(',QtCore.Qt.MatchStartsWith)
if iRes>=0:
self.residueCombo.setCurrentIndex(iRes)
if self.mode == 'atom':
iAtom = self.atomCombo.findText(full_id[4])
if iAtom>=0:
self.atomCombo.setCurrentIndex(iAtom)
iRes2 = self.rangeCombo.findText(full_id[3])
if iRes2<0: iRes2 = self.rangeCombo.findText(full_id[3]+'(',QtCore.Qt.MatchStartsWith)
print 'mgAtomPicker.setSelection iRes2',iRes,iRes2
if iRes2>=0:
self.rangeCombo.setCurrentIndex(iRes2)
'''
return 0
def selection(self):
return str(self.textBox.text())
def modelAtomPtr(self):
dobj = self.getDataobj()
if not dobj: return (None,None)
atm_ptr = dobj.interpretAtomID(dobj,str(self.textBox.text()),force_one_atom=1)
#print "modelAtomPtr",self.dataName,str(self.textBox.text()),atm_ptr
return dobj,atm_ptr
def modelNameAtomName(self):
# Use modelAtomPtr to check that atom id is interpretable
ret = self.modelAtomPtr()
#print "modelNameAtomName ret",ret
if ret:
return ret[0].name,str(self.textBox.text())
else:
return ()
def residueChanged(self,ires,updateText=1):
if ires < 0: return
if self.showDataCombo and self.dataCombo.count()==0: return
if self.showModelCombo and self.modelCombo.count()==0: return
if self.chainCombo.count()==0: return
dobj = self.getDataobj()
imodel = self.getModelNumber()
ichain = self.chainCombo.currentIndex()-self.blankOption
ires = ires - self.blankOption
if self.mode == 'atom':
self.atomCombo.clear()
if self.blankOption: self.atomCombo.addItem('')
if ires>=0 and ichain>=0 and imodel>=0:
natoms = dobj.molHnd.GetModel(imodel).GetChain(ichain).GetResidue(ires).GetNumberOfAtoms()
if natoms == 0:
return
pres = dobj.molHnd.GetModel(imodel).GetChain(ichain).GetResidue(ires)
init_atom = 0
for j in range(natoms):
pat = pres.GetAtom(j)
atomID = pat.GetAtomName().strip()
if atomID == 'CA': init_atom = j
if pat.GetAltLoc(): atomID =atomID+':'+ pat.GetAltLoc()
self.atomCombo.addItem(atomID)
if self.atomCombo.currentIndex !=init_atom: self.atomCombo.setCurrentIndex(init_atom)
self.atomChanged(init_atom,updateText)
else:
if updateText: self.updateTextBox()
def chainChanged(self,ichain,updateText=1):
if ichain < 0: return
if self.showDataCombo and self.dataCombo.count()==0: return
if self.showModelCombo and self.modelCombo.count()==0: return
ichain = ichain - self.blankOption
self.residueCombo.clear()
self.rangeCombo.clear()
if self.blankOption:
self.residueCombo.addItem('')
self.rangeCombo.addItem('')
dobj = self.getDataobj()
imodel = self.getModelNumber()
if ichain>=0 and imodel>=0:
nres = dobj.molHnd.GetModel(imodel).GetChain(ichain).GetNumberOfResidues()
if nres == 0:
if self.mode == 'atom': self.atomCombo.clear()
return
pch = dobj.molHnd.GetModel(imodel).GetChain(ichain)
for j in range(nres):
pres = pch.GetResidue(j)
resID = pres.GetResName()
resNo = pres.GetSeqNum()
resIns = pres.GetInsCode()
if resIns:
name = str(resNo)+"."+resIns+"("+resID+")"
else:
name = str(resNo)+"("+resID+")"
self.residueCombo.addItem(name)
#if self.mode == 'range': self.rangeCombo.addItem(name)
self.rangeCombo.addItem(name)
self.residueChanged(0,updateText)
if self.residueCombo.currentIndex !=0: self.residueCombo.setCurrentIndex(0)
#if self.mode == 'range':
if self.rangeCombo.currentIndex !=0: self.rangeCombo.setCurrentIndex(0)
def modelChanged(self,imodel,updateText=1):
if imodel < 0: return
if self.showDataCombo and self.dataCombo.count()==0: return
imodel = (imodel - self.blankOption) + 1
self.chainCombo.clear()
if self.blankOption: self.chainCombo.addItem(' ')
self.residueCombo.clear()
if self.mode == 'atom': self.atomCombo.clear()
if self.mode == 'range': self.rangeCombo.clear()
if imodel>0:
dobj = self.getDataobj()
nchains = dobj.molHnd.GetModel(imodel).GetNumberOfChains()
if nchains == 0: return
for j in range(nchains):
chainID = dobj.molHnd.GetModel(imodel).GetChain(j).GetChainID()
self.chainCombo.addItem(chainID)
self.chainChanged(0,updateText)
if self.chainCombo.currentIndex !=0: self.chainCombo.setCurrentIndex(0)
def dataObjChanged(self,i,updateText=1):
dobj = self.getDataobj()
if not dobj: return
if self.showModelCombo:
self.modelCombo.clear()
nmodels = dobj.molHnd.GetNumberOfModels()
if nmodels == 0:
self.chainCombo.clear()
self.residueCombo.clear()
if self.mode == 'range': self.rangeCombo.clear()
if self.mode == 'atom': self.atomCombo.clear()
return
if self.blankOption: self.modelCombo.addItem('')
for j in range(nmodels):
self.modelCombo.addItem(str(j+1))
self.modelChanged(0,updateText)
if self.modelCombo.currentIndex !=0: self.modelCombo.setCurrentIndex(0)
else:
# Set the chainCombo
self.modelChanged(self.blankOption,updateText)
def __init__(self,parent=None,MolData_name='',mode = 'atom',blank=0):
QtGui.QFrame.__init__(self)
self.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
self.showModelCombo = 1
self.mode = mode
if MolData_name:
self.showDataCombo = 0
dobj = global_definitions.data(MolData_name)
if dobj and dobj.molHnd.GetNumberOfModels() == 1: self.showModelCombo = 0
else:
self.showDataCombo = 1
self.blankOption = blank
self.dataName = MolData_name
self.imodel = 0
self.ichain = 0
self.iresidue = 0
self.iatom = 0
self.signalBlocked = 0
self.lastEmitSelection = [self.dataName,0,0,0,0,0]
vblayout = QtGui.QHBoxLayout()
vblayout.setContentsMargins(0,0,0,0)
vblayout.setSpacing(0)
if self.showDataCombo:
self.dataCombo = mgDataObjCombo(object_type='MolData',parent=self)
vblayout.addWidget(self.dataCombo)
if self.showModelCombo:
self.modelCombo = QtGui.QComboBox()
self.modelCombo.setMaxVisibleItems(10)
self.modelCombo.setMinimumContentsLength(1)
vblayout.addWidget(self.modelCombo)
self.chainCombo = QtGui.QComboBox()
self.chainCombo.setMaxVisibleItems(10)
self.chainCombo.setMinimumContentsLength(1)
vblayout.addWidget(self.chainCombo)
self.residueCombo = QtGui.QComboBox()
self.residueCombo.setMaxVisibleItems(10)
self.residueCombo.setMinimumContentsLength(8)
vblayout.addWidget(self.residueCombo)
self.atomCombo = QtGui.QComboBox()
self.atomCombo.setMinimumContentsLength(4)
if self.mode == 'atom':vblayout.addWidget(self.atomCombo)
self.to_label = QtGui.QLabel('to',self)
self.rangeCombo = QtGui.QComboBox()
self.rangeCombo.setMinimumContentsLength(8)
if self.mode == 'range':
vblayout.addWidget(self.to_label)
vblayout.addWidget(self.rangeCombo)
else:
self.to_label.hide()
self.rangeCombo.hide()
#self.textBox = QtGui.QLineEdit()
self.textBox = mgLineEdit()
someText = "/99/Z/999.2/HG51"
dummy = QtGui.QTextEdit()
fn = dummy.currentFont()
fm = QtGui.QFontMetrics(fn)
textWidth = fm.width(someText)
vblayout.addWidget(self.textBox)
vblayout.addStretch(5)
self.textBox.setMinimumWidth(textWidth)
#self.textBox.setValidator(mgCidValidator(self,'atom'))
self.dataObjChanged(0)
if self.showDataCombo and self.dataCombo.count()>0: self.dataCombo.setCurrentIndex(0)
if self.showDataCombo: self.connect(self.dataCombo,QtCore.SIGNAL("currentIndexChanged(int)"),self.dataObjChanged)
if self.showModelCombo: self.connect(self.modelCombo,QtCore.SIGNAL("currentIndexChanged(int)"),self.modelChanged)
self.setToolTip()
self.connect(self.chainCombo,QtCore.SIGNAL("currentIndexChanged(int)"),self.chainChanged)
self.connect(self.residueCombo,QtCore.SIGNAL("currentIndexChanged(int)"),self.residueChanged)
self.connect(self.atomCombo,QtCore.SIGNAL("currentIndexChanged(int)"),self.atomChanged)
self.connect(self.rangeCombo,QtCore.SIGNAL("currentIndexChanged(int)"),self.rangeChanged)
#self.connect(self.textBox,QtCore.SIGNAL("textEdited(const QString&)"),self.textChanged)
self.connect(self.textBox,QtCore.SIGNAL("editingFinished()"),self.textChanged0)
self.connect(self.textBox,QtCore.SIGNAL("apply"),self.textChanged0)
#self.connect(self.textBox,QtCore.SIGNAL("mouseRelease()"),self.pasteFromAtomPick)
self.setLayout(vblayout)
def getDataobj(self):
if self.showDataCombo:
name = str(self.dataCombo.itemText(self.dataCombo.currentIndex()))
else:
name = self.dataName
return global_definitions.data(name)
def getModelNumber(self):
if self.showModelCombo:
return (self.modelCombo.currentIndex()-self.blankOption)+1
else:
return 1
def setToolTip(self,text=''):
if text: text = text + ' '
if self.showDataCombo:
self.dataCombo.setToolTip(text+'Model object - equivalent to PDB file')
if self.showModelCombo:
self.modelCombo.setToolTip(text + "'NMR' or symmetry model number")
self.chainCombo.setToolTip(text+"Chain ID")
self.residueCombo.setToolTip(text+"Residue sequence number and type")
if self.mode == 'atom': self.atomCombo.setToolTip(text+"Atom name")
if self.mode == 'range': self.rangeCombo.setToolTip(text+"end of residue range")
self.textBox.setToolTip(text+"Full atom id")
def pasteFromAtomPick(self):
# This is NOT used - instead uses the standard QT paster buffer
# But this would have advatage that user does not have to delete
# any existing text in the text input
#print 'mgAtomPicker.pasteFromAtomPick'
pickevent = MAINWINDOW().getLastPickEvent()
if not pickevent: return
atoms = pickevent.getPickedAtoms()
if len(atoms) == 1:
#print 'pasteFromAtomPick',atoms,atoms[0].GetAtomID()
self.textChanged(atoms[0].GetAtomID())
def setMode(self,mode):
if mode == self.mode: return
self.blockSignals(1)
if self.mode == 'atom':
self.atomCombo.clear()
self.layout().removeWidget(self.atomCombo)
self.atomCombo.hide()
elif self.mode == 'range':
self.layout().removeWidget(self.to_label)
self.layout().removeWidget(self.rangeCombo)
self.rangeCombo.clear()
self.rangeCombo.hide()
self.to_label.hide()
idx = self.layout().indexOf(self.textBox)
if mode == 'atom':
self.atomCombo.show()
self.layout().insertWidget(idx,self.atomCombo)
self.residueChanged(self.residueCombo.currentIndex())
elif mode == 'range':
self.to_label.show()
self.rangeCombo.show()
self.layout().insertWidget(idx,self.to_label)
self.layout().insertWidget(idx+1,self.rangeCombo)
self.chainChanged(self.chainCombo.currentIndex())
self.mode = mode
self.updateTextBox()
self.blockSignals(0)
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class CartesianPickerDialog(MGSimpleDialog.MultiDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
"""
Pick a point in 3D Cartesian space.
"""
def Apply2(self,pos):
self.emit(QtCore.SIGNAL("PositionChanged"),pos)
def Apply(self):
xyz = ['x','y']
if self.dim >=3:xyz.append('z')
pos = []
#for item in xyz: pos.append(self.cartesian.widgets[item].value())
for item in xyz:
p = self.cartesian.widgets[item].text()
if not p: p = 0.0
pos.append(float(p))
self.emit(QtCore.SIGNAL("PositionChanged"),pos)
def ApplyAndClose(self):
self.Apply()
self.Close()
def __init__(self,parent=None,x=0.0,y=0.0,z=0.0,dim=3):
MGSimpleDialog.MultiDialog.__init__(self,parent)
self.setWindowTitle(self.tr("Cartesian point picker"))
self.dim = dim
mylayout = QtGui.QVBoxLayout()
self.cartesian = CartesianPicker(self,x=x,y=y,z=z,dim=dim)
if QtCore.PYQT_VERSION >= 0x040500 and sip.SIP_VERSION >= 0x040800:
self.cartesian.PositionChanged.connect(self.Apply2)
else:
self.connect(self.cartesian,QtCore.SIGNAL("PositionChanged"),self.Apply2)
mylayout.addWidget(self.cartesian)
dialog_buttons = QtGui.QDialogButtonBox()
# 'Enter' or 'return' key anywhere in the dialog box seems to fire
# the ok button and exit the dialog box. Remove ok button for now
#ok_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Ok)
apply_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Apply)
cancel_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Cancel)
self.connect(cancel_button,QtCore.SIGNAL('clicked()'),self.Close)
#self.connect(ok_button,QtCore.SIGNAL('clicked()'),self.ApplyAndClose)
self.connect(apply_button,QtCore.SIGNAL('clicked()'),self.Apply)
mylayout.addWidget(dialog_buttons)
self.setLayout(mylayout)
self.setSizeGripEnabled(0)
self.CreateMenuEntry()
def setParams(self,params={},**kw):
params.update(kw)
self.cartesian.setParams(params)
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class CartesianPicker(QtGui.QWidget):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
if QtCore.PYQT_VERSION >= 0x040500 and sip.SIP_VERSION >= 0x040800:
PositionChanged = QtCore.pyqtSignal(list)
def __init__(self,parent=None,dim=3,params={},**kw):
QtGui.QWidget.__init__(self,parent)
hlayout = QtGui.QHBoxLayout()
self.widgets = {}
items = ['x','y']
if dim>=3: items.append('z')
self.validator = QtGui.QDoubleValidator(-1000.0,1000.0,2,self)
for item in items:
label = QtGui.QLabel(item+':')
self.widgets[item] = QtGui.QLineEdit(self)
self.widgets[item].setValidator(self.validator)
#self.widgets[item] = mgDeltaSlider(QtCore.Qt.Vertical,self)
#self.widgets[item].setRange(-100.0,100.0)
#self.widgets[item].setSingleStep(0.5)
#self.widgets[item].setMaximumHeight(30)
self.widgets[item].setObjectName('CartesianPicker-'+item)
self.connect(self.widgets[item],QtCore.SIGNAL("valueChanged(double)"),self.Apply)
hlayout.addWidget(label)
hlayout.addWidget(self.widgets[item])
self.setLayout(hlayout)
params.update(kw)
self.setParams(params)
def setParams(self,params={},**kw):
params.update(kw)
for key,value in params.items():
if self.widgets.has_key(key):
self.widgets[key].setText(str(value))
#self.widgets[key].setValue(value)
def Apply(self):
pos = []
#for item in ['x','y']: pos.append(self.widgets[item].value())
#if self.widgets.has_key('z'):pos.append(self.widgets['z'].value())
xyz = ['x','y']
if self.widgets.has_key('z'): xyz.append('z')
for item in items:
p = self.widgets[item].text()
if not p: p = 0.0
pos.append(float(p))
if QtCore.PYQT_VERSION >= 0x040500 and sip.SIP_VERSION >= 0x040800:
self.PositionChanged.emit(pos)
else:
self.emit(QtCore.SIGNAL("PositionChanged"),pos)
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class animationIntervalWidget(mgSlider):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
def __init__(self,parent):
mgSlider.__init__(self,QtCore.Qt.Horizontal,parent)
# Enable range of 0 - 1000 ms
self.setRange(1,1000,integer=1)
self.setValue(global_definitions.MAINWINDOW().animationInterval())
self.connect(self,QtCore.SIGNAL("valueChanged(int)"),self.apply)
#-------------------------------------------------------------------
def apply(self):
#-------------------------------------------------------------------
#print "animationIntervalGUI.apply",self.value()
global_definitions.MAINWINDOW().setAnimationInterval(int(self.value()))
# ?? Test for other instances of this widget and update them
def ColourBrowserManager():
if not ColBrowserManager.insts:
ColBrowserManager()
return ColBrowserManager.insts
class ColBrowserManager(QtCore.QObject):
insts = None
def __init__(self):
QtCore.QObject.__init__(self)
ColBrowserManager.insts = self
def coloursChanged(self):
self.emit(QtCore.SIGNAL('coloursChanged'))
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class mgColourBrowser(ColourBrowser.ColourBrowser):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
def __init__(self,parent=None,selected_colour=''):
#-------------------------------------------------------------------
COL = global_definitions.MGCOLOUR()
if selected_colour == 'complement': selected_colour = 'white'
ColourBrowser.ColourBrowser.__init__(self,parent,standard_colours=COL.get_standard_colours(),custom_colours=COL.get_custom_colours(),new_name_number=COL.new_name_number,selected_colour=selected_colour)
self.show()
self.connect(self,QtCore.SIGNAL("clearCustomColours"),self.handleClearCustomColours)
self.connect(self,QtCore.SIGNAL("deleteColour"),self.handleDeleteColour)
self.connect(self,QtCore.SIGNAL("newColour"),self.handleNewColour)
self.connect(self,QtCore.SIGNAL("colourNameEdit(PyQt_PyObject)"),self.handleRenameColour)
self.connect(ColourBrowserManager(),QtCore.SIGNAL('coloursChanged'),self.updateCustomColours)
def updateCustomColours(self):
ColourBrowser.ColourBrowser.updateCustomColours(self,global_definitions.MGCOLOUR().get_custom_colours())
#-------------------------------------------------------------------
def handleNewColour(self,colour=[]):
#-------------------------------------------------------------------
rgb = []
for ii in range(1,4):
rgb.append(float(colour[ii])/float(256.0))
#print "handleNewColour rgb",rgb
global_definitions.MGCOLOUR().new(colour[0],rgb)
ColourBrowserManager().coloursChanged()
#-------------------------------------------------------------------
def handleRenameColour(self,args):
#-------------------------------------------------------------------
#print 'mgColourBrowser.handleRenameColour',args
if not len(args)==2: return
global_definitions.MGCOLOUR().rename(args[0],args[1])
ColourBrowserManager().coloursChanged()
#-------------------------------------------------------------------
def handleDeleteColour(self,colour):
#-------------------------------------------------------------------
global_definitions.MGCOLOUR().delete(colour)
ColourBrowserManager().coloursChanged()
#-------------------------------------------------------------------
def handleClearCustomColours(self):
#-------------------------------------------------------------------
global_definitions.MGCOLOUR().clear_custom_colours()
ColourBrowserManager().coloursChanged()
class GridWidget(QtGui.QWidget):
def __init__(self,parent=None,rows=0,cols=0):
QtGui.QWidget.__init__(self,parent)
layout = QtGui.QGridLayout()
self.setLayout(layout)
self.validator = QtGui.QDoubleValidator(self)
for i in range(rows):
for j in range(cols):
le = QtGui.QLineEdit(self)
le.setValidator(self.validator)
layout.addWidget(le,i,j)
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class TransformMatrixDialog(MGSimpleDialog.MultiDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
def __init__(self,parent=None,title="Transformation matrix"):
MGSimpleDialog.MultiDialog.__init__(self,parent)
self.setWindowTitle(title)
layout = QtGui.QVBoxLayout()
widget = QtGui.QLabel('Rotation matrix:',self)
layout.addWidget(widget)
self.rotmat=GridWidget(self,3,3)
self.rotmat.setMaximumSize(QtCore.QSize(400,100))
layout.addWidget(self.rotmat)
line_layout = QtGui.QHBoxLayout()
widget = QtGui.QLabel('Not doing what you expected? Try',self)
line_layout.addWidget(widget)
widget = QtGui.QPushButton('Flip matrix',self)
line_layout.addWidget(widget)
self.connect(widget,QtCore.SIGNAL('clicked()'),self.flipMatrix)
layout.addLayout(line_layout)
widget = QtGui.QLabel('Translation vector:',self)
layout.addWidget(widget)
self.transvect = GridWidget(self,1,3)
layout.addWidget(self.transvect)
absLayout = QtGui.QHBoxLayout()
absLabel = QtGui.QLabel(self.tr('Apply transformation to '))
absLayout.addWidget(absLabel)
self.absCombo = QtGui.QComboBox()
self.absCombo.addItem(self.tr('absolute coordinates'))
self.absCombo.addItem(self.tr('current view'))
absLayout.addWidget(self.absCombo)
absLayout.addStretch()
layout.addLayout(absLayout)
dialog_buttons = QtGui.QDialogButtonBox()
apply_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Apply)
undo_button = dialog_buttons.addButton('Undo transformation',QtGui.QDialogButtonBox.ResetRole)
cancel_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Cancel)
self.connect(cancel_button,QtCore.SIGNAL('clicked()'),self.Close)
#self.connect(ok_button,QtCore.SIGNAL('clicked()'),self.ApplyAndClose)
self.connect(apply_button,QtCore.SIGNAL('clicked()'),self.Apply)
self.connect(undo_button,QtCore.SIGNAL('clicked()'),self.Undo)
layout.addWidget(dialog_buttons)
self.setLayout(layout)
self.setSizeGripEnabled(0)
self.CreateMenuEntry()
#-------------------------------------------------------------------
def setParams(self,params={},**kw):
#-------------------------------------------------------------------
params.update(kw)
#print 'TransformMatrixDialog.setParams',params
import types
import re,string
if params.has_key('rotation'):
if (isinstance(params['rotation'],types.ListType) or isinstance(params['rotation'],types.TupleType) ) and len(params['rotation'])==9:
self.setGrid(self.rotmat,params['rotation'])
elif isinstance(params['rotation'],types.StringType):
rotmat = string.split(re.sub(',',' ',params['rotation']))
self.setGrid(self.rotmat,rotmat)
if params.has_key('translation'):
if (isinstance(params['translation'],types.ListType) or isinstance(params['translation'],types.TupleType) ) and len(params['translation'])==3:
self.setGrid(self.transvect,params['translation'])
elif isinstance(params['translation'],types.StringType):
rotmat = string.split(re.sub(',',' ',params['translation']))
self.setGrid(self.transvect,rotmat)
#-------------------------------------------------------------------
def getParams(self):
#-------------------------------------------------------------------
import re,string
pars = {}
text = self.absCombo.currentText()
if self.tr(text) == self.tr('absolute coordinates'):
pars['transmode'] = 'absolute'
else:
pars['transmode'] = 'relative'
#text = str(self.transvect.text())
if False:
pars['translation'] = [0.0,0.0,0.0]
else:
numlist = self.extractGrid(self.transvect)
if len(numlist)==3: pars['translation'] = numlist
#text = str(self.rotmat.toPlainText())
if False:
pars['rotation'] = [1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0]
else:
tmtrx = self.extractGrid(self.rotmat)
print tmtrx
if len(tmtrx)==9:
det = ( tmtrx[0] * ( tmtrx[4]* tmtrx[8] - tmtrx[5]* tmtrx[7] ) ) + \
( tmtrx[1] * ( tmtrx[5]* tmtrx[6] - tmtrx[3]* tmtrx[8] ) ) + \
( tmtrx[2] * ( tmtrx[3]* tmtrx[7] - tmtrx[4]* tmtrx[6] ) )
print "det",det
import math
det = math.fabs(det)
if det > 0.99 and det < 1.01:
pars['rotation'] = tmtrx
return pars
def setGrid(self,grid,vals):
ij = 0
for i in range(grid.layout().rowCount()):
for j in range(grid.layout().columnCount()):
try:
grid.layout().itemAtPosition(i,j).widget().setText(str(vals[ij]))
except:
print ij,"out of range ? in", grid.layout().rowCount(),"x",grid.layout().columnCount()
ij += 1
def extractGrid(self,grid):
vals = []
for i in range(grid.layout().rowCount()):
for j in range(grid.layout().columnCount()):
vals.append(float(grid.layout().itemAtPosition(i,j).widget().text()))
return vals
#-------------------------------------------------------------------
def extractVector(self,text):
#-------------------------------------------------------------------
import re,string
strlist = string.split(re.sub(',',' ',text))
numlist = []
for item in strlist:
try:
numlist.append(float(item))
except:
pass
return numlist
#-------------------------------------------------------------------
def Apply(self):
#-------------------------------------------------------------------
pars = self.getParams()
errmess = ''
if not pars.has_key('rotation'): errmess = errmess + 'Rotation is not correct\n'
if not pars.has_key('translation'): errmess = errmess + 'Translation is not correct\n'
if errmess:
QtGui.QMessageBox.warning(None,self.windowTitle(),'Can not apply transformation\n'+errmess)
else:
self.emit(QtCore.SIGNAL('transformationChanged'))
#-------------------------------------------------------------------
def Undo(self):
#-------------------------------------------------------------------
self.setParams(rotation = ( 1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 ),
translation = ( 0.0, 0.0, 0.0 ) )
self.emit(QtCore.SIGNAL('transformationUndone'))
#-------------------------------------------------------------------
def flipMatrix(self):
#-------------------------------------------------------------------
params = self.getParams()
if not params.has_key('rotation'):
QtGui.QMessageBox.warning(None,'Can not flip matrix\n'+'Rotation is not correct')
return
mx = params['rotation']
self.setParams(rotation = ( mx[0] , mx[3], mx[6],
mx[1], mx[4], mx[7],
mx[2], mx[5], mx[8] ) )
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class saveMultiDataObj(QtGui.QDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
def __init__(self,parent,title='Save all data files',tag='',version='',message=''):
QtGui.QDialog.__init__(self,parent)
self.setWindowTitle(title)
layout = QtGui.QVBoxLayout()
if message:
line_layout = QtGui.QHBoxLayout()
line_layout.addWidget(QtGui.QLabel(message))
line_layout.addStretch(5)
layout.addLayout(line_layout)
line_layout = QtGui.QHBoxLayout()
line_layout.addWidget(QtGui.QLabel('Save files with tag',self))
self.tag = QtGui.QLineEdit(self)
line_layout.addWidget(self.tag)
line_layout.addWidget(QtGui.QLabel('and version number'))
self.tag.setText(tag)
self.version = QtGui.QSpinBox(self)
self.version.setRange(0,100)
self.version.setSingleStep(1)
self.version.setValue(version)
line_layout.addWidget(self.version)
line_layout.addStretch(5)
layout.addLayout(line_layout)
self.mode = QtGui.QButtonGroup(self)
line_layout = QtGui.QHBoxLayout()
self.append_tag = QtGui.QRadioButton('Save to filename with tag appended',self)
self.mode.addButton(self.append_tag,0)
line_layout.addWidget(self.append_tag)
line_layout.addStretch(5)
layout.addLayout(line_layout)
line_layout = QtGui.QHBoxLayout()
self.backup = QtGui.QRadioButton('Save to same filename and backup to file with tag',self)
self.mode.addButton(self.backup,0)
line_layout.addWidget(self.backup)
line_layout.addStretch(5)
layout.addLayout(line_layout)
dialog_buttons = QtGui.QDialogButtonBox()
apply_button = dialog_buttons.addButton('Save',QtGui.QDialogButtonBox.ApplyRole)
cancel_button = dialog_buttons.addButton('Close',QtGui.QDialogButtonBox.RejectRole)
self.connect(apply_button,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.emit,QtCore.SIGNAL('save')))
self.connect(apply_button,QtCore.SIGNAL('clicked()'),self.Apply)
self.connect(cancel_button,QtCore.SIGNAL('clicked()'),self.close)
layout.addWidget(dialog_buttons)
self.setLayout(layout)
self.show()
def getMode(self):
return ['append','backup'][int(self.mode.checkedId())]
def getTag(self):
return str(self.tag.text()) + str(self.version.value())
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class RoundToMultipleSpin(QtGui.QSpinBox):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
def __init__(self,parent=None):
QtGui.QSpinBox.__init__(self,parent)
self.setMultiple(1)
def setMultiple(self,value):
self.multiple = value
self.setSingleStep(value)
def fixValue(self):
v = self.value()
vnew = (v+(self.multiple-1))/self.multiple * self.multiple
self.setValue(vnew)
def fixup(self,input):
v = int(input.toAscii())
vnew = (v+(self.multiple-1))/self.multiple * self.multiple
input.replace(0,len(input),str(vnew))
def validate(self,input,pos):
try:
v = int(input.toAscii())
if v/self.multiple *self.multiple == v:
return (QtGui.QValidator.Acceptable,pos)
except:
return (QtGui.QValidator.Invalid,pos)
return (QtGui.QValidator.Intermediate,pos)
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class RestrictedSpinBox(QtGui.QSpinBox):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
def __init__(self,parent=None):
QtGui.QSpinBox.__init__(self,parent)
self.restriction = []
def setRestriction(self,value):
self.restriction = value
def fixup(self,input):
v = int(input.toAscii())
if len(self.restriction)>0:
if self.restriction.count(v)==0:
input.replace(0,len(str(self.restriction[0])),str(self.restriction[0]))
def validate(self,input,pos):
try:
v = int(input.toAscii())
if len(self.restriction)>0:
if self.restriction.count(v)>0:
return (QtGui.QValidator.Acceptable,pos)
else:
return (QtGui.QValidator.Acceptable,pos)
except:
return (QtGui.QValidator.Invalid,pos)
return (QtGui.QValidator.Intermediate,pos)
class DoubleColourSlider(QtGui.QWidget):
def __init__(self,parent=None):
QtGui.QWidget. __init__(self,parent)
colourLayout = QtGui.QGridLayout()
#colourLayout.setContentsMargins(0,0,0,0)
unAlignedLabel = QtGui.QLabel(self.tr("Unaligned colour"),self)
self.nonAlignedCombo = mgColourCombo(self,'white',browser=1)
interpLabel = QtGui.QLabel(self.tr("Blend from "),self)
interpLabel2 = QtGui.QLabel(self.tr(" to "),self)
self.interpCombo = QtGui.QComboBox(self)
self.interpCombo.addItems(["Between RGB values","Colour wheel clockwise","Colour wheel anti-clockwise"])
self.slider = UpperLowerSlider(QtCore.Qt.Horizontal,self)
self.slider.setRange(0,1,minDecimals=4)
self.lowColourCombo = mgColourCombo(self,'yellow',browser=1)
self.highColourCombo = mgColourCombo(self,'red',browser=1)
editMax = QtGui.QPushButton("Change max. value")
colourLayout.addWidget(interpLabel,0,0)
colourLayout.addWidget(self.lowColourCombo,0,1)
colourLayout.addWidget(interpLabel2,0,2)
colourLayout.addWidget(self.highColourCombo,0,3)
colourLayout.addWidget(self.interpCombo,1,1,1,3)
colourLayout.addWidget(self.slider,2,0,1,4)
colourLayout.addWidget(unAlignedLabel,3,0)
colourLayout.addWidget(self.nonAlignedCombo,3,1)
colourLayout.addWidget(editMax,3,3)
self.setLayout(colourLayout)
self.connect(self.lowColourCombo,QtCore.SIGNAL('currentIndexChanged(const QString&)'),self.valuesChanged)
self.connect(self.highColourCombo,QtCore.SIGNAL('currentIndexChanged(const QString&)'),self.valuesChanged)
self.connect(self.nonAlignedCombo,QtCore.SIGNAL('currentIndexChanged(const QString&)'),self.valuesChanged)
self.connect(self.interpCombo,QtCore.SIGNAL('currentIndexChanged(const QString&)'),self.valuesChanged)
self.connect(self.slider,QtCore.SIGNAL("rangeChanged"),self.valuesChanged)
self.connect(self, QtCore.SIGNAL('finished(int)'), self.hide)
self.connect(editMax, QtCore.SIGNAL('clicked(bool)'), self.editMaximumValue)
def editMaximumValue(self):
w = QtGui.QDialog()
layout = QtGui.QVBoxLayout()
lineEdit = QtGui.QLineEdit()
validator = QtGui.QDoubleValidator(lineEdit)
lineEdit.setText(str(self.slider.maximum()))
lineEdit.setValidator(validator)
layout.addWidget(lineEdit)
w.setLayout(layout)
w.setWindowTitle("Set maximum slider value")
def setEditMax():
minVal = self.slider.minimum()
maxVal = float(lineEdit.text())
decimals = self.slider.decimals()
lower = self.slider.lowerSpin.value()
upper = self.slider.upperSpin.value()
self.slider.setRange(minVal,maxVal,decimals)
self.slider.lowerSpin.setValue(lower)
self.slider.upperSpin.setValue(upper)
self.connect(lineEdit,QtCore.SIGNAL("textEdited(const QString&)"),setEditMax)
w.exec_()
def getValues(self):
import atom_util
mode = 1
dirn = atom_util.COLOUR_WHEEL_CLOCK
if str(self.interpCombo.currentText().toUtf8()) == "Colour wheel clockwise":
mode = 2
if str(self.interpCombo.currentText().toUtf8()) == "Colour wheel anti-clockwise":
mode = 2
dirn = atom_util.COLOUR_WHEEL_ANTICLOCK
colourInfo = {'lowerColour':str(self.lowColourCombo.currentText().toUtf8()),'upperColour':str(self.highColourCombo.currentText().toUtf8()),'lower':self.slider.getValues()[0],'upper':self.slider.getValues()[1],"mode":mode,"direction":dirn,'noneColour':str(self.nonAlignedCombo.currentText().toUtf8())}
return colourInfo
def getValuesAsColourInfo(self):
import atom_util
mode = 1
dirn = atom_util.COLOUR_WHEEL_CLOCK
if str(self.interpCombo.currentText().toUtf8()) == "Colour wheel clockwise":
mode = 2
if str(self.interpCombo.currentText().toUtf8()) == "Colour wheel anti-clockwise":
mode = 2
dirn = atom_util.COLOUR_WHEEL_ANTICLOCK
colourInfo = mgapp.DoubleColourSliderInfo(str(self.lowColourCombo.currentText().toUtf8()),str(self.highColourCombo.currentText().toUtf8()),self.slider.getValues()[0],self.slider.getValues()[1],mode,dirn,str(self.nonAlignedCombo.currentText().toUtf8()))
return colourInfo
def valuesChanged(self,val=None):
import atom_util
if QtCore.QString('Colour browser') == val:
return
mode = 1
dirn = atom_util.COLOUR_WHEEL_CLOCK
if str(self.interpCombo.currentText().toUtf8()) == "Colour wheel clockwise":
mode = 2
if str(self.interpCombo.currentText().toUtf8()) == "Colour wheel anti-clockwise":
mode = 2
dirn = atom_util.COLOUR_WHEEL_ANTICLOCK
colourInfo = mgapp.DoubleColourSliderInfo(str(self.lowColourCombo.currentText().toUtf8()),str(self.highColourCombo.currentText().toUtf8()),self.slider.getValues()[0],self.slider.getValues()[1],mode,dirn,str(self.nonAlignedCombo.currentText().toUtf8()))
self.emit(QtCore.SIGNAL("valuesChanged"),colourInfo)