""" qtgui/displayTable.py: CCP4MG Molecular Graphics Program Copyright (C) 2001-2008 University of York, CCLRC Copyright (C) 2009-2011 University of York Copyright (C) 2012 STFC This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3, modified in accordance with the provisions of the license to address the requirements of UK law. You should have received a copy of the modified GNU Lesser General Public License along with this library. If not, copies may be downloaded from http://www.ccp4.ac.uk/ccp4license.php This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. """ from PyQt4 import QtGui,QtCore import sys,copy from global_definitions import * import rebuild import guiUtils import MGSimpleDialog import functools import gc margin = 0 # Code like the line below can trigger a crash when Qt tries to access # objects which have been deleted but somehow have connections elsewhere. # # dispobj.setParent(None) # # Instead createding a dummy widget and using # # dispobj.setParent(theDummy) # # seems to create a much more stable system. # if not '-quit' in sys.argv: theDummy = QtGui.QWidget() class MGDisplayTable(QtGui.QWidget): rowHeight = 21 floatingWidth = 100 dockedWidth = 50 floatingBodyWidth = 12 dockedBodyWidth = 6 # Try this for super-compact DT, useful with icons. #dockedBodyWidth = 3 compactWidth = 6 pixmaps = {} loaded_icons = {} label_columns = 0 # Not implemented - do we need to label columns? floatingMaxLabelLength = 15 dockedMaxLabelLength = 6 dataobj_types = {} dispobj_types = {} dataobj_hide_if_empty = [] dispobj_make_parent = {} def setFloating(self): self.docked = False def setFloatingSize(self): MGDisplayTable.width = MGDisplayTable.floatingWidth MGDisplayTable.bodyWidth = MGDisplayTable.floatingBodyWidth MGDisplayTable.maxLabelLength = MGDisplayTable.floatingMaxLabelLength MGDisplayTable.width = (MGDisplayTable.bodyWidth+3+self.status_open)*MGDisplayTable.rowHeight def setDocked(self): self.docked = True def setDockedSize(self): MGDisplayTable.width = MGDisplayTable.dockedWidth MGDisplayTable.bodyWidth = MGDisplayTable.dockedBodyWidth MGDisplayTable.maxLabelLength = MGDisplayTable.dockedMaxLabelLength MGDisplayTable.width = (MGDisplayTable.bodyWidth+3+self.status_open)*MGDisplayTable.rowHeight def __init__(self,parent=None,docked=False,super_compact=False): self.movingObjects = [] self.movingTargets = [] super(MGDisplayTable,self).__init__(parent) self.GDataObjs = {} self.block_emit =0 self.status_open = 0 if super_compact: MGDisplayTable.dockedBodyWidth = 3 else: MGDisplayTable.dockedBodyWidth = 6 if docked: self.setDockedSize() self.setDocked() else: self.setFloatingSize() self.setFloating() MGDisplayTable.rowHeight = int(self.fontSize()) MGDisplayTable.width = (MGDisplayTable.bodyWidth+3+self.status_open)*MGDisplayTable.rowHeight MGDisplayTable.compact_width = MGDisplayTable.compactWidth*MGDisplayTable.rowHeight #print "MGDisplayTable rowHeight",self,MGDisplayTable.rowHeight, MGDisplayTable.width self.loadPixmaps(width=MGDisplayTable.rowHeight) import displayTableObjects MGDisplayTable.fixed_order = ['CrystalData','MolData','MapData','VectorsData','GL2dScreen'] MGDisplayTable.dataobj_types = { 'MolData' : displayTableObjects.GMolData, 'MapData' : displayTableObjects.GMapData, 'CrystalData' : displayTableObjects.GCrystalContainer, 'GL2dScreen' : displayTableObjects.GGL2dScreen, 'VectorsData' :displayTableObjects.GVectorsData } MGDisplayTable.dispobj_types = { 'MolDisp' : displayTableObjects.GMolDisp, 'MapDisp' : displayTableObjects.GMapDisp, 'SurfaceDispobj' : displayTableObjects.GSurfaceDispobj, 'HBonds' : displayTableObjects.GHBonds, 'Contacts' : displayTableObjects.GContacts, 'Annotation': displayTableObjects.GAnnotation, 'Crystal' : displayTableObjects.GCrystal, 'Image' : displayTableObjects.GImage, 'Legend' : displayTableObjects.GLegend, 'ColourLegend' : displayTableObjects.GColourLegend, 'VectorsDispobj' : displayTableObjects.GVectorsDispobj } MGDisplayTable.dataobj_hide_if_empty = ['CrystalData','Legends&Images'] MGDisplayTable.dispobj_make_parent = { 'Crystal' : 'CrystalData', 'Legend' : 'GL2dScreen', 'Image' : 'GL2dScreen' } def loadPixmaps(self,dir='',width=32,height=0): import os,glob,string if not dir: dir = os.path.join(os.environ['CCP4MG'],'qticons') #print "loadPixmaps",dir MGDisplayTable.pixmaps = {} if height<=0: height = width for subd in ['disptab']: # folder-open and folder-closed are currently 22x22 and # dont really want to scale them up #tr = QtGui.QTransform() #tr.translate((width-22.0)/2.0,(height-22.0)/2.0) #print "QTransform",tr.dx(),tr.dy() for ext in ['*.png','*.svg']: for file in glob.glob(os.path.join(dir,subd,ext)): name = os.path.split(file)[-1][0:-4] MGDisplayTable.pixmaps[name] = QtGui.QPixmap(file).scaled(32,32) def getIcon(self,name,visible=1,dir='',width=32,height=0): import os,glob,string if not dir: dir = os.path.join(os.environ['CCP4MG'],'qticons') if height<=0: height = width if not visible: name = name+'_off' #print "getIcon name",name,MGDisplayTable.loaded_icons if MGDisplayTable.loaded_icons.has_key(name): return MGDisplayTable.loaded_icons[name] else: for file in [ os.path.join(dir,'dispobj',name+'.svg'), os.path.join(dir,'dispobj',name+'.png')]: if os.path.exists(file): pix = QtGui.QPixmap(file).scaled(width,height) #print "getIcon pix",pix MGDisplayTable.loaded_icons[name] = QtGui.QIcon(pix) return MGDisplayTable.loaded_icons[name] if name[0:4] != 'unkn': return self.getIcon('unknown',visible=1,dir=dir,height=height,width=width) else: return None def getWidth(self): return (MGDisplayTable.bodyWidth+3+self.status_open)*MGDisplayTable.rowHeight + 20 def emitSignal(self,mode=''): #print "DisplayTable.emitSignal",mode, self.block_emit if not self.block_emit: self.emit(QtCore.SIGNAL(mode)) self.emit(QtCore.SIGNAL("DisplayTableChanged")) def DispObjOpen(self): for obj in self.findChildren(GDataObj): if obj.isOpen(): return 1 return 0 def showAllDataObj(self,visible=1): for obj in self.findChildren(GDataObj): obj.set_visibility(visible,redraw=0) #?? should we force all display objects visible rebuild.UpdateDisplay() def deleteAllDataObj(self): for obj in self.findChildren(GDataObj): self.deleteDataObj(obj.objectName(),update=0) # Just to be sure delete any dataobj left that were # not on the display table dellist = [] for dataobj in get_dataobj(): if not (hasattr(dataobj,'master_application') and dataobj.master_application): dellist.append(dataobj) if dellist: print "DISPLAYTABLE.deleteAllDataObj found objects without graphical interface to delete",dellist for dataobj in dellist: dataobj.delete() #del dataobj if hasattr(dataobj,"close"): dataobj.close() if not self.block_emit: print "Emitting", "removeAllDataObj" self.emit(QtCore.SIGNAL('removeAllDataObj')) else: print "Emits blocked" def loadAllDataObj(self): self.block_emit = 1 obj_list = get_dataobj() #print "DISPLAYTABLE.loadAllDataObj",obj_list for obj in obj_list: #print "loadAllDataObj", obj.get_dispobj(),obj.name if MGDisplayTable.dataobj_hide_if_empty.count(obj.name) and not obj.get_dispobj(): pass elif self.findChild(GDataObj,obj.name): pass else: self.addDataObj(name=obj.name,label=obj.name_label,object_type=obj.object_type) self.block_emit = 0 self.emitSignal('loadAllDataObj') def getDataObj(self,name=''): if not name: return None widget = self.findChild(GDataObj,name) #if not widget: # if name == 'Legends&Images': # widget = self.findChild(GDataObj,'GL2dScreen') return widget def getDispObj(self,name=''): if not name: return None widget = self.findChild(GDispObj,name) #if not widget: # if name == 'Legends&Images': # widget = self.findChild(GDataObj,'GL2dScreen') return widget def addDataObj(self,object_type='MolData',name='',label='',getDispObj=1): #print 'MGDisplayTable.addDataObj',object_type,name,label if not label: label = name+ ' ' if not self.GDataObjs.has_key(object_type): self.GDataObjs[object_type] = GDataObjs(self,object_type=object_type) graph_obj = self.findChild(GDataObj,name) if not graph_obj: graph_obj = self.GDataObjs[object_type].addGDataObj(table=self,name=name,label=label) #print "addDataObj graph_obj",graph_obj if not graph_obj: return None if getDispObj: graph_obj.updateDispObj() self.emitSignal('addDataObj') return graph_obj def deleteDataObj(self,name='',update=1): self.block_emit = 1 self.removeDataObj(name=name) target = get_dataobj(name=name) #print "deleteDataObj",name,target if target: # Are there any other objects that should be deleted # along with this one (eg Crystal gets deleted with map) dependents = target[0].getDependentsForDeletion() #print 'displayTable deleteDataObj dependents',dependents target[0].delete() if dependents: # In principle there could be a recursion here. for dep in dependents: dep_target = get_dataobj(name=dep) if dep_target: dep_target[0].delete() self.removeDataObj(dep) else: dep_target = get_dispobj(name=dep) if dep_target: dep_target.delete() self.removeDispObj(dep) self.block_emit = 0 self.emitSignal('deleteDataObj') if update: rebuild.UpdateDisplay() if not self.block_emit: print "Emitting", "removeDataObjByName", name self.emit(QtCore.SIGNAL('removeDataObjByName'),name) else: print "Emits blocked" dobjs = get_dataobj(object_type='MolData') if len(dobjs)==0: import model model.MolData.colour_counter['bymol']='' # If we are using old colours from an old status file # then reset to the new default colours when the last # object is deleted. remaining = self.findChildren(GDataObj) mapMolDataLeft = False import displayTableObjects for obj in self.findChildren(GDataObj): if type(obj) == displayTableObjects.GMolData or type(obj) == displayTableObjects.GMapData: mapMolDataLeft = True if not mapMolDataLeft and hasattr(MGCOLOUR(),"usingOldColours") and MGCOLOUR().usingOldColours: MGCOLOUR().rgbreps = [] MGCOLOUR().RGBReps.clear() MGCOLOUR().load_default() MGCOLOUR().initialiseRGBReps() MGCOLOUR().usingOldColours = False def removeDataObj(self,name=''): #print 'MGDisplayTable.removeDataObj',name group_list = [] if name == 'all': dataobj_list = self.findChildren(GDataObj) else: dataobj_list = [] dataobj = self.findChild(GDataObj,name) if dataobj: dataobj_list.append(dataobj) for dataobj in dataobj_list: if self.movingObjects.count(dataobj): self.movingObjects.remove(dataobj) for dataobj in dataobj_list: dispobjs = self.findChildren(GDispObj) for dispobj in dispobjs: if hasattr(dispobj,"statusWidget"): if dispobj in self.movingObjects: self.movingObjects.remove(dispobj) group = dataobj.parentWidget() if not group_list.count(group): group_list.append(group) dataobj.delete() #dataobj.setParent(None) dataobj.setParent(theDummy) #del dataobj if dataobj and hasattr(dataobj,"close"): dataobj.close() for group in group_list: group.setDataObjGeometry() self.emitSignal('removeDataObj') def addDispObj(self,parent_name='',object_type='',name='',resize=1): dataobj = self.findChild(GDataObj,parent_name) #print "Table.addDispObj dataobj",dataobj,parent_name if not dataobj: parent_type = MGDisplayTable.dispobj_make_parent.get(object_type,'') print "Table.addDispObj calling addDataObj",parent_type if parent_type: print name, parent_type if parent_type == 'GL2dScreen': dataobj = self.addDataObj(object_type=parent_type,getDispObj=0,name='Legends&Images') elif parent_type == 'CrystalData': dataobj = self.addDataObj(object_type=parent_type,getDispObj=0,name='CrystalData') else: dataobj = self.addDataObj(object_type=parent_type,getDispObj=0) print "addDispObj creating DataObj",parent_type,dataobj else: return obj = dataobj.addGDispObj(object_type=object_type,name=name,resize=resize) #obj.delete() #obj.deleteLater() return obj def removeDispObj(self,name='',resize=1): dispobj = self.findChild(GDispObj,name) #print 'removeDispObj',name,dispobj if not dispobj: return if hasattr(dispobj,"statusWidget"): if dispobj in self.movingObjects: self.movingObjects.remove(dispobj) dataobj = dispobj.parent().parent() dispobj.blockSignals(True) dispobj.setParent(None) #dispobj.setParent(theDummy) dispobj.delete() dispobj.close() dispobj.deleteLater() if resize: dataobj.setBodyGeometry() self.emitSignal('removeDispobj') def deleteDispObj(self,name=''): print "-------------------- Attempt deleteDispObj",name import types if isinstance(name,types.ListType): namelist = name else: namelist = [name] print "namelist",namelist for name in namelist: self.removeDispObj(name) target = get_dispobj(name=name) print "deleteDispObj",name,target if target: if hasattr(target,"delete"): target.delete() if hasattr(target,"close"): target.close() if hasattr(target,"deleteLater"): target.deleteLater() #print target #del target rebuild.UpdateDisplay() def fontSize(self): font = self.font() #print "font",font fm = QtGui.QFontMetricsF(font) #print 'font',fm.width('W'),fm.height() return max(int(fm.height()),32) def sizeHint(self): nr = 0 for dobjs in self.findChildren(GDataObjs): for datobj in dobjs.findChildren(GDataObj): nr = nr+1 if datobj.isOpen(): nr = nr + len(datobj.body.findChildren(GDispObj)) w = self.getWidth() h = nr*MGDisplayTable.rowHeight return QtCore.QSize(w,h) def minimumSizeHint(self): #print "in minimumSizeHint" return self.sizeHint() def setDataObjsGeometry(self): nrTot = 0 width = self.getWidth() height=MGDisplayTable.rowHeight #print "setDataObjsGeometry",self.GDataObjs # Draw different object types in a fixed order for object_type in MGDisplayTable.fixed_order: if self.GDataObjs.has_key(object_type): nr = self.GDataObjs[object_type].nRows self.GDataObjs[object_type].setGeometry(0,nrTot*height,width,nr*height) nrTot = nrTot +nr # Are there any object_types not in the fixed_order list for object_type in self.GDataObjs.keys(): if not MGDisplayTable.fixed_order.count(object_type): nr = self.GDataObjs[object_type].nRows self.GDataObjs[object_type].setGeometry(0,nrTot*height,width,nr*height) nrTot = nrTot +nr # resize window required_height = height*nrTot self.setFixedHeight(required_height) current_height = self.parent().height() new_height = -1 if current_heightrequired_height: new_height = required_height return if new_height>0: self.window().resize(QtCore.QSize(self.window().size().width(),new_height+20)) def set_all_visibility_from_objects(self): dataobj_list = self.findChildren(GDataObj) for dataobj in dataobj_list: visible = get_dataobj(name=dataobj.objectName())[0].get_visibility() object_type = dataobj.parentWidget().object_type dataobj.iconButton.setIcon(self.getIcon(object_type,visible=visible)) def update(self,all=0): self.block_emit = 1 if not all: #print "MGDisplayTable.update",HISTORY().update_gui for item in HISTORY().update_gui: if item[0] == 'update_DataObj': widget = self.getDataObj(name=item[1]) #print "MGDisplayTable.update",item[1],widget if widget: widget.update() elif item[0] == 'add_DataObj': obj = get_dataobj(name=item[1]) if obj: obj = obj[0] self.addDataObj(object_type=obj.object_type,name=obj.name) elif item[0] == 'delete_DataObj': self.removeDataObj(name=item[1]) else: # Alternative sledgehammer update of display table.. self.removeDataObj('all') self.loadAllDataObj() self.block_emit = 0 if not all: self.emitSignal('update') def updateDataObjLabels(self): for obj in self.findChildren(GDataObj): obj.updateLabel() self.emit(QtCore.SIGNAL('update_labels')) def setMovingObject(self,object='',unset=1): if self.movingObjects.count(object): if unset: self.movingObjects.remove(object) else: # For now allow only one moving object - unset any # current selection for obj in self.movingObjects: obj.toggleMoving() self.movingObjects = [] self.movingObjects.append(object) self.movingTargets = [] for obj in self.movingObjects: name = obj.objectName() if isinstance(obj,GDataObj): self.movingTargets.append(get_dataobj(name=name)[0]) else: self.movingTargets.append(get_dispobj(name=name)) #print "setMovingObject",self.movingTargets def handleObjectMoving(self,glwidget): #print "MGDisplayTable.handleObjectMoving",self.movingTargets,args for obj in self.movingTargets: obj.transform(glwidget) for obj in self.movingObjects: obj.updateAfterMoving() import rebuild rebuild.UpdateDisplay() MAINWINDOW().updateGLWindows() def Exit(self): for obj in self.findChildren(GDataObj): obj.Exit() class GDataObjs(QtGui.QWidget): def __init__(self,parent=None,object_type=''): super(GDataObjs,self).__init__(parent) self.object_type = object_type self.nRows = 0 def addGDataObj(self,table=None,name='',label=''): #print "GDataObjs.addGDataObj",self.object_type,name,label obj = None if MGDisplayTable.dataobj_types.has_key( self.object_type ): obj = MGDisplayTable.dataobj_types[self.object_type](self,table=table,name=name,label=label) self.setDataObjGeometry() return obj def setDataObjGeometry(self): self.show() nrTot = 0 height = MGDisplayTable.rowHeight width = self.parent().getWidth() for datobj in self.findChildren(GDataObj): if datobj.isVisible(): if datobj.isOpen(): nr = 1 + len(datobj.body.findChildren(GDispObj)) else: nr = 1 datobj.setGeometry(0, nrTot*height,width,nr*height) nrTot = nrTot + nr self.nRows = nrTot self.parentWidget().setDataObjsGeometry() class GDataObj(QtGui.QWidget): def updateMenu(self,name='icon'): if name == 'icon': guiUtils.clearMenu(self.iconMenu) defn = self.getGuiDef(name='icon') #print 'GDataObj.updateMenu',defn if defn: guiUtils.populateMenu(self,self.iconMenu,defn,self.getActionDef,default_icon='') def toggleBodyVisibility(self,updateWidth=1): #Toggle the open/closed state of subframe if apt #print "in toggleBodyVisibility",self visible = 1 - self.open if visible: self.treeWidget.resetIcon('toc-minus') else: self.treeWidget.resetIcon('toc-plus') self.body.setVisible(visible) self.open = visible get_dataobj(name=self.objectName())[0].set_expanded(expanded=self.open) #self.resize(self.sizeHint()) self.parentWidget().setDataObjGeometry() if updateWidth: MAINWINDOW().wMGDisplayTable.updateWidth() def toggleMoving(self,mode=-1): if mode <0: # This is probably from gui - just toggle the moving status if self.status == 1: self.setStatus(moving =0) else: self.setStatus(moving =1) self.table.setMovingObject(self,unset=1) else: # This is probably from table.setMovingObject self.setStatus(moving = mode) if mode == 0: self.table.setMovingObject(self,unset=1) else: self.table.setMovingObject(self,unset=0) def updateAfterMoving(self): pass def __init__(self,parent=None,table=None,name='',label='',autoClose=0): #print "GDataObj label",label #print "GDataObj name",name self.open = 1 self.autoClose = autoClose # status:: 0=not active, 1 = moving self.status = 0 self.table=table #super(GDataObj,self).__init__(parent,QtCore.Qt.WA_DeleteOnClose) super(GDataObj,self).__init__(parent) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) #print 'GDataObj.init',self,name self.setObjectName(name) # set up title and body containers height = MGDisplayTable.rowHeight self.title = QtGui.QWidget(self) self.body = QtGui.QWidget(self) self.title.setGeometry(0,0,self.table.getWidth(),height) self.body.setGeometry(0,height,self.table.getWidth(),0) self.statusWidget = GTreeFeature(self,'blank') self.treeWidget = GTreeFeature(self,'toc-minus') self.connect(self.treeWidget,QtCore.SIGNAL('contextMenu'),self.drawTreeMenu) #print "GDataObj treeWidget",self,self.treeWidget self.connect(self.treeWidget,QtCore.SIGNAL('mouseRelease'),self.toggleBodyVisibility) object_type = self.parentWidget().object_type # use QToolButton sub-class to get a right-mouse signal target = data(name) if target: vis = target.get_visibility() else: vis = 0 if target: expanded = target.get_expanded() else: expanded = 0 if expanded == 0: self.toggleBodyVisibility(updateWidth=0) self.iconButton = mgIconButton(self,icon=table.getIcon(object_type,visible=vis)) self.iconMenu = QtGui.QMenu(self) self.iconButton.setMenu(self.iconMenu) self.connect(self.iconMenu,QtCore.SIGNAL("aboutToShow()"),guiUtils.partial(self.updateMenu,'icon')) self.connect(self.iconButton,QtCore.SIGNAL("rightMouseRelease"),self.handleButtonClick) lab = QtGui.QLabel(self) lab.setObjectName('label') self.updateLabel() self.statusWidget.setGeometry(0,0,height,height) self.treeWidget.setGeometry(self.table.status_open*height,0,height,height) self.iconButton.setGeometry((1+self.table.status_open)*height,0,height,height) lab.setGeometry(((2+self.table.status_open)*height)+2,0,10*height,height) #Layout the body self.body.setVisible(1) # Need to create the visible QAction before possiblity of # call to handleButtonClick which might find the DispObj QAction vis = guiUtils.createAction('data_visible',self) def Exit(self): pass def delete(self): children = self.findChildren(GDispObj) #print 'GDataObj.delete GDispObj children',children for cc in children: cc.delete() children = self.findChildren(QtGui.QDialog) #print 'GDataObj.delete MGSimpleDialog children',children for cc in children: cc.close() def updateLabel(self,text=''): lab = self.findChild( QtGui.QLabel,'label') if lab: if text: lab.setText(text) else: target = get_dataobj(name=self.objectName()) if len(target)>0 and target[0] and hasattr(target[0],"molHnd"): if hasattr(target[0].molHnd,"StructureTitle") and callable(target[0].molHnd.StructureTitle): toolTip = str(target[0].molHnd.StructureTitle())[:150] if hasattr(target[0].molHnd,"Source") and callable(target[0].molHnd.Source): source = target[0].molHnd.Source() if 'ORGANISM_SCIENTIFIC:' in source: organism = source[source.find('ORGANISM_SCIENTIFIC:')+len('ORGANISM_SCIENTIFIC:'):].split(';')[0].strip()[:150] toolTip = toolTip + ' ('+organism+')' lab.setToolTip(toolTip) #print 'GDispObj.updateLabel',target[0].get_label() if target: lab.setText(target[0].get_label()) def setStatus(self,moving=-1): # status probably ought to be a bitmap to accomodate multiple # moving/selected/highlighted flags. icons = ['blank','moving'] toolTips = [ self.tr('This object is not active'), self.tr('Move this object holding down x key and left/middle mouse')] update = 0 if moving>=0: if self.status != moving: update = 1 self.status = moving if update: self.statusWidget.resetIcon(icons[self.status]) # bummer -labels probably cant have tool tips self.statusWidget.setToolTip(toolTips[self.status]) def handleButtonClick(self,**args): # Right mouse click is shortcut for toggling visiblity # toggle the 'visible' QAction and call set_visibility vis = self.findChild(QtGui.QAction,'data_visible') if vis: vis.trigger() def isOpen(self): return self.open def drawTreeMenu(self,x,y): import guiUtils #print 'GDataObj.drawTreeMenu',x,y if not hasattr(self,'treeMenu'): self.treeMenu = QtGui.QMenu(self) else: guiUtils.clearMenu(self.treeMenu) if self.isOpen(): action = self.treeMenu.addAction(self.tr('Hide display objects')) action.setToolTip(self.tr('Do not show display object in the display table')) self.connect(action,QtCore.SIGNAL('triggered()'),guiUtils.partial(self.handleTreeMenu,'close')) else: action = self.treeMenu.addAction(self.tr('Show display objects')) action.setToolTip(self.tr('Show display object in the display table')) self.connect(action,QtCore.SIGNAL('triggered()'),guiUtils.partial(self.handleTreeMenu,'open')) action = self.treeMenu.addAction(self.tr('Show for this data only')) action.setToolTip(self.tr('Show display object for only this data in the display table')) self.connect(action,QtCore.SIGNAL('triggered()'),guiUtils.partial(self.handleTreeMenu,'open_this')) action = self.treeMenu.addAction(self.tr('Show all display objects')) action.setToolTip(self.tr('Show all display object in the display table')) self.connect(action,QtCore.SIGNAL('triggered()'),guiUtils.partial(self.handleTreeMenu,'open_all')) action = self.treeMenu.addAction(self.tr('Hide all display objects')) action.setToolTip(self.tr('Hide all display object in the display table')) self.connect(action,QtCore.SIGNAL('triggered()'),guiUtils.partial(self.handleTreeMenu,'close_all')) self.treeMenu.popup(QtCore.QPoint(x,y)) def handleTreeMenu(self,mode=''): #print 'GDataObj.handleTreeMenu',mode if mode == 'open': if not self.isOpen(): self.toggleBodyVisibility() elif mode == 'close': if self.isOpen(): self.toggleBodyVisibility() elif mode == 'open_this': if not self.isOpen(): self.toggleBodyVisibility(updateWidth=0) for obj in self.table.findChildren(GDataObj): if obj != self and obj.isOpen(): obj.toggleBodyVisibility(updateWidth=0) #self.window().updateWidth() elif mode == 'open_all': for obj in self.table.findChildren(GDataObj): if not obj.isOpen(): obj.toggleBodyVisibility(updateWidth=0) #self.window().updateWidth() elif mode == 'close_all': for obj in self.table.findChildren(GDataObj): if obj.isOpen(): obj.toggleBodyVisibility(updateWidth=0) #self.window().updateWidth() def addGDispObj(self,object_type='',name='',resize=1): if MGDisplayTable.dispobj_types.has_key(object_type): #print "Creating a ",MGDisplayTable.dispobj_types[object_type] obj = MGDisplayTable.dispobj_types[object_type](self,table=self.table,name=name) if resize: self.setBodyGeometry() return obj else: print 'Do not know how to make display table display object',object_type return None def cleanupGDispObj(self): disp_list = self.body.findChildren(GDispObj) for obj in disp_list: if hasattr(obj,'for_delete'): obj.close() #del disp_list self.setBodyGeometry() def setBodyGeometry(self): #if not self.isOpen(): return if self.autoClose and len(self.body.findChildren(GDispObj))==0: self.hide() else: height = MGDisplayTable.rowHeight width = self.table.getWidth() disp_list = self.body.findChildren(GDispObj) #print "setBodyGeometry",self,len(disp_list) nr = 0 for obj in disp_list[0:-1]: obj.setGeometry(0,nr*height,width,height) obj.treeWidget.resetIcon('tjunc') nr = nr + 1 if disp_list: disp_list[-1].setGeometry(0,nr*height,width,height) disp_list[-1].treeWidget.resetIcon('ljunc') self.body.setGeometry(0,height,width,len(disp_list)*height) #print "setBodyGeometry final nr",self,nr self.show() self.parentWidget().setDataObjGeometry() #-------------------------------------------------------------- def add_dispobj(self,args=[],target=None,object_type=''): #-------------------------------------------------------------- #print "add_dispobj",object_type ''' Create a display object for parent 'target' and add display object to the display table ''' if args: target = args[0] object_type = args[1] if not target: target = get_dataobj(name=self.objectName()) dobj = target.add_object(object_type=object_type) #print "GDataObj.add_dispobj dobj",dobj,object_type if dobj: ndispobj = len(self.findChildren(GDispObj)) created_obj = self.table.addDispObj(parent_name=target.name, object_type=object_type,name=dobj.name) rebuild.UpdateDisplay() # If this is first display object recentre if ndispobj == 0: MAINWINDOW().handleRecentre() return created_obj #------------------------------------------------------------- def del_dispobj(self,name=''): #------------------------------------------------------------- target = get_dispobj(name=name) if target: target.delete() self.table.removeDispObj(name) #------------------------------------------------------------- def updateDispObj(self,emit=True): #------------------------------------------------------------- for dispobj in self.body.children(): """ # Even this does not help! theName = str(dispobj.objectName()) self.table.removeDispObj(theName,resize=0) # But the stuff below does?!!! """ dispobj.blockSignals(True) if hasattr(dispobj,"statusWidget"): if dispobj in self.table.movingObjects: self.table.movingObjects.remove(dispobj) dispobj.setParent(None) dispobj.close() dispobj.delete() dispobj.deleteLater() if(emit): self.table.emitSignal('removeDispobj') # Update the display objects of dataobj name name = self.objectName() dataobj = get_dataobj(name=name) if dataobj: #print "updateDispObj objinsts",dataobj[0].objinsts for dispobj in dataobj[0].objinsts: #print "addDataObj dispobj",dispobj,dispobj.name,dispobj.object_type o = self.table.addDispObj(parent_name=name,name=dispobj.name,object_type=dispobj.object_type,resize=0) #print "==================== AT CREATION, referrers",gc.get_referrers(o),len(gc.get_referrers(o)) # Not doing these leaks lots of memory. But why???? #o.delete() #o.deleteLater() self.table.getDataObj(name).setBodyGeometry() #--------------------------------------------------------------------- def set_visibility(self,visible=-1,redraw=1): #--------------------------------------------------------------------- object_type = self.parentWidget().object_type if visible<0: visible = int(self.findChild(QtGui.QAction,'data_visible').isChecked()) #print "GDispObj.set_visibility",visible,object_type self.iconButton.setIcon(self.table.getIcon(object_type,visible=visible)) get_dataobj(name=self.objectName())[0].set_visibility(visibility=visible) DISPLAYTABLE().emit(QtCore.SIGNAL('visibilityChanged')) if redraw: rebuild.UpdateDisplay() #--------------------------------------------------------------------- def getGuiDef(self,name='',**info): #--------------------------------------------------------------------- #print "GDataObj.getGuiDef name",name if name == 'context': return [] else: return [] #--------------------------------------------------------------------- def getActionDef(self,name,target=None,**info): #--------------------------------------------------------------------- #print "GDataObj getActionDef",name,target if name == 'data_visible': return dict ( text = self.tr("Visible"), tip = self.tr('Toggle all of this data object visible or invisible'), slot = self.set_visibility, checkable = 1, checked = target.get_visibility ) elif name == 'move': return dict ( text = self.tr("Move ")+self.objectName(), tip = self.tr('Move this data object with the mouse'), slot = self.toggleMoving, checkable = 1, checked = self.isMoving, deleteLater = 0 ) elif name == 'data_delete': return dict ( text = self.tr("Delete"), tip = self.tr('Delete this data object'), slot = guiUtils.partial(self.table.deleteDataObj,self.objectName()) ) elif name == 'data_list_data': return dict (text = self.tr('List data'), tip = self.tr('List data file in file viewer'), slot = self.listData ) elif name == 'data_clone': return dict (text = self.tr('Clone'), tip = self.tr('Load the data object again with one display object'), slot = self.clone ) elif name == 'data_clone_dispobj': return dict (text = self.tr('Clone all display'), tip = self.tr('Load the data object again with the same display objects'), slot = guiUtils.partial(self.clone,1) ) else: return {} #------------------------------------------------------------- def isMoving(self): #------------------------------------------------------------- return self.status == 1 #------------------------------------------------------------- def update(self): #------------------------------------------------------------- target = get_dataobj(name=self.objectName()) if not target: return target = target[0] #print "DataObj.update",self,target.update_gui for item in target.update_gui: #print "item",item if item[0] == 'visible': object_type = self.parentWidget().object_type self.iconButton.setIcon(self.table.getIcon(object_type,visible=target.visible)) elif item[0] == 'add': obj = get_dispobj(name=item[1]) if obj: self.table.addDispObj(parent_name=self.objectName(),object_type=obj.object_type,name=item[1]) elif item[0] == 'delete': self.table.removeDispObj(item[1]) elif item[0] == 'update_DispObj': self.findChild(GDispObj,item[1]).update() elif item[0] == 'update': import types for widget in self.findChildren(QtGui.QAction): if widget.parent() == self: name = widget.objectName() if not ['visible'].count(name): defn = self.getActionDef(name) if defn.has_key('checked'): #print "DataObj.update action",name if isinstance(defn['checked'],types.IntType): widget.setChecked(int(defn['checked'])) else: try: widget.setChecked(defn['checked']()) except: pass if defn.has_key('enabled'): if isinstance(defn['enabled'],types.IntType): widget.setEnabled(defn['enabled']) else: try: widget.setEnabled(defn['enabled']()) except: pass target.update_gui=[] def listData(self): target = data(self.objectName()) if target: text = target.list_data() if text: viewer = FILEVIEWER('data_listing') window = viewer.loadText(text,target.filename[2]) def pickInfo(self,event,text=''): pos = event.getPickPosition() pos_text = "%8.2f %8.2f %8.2f" % (pos[0],pos[1],pos[2]) out = self.tr('Picked ')+event.getLabel(format='full')+'\n' + \ self.tr('Position: ')+pos_text +'\n' + \ self.tr('Display object: ')+ event.getDispObj().name+ '\n' + \ self.tr('Data object: ') + event.getDataObj().name_label + '\n' + \ self.tr('Data file: ') + event.getDataObj().filename[2] + '\n\n' + \ text + '\n' # Want a non-modal message box box = QtGui.QMessageBox(self) box.setWindowTitle('Info '+event.getLabel()) box.setText(out) box.setWindowModality(QtCore.Qt.NonModal) box.show() #------------------------------------------------------------- def clone(self,withDispobj=0,name=""): #------------------------------------------------------------- #print 'GDataObj.clone',withDispobj target = get_dataobj(name=self.objectName()) if not target: return target = target[0] new_data = target.clone(withDispobj=withDispobj,name=name) if not new_data: return #print 'GDataObj.clone',target,new_data,new_data.object_type,new_data.name # Create copy of DispObj if withDispobj: # Make copies of the display objects for disp in target.objinsts: new_disp = new_data.add_object(object_type=disp.object_type,visible=disp.visible, params=disp.params(),selparams=disp.selparams(), colparams=disp.colparams(),styleparams=disp.styleparams()) else: # Create one default display object new_data.add_object() self.table.addDataObj(object_type=new_data.object_type,name=new_data.name, label=getattr(new_data,'name_label',''),getDispObj=1) #print 'GDataObj.clone done table.addDataObj' #------------------------------------------------------------- #------------------------------------------------------------- #------------------------------------------------------------- class GDispObj(QtGui.QWidget): #------------------------------------------------------------- #------------------------------------------------------------- #------------------------------------------------------------- def __init__(self,parent,table=None,name='',object_type=''): #print "GDispObj name",name,self,parent self.table=table self.status = 0 super(GDispObj,self).__init__(parent.body) self.setObjectName(name) self.object_type = object_type # type_label is a word explaining the object type ot be used in gui self.type_label = '' # Draw the 'tree' lines and icon w = MGDisplayTable.rowHeight self.statusWidget = GTreeFeature(self,'blank') self.statusWidget.setGeometry(0,0,w,w) self.treeWidget = GTreeFeature(self,'tjunc') self.treeWidget.setGeometry((1+self.table.status_open)*w,0,w,w) target = get_dispobj(name=name) if not target or target == '': visible = 1 else: visible = target.get_visibility() self.iconButton = mgIconButton(self,icon=table.getIcon(object_type,visible=visible)) self.iconButton.setGeometry((2+self.table.status_open)*w,0,w,w) self.iconMenu = guiUtils.mgMenu(self) self.iconButton.setMenu(self.iconMenu) self.connect(self.iconMenu,QtCore.SIGNAL("aboutToShow()"),guiUtils.partial(self.updateMenu,'icon')) self.connect(self.iconButton,QtCore.SIGNAL("rightMouseRelease"),self.handleButtonClick) self.widgets = dict (icon = self.iconButton) bw = MGDisplayTable.bodyWidth i = 0 x = (3+self.table.status_open)*w format_list = self.getGuiDef() nslider = 0 if bw < 6: for format in format_list: mode = format.get('mode') if str(mode) == "VALUESLIDER": nslider = nslider + 1 if format_list: widthFactor = float(bw)/(len(format_list)+nslider) else: widthFactor = bw offset = 0 for format in format_list: i = i + 1 name = format.get('name') #print "format",name,format if format['mode'] == 'MENU': self.widgets[name] = QtGui.QToolButton(self) self.widgets[name].setPopupMode(QtGui.QToolButton.InstantPopup) #self.widgets[name].setPopupMode(QtGui.QToolButton.MenuButtonPopup) menu = guiUtils.mgMenu(self) self.widgets[name].setMenu(menu) self.connect(menu,QtCore.SIGNAL("aboutToShow()"),guiUtils.partial(self.updateMenu,name)) elif format['mode'] == 'VALUESLIDER': import mgWidgets minimum = 0 maximum = 999 if format.has_key('range'): minimum = format['range'][0] maximum = format['range'][1] self.widgets[name] = mgWidgets.mgSlider(QtCore.Qt.Horizontal,self) self.widgets[name].setRange(format.get('minimum',minimum),format.get('maximum',maximum)) #self.widgets[name+'_docked_'] = QtGui.QDoubleSpinBox(self) self.widgets[name+'_docked_'] = mgWidgets.DropDownSliderWithValue(QtCore.Qt.Horizontal,self) self.widgets[name+'_docked_'].setRange(format.get('minimum',minimum),format.get('maximum',maximum)) if bw < 6: self.widgets[name+'_docked_'].setGeometry(x,0,int(widthFactor*w*2),w) offset = offset + int(widthFactor*w) else: self.widgets[name+'_docked_'].setGeometry(x,0,int(widthFactor*w),w) if self.table and self.table.docked: self.widgets[name+'_docked_'].show() self.widgets[name].hide() else: self.widgets[name+'_docked_'].hide() self.widgets[name].show() if format.get('callback',''): self.connect(self.widgets[name],QtCore.SIGNAL("valueChanged(double)"),format['callback']) self.connect(self.widgets[name+'_docked_'],QtCore.SIGNAL("valueChanged(double)"),format['callback']) self.connect(self.widgets[name],QtCore.SIGNAL("valueChanged(double)"),functools.partial(self.updateAlternative,self.widgets[name+'_docked_'],self.widgets[name])) self.connect(self.widgets[name+'_docked_'],QtCore.SIGNAL("valueChanged(double)"),functools.partial(self.updateAlternative,self.widgets[name],self.widgets[name+'_docked_'])) elif format['mode'] == 'SLIDER': self.widgets[name] = QtGui.QSlider(QtCore.Qt.Horizontal,self) self.widgets[name].setRange(format.get('minimum',0),format.get('maximum',999)) if format.get('callback',''): self.connect(self.widgets[name],QtCore.SIGNAL("valueChanged(int)"),format['callback']) elif format['mode'] == 'PUSHBUTTON': #print "PUSHBUTTON label", self.format[name]['label'] self.widgets[name] = QtGui.QToolButton(self) if format.get('callback',''): self.connect(self.widgets[name],QtCore.SIGNAL("released()"),format['callback']) self.updateLabel(name) self.widgets[name].setGeometry(x,0,int(widthFactor*w),w) x = x + int(widthFactor*w) + offset toolTip = format.get('toolTip','') if toolTip: self.widgets[name].setToolTip(toolTip) self.show() def updateAlternative(self,toChange,changed): val = changed.value() toChange.blockSignals(True) toChange.setValue(val) toChange.blockSignals(False) def delete(self): children = self.findChildren(QtGui.QWidget) #print 'GDispObj.delete MGSimpleDialog children',self,children for cc in children: #print "Closing",cc cc.close() cc.deleteLater() def toggleMoving(self,mode=-1): if mode <0: # This is probably from gui - just toggle the moving status if self.status == 1: self.setStatus(moving =0) else: self.setStatus(moving =1) else: # This is probably from table.setMovingObject self.setStatus(moving = mode) self.table.setMovingObject(self,unset=1) def updateAfterMoving(self): pass def setStatus(self,moving=-1): icons = ['blank','moving'] update = 0 if moving>=0: if self.status != moving: update = 1 self.status = moving if update: self.statusWidget.resetIcon(icons[self.status]) #------------------------------------------------------------- def handleButtonClick(self,**args): #------------------------------------------------------------- # Right mouse click is shortcut for toggling visiblity # toggle the 'visible' QAction and call set_visibility vis = self.findChild(QtGui.QAction,'visible') if not vis: # Need to create the QAction vis = guiUtils.createAction('visible',self) vis.trigger() #------------------------------------------------------------- def updateMenu(self,menuName=''): #------------------------------------------------------------- guiUtils.clearMenu( self.widgets[menuName].menu()) guiUtils.populateMenu(self,self.widgets[menuName].menu(),self.getGuiDef(menuName),default_icon='') #------------------------------------------------------------------- def colour_browser(self): #------------------------------------------------------------------- target = get_dispobj(name=self.objectName()) selected_colour=target.get_colour_label() if not hasattr(self,'colour_browser_gui'): import mgWidgets self.colour_browser_gui = mgWidgets.mgColourBrowser(MAINWINDOW(),selected_colour=selected_colour) self.connect(self.colour_browser_gui,QtCore.SIGNAL("ColourSelected"),self.set_browser_colour) self.colour_browser_gui.show() self.colour_browser_gui.raise_() #---------------------------------------------------------------------- def set_browser_colour(self,colour=''): #---------------------------------------------------------------------- #print "ColourSelected set_browser_colour",colour if colour: target = get_dispobj(name=self.objectName()) target.set_colour(colour) self.updateLabel('colour') rebuild.UpdateDisplay() #---------------------------------------------------------------------- def getGuiDef(self,name='',**info): #---------------------------------------------------------------------- return [] #-------------------------------------------------------------------- def getActionDef(self,name='',target=None,**info): #-------------------------------------------------------------------- ''' Generic action definitions for GDispObj ''' #print "DispObj.getActionDef",target if name == 'visible': if hasattr(target,'visible'): return dict ( text = self.tr("Visible"), tip = self.tr('Toggle this display object visible/invisible'), slot = self.set_visibility, checkable = 1, checked = target.get_visibility, deleteLater = 0 ) elif name[0:len('apply_biomolecule_')] == 'apply_biomolecule_': nbio = int(name[len('apply_biomolecule_'):]) def c(): return int(target.doBiomolecule == True and target.nbiomol==nbio) return dict ( text = "Show biomolecule "+name[len('apply_biomolecule_'):], slot = guiUtils.partial(target.toggleBiomolecule,int(name[len('apply_biomolecule_'):])), checkable = 1, checked = c ) elif name[0:len('apply_biomolecule')] == 'apply_biomolecule': def c(): return int(target.doBiomolecule == True) return dict ( text = "Show biomolecule", slot = guiUtils.partial(target.toggleBiomolecule), checkable = 1, checked = c ) elif name[0:len('apply_symmetry')] == 'apply_symmetry': def c(): return int(target.doSymmetry == True) return dict ( text = "Apply symmetry", slot = guiUtils.partial(target.toggleSymmetryStatus), checkable = 1, checked = c ) elif name[0:len('draw_central')] == 'draw_central': def c(): return int(target.doCentralSymmetry == True) return dict ( text = "Draw central copy", slot = guiUtils.partial(target.toggleCentralSymmetryStatus), checkable = 1, checked = c ) elif name == 'flash': def c(): return target.isFlashing() return dict ( text = self.tr("Flash"), tip = self.tr('Start or stop this display object flashing'), slot = target.set_flashing, checkable = 1, checked = c, deleteLater = 0 ) elif name == 'transparency': def c(): return int(target.opacity<=0.99) return dict ( text = self.tr("Set transparency"), tip = self.tr('Set the transparency level for this object'), slot = self.openTransparencyGui, checkable = 1, checked = c, deleteLater = 0 ) elif name == 'delete': return dict ( text = self.tr("Delete"), tip = self.tr('Delete this display object'), slot = guiUtils.partial(self.table.deleteDispObj,self.objectName() ) ) elif name == 'clone': return dict ( text = self.tr("Clone"), tip = self.tr('Make a new display object the same as this one'), slot = self.clone, enabled = 1) elif name == 'help': return dict ( text = self.tr("Help"), enabled = 0) elif name == 'custom_drawing_style': def c(): return hasattr(target,'drawingStylePM') return dict ( text = self.tr('Custom drawing style'), slot = self.displayStyleGui, checkable = 1, checked = c, toolTip = self.tr('Customise display style of this object') ) elif name == 'list_data': return dict ( text = self.tr('List data'), toolTip = self.tr('List or write to file'), slot = self.listData ) return {} #--------------------------------------------------------------------- def set_visibility(self,visible=-1): #--------------------------------------------------------------------- # Not sure why the following line does not work.. #if visible<0: visible = int(self.findChild(QtGui.QAction,'visible').isChecked()) target = get_dispobj(name=self.objectName()) if visible<0: visible = 1 - target.get_visibility() #print "GDispObj set_visibility",visible self.iconButton.setIcon(self.table.getIcon(self.object_type,visible=visible)) get_dispobj(name=self.objectName()).set_visibility(visibility=visible) #print "Emit visibilityChanged! dispobj" DISPLAYTABLE().emit(QtCore.SIGNAL('visibilityChanged')) rebuild.UpdateDisplay() #------------------------------------------------------------------- def listData(self): #------------------------------------------------------------------- target = get_dispobj(name=self.objectName()) if not target: return text = target.list_data() viewer = FILEVIEWER('data_listing') if not viewer: return print 'GDispObj.listData',text window = viewer.loadText(text,title=self.type_label+' '+target.parent.name_label) window.setFont(style='fixed_width') #------------------------------------------------------------------- def openTransparencyGui(self): #------------------------------------------------------------------- if not hasattr(self,'transparencyGui'): import mgWidgets target = get_dispobj(name=self.objectName()) self.transparencyGui = QtGui.QDialog(self) self.transparencyGui.setWindowTitle(self.objectName()+'transparency') layout = QtGui.QHBoxLayout() layout.addWidget(QtGui.QLabel('Opacity')) self.transpararencySlider = mgWidgets.mgSlider(QtCore.Qt.Horizontal,self) self.transpararencySlider.setImmediateMode(0) self.transpararencySlider.setRange(0.0,1.0) self.transpararencySlider.setSingleStep(0.02) self.transpararencySlider.setValue(target.opacity) self.transpararencySlider.slider.setTracking(1) layout.addWidget(self.transpararencySlider) self.transparencyGui.setLayout(layout) self.connect(self.transpararencySlider,QtCore.SIGNAL("valueChanged(double)"),self.setTransparency) self.transparencyGui.show() self.transparencyGui.raise_() #------------------------------------------------------------------- def setTransparency(self,value): #------------------------------------------------------------------- #print 'setTransparency',value if not hasattr(self,'transpararencySlider'): return get_dispobj(name=self.objectName()).set_opacity(value) rebuild.UpdateDisplay() #------------------------------------------------------------------- def displayStyleGui(self): #------------------------------------------------------------------- target = get_dispobj(name=self.objectName()) pm = target.getDrawingStylePM(custom=1) #print "GDispObj.displayStyleGui",pm.name if not self.findChild(QtGui.QWidget,pm.name): import mgPreferences dialog = QtGui.QDialog(self) dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose) dialog.setWindowTitle(pm.title) layout = QtGui.QVBoxLayout() scrollarea = QtGui.QScrollArea(self) layout.addWidget(scrollarea) # getDrawingStylePM will make a custom pm if one does not exist styleGui = mgPreferences.paramsManagerGui(dialog,pm=pm) styleGui.setObjectName(pm.name) scrollarea.setWidget(styleGui) scrollarea.setWidgetResizable(1) scrollarea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) buttons = mgPreferences.preferenceButtons(self) for item in ['apply','reset','help','close']: self.connect(buttons.findChild(QtGui.QWidget,item),QtCore.SIGNAL('released()'),guiUtils.partial(self.handleStyleGui,item)) resetDefaults = QtGui.QPushButton("Reset to global") if sys.platform == "darwin": prefMenu = "QtMG" else: prefMenu = "Edit" resetDefaults.setToolTip(resetDefaults.tr("Remove custom preferences for this object\nand put back under control of global preferences.\ni.e. "+prefMenu+"->Preferences->Model display->Model drawing style")) self.connect(resetDefaults,QtCore.SIGNAL('clicked(bool)'),guiUtils.partial(self.handleStyleGui,"global")) buttons.layout().addWidget(resetDefaults) layout.addWidget(buttons) dialog.setLayout(layout) #if pm.apply_mode != 'on_request': # self.connect(styleGui,QtCore.SIGNAL('changed'),guiUtils.partial(self.handleStyleGui,'apply')) styleGui.window().show() styleGui.window().raise_() #------------------------------------------------------------------- def handleStyleGui(self,item=''): #------------------------------------------------------------------- target = get_dispobj(name=self.objectName()) pm = target.getDrawingStylePM() styleGui = self.findChild(QtGui.QWidget,pm.name) if item == 'apply': pm.setparams(styleGui.getParams()) # NB pm.setparams should have done the redraw elif item == 'reset': styleGui.resetDefaults() elif item == 'help': styleGui.help() elif item == 'close': styleGui.window().close() elif item == 'global': globalPM = PM('model_drawing_style') styleGui.window().close() # Set custom params to be same as global and thus redraw oldpm = target.getDrawingStylePM() oldpm.setparams(globalPM.getparams()) # Then remove the custom style target.removeCustomDrawingStyle() DISPLAYTABLE().emit(QtCore.SIGNAL("CustomDrawingStyleChanged")) #------------------------------------------------------------- def updateLabel(self,widget): #------------------------------------------------------------- import os row_defn = self.getGuiDef('row') icon='' useIcons = PM('advanced_options').getparams()['iconized_display_table'] for defn in row_defn: if defn.get('name','') == widget: if useIcons and defn.has_key('getIcon'): icon = defn['getIcon']() if defn.has_key('getLabel'): text = defn['getLabel']() elif defn.has_key('getValue'): text = defn['getValue']() elif defn.has_key('label'): text = defn['label'] #print "DispObj.updateLabel",self,widget,text if ['SLIDER','VALUESLIDER'].count(defn['mode']): self.widgets[widget].setValue(text) if self.widgets.has_key(widget+'_docked_'): self.widgets[widget+'_docked_'].setValue(self.widgets[widget].value()) else: if len(text)>MGDisplayTable.maxLabelLength: self.widgets[widget].setText(text[0:MGDisplayTable.maxLabelLength-2]+'..') else: self.widgets[widget].setText(text) if widget == 'selection': self.widgets[widget].setToolTip("Select atoms to draw.

