class CustomEditor(Editor): """ Custom style of editor for instances. If selection among instances is allowed, the editor displays a combo box listing instances that can be selected. If the current instance is editable, the editor displays a panel containing trait editors for all the instance's traits. """ # Background color when an item can be dropped on the editor: ok_color = DropColor # The orientation of the instance editor relative to the instance selector: orientation = "vertical" # Class constant: extra = 0 # --------------------------------------------------------------------------- # Trait definitions: # --------------------------------------------------------------------------- # List of InstanceChoiceItem objects used by the editor items = Property # The view to use for displaying the instance view = AView # --------------------------------------------------------------------------- # Finishes initializing the editor by creating the underlying toolkit # widget: # --------------------------------------------------------------------------- def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ factory = self.factory if factory.name != "": self._object, self._name, self._value = self.parse_extended_name(factory.name) # Create a panel to hold the object trait's view: if factory.editable: self.control = self._panel = parent = SimplePanel() # Build the instance selector if needed: selectable = factory.selectable droppable = factory.droppable items = self.items for item in items: droppable |= item.is_droppable() selectable |= item.is_selectable() if selectable: self._object_cache = {} item = self.item_for(self.value) if item is not None: self._object_cache[id(item)] = self.value self._choice = ListBox() self._choice.setVisibleItemCount(0) self._choice.addChangeLister(getattr(self, "update_object")) self.set_tooltip(self._choice) if factory.name != "": self._object.on_trait_change(self.rebuild_items, self._name, dispatch="ui") self._object.on_trait_change(self.rebuild_items, self._name + "_items", dispatch="ui") factory.on_trait_change(self.rebuild_items, "values", dispatch="ui") factory.on_trait_change(self.rebuild_items, "values_items", dispatch="ui") self.rebuild_items() elif droppable: self._choice = TextBox() self._choice.setEnabled(False) self.set_tooltip(self._choice) # if droppable: # self._choice.SetDropTarget( PythonDropTarget( self ) ) orientation = factory.orientation if orientation is "default": orientation = self.orientation if (selectable or droppable) and factory.editable: if orientation is "horizontal": panel = HorizontalPanel() else: panel = VerticalPanel() # layout = QtGui.QBoxLayout(orientation, parent) # layout.setMargin(0) # layout.addWidget(self._choice) # # if orientation == QtGui.QBoxLayout.TopToBottom: # hline = QtGui.QFrame() # hline.setFrameShape(QtGui.QFrame.HLine) # hline.setFrameShadow(QtGui.QFrame.Sunken) # # layout.addWidget(hline) self.create_editor(parent, panel) elif self.control is None: if self._choice is None: self._choice = ListBox() self._choice.setVisibleItemCount(0) self._choice.addChangeLister(getattr(self, "update_object")) self.control = self._choice else: if orientation is "horizontal": panel = HorizontalPanel() else: panel = VerticalPanel() self.create_editor(parent, panel) # Synchronize the 'view' to use: # fixme: A normal assignment can cause a crash (for unknown reasons) in # some cases, so we make sure that no notifications are generated: self.trait_setq(view=factory.view) self.sync_value(factory.view_name, "view", "from") # --------------------------------------------------------------------------- # Creates the editor control: # --------------------------------------------------------------------------- def create_editor(self, parent, panel): """ Creates the editor control. """ self._panel = SimplePanel() panel.addWidget(self._panel) # --------------------------------------------------------------------------- # Gets the current list of InstanceChoiceItem items: # --------------------------------------------------------------------------- def _get_items(self): """ Gets the current list of InstanceChoiceItem items. """ if self._items is not None: return self._items factory = self.factory if self._value is not None: values = self._value() + factory.values else: values = factory.values items = [] adapter = factory.adapter for value in values: if not isinstance(value, InstanceChoiceItem): value = adapter(object=value) items.append(value) self._items = items return items # --------------------------------------------------------------------------- # Rebuilds the object selector list: # --------------------------------------------------------------------------- def rebuild_items(self): """ Rebuilds the object selector list. """ # Clear the current cached values: self._items = None # Rebuild the contents of the selector list: name = -1 value = self.value choice = self._choice choice.clear() for i, item in enumerate(self.items): if item.is_selectable(): choice.addItem(item.get_name()) if item.is_compatible(value): name = i # Reselect the current item if possible: if name >= 0: choice.setSelectedIndex(name) else: # Otherwise, current value is no longer valid, try to discard it: try: self.value = None except: pass # --------------------------------------------------------------------------- # Returns the InstanceChoiceItem for a specified object: # --------------------------------------------------------------------------- def item_for(self, object): """ Returns the InstanceChoiceItem for a specified object. """ for item in self.items: if item.is_compatible(object): return item return None # --------------------------------------------------------------------------- # Returns the view to use for a specified object: # --------------------------------------------------------------------------- def view_for(self, object, item): """ Returns the view to use for a specified object. """ view = "" if item is not None: view = item.get_view() if view == "": view = self.view return self.ui.handler.trait_view_for(self.ui.info, view, object, self.object_name, self.name) # --------------------------------------------------------------------------- # Handles the user selecting a new value from the combo box: # --------------------------------------------------------------------------- def update_object(self, text): """ Handles the user selecting a new value from the combo box. """ name = unicode(text) for item in self.items: if name == item.get_name(): id_item = id(item) object = self._object_cache.get(id_item) if object is None: object = item.get_object() if (not self.factory.editable) and item.is_factory: view = self.view_for(object, self.item_for(object)) view.ui(object, self.control, "modal") if self.factory.cachable: self._object_cache[id_item] = object self.value = object self.resynch_editor() break # --------------------------------------------------------------------------- # Updates the editor when the object trait changes external to the editor: # --------------------------------------------------------------------------- def update_editor(self): """ Updates the editor when the object trait changes externally to the editor. """ # Synchronize the editor contents: self.resynch_editor() # Update the selector (if any): choice = self._choice item = self.item_for(self.value) if (choice is not None) and (item is not None): name = item.get_name(self.value) if self._object_cache is not None: idx = choice.findText(name) for idx in range(choice.getItemCount()): value = choice.getValue(idx) if value == name: break else: idx = -1 if idx < 0: idx = choice.getItemCount() choice.addItem(name) choice.setSelectedIndex(idx) else: choice.setItemText(name, choice.getSelectedIndex()) # --------------------------------------------------------------------------- # Resynchronizes the contents of the editor when the object trait changes # external to the editor: # --------------------------------------------------------------------------- def resynch_editor(self): """ Resynchronizes the contents of the editor when the object trait changes externally to the editor. """ panel = self._panel if panel is not None: # Dispose of the previous contents of the panel: layout = panel.layout() if layout is None: layout = VerticalPanel() # layout.setMargin(0) elif self._ui is not None: self._ui.dispose() self._ui = None else: # child = layout.takeAt(0) # while child is not None: # child = layout.takeAt(0) # # del child pass # Create the new content for the panel: stretch = 0 value = self.value if not isinstance(value, HasTraits): str_value = "" if value is not None: str_value = self.str_value control = Label(str_value) else: view = self.view_for(value, self.item_for(value)) context = value.trait_context() handler = None if isinstance(value, Handler): handler = value context.setdefault("context", self.object) context.setdefault("context_handler", self.ui.handler) self._ui = ui = view.ui( context, panel, "subpanel", value.trait_view_elements(), handler, self.factory.id ) control = ui.control self.scrollable = ui._scrollable ui.parent = self.ui if view.resizable or view.scrollable or ui._scrollable: stretch = 1 # FIXME: Handle stretch. layout.add(control) # --------------------------------------------------------------------------- # Disposes of the contents of an editor: # --------------------------------------------------------------------------- def dispose(self): """ Disposes of the contents of an editor. """ # Make sure we aren't hanging on to any object refs: self._object_cache = None if self._ui is not None: self._ui.dispose() if self._choice is not None: if self._object is not None: self._object.on_trait_change(self.rebuild_items, self._name, remove=True) self._object.on_trait_change(self.rebuild_items, self._name + "_items", remove=True) self.factory.on_trait_change(self.rebuild_items, "values", remove=True) self.factory.on_trait_change(self.rebuild_items, "values_items", remove=True) super(CustomEditor, self).dispose() # --------------------------------------------------------------------------- # Handles an error that occurs while setting the object's trait value: # --------------------------------------------------------------------------- def error(self, excp): """ Handles an error that occurs while setting the object's trait value. """ pass # --------------------------------------------------------------------------- # Returns the editor's control for indicating error status: # --------------------------------------------------------------------------- def get_error_control(self): """ Returns the editor's control for indicating error status. """ return self._choice or self.control # -- UI preference save/restore interface ----------------------------------- # --------------------------------------------------------------------------- # Restores any saved user preference information associated with the # editor: # --------------------------------------------------------------------------- def restore_prefs(self, prefs): """ Restores any saved user preference information associated with the editor. """ ui = self._ui if (ui is not None) and (prefs.get("id") == ui.id): ui.set_prefs(prefs.get("prefs")) # --------------------------------------------------------------------------- # Returns any user preference information associated with the editor: # --------------------------------------------------------------------------- def save_prefs(self): """ Returns any user preference information associated with the editor. """ ui = self._ui if (ui is not None) and (ui.id != ""): return {"id": ui.id, "prefs": ui.get_prefs()} return None # -- Traits event handlers -------------------------------------------------- def _view_changed(self, view): self.resynch_editor()
class I2CPanel : class saveStateListener : def __init__(self, panel) : self._saveStatePanel=panel def onRemoteResponse(self, response, request_info): self._saveStatePanel.returnStatement.setText("File saved:" + response) def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server" ) class loadStateListener : def __init__(self, panel) : self._saveStatePanel=panel def onRemoteResponse(self, response, request_info): self._saveStatePanel.returnStatement.setText("File loaded:" + response) self._saveStatePanel.rpcService.I2CRegisterValues( self._saveStatePanel.getTotalCBCs(), I2CPanel.ReadRegisterValueListener(self._saveStatePanel) ) #refresh of text boxes def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server" ) class ConnectedCBCListener : """ A class to listen for the response to the connectedCBCNames call """ def __init__(self, listBox) : self.listBox=listBox def onRemoteResponse(self, response, request_info): self.listBox.clear() if response == None: self.listBox.addItem("<none>") self.listBox.setEnabled( False ) else : for name in response : self.listBox.addItem(name) #e.g FE0CBC0 self.listBox.setEnabled(True) def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server" ) class ReadRegisterValueListener : """ A class to listen for the response to the call to get the register values """ def __init__(self, panel) : self._I2Cpanel=panel self.textBoxes=self._I2Cpanel.i2cValueEntries def onRemoteResponse(self, response, request_info): #Call is now made for all connected CBCs for better stability of status box- fb for cbcName in self._I2Cpanel.getActiveCBCs(): if cbcName=='FE0CBC0': valuesTuple = response[response.keys()[0]] elif cbcName=='FE0CBC1': valuesTuple = response[response.keys()[1]] # For this chip loop over all the register and set the text box values for registerName in valuesTuple : box=self.textBoxes[registerName] status=self._I2Cpanel.statusValueEntries[registerName] box.setText( "0x%02x"%valuesTuple[registerName] ) box.setStyleAttribute( "background-color", "#FFFFFF" ) box.setEnabled( True ) #for some reason pyjas likes these separated - fb for registerName in valuesTuple: if response['FE0CBC0'][registerName]==response['FE0CBC1'][registerName]: self._I2Cpanel.statusValueEntries[registerName].setText("==") else: self._I2Cpanel.statusValueEntries[registerName].setText(" //") def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server" ) class RefreshListener : """ A class that will wait for a response before refreshing the status box """ def __init__(self, panel) : self._Refresh = panel def onRemoteResponse(self, response, request_info): self._Refresh.rpcService.I2CRegisterValues( self._Refresh.getTotalCBCs(), I2CPanel.ReadRegisterValueListener(self._Refresh) ) #Live refresh of the status box def onRemoteError(self, code, message, request_info): ErrorMessage( "Unable to contact server" ) def __init__( self ) : # This is the service that will be used to communicate with the DAQ software self.rpcService = GlibRPCService.instance() # The main panel that everythings will be insided self.mainPanel = HorizontalPanel() self.mainPanel.setSpacing(10) self.i2cValueEntries = {} # The input boxes for all the registers self.statusValueEntries = {} # Displays the status of the i2cValueEntries self.stateValueEntries = {} # For load/save state self.fileName = {} # File name of the i2c registers # This is the list of available CBC chips. It will be populated by a call to the # server later. self.cbcList=ListBox(MultipleSelect=True, VisibleItemCount=10) self.cbcList.addItem( "waiting..." ) # Default text until I hear from the server what's connected self.cbcList.setEnabled( False ) self.cbcList.addChangeListener(self) self.rpcService.connectedCBCNames( None, I2CPanel.ConnectedCBCListener(self.cbcList) ) # Ask the server what's connected # This is the panel that will have the list of I2C registers. I'll split up the # registers into subjects to make them more manageable. self.mainSettings = DisclosurePanel("Main Control Registers") self.channelMasks = DisclosurePanel("Channel Masks") self.channelTrims = DisclosurePanel("Channel Trims") self.callSettings = VerticalPanel("Load/Save States") self.callSettings.setBorderWidth(1) self.callSettings.add(HTML("<center>Load/Save State</center>")) cbcListAndCallSettings=VerticalPanel() cbcListAndCallSettings.add(self.cbcList) cbcListAndCallSettings.add(self.callSettings) self.mainPanel.add(cbcListAndCallSettings) self.mainPanel.add(self.mainSettings) self.mainPanel.add(self.channelMasks) self.mainPanel.add(self.channelTrims) self.callSettings.add( self.createStatesPanel()) self.mainSettings.add( self.createRegisterPanel(["FrontEndControl","TriggerLatency","HitDetectSLVS","Ipre1","Ipre2","Ipsf","Ipa","Ipaos","Vpafb","Icomp","Vpc","Vplus","VCth","TestPulsePot","SelTestPulseDel&ChanGroup","MiscTestPulseCtrl&AnalogMux","TestPulseChargePumpCurrent","TestPulseChargeMirrCascodeVolt","CwdWindow&Coincid","MiscStubLogic"]) ) self.channelMasks.add( self.createRegisterPanel(["MaskChannelFrom008downto001","MaskChannelFrom016downto009","MaskChannelFrom024downto017","MaskChannelFrom032downto025","MaskChannelFrom040downto033","MaskChannelFrom048downto041","MaskChannelFrom056downto049","MaskChannelFrom064downto057","MaskChannelFrom072downto065","MaskChannelFrom080downto073","MaskChannelFrom088downto081","MaskChannelFrom096downto089","MaskChannelFrom104downto097","MaskChannelFrom112downto105","MaskChannelFrom120downto113","MaskChannelFrom128downto121","MaskChannelFrom136downto129","MaskChannelFrom144downto137","MaskChannelFrom152downto145","MaskChannelFrom160downto153","MaskChannelFrom168downto161","MaskChannelFrom176downto169","MaskChannelFrom184downto177","MaskChannelFrom192downto185","MaskChannelFrom200downto193","MaskChannelFrom208downto201","MaskChannelFrom216downto209","MaskChannelFrom224downto217","MaskChannelFrom232downto225","MaskChannelFrom240downto233","MaskChannelFrom248downto241","MaskChannelFrom254downto249"]) ) self.channelTrims.add( self.createRegisterPanel(["Channel001","Channel002","Channel003","Channel004","Channel005","Channel006","Channel007","Channel008","Channel009","Channel010","Channel011","Channel012","Channel013","Channel014","Channel015","Channel016","Channel017","Channel018","Channel019","Channel020","Channel021","Channel022","Channel023","Channel024","Channel025","Channel026","Channel027","Channel028","Channel029","Channel030","Channel031","Channel032","Channel033","Channel034","Channel035","Channel036","Channel037","Channel038","Channel039","Channel040","Channel041","Channel042","Channel043","Channel044","Channel045","Channel046","Channel047","Channel048","Channel049","Channel050","Channel051","Channel052","Channel053","Channel054","Channel055","Channel056","Channel057","Channel058","Channel059","Channel060","Channel061","Channel062","Channel063","Channel064","Channel065","Channel066","Channel067","Channel068","Channel069","Channel070","Channel071","Channel072","Channel073","Channel074","Channel075","Channel076","Channel077","Channel078","Channel079","Channel080","Channel081","Channel082","Channel083","Channel084","Channel085","Channel086","Channel087","Channel088","Channel089","Channel090","Channel091","Channel092","Channel093","Channel094","Channel095","Channel096","Channel097","Channel098","Channel099","Channel100","Channel101","Channel102","Channel103","Channel104","Channel105","Channel106","Channel107","Channel108","Channel109","Channel110","Channel111","Channel112","Channel113","Channel114","Channel115","Channel116","Channel117","Channel118","Channel119","Channel120","Channel121","Channel122","Channel123","Channel124","Channel125","Channel126","Channel127","Channel128","Channel129","Channel130","Channel131","Channel132","Channel133","Channel134","Channel135","Channel136","Channel137","Channel138","Channel139","Channel140","Channel141","Channel142","Channel143","Channel144","Channel145","Channel146","Channel147","Channel148","Channel149","Channel150","Channel151","Channel152","Channel153","Channel154","Channel155","Channel156","Channel157","Channel158","Channel159","Channel160","Channel161","Channel162","Channel163","Channel164","Channel165","Channel166","Channel167","Channel168","Channel169","Channel170","Channel171","Channel172","Channel173","Channel174","Channel175","Channel176","Channel177","Channel178","Channel179","Channel180","Channel181","Channel182","Channel183","Channel184","Channel185","Channel186","Channel187","Channel188","Channel189","Channel190","Channel191","Channel192","Channel193","Channel194","Channel195","Channel196","Channel197","Channel198","Channel199","Channel200","Channel201","Channel202","Channel203","Channel204","Channel205","Channel206","Channel207","Channel208","Channel209","Channel210","Channel211","Channel212","Channel213","Channel214","Channel215","Channel216","Channel217","Channel218","Channel219","Channel220","Channel221","Channel222","Channel223","Channel224","Channel225","Channel226","Channel227","Channel228","Channel229","Channel230","Channel231","Channel232","Channel233","Channel234","Channel235","Channel236","Channel237","Channel238","Channel239","Channel240","Channel241","Channel242","Channel243","Channel244","Channel245","Channel246","Channel247","Channel248","Channel249","Channel250","Channel251","Channel252","Channel253","Channel254","ChannelDummy"]) ) self.mainSettings.add() self.echo=Label() self.mainPanel.add(self.echo) def getPanel( self ) : return self.mainPanel def onChange( self, sender ) : if sender == self.cbcList : # Make a call to the RPC service to get the register values self.rpcService.I2CRegisterValues( self.getTotalCBCs(), I2CPanel.ReadRegisterValueListener(self) )#fb - sends all CBCs self.load.setEnabled(True) self.save.setEnabled(True) elif sender == self.save: msg = self.saveFileName.getText() self.rpcService.saveI2cRegisterValues(msg, I2CPanel.saveStateListener(self) ) elif sender == self.load: msg = self.loadFileName.getText() self.rpcService.loadI2cRegisterValues(msg, I2CPanel.loadStateListener(self) ) self.rpcService.I2CRegisterValues( self.getTotalCBCs(), I2CPanel.ReadRegisterValueListener(self) )# # Sender must be a text box. Need to format the input. else : try: # For some reason the '0x' at the start of the string is causing exceptions, # even though it works fine with interactive python. I'll take it off anyway. string=sender.getText() if( len(string)>=2 ) : if string[0]=='0' and string[1]=='x' : string=string[2:] value=int( string, 16 ) # convert as hex # Cap values at 255 if value<0 : value=0 if value>255 : value=255 sender.setStyleAttribute( "background-color", "#FFFFFF" ) # Convert to the same format as everything else sender.setText( "0x%02x"%value ) # Send the change to the RPC service messageParameters = {} for cbcName in self.getActiveCBCs() : messageParameters[cbcName]={ sender.getTitle():value } self.rpcService.setI2CRegisterValues( messageParameters, I2CPanel.RefreshListener(self) ) except ValueError: sender.setStyleAttribute( "background-color", "#FF3333" ) #self.echoSelection() def echoSelection(self): #fb - a good "print screen" method msg = " File saved: " for names in self.getCheckedStates(): msg += names self.echo.setText(msg) def getList(self): selectCBCs = [] for i in range(self.cbcList.getItemCount()) : if self.cbcList.isItemSelected(i): selectedCBCs.append(self.cbcList.getItemText(i)) def getTotalCBCs(self) : #fb totalCBCs = [] for i in range(self.cbcList.getItemCount()) : totalCBCs.append(self.cbcList.getItemText(i)) return totalCBCs def getSpecificCBC(self, i): #fb specificCBC = [] specificCBC.append(self.cbcList.getItemText(i)) return specificCBC def getActiveCBCs(self) : selectedCBCs = [] for i in range(self.cbcList.getItemCount()) : if self.cbcList.isItemSelected(i): selectedCBCs.append(self.cbcList.getItemText(i)) return selectedCBCs def getCheckedStates(self): # returns the checked boxes + filename selectedStates = [] #for names in self.stateValueEntries: #if str(self.stateValueEntries[names].isChecked())=="True": # selectedStates.append(names) selectedStates.append(self.saveFileName.getText()) return selectedStates def createRegisterPanel( self, registerNames ) : """ Creates panels and buttons for everything given in registerNames, and returns the main panel. """ flowPanel=FlowPanel() for buttonName in registerNames : newPanel=HorizontalPanel() label=Label(buttonName) newPanel.add( label ) newTextBox=TextBox() newTextBox.setEnabled(False) newTextBox.setWidth(80) statusBox=TextBox() statusBox.setEnabled(False) statusBox.setWidth(30) newPanel.add(newTextBox) newPanel.add(statusBox) newPanel.setCellHorizontalAlignment( newTextBox, HasHorizontalAlignment.ALIGN_RIGHT ) newPanel.setCellHorizontalAlignment( statusBox, HasHorizontalAlignment.ALIGN_RIGHT ) newPanel.setCellWidth( statusBox, "20px" ) newPanel.setWidth("100%") #newPanel.setStyleName("areaStyle"); #newPanel.setBorderWidth(5); newTextBox.setText("select chip...") newTextBox.addChangeListener(self) newTextBox.setTitle(buttonName) # This isn't displayed, but it's useful to have stored self.i2cValueEntries[buttonName]=newTextBox self.statusValueEntries[buttonName]=statusBox statusBox.setTitle(buttonName) statusBox.setText("...") flowPanel.add(newPanel) return flowPanel def createStatesPanel(self): vertPanel=VerticalPanel() vertPanel.setSpacing(10) selectionNames = (["Main Control", "Masks", "Trims"]) registerSelection = VerticalPanel() for name in selectionNames : checkBox = CheckBox(name) checkBox.setTitle(name) self.stateValueEntries[name]=checkBox registerSelection.add(checkBox) #Tidy up loadPanel = HorizontalPanel() loadFileTextBox = TextBox() loadFileTextBox.setText("MyI2cCfg") loadFileTextBox.setWidth(80) self.loadFileName = loadFileTextBox loadPanel.add(loadFileTextBox) self.load = Button("Load",getattr(self,"onChange")) #overrides default and sends it to onChange loadPanel.add(self.load) self.load.setEnabled(False) savePanel = HorizontalPanel() saveFileTextBox = TextBox() saveFileTextBox.setText("MyI2cCfg") saveFileTextBox.setWidth(80) self.saveFileName = saveFileTextBox savePanel.add(saveFileTextBox) self.save = Button("Save", getattr(self,"onChange")) savePanel.add(self.save) self.save.setEnabled(False) self.returnStatement = Label() vertPanel.add(registerSelection) vertPanel.add(loadPanel) vertPanel.add(savePanel) vertPanel.add(self.returnStatement) return vertPanel
class DisplayHistogramsView(object) : """ @brief View in the MVP pattern for displaying histograms. @author Mark Grimes ([email protected]) @date 09/Feb/2014 """ def __init__( self ) : self.cbcList=ListBox(MultipleSelect=True, VisibleItemCount=4) self.channelList=ListBox(MultipleSelect=True, VisibleItemCount=20) self.updateButton=Button("Update") controls=VerticalPanel() controls.add(self.updateButton) controls.add(self.cbcList) controls.add(self.channelList) controls.setCellHorizontalAlignment( self.updateButton, HasHorizontalAlignment.ALIGN_CENTER ) self.cbcList.setWidth("95%") self.channelList.setWidth("95%") self.cbcList.addItem( "waiting..." ) for index in range(0,254) : self.channelList.addItem( "Channel %3d"%index ) self.histogram = Image() self.mainPanel = HorizontalPanel() self.mainPanel.add( controls ) self.mainPanel.add( self.histogram ) self.histogram.setUrl( "defaultScurveHistogram.png" ) def getPanel( self ) : return self.mainPanel def setAvailableCBCs( self, cbcNames ) : self.cbcList.clear() for name in cbcNames : self.cbcList.addItem( name ) def enable( self ) : self.updateButton.setEnabled(True) self.cbcList.setEnabled(True) self.channelList.setEnabled(True) def disable( self ) : self.updateButton.setEnabled(False) self.cbcList.setEnabled(False) self.channelList.setEnabled(False) def getUpdateButton( self ) : return self.updateButton def getSelectedCBCChannels( self ) : """ Returns a dictionary of which channels are selected, with CBC name as a key and an array of the channels for that CBC as the value. """ # The way this view is currently set up, the selected channels have to be the same # for each selected CBC. selectedChannels=[] for index in range(self.channelList.getItemCount()) : if self.channelList.isItemSelected(index) : selectedChannels.append(index) returnValue={} for index in range(self.cbcList.getItemCount()) : if self.cbcList.isItemSelected(index) : returnValue[self.cbcList.getItemText(index)]=selectedChannels return returnValue def setImage( self, url ) : self.histogram.setUrl( url )