Currently: "+text) if widget == 'colour': self.widgets[widget].setToolTip("Select colour scheme.

Currently: "+text) if widget == 'style': self.widgets[widget].setToolTip("Select style.

Currently: "+text) if hasattr(self.widgets[widget],'setIcon'): if hasattr(self.widgets[widget],'setToolButtonStyle'): if DISPLAYTABLE().docked: self.widgets[widget].setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) else: self.widgets[widget].setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) import cprim if icon: if type(icon) == QtGui.QIcon: theIcon = QtGui.QIcon(icon) elif os.path.exists(icon): theIcon = QtGui.QIcon(icon) elif cprim.RGBReps().GetColourNumber(icon)>-1: cols = cprim.RGBReps().GetColour(icon) col = QtGui.QColor() col.setRgbF(cols[0],cols[1],cols[2],1) pixmap = QtGui.QPixmap(28,28) pixmap.fill(col) theIcon = QtGui.QIcon(pixmap) else: theIcon = QtGui.QIcon() self.widgets[widget].setIcon(theIcon) self.widgets[widget].setIconSize(QtCore.QSize(28,28)) else: theIcon = QtGui.QIcon() self.widgets[widget].setIcon(theIcon) #------------------------------------------------------------- def update(self): #------------------------------------------------------------- target = get_dispobj(name=self.objectName()) #print "GDispObj.update actions",target.update_gui for item in target.update_gui: if item[0] == 'visible': self.iconButton.setIcon(self.table.getIcon(self.object_type, visible= target.visible)) elif item[0] == 'update': row_def = self.getGuiDef('row') #print "DispObj.update",self,row_def for defn in row_def: self.updateLabel(defn['name']) for widget in self.findChildren(QtGui.QAction): name = widget.objectName() #print "action",name,self.getActionDef(name) if not ['visible'].count(name): defn = self.getActionDef(name) #print 'GDispObj.update defn',defn if defn.has_key('checked'): #print "DispObj.update action",name if callable(defn['checked']): widget.setChecked(defn['checked']()) else: widget.setChecked(defn['checked']) if defn.has_key('enabled'): if callable(defn['enabled']): widget.setEnabled(defn['enabled']()) else: widget.setEnabled(defn['enabled']) target.update_gui =[] #------------------------------------------------------------- def clone(self): #------------------------------------------------------------- #print 'GDispObj.clone',self.objectName(),get_dispobj(name=self.objectName()) target = get_dispobj(name=self.objectName()) if not target: return # Create copy of DispObj params=copy.deepcopy(target.params()) selparams=target.selparams() colparams=target.colparams() styleparams=target.styleparams() doDrawingStyle = False if params.has_key('drawing_style'): doDrawingStyle = True if sys.platform != 'win32': import uuid uuid._uuid_generate_time = None uuid._uuid_generate_random = None uuid_str = uuid.uuid4().get_hex() else: import msilib uuid_str = msilib.gen_uuid().strip('{').strip('}').replace('-','') pmold = PM(params['drawing_style']) name = params['drawing_style'] + uuid_str params.pop('drawing_style') dobj = target.parent.add_object(object_type=target.object_type,visible=1, params=params,selparams=selparams, colparams=colparams,styleparams=styleparams) #print 'GDispObj.clone self',target.name,'clone',dobj,dobj.name if not dobj: return # (Hack?) force redrawing of dependents. if doDrawingStyle: pm = dobj.getDrawingStylePM(name=name,custom=1) pm.setparams(pmold.getparams()) # Add to display table self.table.addDispObj(parent_name=target.parent.name, object_type=target.object_type,name=dobj.name) import rebuild rebuild.UpdateDisplay() #--------------------------------------------------------------------- class GTreeFeature(QtGui.QLabel): #--------------------------------------------------------------------- # Tried implementing as a QPushButton with image # drawn as QIcon -- could not get image right size # or right background colour def __init__(self,parent,feature): super(GTreeFeature,self).__init__(parent) pmaps = MGDisplayTable.pixmaps if pmaps.has_key(feature): self.setPixmap(pmaps[feature]) if pmaps[feature].isQBitmap(): self.setMask(pmaps[feature].mask()) def mouseReleaseEvent(self,event): # Reimplementing QWidget.mouseReleaseEvent because # QLabel does not have required signal if event.button() == QtCore.Qt.RightButton: event.accept() self.emit(QtCore.SIGNAL('contextMenu'),event.globalX(),event.globalY()) else: event.accept() self.emit(QtCore.SIGNAL('mouseRelease')) def resetIcon(self,feature): #print "resetIcon",feature pmaps = MGDisplayTable.pixmaps if pmaps.has_key(feature): self.setPixmap(pmaps[feature]) if pmaps[feature].isQBitmap(): self.setMask(pmaps[feature].mask()) class DispWindowCore: def setObjectsChanged(self,theWidget): pass def setWidth(self,compact=0): print 'DispWindow.setWidth',self.compact,compact #return if compact == self.compact: return if compact: self.setFixedWidth(MGDisplayTable.compact_width+self.scrollWidth) else: self.setFixedWidth(MGDisplayTable.width+self.scrollWidth) self.compact = compact def updateWidth(self): self.setWidth(1-self.scrollarea.widget().DispObjOpen()) def Close(self): self.hide() def populateStuffMenu(self): self.stuffMenu.clear() alldata = self.stuffMenu.addMenu("For all data") alldo = self.stuffMenu.addMenu("For all display objects") for action_name in ['all_data_hide','all_data_show']: action = guiUtils.createAction(action_name,self.parent()) alldata.addAction(action) for action_name in ['all_disp_labels','all_disp_flashing','all_disp_transparency']: action = guiUtils.createAction(action_name,self.parent()) alldo.addAction(action) def populateCreateMenu(self): self.createMenu.clear() for action_name in self.parent().menuDefinitions['_file_create'][0][1:]: action = guiUtils.createAction(action_name,self.parent()) self.createMenu.addAction(action) class DispWindowNoDock(DispWindowCore, MGSimpleDialog.MGSimpleDialog): def setObjectsChanged(self,theWidget): self.blockSignals(True) DISPLAYTABLE().update(all=1) self.blockSignals(False) def __init__(self,parent=None,MGDisplayTable=None): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.menu = "Windows" layout = QtGui.QVBoxLayout() tbLayout = QtGui.QHBoxLayout() tb = QtGui.QToolButton(self) tb.setText("Create object") self.createMenu = QtGui.QMenu(self) tb.setMenu(self.createMenu) tb.setPopupMode(QtGui.QToolButton.InstantPopup) tbLayout.addWidget(tb) tb2 = QtGui.QToolButton(self) self.stuffMenu = QtGui.QMenu(self) tb2.setMenu(self.stuffMenu) tb2.setPopupMode(QtGui.QToolButton.InstantPopup) tb2.setText("Tools") tbLayout.addWidget(tb2) tbLayout.addStretch(2) layout.addLayout(tbLayout) self.populateCreateMenu() self.populateStuffMenu() self.setLayout(layout) layout.setContentsMargins(margin,margin,margin,margin) self.scrollarea = QtGui.QScrollArea() layout.addWidget(self.scrollarea) self.scrollarea.setWidget(MGDisplayTable) self.scrollarea.setWidgetResizable(1) self.scrollarea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.scrollWidth=self.scrollarea.verticalScrollBar().height() #print "scrollWidth",scrollWidth self.compact = -1 self.setWidth() self.setWindowTitle(self.tr('Display Table')) self.CreateMenuEntry() def UnClose(self): #print 'DispWindow.UnClose' MGSimpleDialog.MGSimpleDialog.UnClose(self) DISPLAYTABLE().update(all=1) #--------------------------------------------------------------------- class DispWindowDock(DispWindowCore, MGSimpleDialog.MGSimpleDockDialog): #--------------------------------------------------------------------- """ def resizeEvent(self,e): if self.size().width()>=500 and e.oldSize().width()<500: MAINWINDOW().MGDisplayTable.setFloatingSize() self.redoDockFloatingSize(self.dockWidget.isTopLevel()) if self.size().width()<500 and e.oldSize().width()>=500: MAINWINDOW().MGDisplayTable.setDockedSize() self.redoDockFloatingSize(self.dockWidget.isTopLevel()) """ def setWidth(self,compact=0): return def dockLocationChanged(self,loc): print "dockLocationChanged",loc; sys.stdout.flush() def topLevelChanged(self,topLevel): if MAINWINDOW() and hasattr(MAINWINDOW(),"MGDisplayTable"): if topLevel: MAINWINDOW().MGDisplayTable.setFloatingSize() MAINWINDOW().MGDisplayTable.setFloating() else: if self.width()<500: MAINWINDOW().MGDisplayTable.setDockedSize() else: MAINWINDOW().MGDisplayTable.setFloatingSize() MAINWINDOW().MGDisplayTable.setDocked() self.redoDockFloatingSize(topLevel) def redoDockFloatingSize(self,topLevel): widgets = MAINWINDOW().MGDisplayTable.findChildren(GDispObj) bw = MGDisplayTable.bodyWidth w = MGDisplayTable.rowHeight for widget in widgets: i = 0 x = (3+widget.table.status_open)*w format_list = widget.getGuiDef() nslider = 0 if bw < 6: for format in format_list: mode = format.get('mode') if str(mode) == "VALUESLIDER": nslider = nslider + 1 if format_list: widthFactor = float(bw)/(len(format_list)+nslider) else: widthFactor = bw offset = 0 for format in format_list: i = i + 1 name = format.get('name') mode = format.get('mode') if str(mode) == "VALUESLIDER": if not topLevel: if widget.widgets.has_key(name+'_docked_'): widget.widgets[name+'_docked_'].show() if bw < 6: widget.widgets[name+'_docked_'].setGeometry(x,0,int(widthFactor*w*2),w) offset = offset + int(widthFactor*w) else: widget.widgets[name+'_docked_'].setGeometry(x,0,int(widthFactor*w),w) widget.widgets[name+'_docked_'].update() widget.widgets[name].hide() else: if widget.widgets.has_key(name+'_docked_'): widget.widgets[name+'_docked_'].hide() widget.widgets[name].show() widget.widgets[name].setGeometry(x,0,int(widthFactor*w),w) widget.widgets[name].update() x = x + int(widthFactor*w) + offset widget.updateLabel(name) widgets = MAINWINDOW().MGDisplayTable.findChildren(GDataObj) width = MAINWINDOW().MGDisplayTable.getWidth() height = MAINWINDOW().MGDisplayTable.height() for widget in widgets: widget.setBodyGeometry() if topLevel: self.dockWidget.resize(width+40,height+40) MAINWINDOW().MGDisplayTable.update() def populateStuffMenu(self): self.stuffMenu.clear() alldata = self.stuffMenu.addMenu("For all data") alldo = self.stuffMenu.addMenu("For all display objects") for action_name in ['all_data_hide','all_data_show']: action = guiUtils.createAction(action_name,self.parent().parent()) alldata.addAction(action) for action_name in ['all_disp_labels','all_disp_flashing','all_disp_transparency']: action = guiUtils.createAction(action_name,self.parent().parent()) alldo.addAction(action) action = guiUtils.createAction("collapse_all",self.parent().parent()) alldata = self.stuffMenu.addAction(action) action = guiUtils.createAction("show_all",self.parent().parent()) alldata = self.stuffMenu.addAction(action) def populateCreateMenu(self): self.createMenu.clear() for action_name in self.parent().parent().menuDefinitions['_file_create'][0][1:]: action = guiUtils.createAction(action_name,self.parent().parent()) self.createMenu.addAction(action) def __init__(self,parent=None,MGDisplayTable=None,defaultDockArea=QtCore.Qt.RightDockWidgetArea): MGSimpleDialog.MGSimpleDockDialog.__init__(self,defaultDockArea=defaultDockArea) self.menu = "Windows" layout = QtGui.QVBoxLayout() tbLayout = QtGui.QToolBar() tb = QtGui.QToolButton(self) tb.setText("Create object") self.createMenu = QtGui.QMenu(self) tb.setMenu(self.createMenu) tb.setPopupMode(QtGui.QToolButton.InstantPopup) tbLayout.addWidget(tb) tb2 = QtGui.QToolButton(self) self.stuffMenu = QtGui.QMenu(self) tb2.setMenu(self.stuffMenu) tb2.setPopupMode(QtGui.QToolButton.InstantPopup) tb2.setText("Tools") tbLayout.addWidget(tb2) tb.setArrowType(QtCore.Qt.DownArrow) tb2.setArrowType(QtCore.Qt.DownArrow) tb.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly) tb2.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly) layout.addWidget(tbLayout) self.populateCreateMenu() self.populateStuffMenu() self.setLayout(layout) layout.setContentsMargins(margin,margin,margin,margin) self.scrollarea = QtGui.QScrollArea() layout.addWidget(self.scrollarea) self.scrollarea.setWidget(MGDisplayTable) self.scrollarea.setWidgetResizable(1) self.scrollarea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.scrollWidth=self.scrollarea.verticalScrollBar().height() #print "scrollWidth",scrollWidth self.connect(self.dockWidget,QtCore.SIGNAL("topLevelChanged(bool)"),self.topLevelChanged) #self.connect(self.dockWidget,QtCore.SIGNAL("dockLocationChanged(Qt::DockWidgetArea)"),self.dockLocationChanged) self.compact = -1 self.setWidth() self.setWindowTitle(self.tr('Display Table')) self.CreateMenuEntry() self.needUpdateAll = False self.connect(self.dockWidget,QtCore.SIGNAL("visibilityChanged(bool)"),self.visibilityChanged) def UnCloseNoUpdate(self): MGSimpleDialog.MGSimpleDockDialog.UnClose(self) def UnClose(self): #print 'DispWindow.UnClose' self.needUpdateAll = False MGSimpleDialog.MGSimpleDockDialog.UnClose(self) DISPLAYTABLE().update(all=1) def visibilityChanged(self,visible): #print "dock changed",visible if self.needUpdateAll and visible: self.needUpdateAll = False self.blockSignals(True) #print "updating" DISPLAYTABLE().update(all=1) self.blockSignals(False) def showEvent(self,e): #print 'DispWindow.showEvent' if self.needUpdateAll: self.needUpdateAll = False self.blockSignals(True) #print "updating" DISPLAYTABLE().update(all=1) self.blockSignals(False) def setObjectsChanged(self,theWidget): if self.dockWidget.isFloating() or len(MAINWINDOW().tabifiedDockWidgets(self.dockWidget))==0 or (len(MAINWINDOW().tabifiedDockWidgets(self.dockWidget))>0 and not theWidget.dockWidget in MAINWINDOW().tabifiedDockWidgets(self.dockWidget)): self.blockSignals(True) #print "updating" DISPLAYTABLE().update(all=1) self.blockSignals(False) else: #print "setting dirty flag" self.needUpdateAll = True #--------------------------------------------------------------------- class mgIconButton(QtGui.QToolButton): #--------------------------------------------------------------------- # Sub-class QToolButton so we can get a signal from # right mouse press def __init__(self,parent=None,icon=None): QtGui.QToolButton.__init__(self,parent) self.setPopupMode(QtGui.QToolButton.InstantPopup) if icon: self.setIcon(icon) # Force larger icons self.setIconSize(QtCore.QSize(32,32)) def mouseReleaseEvent(self,event): #print "mouseReleaseEvent",event.button() if event.button() == QtCore.Qt.RightButton: event.accept() self.emit(QtCore.SIGNAL('rightMouseRelease')) else: event.ignore()