def update(self):
        """
        Updates the clipboard items in the L{PM_Clipboard} groupbox. Also
        updates its element viewer.
        """
        PM_GroupBox.update(self)
        self.pastableItems = self.w.assy.shelf.getPastables()
        i = self.clipboardListWidget.currentRow()
        self.clipboardListWidget.clear()
        newModel = None

        if len(self.pastableItems):
            for item in self.pastableItems:
                self.clipboardListWidget.addItem(item.name)

            if i >= self.clipboardListWidget.count():
                i = self.clipboardListWidget.count() - 1

            if i < 0:
                i = 0

            self.clipboardListWidget.setCurrentItem(
                    self.clipboardListWidget.item(i))


            newModel = self.pastableItems[i]

        self._updateElementViewer(newModel)
 def _loadTranslateGroupBox(self, inPmGroupBox):
     """
     Load widgets in the Translate group box.
     @param inPmGroupBox: The Translate group box in the PM
     @type  inPmGroupBox: L{PM_GroupBox}
     """
     
     translateChoices = [ "Free Drag", 
                          "By Delta XYZ", 
                          "To XYZ Position" ]
     
     self.translateComboBox = \
         PM_ComboBox( inPmGroupBox,
                      label        = '', 
                      choices      = translateChoices, 
                      index        = 0, 
                      setAsDefault = False,
                      spanWidth    = True )
     
     self.freeDragTranslateGroupBox = PM_GroupBox( inPmGroupBox )
     self._loadFreeDragTranslateGroupBox(self.freeDragTranslateGroupBox)
             
     self.byDeltaGroupBox = PM_GroupBox( inPmGroupBox )
     self._loadByDeltaGroupBox(self.byDeltaGroupBox)
     
     self.toPositionGroupBox = PM_GroupBox( inPmGroupBox )
     self._loadToPositionGroupBox(self.toPositionGroupBox)
     
     self.updateTranslateGroupBoxes(0)
 def restoreDefault(self):
     """
     Restores the default checked (selected) element and atom type buttons.
     """
     PM_GroupBox.restoreDefault(self)
     self._updateAtomTypesButtons()
     return
    def __init__(self,
                 parentWidget,
                 paramsForCheckBoxes=(),
                 checkBoxColumn=1,
                 title=''):
        """
        @param parentWidget: The parent dialog or group box containing this
                             widget.
        @type  parentWidget: L{PM_Dialog} or L{PM_GroupBox}
        
        @param title: The title (button) text. If empty, no title is added.
        @type  title: str
        
        @param paramsForCheckBoxes: A list object that contains tuples like the
               following : ('checkBoxTextString' , preference_key). The 
               checkboxes will be constucted by looping over this list.
        @type paramsForCheckBoxes:list
        @param checkBoxColumn: The widget column in which all the checkboxes
               will be inserted. 
        @type  checkBoxColumn: int
        
        @see: DnaDuplexPropertyManager._loadDisplayOptionsGroupBox for an 
              example use.
        """
        PM_GroupBox.__init__(self, parentWidget, title=title)

        self._checkBoxColumn = checkBoxColumn

        #Also maintain all checkboxes created by this class in this list,
        #just in case the caller needs them. (need access methods for this)
        self.checkBoxes = []

        #Create checkboxes and also connect them to their preference keys.
        self._addCheckBoxes(paramsForCheckBoxes)
 def __init__(self, 
              parentWidget,
              glpane = None,
              title = 'Preview'
              ):
     """
     Appends a PM_PreviewGroupBox widget to I{parentWidget},a L{PM_Dialog}
             
     @param parentWidget: The parent dialog (Property manager) containing 
                          this  widget.
     @type  parentWidget: L{PM_Dialog}
     
     @param glpane: GLPane object used in construction of the 
                    L{self.elementViewer}
     @type  glpane: L{GLPane} or None
     
     @param title: The title (button) text.
     @type  title: str      
     
     """
     PM_GroupBox.__init__(self, parentWidget, title)
     
     self.glpane = glpane 
     self.parentWidget = parentWidget        
     self._loadPreviewGroupBox()
Example #6
0
    def __init__(self, parentWidget, title="Clipboard", win=None, elementViewer=None):

        """
        Appends a PM_Clipboard groupbox widget to I{parentWidget},a L{PM_Dialog}
                
        @param parentWidget: The parent dialog (Property manager) containing 
                             this  widget.
        @type  parentWidget: L{PM_Dialog}
        
        @param title: The title (button) text.
        @type  title: str
        
        @param win: MainWindow object
        @type  win: L{MWsemantics} or None
        
        @param elementViewer: The associated preview pane groupbox. If provided, 
                              The selected item in L{self.clipboardListWidget}
                              is shown (previewed) by L{elementViewer}.
                              The object being previewed can then be deposited 
                              into the 3D workspace.
        @type  elementViewer: L{PM_PreviewGroupBox} or None
        
        """

        self.w = win
        self.elementViewer = elementViewer
        self.elementViewer.setDisplay(diTUBES)
        self.pastableItems = None

        PM_GroupBox.__init__(self, parentWidget, title)

        self._loadClipboardGroupbox()
    def _addGroupBoxes( self ):
        """
        Add the Insert Nanotube Property Manager group boxes.
        """

        self._pmGroupBox1 = PM_GroupBox( self, title = "Endpoints" )
        self._loadGroupBox1( self._pmGroupBox1 )
        self._pmGroupBox1.hide()

        self._pmGroupBox2 = PM_GroupBox( self, title = "Parameters" )
        self._loadGroupBox2( self._pmGroupBox2 )

        self._displayOptionsGroupBox = PM_GroupBox( self,
                                                    title = "Display Options" )
        self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )

        self._pmGroupBox3 = PM_GroupBox( self, title = "Nanotube Distortion" )
        self._loadGroupBox3( self._pmGroupBox3 )
        self._pmGroupBox3.hide() #@ Temporary.

        self._pmGroupBox4 = PM_GroupBox( self, title = "Multi-Walled CNTs" )
        self._loadGroupBox4( self._pmGroupBox4 )
        self._pmGroupBox4.hide() #@ Temporary.

        self._pmGroupBox5 = PM_GroupBox( self, title = "Advanced Options" )
        self._loadGroupBox5( self._pmGroupBox5 )
        self._pmGroupBox5.hide() #@ Temporary.
 def _loadRotateGroupBox(self, inPmGroupBox):
     """
     Load widgets in the Rotate group box, 
     @param inPmGroupBox: The Rotate GroupBox in the PM
     @type  inPmGroupBox: L{PM_GroupBox}
     """
     
     rotateChoices = [ "Free Drag", "By Specified Angle"]
     
     self.rotateComboBox = \
         PM_ComboBox( inPmGroupBox,
                      label        = '', 
                      choices      = rotateChoices, 
                      index        = 0, 
                      setAsDefault = False,
                      spanWidth    = True )
     
     self.rotateAsUnitCB = \
         PM_CheckBox( inPmGroupBox,
                      text         = 'Rotate as a unit' ,
                      widgetColumn = 0,
                      state        = Qt.Checked )
     
            
     self.freeDragRotateGroupBox = PM_GroupBox( inPmGroupBox )
     self._loadFreeDragRotateGroupBox(self.freeDragRotateGroupBox)
     
     self.bySpecifiedAngleGroupBox = PM_GroupBox( inPmGroupBox )
     self._loadBySpecifiedAngleGroupBox(self.bySpecifiedAngleGroupBox)
     
     self.updateRotateGroupBoxes(0)    
 def expand(self):
     """
     Expand this group box i.e. show all its contents and change the look 
     and feel of the groupbox button. It also sets the gridlayout margin and
     spacing to 0. (necessary to get rid of the extra space inside the 
     groupbox.)       
     
     @see: L{PM_GroupBox.expand}
     """
     PM_GroupBox.expand(self)
     self.gridLayout.setMargin(0)
     self.gridLayout.setSpacing(0)
Example #10
0
    def _addGroupBoxes(self):
        """
        Add the Property Manager group boxes.
        """
        self._pmGroupBox1 = PM_GroupBox(self, title="Favorites")
        self._loadGroupBox1(self._pmGroupBox1)

        self._pmGroupBox2 = PM_GroupBox(self, title="Display")
        self._loadGroupBox2(self._pmGroupBox2)

        self._pmGroupBox3 = PM_GroupBox(self, title="Color")
        self._loadGroupBox3(self._pmGroupBox3)
 def _addGroupBoxes( self ):
     """
     Add the DNA Property Manager group boxes.
     """                  
     self._joinOptionsGroupBox = PM_GroupBox(self, title = "Join Options")
     self._loadJoinOptionsGroupbox(self._joinOptionsGroupBox)
     self._displayOptionsGroupBox = PM_GroupBox( self, title = "Display Options" )
     self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox ) 
     self._baseNumberLabelGroupBox = PM_GroupBox( self, title = "Base Number Labels" )
     self._loadBaseNumberLabelGroupBox(self._baseNumberLabelGroupBox)
     
     
     return
    def _addGroupBoxes(self):
        """
        Add the Property Manager group boxes.
        """
        self._pmGroupBox2 = PM_GroupBox(self,
                                        title="Backrub Specific Parameters")
        self._loadGroupBox2(self._pmGroupBox2)

        self._pmGroupBox1 = PM_GroupBox(
            self, title="Rosetta Sequence Design Parameters")
        self._loadGroupBox1(self._pmGroupBox1)

        return
 def _addGroupBoxes( self ):
     """
     Add the DNA Property Manager group boxes.
     """        
     #Unused 'References List Box' to be revided. (just commented out for the
     #time being. 
     ##self._pmGroupBox1 = PM_GroupBox( self, title = "Reference Plane" )
     ##self._loadGroupBox1( self._pmGroupBox1 )
     
     self._pmGroupBox2 = PM_GroupBox( self, title = "Strands" )
     self._loadGroupBox2( self._pmGroupBox2 )
     
     self._pmGroupBox3 = PM_GroupBox( self, title = "Segments" )
     self._loadGroupBox3( self._pmGroupBox3 )
Example #14
0
    def _addGroupBoxes(self):
        """
        Add the Property Manager group boxes.
        """
        self._breakOptionsGroupbox = PM_GroupBox(self, title="Break Options")
        self._loadBreakOptionsGroupbox(self._breakOptionsGroupbox)

        self._displayOptionsGroupBox = PM_GroupBox(self,
                                                   title="Display Options")
        self._loadDisplayOptionsGroupBox(self._displayOptionsGroupBox)

        self._baseNumberLabelGroupBox = PM_GroupBox(self,
                                                    title="Base Number Labels")
        self._loadBaseNumberLabelGroupBox(self._baseNumberLabelGroupBox)
Example #15
0
    def _addGroupBoxes(self):
        """
        Add the Property Manager group boxes.
        """
        self._pmGroupBox1 = PM_GroupBox(self, title="Favorites")
        self._loadGroupBox1(self._pmGroupBox1)

        self._pmGroupBox2 = PM_GroupBox(self, title="Background")
        self._loadGroupBox2(self._pmGroupBox2)

        self._pmGroupBox3 = PM_GroupBox(self,
                                        title="Highlighting and Selection")
        self._loadGroupBox3(self._pmGroupBox3)

        self._updateAllWidgets()
Example #16
0
    def __init__(self,
                 parentWidget,
                 title='Part Library',
                 win=None,
                 elementViewer=None):
        self.w = win
        self.elementViewer = elementViewer
        # piotr 080410 changed diTUBES to diTrueCPK
        self.elementViewer.setDisplay(diTrueCPK)
        self.partLib = None
        self.newModel = None

        PM_GroupBox.__init__(self, parentWidget, title)

        self._loadPartLibGroupBox()
 def _addLayerPropertiesGroupBox(self):
     """
     Add 'Layer Properties' groupbox to the PM
     """
     self.layerPropertiesGroupBox = \
         PM_GroupBox(self, title = "Layer Properties")
     self._loadLayerPropertiesGroupBox(self.layerPropertiesGroupBox)
Example #18
0
    def _loadDisplayOptionsGroupBox(self, pmGroupBox):
        """
        Load widgets in the Display Options GroupBox
        @see: DnaOrCnt_PropertyManager. _loadDisplayOptionsGroupBox
        """
        #Call the superclass method that loads the cursor text checkboxes.
        #Note, as of 2008-05-19, the superclass, DnaOrCnt_PropertyManager
        #only loads the cursor text groupboxes. Subclasses like this can
        #call custom methods like self._loadCursorTextCheckBoxes etc if they
        #don't need all groupboxes that the superclass loads.
        _superclass._loadDisplayOptionsGroupBox(self, pmGroupBox)

        self._rubberbandLineGroupBox = PM_GroupBox(pmGroupBox,
                                                   title='Rubber band line:')

        dnaLineChoices = ['Ribbons', 'Ladder']
        self.dnaRubberBandLineDisplayComboBox = \
            PM_ComboBox( self._rubberbandLineGroupBox ,
                         label         =  " Display as:",
                         choices       =  dnaLineChoices,
                         setAsDefault  =  True)

        self.lineSnapCheckBox = \
            PM_CheckBox(self._rubberbandLineGroupBox ,
                        text         = 'Enable line snap' ,
                        widgetColumn = 1,
                        state        = Qt.Checked
                    )
Example #19
0
 def _loadPM_CheckBox(self, inPmGroupBox):
     """
     PM_CheckBox.
     """
     self.checkBoxGroupBox = \
         PM_GroupBox( inPmGroupBox, 
                      title          = "<b> PM_CheckBox examples</b>" )
     
     self.checkBox1 = \
         PM_CheckBox( self.checkBoxGroupBox,
                      text         = "Label on left:",
                      widgetColumn = 1,
                      state        = Qt.Checked,
                      setAsDefault = True,
                     )
     
     self.checkBox2 = \
         PM_CheckBox( self.checkBoxGroupBox,
                      text          = ": Label on right",
                      widgetColumn  = 1,
                      state         = Qt.Checked,
                      setAsDefault  = True,
                     )
     
     self.checkBox3 = \
         PM_CheckBox( self.checkBoxGroupBox,
                      text         = "CheckBox (spanWidth = True):",
                      state        = Qt.Unchecked,
                      setAsDefault = False,
                    )
Example #20
0
    def __init__(self, 
                 parentWidget,
                 title = 'Part Library',
                 win   = None,
                 elementViewer = None
                 ):            
        self.w = win
        self.elementViewer = elementViewer
        # piotr 080410 changed diTUBES to diTrueCPK
        self.elementViewer.setDisplay(diTrueCPK)
        self.partLib = None
        self.newModel = None

        PM_GroupBox.__init__(self, parentWidget, title)

        self._loadPartLibGroupBox()
Example #21
0
 def _addGroupBoxes(self):
     """
     Add the Nanotube Property Manager group boxes.
     """
     self._pmGroupBox1 = PM_GroupBox(self, title="Nanotubes")
     self._loadGroupBox1(self._pmGroupBox1)
     return
 def _addCrystalSpecsGroupbox(self):
     """
     Add 'Crystal groupbox' to the PM
     """
     self.crystalSpecsGroupBox = \
         PM_GroupBox(self, title = "Crystal Specifications")
     self._loadCrystalSpecsGroupBox(self.crystalSpecsGroupBox)
Example #23
0
 def _addGroupBoxes(self):
     """
     Add the Build Protein Property Manager group boxes.
     """
     self._pmGroupBox1 = PM_GroupBox(self, title="Peptides")
     self._loadGroupBox1(self._pmGroupBox1)
     return
Example #24
0
 def _addGroupBoxes(self):
     """
     Add the DNA Property Manager group boxes.
     """
     self._pmGroupBox1 = PM_GroupBox(self, title="Parameters")
     self._loadGroupBox1(self._pmGroupBox1)
     return
 def _addGroupBoxes(self):
     """
     Add the Property Manager group boxes.
     """
     self._pmGroupBox1 = PM_GroupBox(self, title="Compare")
     self._loadGroupBox1(self._pmGroupBox1)
     return
    def _addGroupBoxes(self):
        """
        Add group boxes to this PM.
        """

        self._pmGroupBox1 = PM_GroupBox(self, title="Parameters")
        self._loadGroupBox1(self._pmGroupBox1)
        self._displayOptionsGroupBox = PM_GroupBox(self,
                                                   title="Display Options")
        self._loadDisplayOptionsGroupBox(self._displayOptionsGroupBox)

        #Sequence Editor. This is NOT a groupbox, needs cleanup. Doing it here
        #so that the sequence editor gets connected! Perhaps
        #superclass should define _loadAdditionalWidgets. -- Ninad2008-10-03
        self._loadSequenceEditor()
        return
    def _addGroupBoxes( self ):
        """
        Add group boxes to this PM.
        """

        self._pmGroupBox1 = PM_GroupBox( self, title = "Parameters" )
        self._loadGroupBox1( self._pmGroupBox1 )
        self._displayOptionsGroupBox = PM_GroupBox( self,
                                                    title = "Display Options" )
        self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )

        #Sequence Editor. This is NOT a groupbox, needs cleanup. Doing it here
        #so that the sequence editor gets connected! Perhaps
        #superclass should define _loadAdditionalWidgets. -- Ninad2008-10-03
        self._loadSequenceEditor()
        return
 def _addGroupBoxes( self ):
     """
     Add the DNA Property Manager group boxes.
     """                  
     self._displayOptionsGroupBox = PM_GroupBox( self, title = "Display options" )
     self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )  
     return
Example #29
0
 def _addGroupBoxes(self):
     """
     Add the Property Manager group boxes.
     """
     self._pmGroupBox1 = PM_GroupBox(self,
                                     title="Segments for Crossover Search")
     self._loadGroupBox1(self._pmGroupBox1)
Example #30
0
 def _addGroupBoxes(self):
     """
     Add group boxes to this Property Manager.
     """
     self.pmGroupBox1 = PM_GroupBox(self, title="Atom Parameters")
     self._loadGroupBox1(self.pmGroupBox1)
     return
 def _addDisplayOptionsGroupBox(self):
     """
     Add 'Display Options' groupbox
     """
     self.displayOptionsGroupBox = PM_GroupBox(self,
                                               title='Display Options')
     self._loadDisplayOptionsGroupBox(self.displayOptionsGroupBox)
    def expand(self):
        """
        Expand this group box i.e. show all its contents and change the look
        and feel of the groupbox button. It also sets the gridlayout margin and
        spacing to 0. (necessary to get rid of the extra space inside the
        groupbox.)

        @see: L{PM_GroupBox.expand}
        """
        PM_GroupBox.expand(self)
        # If we don't do this, we get a small space b/w the
        # title button and the MessageTextEdit widget.
        # Extra code unnecessary, but more readable.
        # Mark 2007-05-21
        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)
Example #33
0
    def expand(self):
        """
        Expand this group box i.e. show all its contents and change the look 
        and feel of the groupbox button. It also sets the gridlayout margin and
        spacing to 0. (necessary to get rid of the extra space inside the 
        groupbox.)       

        @see: L{PM_GroupBox.expand}
        """
        PM_GroupBox.expand(self)
        # If we don't do this, we get a small space b/w the
        # title button and the MessageTextEdit widget.
        # Extra code unnecessary, but more readable.
        # Mark 2007-05-21
        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)
Example #34
0
    def addGroupBoxes(self):
        """
        Add the 1 groupbox for the Atom Property Manager.
        """

        self.pmGroupBox1 = \
            PM_GroupBox( self,
                         title =  "Atom Position" )

        self.loadGroupBox1(self.pmGroupBox1)

        self.pmElementChooser =  PM_ElementChooser(self)

        AddTestGroupBoxes = True # For testing. Mark 2007-05-24

        if not AddTestGroupBoxes: # Add test widgets to their own groupbox.
            return


        """
        self.testGroupBox1 = \
            PM_GroupBox( self,
                         title = "Test Widgets1" )

        self.loadTestWidgets1(self.testGroupBox1)

        self.pmLineEditGroupBox = \
            PM_GroupBox( self,
                         title = "PM_LineEdit Widgets" )

        self.loadLineEditGroupBox(self.pmLineEditGroupBox)
        """

        """
Example #35
0
 def _addMovieFilesGroupBox(self):
     """
     Add Open / Save Movie File groupbox
     """
     self.movieFilesGroupBox = PM_GroupBox(self,
                                           title="Open/Save Movie File")
     self._loadMovieFilesGroupBox(self.movieFilesGroupBox)
 def _addAdvancedOptionsGroupBox(self):
     """
     Add 'Advanced Options' groupbox
     """
     self.advancedOptionsGroupBox = \
         PM_GroupBox( self, title = "Advanced Options" )
     self._loadAdvancedOptionsGroupBox(self.advancedOptionsGroupBox)
 def _addGroupBoxes(self):
     """
     Add the Property Manager group boxes.
     """
     self._pmGroupBox1 = PM_GroupBox(
         self, title="Rosetta Fixed backbone sequence design")
     self._loadGroupBox1(self._pmGroupBox1)
     return
 def _addMovieControlsGroupBox(self):
     """
     Add Movie Controls groupbox
     """
     self.movieControlsGroupBox = PM_GroupBox(self, 
                                              title = "Movie Controls"
                                              )
     self._loadMovieControlsGroupBox(self.movieControlsGroupBox)
 def _addMovieOptionsGroupBox(self):
     """
     Add Movie Options groupbox
     """
     self.movieOptionsGroupBox = PM_GroupBox(self, 
                                              title = "Movie Options"
                                              )
     self._loadMovieOptionsGroupBox(self.movieOptionsGroupBox)
    def _addSelectionOptionsGroupBox(self):
        """
        Add 'Selection Options' groupbox
        """
        self.selectionOptionsGroupBox = \
            PM_GroupBox( self, title = "Selection Options" )

        self._loadSelectionOptionsGroupBox(self.selectionOptionsGroupBox)
    def _addBondToolsGroupBox(self):
        """
        Add the 'Bond Tools' groupbox.
        """
        self.bondToolsGroupBox = \
            PM_GroupBox( self, title = "Bond Tools")

        self._loadBondToolsGroupBox(self.bondToolsGroupBox)
Example #42
0
    def _addGroupBoxes(self):
        """
        Add the Property Manager group boxes.
        """

        if sys.platform == "darwin":
            # Workaround for table font size difference between Mac/Win
            self.labelfont = QFont("Helvetica", 12)
            self.descriptorfont = QFont("Courier New", 12)
        else:
            self.labelfont = QFont("Helvetica", 9)
            self.descriptorfont = QFont("Courier New", 9)

        self._pmGroupBox1 = PM_GroupBox(self, title="Descriptors")
        self._loadGroupBox1(self._pmGroupBox1)

        self._pmGroupBox2 = PM_GroupBox(self, title="Sequence")
        self._loadGroupBox2(self._pmGroupBox2)
    def _loadSelectionOptionsGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Selection Options group box.
        @param inPmGroupBox: The Selection Options box in the PM
        @type  inPmGroupBox: L{PM_GroupBox}
        """

        self.selectionFilterCheckBox = \
            PM_CheckBox( inPmGroupBox,
                         text  = "Enable atom selection filter",
                         widgetColumn = 0,
                         state        = Qt.Unchecked  )
        self.selectionFilterCheckBox.setDefaultValue(False)

        self.filterlistLE = PM_LineEdit( inPmGroupBox,
                                         label        = "",
                                         text         = "",
                                         setAsDefault = False,
                                         spanWidth    = True )
        self.filterlistLE.setReadOnly(True)

        if self.selectionFilterCheckBox.isChecked():
            self.filterlistLE.setEnabled(True)
        else:
            self.filterlistLE.setEnabled(False)

        self.showSelectedAtomInfoCheckBox = \
            PM_CheckBox(
                inPmGroupBox,
                text  = "Show Selected Atom Info",
                widgetColumn = 0,
                state        = Qt.Unchecked)

        self.selectedAtomPosGroupBox = \
            PM_GroupBox( inPmGroupBox, title = "")
        self._loadSelectedAtomPosGroupBox(self.selectedAtomPosGroupBox)

        self.toggle_selectedAtomPosGroupBox(show = 0)
        self.enable_or_disable_selectedAtomPosGroupBox( bool_enable = False)

        self.reshapeSelectionCheckBox = \
            PM_CheckBox( inPmGroupBox,
                         text         = 'Dragging reshapes selection',
                         widgetColumn = 0,
                         state        = Qt.Unchecked  )

        connect_checkbox_with_boolean_pref( self.reshapeSelectionCheckBox,
                                            reshapeAtomsSelection_prefs_key )

        env.prefs[reshapeAtomsSelection_prefs_key] = False

        self.waterCheckBox = \
            PM_CheckBox( inPmGroupBox,
                         text         = "Z depth filter (water surface)",
                         widgetColumn = 0,
                         state        = Qt.Unchecked  )
 def _addGroupBoxes(self):
     """
     Add groupboxes to the Property Manager dialog. 
     """
     
     self.translateGroupBox = PM_GroupBox( self, 
                                           title = "Translate",
                                           connectTitleButton = False)
     self.translateGroupBox.titleButton.setShortcut('T')
     self._loadTranslateGroupBox(self.translateGroupBox)
     
     self.rotateGroupBox = PM_GroupBox( self, 
                                        title = "Rotate",
                                        connectTitleButton = False)
     self.rotateGroupBox.titleButton.setShortcut('R')
     self._loadRotateGroupBox(self.rotateGroupBox)
     
     self.translateGroupBox.collapse()
     self.rotateGroupBox.collapse()
 def _addGroupBoxes( self ):
     """
     Add the DNA Property Manager group boxes.
     """        
             
     self._pmGroupBox1 = PM_GroupBox( self, title = "Parameters" )
     self._loadGroupBox1( self._pmGroupBox1 )
     self._displayOptionsGroupBox = PM_GroupBox( self, 
                                                 title = "Display Options" )
     self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )
    def __init__(self,
                 parentWidget,
                 parentPropMgr   = None,
                 title           = "Molecular Modeling Kit",
                 element         = "",
                 elementViewer   =  None,
                 ):
        """
        Appends a AtomChooser widget (see subclasses) to the bottom of
        I{parentWidget}, a Property Manager dialog.
        (or as a sub groupbox for Atom Chooser  GroupBox.)

        @param parentWidget: The parent PM_Dialog or PM_groupBox containing this
                             widget.
        @type  parentWidget: PM_Dialog or PM_GroupBox

        @param parentPropMgr: The parent Property Manager
        @type  parentPropMgr: PM_Dialog or None

        @param title: The button title on the group box containing the
                      Element Chooser.
        @type  title: str

        @param element: The initially selected element. It can be either an
                        element symbol or name.
        @type  element: str
        """

        PM_GroupBox.__init__(self, parentWidget, title)

        self.element = self._periodicTable.getElement(element)
        self.elementViewer = elementViewer
        self.updateElementViewer()

        if parentPropMgr:
            self.parentPropMgr = parentPropMgr
        else:
            self.parentPropMgr = parentWidget

        self._addGroupBoxes()
        self.connect_or_disconnect_signals(True)
    def _addGroupBoxes( self ):
        """
        Add the DNA Property Manager group boxes.
        """
        self._pmReferencePlaneGroupBox = PM_GroupBox( self,
                                                      title = "Placement Options" )
        self._loadReferencePlaneGroupBox( self._pmReferencePlaneGroupBox )

        self._pmGroupBox1 = PM_GroupBox( self, title = "Endpoints" )
        self._loadGroupBox1( self._pmGroupBox1 )

        self._pmGroupBox1.hide()

        self._pmGroupBox2 = PM_GroupBox( self, title = "Parameters" )
        self._loadGroupBox2( self._pmGroupBox2 )

        self._displayOptionsGroupBox = PM_GroupBox( self,
                                                    title = "Display Options" )
        self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )
Example #48
0
 def __init__(self, 
              parentWidget, 
              title        = '', 
              label = '',
              labelColumn = 0,
              buttonList   = [],
              checkedId    = -1,
              setAsDefault = False, 
              spanWidth   = True, 
              borders = True
              ):
     """
     Appends a PM_RadioButtonList widget to the bottom of I{parentWidget}, 
     the Property Manager dialog or group box.
     
     @param parentWidget: The parent group box containing this widget.
     @type  parentWidget: PM_GroupBox or PM_Dialog
     
     @param title: The group box title.
     @type  title: str
     
     @param label:      The label for the coordinate spinbox.
     @type  label:      str
     
     @param labelColumn: The column in the parentWidget's grid layout to 
                         which this widget's label will be added. 
                         The labelColum can only be E{0} or E{1}
     @type  labelColumn: int
             
     
     @param buttonList: A list of I{button info lists}. There is one button
                        info list for each radio button in the list. The 
                        button info list contains the following three items:
                        1). Button Id (int), 
                        2). Button text (str),
                        3). Button tool tip (str).
     @type  buttonList: list
     
     @param spanWidth: If True, the widget and its label will span the width
                      of the group box. Its label will appear directly above
                      the widget (unless the label is empty) and is left 
                      justified.
     @type  spanWidth: bool (default False)
     
     
     @param borders: If true (default), this widget will have borders displayed. 
                     otherwise the won't be any outside borders around the 
                     set of radio buttons this class provides
     @type borders: boolean
     """
     
     # Intializing label, labelColumn etc is needed before doing 
     # PM_GroupBox.__init__. This is done so that 
     # self.parentWidget.addPmWidget(self) done at the end of __init__
     # works properly. 
     # 'self.parentWidget.addPmWidget(self)' is done to avoid a bug where a 
     # groupbox is always appended as the 'last widget' when its 
     # parentWidget is also a groupbox. This is due to other PM widgets 
     #(e.g. PM_PushButton)add themselves to their parent widget in their 
     #__init__ using self.parentWidget.addPmWidget(self). So doing the
     #same thing here. More general fix is needed in PM_GroupBox code
     # --Ninad 2007-11-14 (comment copied from PM_coordinateSpinBoxes)
     self.label = label
     self.labelColumn = labelColumn
     self.spanWidth = spanWidth
     
     if label: # Create this widget's QLabel.
         self.labelWidget = QLabel()
         self.labelWidget.setText(label)
         
     
     PM_GroupBox.__init__(self, parentWidget, title)
     
     # These are needed to properly maintain the height of the grid if 
     # all buttons in a row are hidden via hide().
     self.vBoxLayout.setMargin(0)
     self.vBoxLayout.setSpacing(0)
     
     self.buttonGroup = QButtonGroup()
     self.buttonGroup.setExclusive(True)
     
     self.parentWidget = parentWidget
     self.buttonList   = buttonList
     
     if setAsDefault:
         self.setDefaultCheckedId(checkedId)
     
     self.buttonsById   = {}
     self.buttonsByText = {}
         
     # Create radio button list from button info.
     for buttonInfo in buttonList:
         buttonId       = buttonInfo[0]
         buttonText     = buttonInfo[1]
         buttonToolTip  = buttonInfo[2]
         
         button = QRadioButton(self)
         
         button.setText(buttonText)
         button.setToolTip(buttonToolTip) # Not working.
         button.setCheckable(True)
         if checkedId == buttonId:
             button.setChecked(True)
         self.buttonGroup.addButton(button, buttonId)
         self.vBoxLayout.addWidget(button)
         
         self.buttonsById[buttonId]    = button
         self.buttonsByText[buttonText] = button
         
     if isinstance(self.parentWidget, PM_GroupBox):
         self.parentWidget.addPmWidget(self)
     else:   
         #@@ Should self be added to self.parentWidget's widgetList?
         #don't know. Retaining old code -- Ninad 2008-06-23
         self._widgetList.append(self)            
         self._rowCount += 1
     
     if not borders:
         #reset the style sheet so that there are no borders around the 
         #radio button set this class provides. 
         self.setStyleSheet(self._getAlternateStyleSheet())
 def __init__(self, 
              parentWidget,
              title = "",
              label = '',
              labelColumn = 0,
              spanWidth   = True 
              ):
     """
     Appends a PM_CoordinateSpinBoxes groupbox widget to I{parentWidget},
     a L{PM_Groupbox} or a L{PM_Dialog}
             
     @param parentWidget: The parent groupbox or dialog (Property manager) 
                          containing this  widget.
     @type  parentWidget: L{PM_GroupBox} or L{PM_Dialog} 
     
     @param title: The title (button) text.
     @type  title: str        
     
     @param label:      The label for the coordinate spinbox.
     @type  label:      str
     
     @param labelColumn: The column in the parentWidget's grid layout to 
                         which this widget's label will be added. 
                         The labelColum can only be E{0} or E{1}
     @type  labelColumn: int
     
     @param spanWidth: If True, the widget and its label will span the width
                      of the group box. Its label will appear directly above
                      the widget (unless the label is empty) and is left 
                      justified.
     @type  spanWidth: bool (default False)
     """
     
     # Intializing label, labelColumn etc is needed before doing 
     # PM_GroupBox.__init__. This is done so that 
     # self.parentWidget.addPmWidget(self) done at the end of __init__
     # works properly. 
     # 'self.parentWidget.addPmWidget(self)' is done to avoid a bug where a 
     # groupbox is always appended as the 'last widget' when its 
     # parentWidget is also a groupbox. This is due to other PM widgets 
     #(e.g. PM_PushButton)add themselves to their parent widget in their 
     #__init__ using self.parentWidget.addPmWidget(self). So doing the
     #same thing here. More general fix is needed in PM_GroupBox code
     # --Ninad 2007-11-14
     self.label = label
     self.labelColumn = labelColumn
     self.spanWidth = spanWidth
     
     if label: # Create this widget's QLabel.
         self.labelWidget = QLabel()
         self.labelWidget.setText(label)
         
     PM_GroupBox.__init__(self, parentWidget, title)
     
     #Initialize attributes
     self.xSpinBox = None
     self.ySpinBox = None
     self.zSpinBox = None
     
     self._loadCoordinateSpinBoxes()
     
     self.parentWidget.addPmWidget(self)
class DnaDuplexPropertyManager( DnaOrCnt_PropertyManager ):
    """
    The DnaDuplexPropertyManager class provides a Property Manager
    for the B{Build > DNA > Duplex} command.

    @ivar title: The title that appears in the property manager header.
    @type title: str

    @ivar pmName: The name of this property manager. This is used to set
                  the name of the PM_Dialog object via setObjectName().
    @type name: str

    @ivar iconPath: The relative path to the PNG file that contains a
                    22 x 22 icon image that appears in the PM header.
    @type iconPath: str
    """

    title         =  "Insert DNA"
    pmName        =  title
    iconPath      =  "ui/actions/Tools/Build Structures/InsertDsDna.png"

    def __init__( self, win, editCommand ):
        """
        Constructor for the DNA Duplex property manager.
        """
        self.endPoint1 = None
        self.endPoint2 = None

        self._conformation  = "B-DNA"
        self._numberOfBases = 0
        self._basesPerTurn  = getDuplexBasesPerTurn(self._conformation)
        self._duplexRise    = getDuplexRise(self._conformation)
        self._duplexLength  = getDuplexLength(self._conformation,
                                              self._numberOfBases)


        _superclass.__init__( self,
                              win,
                              editCommand)

        self.showTopRowButtons( PM_DONE_BUTTON | \
                                PM_CANCEL_BUTTON | \
                                PM_WHATS_THIS_BUTTON)


    def connect_or_disconnect_signals(self, isConnect):
        """
        Connect or disconnect widget signals sent to their slot methods.
        This can be overridden in subclasses. By default it does nothing.
        @param isConnect: If True the widget will send the signals to the slot
                          method.
        @type  isConnect: boolean
        """
        if isConnect:
            change_connect = self.win.connect
        else:
            change_connect = self.win.disconnect


        change_connect(self._placementOptions.buttonGroup,
                       SIGNAL("buttonClicked(int)"),
                       self.activateSpecifyReferencePlaneTool)

        change_connect( self.conformationComboBox,
                        SIGNAL("currentIndexChanged(int)"),
                        self.conformationComboBoxChanged )

        change_connect( self.numberOfBasePairsSpinBox,
                        SIGNAL("valueChanged(int)"),
                        self.numberOfBasesChanged )

        change_connect( self.basesPerTurnDoubleSpinBox,
                        SIGNAL("valueChanged(double)"),
                        self.basesPerTurnChanged )

        change_connect( self.duplexRiseDoubleSpinBox,
                        SIGNAL("valueChanged(double)"),
                        self.duplexRiseChanged )

        change_connect(self.showCursorTextCheckBox,
                       SIGNAL('stateChanged(int)'),
                       self._update_state_of_cursorTextGroupBox)
        
        self.duplexRiseDoubleSpinBox.connectWithState(
            Preferences_StateRef_double( bdnaRise_prefs_key, 
                                         env.prefs[bdnaRise_prefs_key] )
            )
        
        self.basesPerTurnDoubleSpinBox.connectWithState(
            Preferences_StateRef_double( bdnaBasesPerTurn_prefs_key, 
                                         env.prefs[bdnaBasesPerTurn_prefs_key] )
            )

        
                
 
    def ok_btn_clicked(self):
        """
        Slot for the OK button
        """
        if self.editCommand:
            self.editCommand.preview_or_finalize_structure(previewing = False)
            ##env.history.message(self.editCommand.logMessage)
        self.win.toolsDone()

    def cancel_btn_clicked(self):
        """
        Slot for the Cancel button.
        """
        if self.editCommand:
            self.editCommand.cancelStructure()
        self.win.toolsCancel()


    def _update_widgets_in_PM_before_show(self):
        """
        Update various widgets  in this Property manager.
        Overrides superclass method

        @see: MotorPropertyManager._update_widgets_in_PM_before_show
        @see: self.show where it is called.
        """
        pass

    def getFlyoutActionList(self):
        """ returns custom actionlist that will be used in a specific mode
        or editing a feature etc Example: while in movie mode,
        the _createFlyoutToolBar method calls
        this """


        #'allActionsList' returns all actions in the flyout toolbar
        #including the subcontrolArea actions
        allActionsList = []

        #Action List for  subcontrol Area buttons.
        #In this mode there is really no subcontrol area.
        #We will treat subcontrol area same as 'command area'
        #(subcontrol area buttons will have an empty list as their command area
        #list). We will set  the Comamnd Area palette background color to the
        #subcontrol area.

        subControlAreaActionList =[]

        self.exitEditCommandAction.setChecked(True)
        subControlAreaActionList.append(self.exitEditCommandAction)

        separator = QAction(self.w)
        separator.setSeparator(True)
        subControlAreaActionList.append(separator)


        allActionsList.extend(subControlAreaActionList)

        #Empty actionlist for the 'Command Area'
        commandActionLists = []

        #Append empty 'lists' in 'commandActionLists equal to the
        #number of actions in subControlArea
        for i in range(len(subControlAreaActionList)):
            lst = []
            commandActionLists.append(lst)

        params = (subControlAreaActionList, commandActionLists, allActionsList)

        return params

    def _addGroupBoxes( self ):
        """
        Add the DNA Property Manager group boxes.
        """
        self._pmReferencePlaneGroupBox = PM_GroupBox( self,
                                                      title = "Placement Options" )
        self._loadReferencePlaneGroupBox( self._pmReferencePlaneGroupBox )

        self._pmGroupBox1 = PM_GroupBox( self, title = "Endpoints" )
        self._loadGroupBox1( self._pmGroupBox1 )

        self._pmGroupBox1.hide()

        self._pmGroupBox2 = PM_GroupBox( self, title = "Parameters" )
        self._loadGroupBox2( self._pmGroupBox2 )

        self._displayOptionsGroupBox = PM_GroupBox( self,
                                                    title = "Display Options" )
        self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )


    def _loadGroupBox1(self, pmGroupBox):
        """
        Load widgets in group box 3.
        """
        #Folllowing toolbutton facilitates entering a temporary DnaLineMode
        #to create a DNA using endpoints of the specified line.
        self.specifyDnaLineButton = PM_ToolButton(
            pmGroupBox,
            text = "Specify Endpoints",
            iconPath  = "ui/actions/Properties Manager/Pencil.png",
            spanWidth = True
        )
        self.specifyDnaLineButton.setCheckable(True)
        self.specifyDnaLineButton.setAutoRaise(True)
        self.specifyDnaLineButton.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)

        #EndPoint1 and endPoint2 coordinates. These widgets are hidden
        # as of 2007- 12 - 05
        self._endPoint1SpinBoxes = PM_CoordinateSpinBoxes(pmGroupBox,
                                                          label = "End Point 1")
        self.x1SpinBox = self._endPoint1SpinBoxes.xSpinBox
        self.y1SpinBox = self._endPoint1SpinBoxes.ySpinBox
        self.z1SpinBox = self._endPoint1SpinBoxes.zSpinBox

        self._endPoint2SpinBoxes = PM_CoordinateSpinBoxes(pmGroupBox,
                                                          label = "End Point 2")
        self.x2SpinBox = self._endPoint2SpinBoxes.xSpinBox
        self.y2SpinBox = self._endPoint2SpinBoxes.ySpinBox
        self.z2SpinBox = self._endPoint2SpinBoxes.zSpinBox

        self._endPoint1SpinBoxes.hide()
        self._endPoint2SpinBoxes.hide()

    def _loadGroupBox2(self, pmGroupBox):
        """
        Load widgets in group box 4.
        """

        self.conformationComboBox  = \
            PM_ComboBox( pmGroupBox,
                         label         =  "Conformation:",
                         choices       =  ["B-DNA"],
                         setAsDefault  =  True)

        dnaModelChoices = ['PAM3', 'PAM5']
        self.dnaModelComboBox = \
            PM_ComboBox( pmGroupBox,
                         label         =  "Model:",
                         choices       =  dnaModelChoices,
                         setAsDefault  =  True)


        self.basesPerTurnDoubleSpinBox  =  \
            PM_DoubleSpinBox( pmGroupBox,
                              label         =  "Bases per turn:",
                              value         =  env.prefs[bdnaBasesPerTurn_prefs_key],
                              setAsDefault  =  True,
                              minimum       =  8.0,
                              maximum       =  20.0,
                              decimals      =  2,
                              singleStep    =  0.1 )
        
        
        self.duplexRiseDoubleSpinBox  =  \
            PM_DoubleSpinBox( pmGroupBox,
                              label         =  "Rise:",
                              value         =  env.prefs[bdnaRise_prefs_key],
                              setAsDefault  =  True,
                              minimum       =  2.0,
                              maximum       =  4.0,
                              decimals      =  3,
                              singleStep    =  0.01 )
        
        
        

        # Strand Length (i.e. the number of bases)
        self.numberOfBasePairsSpinBox = \
            PM_SpinBox( pmGroupBox,
                        label         =  "Base pairs:",
                        value         =  self._numberOfBases,
                        setAsDefault  =  False,
                        minimum       =  0,
                        maximum       =  10000 )

        self.numberOfBasePairsSpinBox.setDisabled(True)

        # Duplex Length
        self.duplexLengthLineEdit  =  \
            PM_LineEdit( pmGroupBox,
                         label         =  "Duplex length: ",
                         text          =  "0.0 Angstroms",
                         setAsDefault  =  False)

        self.duplexLengthLineEdit.setDisabled(True)


    def _loadDisplayOptionsGroupBox(self, pmGroupBox):
        """
        Load widgets in the Display Options GroupBox
        @see: DnaOrCnt_PropertyManager. _loadDisplayOptionsGroupBox
        """
        #Call the superclass method that loads the cursor text checkboxes.
        #Note, as of 2008-05-19, the superclass, DnaOrCnt_PropertyManager
        #only loads the cursor text groupboxes. Subclasses like this can
        #call custom methods like self._loadCursorTextCheckBoxes etc if they
        #don't need all groupboxes that the superclass loads.
        _superclass._loadDisplayOptionsGroupBox(self, pmGroupBox)

        self._rubberbandLineGroupBox = PM_GroupBox(
            pmGroupBox,
            title = 'Rubber band line:')

        dnaLineChoices = ['Ribbons', 'Ladder']
        self.dnaRubberBandLineDisplayComboBox = \
            PM_ComboBox( self._rubberbandLineGroupBox ,
                         label         =  " Display as:",
                         choices       =  dnaLineChoices,
                         setAsDefault  =  True)

        self.lineSnapCheckBox = \
            PM_CheckBox(self._rubberbandLineGroupBox ,
                        text         = 'Enable line snap' ,
                        widgetColumn = 1,
                        state        = Qt.Checked
                    )

    def _connect_showCursorTextCheckBox(self):
        """
        Connect the show cursor text checkbox with user prefs_key.
        Overrides
        DnaOrCnt_PropertyManager._connect_showCursorTextCheckBox
        """
        connect_checkbox_with_boolean_pref(
            self.showCursorTextCheckBox ,
            dnaDuplexEditCommand_showCursorTextCheckBox_prefs_key)


    def _params_for_creating_cursorTextCheckBoxes(self):
        """
        Returns params needed to create various cursor text checkboxes connected
        to prefs_keys  that allow custom cursor texts.
        @return: A list containing tuples in the following format:
                ('checkBoxTextString' , preference_key). PM_PrefsCheckBoxes
                uses this data to create checkboxes with the the given names and
                connects them to the provided preference keys. (Note that
                PM_PrefsCheckBoxes puts thes within a GroupBox)
        @rtype: list
        @see: PM_PrefsCheckBoxes
        @see: self._loadDisplayOptionsGroupBox where this list is used.
        @see: Superclass method which is overridden here --
        DnaOrCnt_PropertyManager._params_for_creating_cursorTextCheckBoxes()
        """
        params = \
        [  #Format: (" checkbox text", prefs_key)
            ("Number of base pairs",
             dnaDuplexEditCommand_cursorTextCheckBox_numberOfBasePairs_prefs_key),

            ("Number of turns",
             dnaDuplexEditCommand_cursorTextCheckBox_numberOfTurns_prefs_key),

            ("Duplex length",
             dnaDuplexEditCommand_cursorTextCheckBox_length_prefs_key),

            ("Angle",
             dnaDuplexEditCommand_cursorTextCheckBox_angle_prefs_key) ]

        return params


    def _addToolTipText(self):
        """
        Tool Tip text for widgets in the DNA Property Manager.
        """
        pass


    def conformationComboBoxChanged( self, inIndex ):
        """
        Slot for the Conformation combobox. It is called whenever the
        Conformation choice is changed.

        @param inIndex: The new index.
        @type  inIndex: int
        """
        conformation  =  self.conformationComboBox.currentText()

        if conformation == "B-DNA":
            self.basesPerTurnDoubleSpinBox.setValue("10.0")

        elif conformation == "Z-DNA":
            self.basesPerTurnDoubleSpinBox.setValue("12.0")

        else:
            msg = redmsg("conformationComboBoxChanged(): \
                         Error - unknown DNA conformation. Index = "+ inIndex)
            env.history.message(msg)

        self.duplexLengthSpinBox.setSingleStep(getDuplexRise(conformation))

    def numberOfBasesChanged( self, numberOfBases ):
        """
        Slot for the B{Number of Bases} spinbox.
        """
        # Update the Duplex Length lineEdit widget.
        text = str(getDuplexLength(self._conformation,
                                   numberOfBases,
                                   self._duplexRise)) \
             + " Angstroms"
        self.duplexLengthLineEdit.setText(text)
        return

    def basesPerTurnChanged( self, basesPerTurn ):
        """
        Slot for the B{Bases per turn} spinbox.
        """
        self.editCommand.basesPerTurn = basesPerTurn
        self._basesPerTurn = basesPerTurn
        return

    def duplexRiseChanged( self, rise ):
        """
        Slot for the B{Rise} spinbox.
        """
        self.editCommand.duplexRise = rise
        self._duplexRise = rise
        return

    def getParameters(self):
        """
        Return the parameters from this property manager
        to be used to create the DNA duplex.
        @return: A tuple containing the parameters
        @rtype: tuple
        @see: L{DnaDuplex_EditCommand._gatherParameters} where this is used
        """
        numberOfBases = self.numberOfBasePairsSpinBox.value()
        dnaForm  = str(self.conformationComboBox.currentText())
        basesPerTurn = self.basesPerTurnDoubleSpinBox.value()
        duplexRise = self.duplexRiseDoubleSpinBox.value()

        dnaModel = str(self.dnaModelComboBox.currentText())

        # First endpoint (origin) of DNA duplex
        x1 = self.x1SpinBox.value()
        y1 = self.y1SpinBox.value()
        z1 = self.z1SpinBox.value()

        # Second endpoint (direction vector/axis) of DNA duplex.
        x2 = self.x2SpinBox.value()
        y2 = self.y2SpinBox.value()
        z2 = self.z2SpinBox.value()

        if not self.endPoint1:
            self.endPoint1 = V(x1, y1, z1)
        if not self.endPoint2:
            self.endPoint2 = V(x2, y2, z2)

        return (numberOfBases,
                dnaForm,
                dnaModel,
                basesPerTurn,
                duplexRise,
                self.endPoint1,
                self.endPoint2)

    def _addWhatsThisText(self):
        """
        What's This text for widgets in this Property Manager.
        """
        whatsThis_DnaDuplexPropertyManager(self)
class DnaStrand_PropertyManager( DnaOrCnt_PropertyManager):
    """
    The DnaStrand_PropertyManager class provides a Property Manager 
    for the DnaStrand_EditCommand.

    @ivar title: The title that appears in the property manager header.
    @type title: str

    @ivar pmName: The name of this property manager. This is used to set
                  the name of the PM_Dialog object via setObjectName().
    @type name: str

    @ivar iconPath: The relative path to the PNG file that contains a
                    22 x 22 icon image that appears in the PM header.
    @type iconPath: str
    """

    title         =  "DnaStrand Properties"
    pmName        =  title
    iconPath      =  "ui/actions/Properties Manager/Strand.png"

    def __init__( self, win, editCommand ):
        """
        Constructor for the Build DNA property manager.
        """
        
        #For model changed signal
        self.previousSelectionParams = None
        
        #see self.connect_or_disconnect_signals for comment about this flag
        self.isAlreadyConnected = False
        self.isAlreadyDisconnected = False
        
        self.sequenceEditor = None      
        
        self._numberOfBases = 0 
        self._conformation = 'B-DNA'
        self.duplexRise = 3.18
        self.basesPerTurn = 10
        self.dnaModel = 'PAM3'
        
        
        _superclass.__init__( self, 
                                    win,
                                    editCommand)


        
        self.showTopRowButtons( PM_DONE_BUTTON | \
                                PM_WHATS_THIS_BUTTON)
        
        self._loadSequenceEditor()
        
        msg = "Use resize handles to resize the strand. Use sequence editor"\
                   "to assign a new sequence or the current one to a file."
        self.updateMessage(msg)
        
               
    
    def _addGroupBoxes( self ):
        """
        Add the DNA Property Manager group boxes.
        """        
                
        self._pmGroupBox1 = PM_GroupBox( self, title = "Parameters" )
        self._loadGroupBox1( self._pmGroupBox1 )
        self._displayOptionsGroupBox = PM_GroupBox( self, 
                                                    title = "Display Options" )
        self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )
    
    def _loadGroupBox1(self, pmGroupBox):
        """
        Load widgets in group box 4.
        """
        
        self.nameLineEdit = PM_LineEdit( pmGroupBox,
                         label         =  "Strand name:",
                         text          =  "",
                         setAsDefault  =  False)
        
        self.numberOfBasesSpinBox = \
            PM_SpinBox( pmGroupBox, 
                        label         =  "Number of bases:", 
                        value         =  self._numberOfBases,
                        setAsDefault  =  False,
                        minimum       =  2,
                        maximum       =  10000 )
        
        self.basesPerTurnDoubleSpinBox  =  \
            PM_DoubleSpinBox( pmGroupBox,
                              label         =  "Bases per turn:",
                              value         =  self.basesPerTurn,
                              setAsDefault  =  True,
                              minimum       =  8.0,
                              maximum       =  20.0,
                              decimals      =  2,
                              singleStep    =  0.1 )
        
        self.duplexRiseDoubleSpinBox  =  \
            PM_DoubleSpinBox( pmGroupBox,
                              label         =  "Rise:",
                              value         =  self.duplexRise,
                              setAsDefault  =  True,
                              minimum       =  2.0,
                              maximum       =  4.0,
                              decimals      =  3,
                              singleStep    =  0.01 )
        
        self.disableStructHighlightingCheckbox = \
            PM_CheckBox( pmGroupBox,
                         text         = "Don't highlight while editing DNA",
                         widgetColumn  = 0,
                         state        = Qt.Unchecked,
                         setAsDefault = True,
                         spanWidth = True
                         )
        
        #As of 2008-03-31, the properties such as number of bases will be 
        #editable only by using the resize handles. post FNANO we will support 
        #the 
        self.numberOfBasesSpinBox.setEnabled(False)
        self.basesPerTurnDoubleSpinBox.setEnabled(False)
        self.duplexRiseDoubleSpinBox.setEnabled(False)
        
    
            
    def _loadSequenceEditor(self):
        """
        Temporary code  that shows the Sequence editor ..a doc widget docked
        at the bottom of the mainwindow. The implementation is going to change
        before 'rattleSnake' product release.
        As of 2007-11-20: This feature (sequence editor) is waiting 
        for the ongoing dna model work to complete.
        """
        self.sequenceEditor = self.win.createDnaSequenceEditorIfNeeded() 
        self.sequenceEditor.hide()
        
        
    def _loadDisplayOptionsGroupBox(self, pmGroupBox):
        """
        Overrides superclass method. 
        Also loads the color chooser widget. 
        """
        self._loadColorChooser(pmGroupBox)
        _superclass._loadDisplayOptionsGroupBox(self, pmGroupBox)
        
         
    def _connect_showCursorTextCheckBox(self):
        """
        Connect the show cursor text checkbox with user prefs_key.
        Overrides 
        DnaOrCnt_PropertyManager._connect_showCursorTextCheckBox
        """
        connect_checkbox_with_boolean_pref(
            self.showCursorTextCheckBox , 
            dnaStrandEditCommand_showCursorTextCheckBox_prefs_key)


    def _params_for_creating_cursorTextCheckBoxes(self):
        """
        Returns params needed to create various cursor text checkboxes connected
        to prefs_keys  that allow custom cursor texts. 
        @return: A list containing tuples in the following format:
                ('checkBoxTextString' , preference_key). PM_PrefsCheckBoxes 
                uses this data to create checkboxes with the the given names and
                connects them to the provided preference keys. (Note that 
                PM_PrefsCheckBoxes puts thes within a GroupBox)
        @rtype: list
        @see: PM_PrefsCheckBoxes
        @see: self._loadDisplayOptionsGroupBox where this list is used. 
        @see: Superclass method which is overridden here --
        DnaOrCnt_PropertyManager._params_for_creating_cursorTextCheckBoxes()
        """
        params = \
               [  #Format: (" checkbox text", prefs_key)
                  ("Number of bases", 
                   dnaStrandEditCommand_cursorTextCheckBox_numberOfBases_prefs_key),

                  ("Number of bases to be changed",
                   dnaStrandEditCommand_cursorTextCheckBox_changedBases_prefs_key) 
                 ]

        return params
    
        
    def getParameters(self):
        numberOfBases = self.numberOfBasesSpinBox.value()
        dnaForm  = self._conformation
        dnaModel = self.dnaModel
        basesPerTurn = self.basesPerTurn
        duplexRise = self.duplexRise
        color = self._colorChooser.getColor()
              
        return (numberOfBases, 
                dnaForm,
                dnaModel,
                basesPerTurn,
                duplexRise, 
                color
                )
    
    def setParameters(self, params):
        """
        This is usually called when you are editing an existing structure. 
        Some property manager ui elements then display the information 
        obtained from the object being edited. 
        TODO:
        - Make this a EditCommand_PM API method? 
        - See also the routines GraphicsMode.setParams or object.setProps
        ..better to name them all in one style?  
        """
        #Set the duplex rise and bases per turn spinbox values. 
        
        numberOfBases, \
                     dnaForm, \
                     dnaModel, \
                     basesPerTurn, \
                     duplexRise, \
                     color  = params 
        
        if numberOfBases is not None:
            self.numberOfBasesSpinBox.setValue(numberOfBases)
        if dnaForm is not None:
            self._conformation = dnaForm
        if dnaModel is not None:
            self.dnaModel = dnaModel
        if duplexRise is not None:
            self.duplexRiseDoubleSpinBox.setValue(duplexRise)
        if basesPerTurn is not None:
            self.basesPerTurnDoubleSpinBox.setValue(basesPerTurn)    
        if color is not None:
            self._colorChooser.setColor(color)
    
    def connect_or_disconnect_signals(self, isConnect):
        """
        Connect or disconnect widget signals sent to their slot methods.
        This can be overridden in subclasses. By default it does nothing.
        @param isConnect: If True the widget will send the signals to the slot 
                          method. 
        @type  isConnect: boolean
        """
        #TODO: This is a temporary fix for a bug. When you invoke a temporary
        # mode Entering such a temporary mode keeps the signals of 
        #PM from the previous mode connected (
        #but while exiting that temporary mode and reentering the 
        #previous mode, it atucally reconnects the signal! This gives rise to 
        #lots  of bugs. This needs more general fix in Temporary mode API. 
        # -- Ninad 2008-01-09 (similar comment exists in MovePropertyManager.py
                
        if isConnect and self.isAlreadyConnected:
            if debug_flags.atom_debug:
                print_compact_stack("warning: attempt to connect widgets"\
                                    "in this PM that are already connected." )
            return 
        
        if not isConnect and self.isAlreadyDisconnected:
            if debug_flags.atom_debug:
                print_compact_stack("warning: attempt to disconnect widgets"\
                                    "in this PM that are already disconnected.")
            return
        
        self.isAlreadyConnected = isConnect
        self.isAlreadyDisconnected = not isConnect
        
        if isConnect:
            change_connect = self.win.connect     
        else:
            change_connect = self.win.disconnect 
          
                
        if self.sequenceEditor:
            self.sequenceEditor.connect_or_disconnect_signals(isConnect)
            
        _superclass.connect_or_disconnect_signals(self, isConnect)
            
        
        change_connect(self.disableStructHighlightingCheckbox, 
                       SIGNAL('stateChanged(int)'), 
                       self.change_struct_highlightPolicy)
        
        change_connect(self.showCursorTextCheckBox, 
                       SIGNAL('stateChanged(int)'), 
                       self._update_state_of_cursorTextGroupBox)
        
    def model_changed(self): 
        """
        @see: DnaStrand_EditCommand.model_changed()
        @see: DnaStrand_EditCommand.hasResizableStructure()
        """
        isStructResizable, why_not = self.editCommand.hasResizableStructure()
        if not isStructResizable:
            #disable all widgets
            if self._pmGroupBox1.isEnabled():
                self._pmGroupBox1.setEnabled(False)
                msg1 = ("Viewing properties of %s <br>") %(self.editCommand.struct.name) 
                msg2 = redmsg("DnaStrand is not resizable. Reason: %s"%(why_not))                    
                self.updateMessage(msg1 + msg2)
        else:
            if not self._pmGroupBox1.isEnabled():
                self._pmGroupBox1.setEnabled(True)
                msg1 = ("Viewing properties of %s <br>") %(self.editCommand.struct.name) 
                msg2 = "Use resize handles to resize the strand. Use sequence editor"\
                    "to assign a new sequence or the current one to a file."
                self.updateMessage(msg1 + msg2)
        
    def show(self):
        """
        Show this PM 
        As of 2007-11-20, it also shows the Sequence Editor widget and hides 
        the history widget. This implementation may change in the near future
        This method also retrives the name information from the 
        editCommand's structure for its name line edit field. 
        @see: DnaStrand_EditCommand.getStructureName()
        @see: self.close()
        """
        _superclass.show(self) 
        self._showSequenceEditor()
    
        if self.editCommand is not None:
            name = self.editCommand.getStructureName()
            if name is not None:
                self.nameLineEdit.setText(name)     
           
    def close(self):
        """
        Close this property manager. 
        Also sets the name of the self.editCommand's structure to the one 
        displayed in the line edit field.
        @see self.show()
        @see: DnaSegment_EditCommand.setStructureName
        """
        if self.editCommand is not None:
            name = str(self.nameLineEdit.text())
            self.editCommand.setStructureName(name)
            
        if self.sequenceEditor:
            self.sequenceEditor.close()
                            
        _superclass.close(self)
            
    def _showSequenceEditor(self):
        if self.sequenceEditor:
            if not self.sequenceEditor.isVisible():
                #Show the sequence editor
                #ATTENTION: the sequence editor also closes (temporarily) the
                #reports dockwidget (if visible) Its state is later restored when
                #the sequuence Editor is closed. 
                self.sequenceEditor.show()     
                                              
            self.updateSequence()

        
    def updateSequence(self):
        """
        Update the sequence string in the sequence editor
        @see: DnaSequenceEditor.setSequence()
        @see DnaSequenceEditor._determine_complementSequence()
        @see: DnaSequenceEditor.setComplementSequence()
        @see: DnaStrand.getStrandSequenceAndItsComplement()
        """
        #Read in the strand sequence of the selected strand and 
        #show it in the text edit in the sequence editor.
        ##strand = self.strandListWidget.getPickedItem()
        
        if not self.editCommand.hasValidStructure():
            return
        
        strand = self.editCommand.struct
        
        titleString = 'Sequence Editor for ' + strand.name
                           
        self.sequenceEditor.setWindowTitle(titleString)
        sequenceString, complementSequenceString = strand.getStrandSequenceAndItsComplement()
        if sequenceString:
            sequenceString = QString(sequenceString) 
            sequenceString = sequenceString.toUpper()
            #Set the initial sequence (read in from the file)
            self.sequenceEditor.setSequence(sequenceString)
            
            #Set the initial complement sequence for DnaSequence editor. 
            #do this independently because 'complementSequenceString' may have
            #some characters (such as * ) that denote a missing base on the 
            #complementary strand. this information is used by the sequence
            #editor. See DnaSequenceEditor._determine_complementSequence() 
            #for more details. See also bug 2787
            self.sequenceEditor.setComplementSequence(complementSequenceString)

            
    def change_struct_highlightPolicy(self,checkedState = False):
        """
        Change the 'highlight policy' of the structure being edited 
        (i.e. self.editCommand.struct) . 
        @param checkedState: The checked state of the checkbox that says 
                             'Don't highlight while editing DNA'. So, it 
                             its True, the structure being edited won't get
                             highlighted. 
        @see: DnaStrand.setHighlightPolicy for more comments        
        """        
        if self.editCommand and self.editCommand.hasValidStructure():
            highlight = not checkedState
            self.editCommand.struct.setHighlightPolicy(highlight = highlight)

    def _addWhatsThisText(self):
        """
        Add what's this text. 
        Abstract method.
        """
        pass
Example #52
0
 def __init__(self, 
              parentWidget,
              title     = '',
              widgetList = [],
              alignment = None,
              label = '',
              labelColumn = 0,
              spanWidth   = True                 
              ):
     
     
     """
     Appends a PM_WidgetGrid (a group box widget) to the bottom of 
     I{parentWidget},the Property Manager Group box.
     
     @param parentWidget: The parent group box containing this widget.
     @type  parentWidget: PM_GroupBox 
     
     @param title: The group box title.
     @type  title: str
     
     @param widgetList: A list of I{widget info lists}. There is one widget
                        info list for each widget in the grid. The widget
                        info list contains custom information about the 
                        widget but the following items are always present:
                        - First Item       : Widget Type (str),
                        - Second Last Item : Column (int), 
                        - Last Item        : Row (int).
     @type  widgetList: list
     
     @param alignment:  The alignment of the widget row in the parent 
                        groupbox. Based on its value,spacer items is added 
                        to the grid layout of the parent groupbox. 
     @type  alignment:  str
     
     @param label:      The label for the widget row. .
     @type  label:      str
     
     @param labelColumn: The column in the parentWidget's grid layout to 
                         which this widget's label will be added. 
                         The labelColum can only be E{0} or E{1}
     @type  labelColumn: int
     
     @param spanWidth: If True, the widget and its label will span the width
                      of the group box. Its label will appear directly above
                      the widget (unless the label is empty) and is left 
                      justified.
     @type  spanWidth: bool (default False)
     
    
     """
      
     
     self.label = label
     self.labelColumn = labelColumn
     self.spanWidth = spanWidth
     
     if label: # Create this widget's QLabel.
         self.labelWidget = QLabel()
         self.labelWidget.setText(label)
     
     PM_GroupBox.__init__(self, parentWidget, title)
     
     # These are needed to properly maintain the height of the grid if 
     # all labels in a row are hidden via hide().
     self.vBoxLayout.setMargin(0)
     self.vBoxLayout.setSpacing(0)
     
     self.gridLayout.setMargin(0)
     self.gridLayout.setSpacing(0)
                  
     self.parentWidget = parentWidget
     self.widgetList   = widgetList
                 
     self.alignment = alignment
     
     self.loadWidgets()
class Ui_BuildAtomsPropertyManager(Command_PropertyManager):
    """
    The Ui_BuildAtomsPropertyManager class defines UI elements for the Property
    Manager of the B{Build Atoms mode}.

    @ivar title: The title that appears in the property manager header.
    @type title: str

    @ivar pmName: The name of this property manager. This is used to set
                  the name of the PM_Dialog object via setObjectName().
    @type name: str

    @ivar iconPath: The relative path to the PNG file that contains a
                    22 x 22 icon image that appears in the PM header.
    @type iconPath: str
    """

    # The title that appears in the Property Manager header
    title = "Build Atoms"
    # The name of this Property Manager. This will be set to
    # the name of the PM_Dialog object via setObjectName().
    pmName = title
    # The relative path to the PNG file that appears in the header
    iconPath = "ui/actions/Tools/Build Structures/BuildAtoms.png"

    def __init__(self, command):
        """
        Constructor for the B{Build Atoms} property manager class that defines
        its UI.

        @param command: The parent mode where this Property Manager is used
        @type  command: L{depositMode}
        """

        self.previewGroupBox = None
        self.regularElementChooser = None
        self.PAM5Chooser = None
        self.PAM3Chooser = None
        self.elementChooser = None
        self.advancedOptionsGroupBox = None
        self.bondToolsGroupBox = None

        self.selectionFilterCheckBox = None
        self.filterlistLE = None
        self.selectedAtomInfoLabel = None

        #Initialize the following to None. (subclasses may not define this)
        #Make sure you initialize it before adding groupboxes!
        self.selectedAtomPosGroupBox = None
        self.showSelectedAtomInfoCheckBox = None

        _superclass.__init__(self, command)

        self.showTopRowButtons(PM_DONE_BUTTON | PM_WHATS_THIS_BUTTON)
        msg = ''
        self.MessageGroupBox.insertHtmlMessage(msg, setAsDefault=False)

    def _addGroupBoxes(self):
        """
        Add various group boxes to the Build Atoms Property manager.
        """
        self._addPreviewGroupBox()
        self._addAtomChooserGroupBox()
        self._addBondToolsGroupBox()

        #@@@TODO HIDE the bonds tool groupbox initially as the
        #by default, the atoms tool is active when BuildAtoms command is
        #finist invoked.
        self.bondToolsGroupBox.hide()

        self._addSelectionOptionsGroupBox()
        self._addAdvancedOptionsGroupBox()

    def _addPreviewGroupBox(self):
        """
        Adde the preview groupbox that shows the element selected in the
        element chooser.
        """
        self.previewGroupBox = PM_PreviewGroupBox( self, glpane = self.o )

    def _addAtomChooserGroupBox(self):
        """
        Add the Atom Chooser groupbox. This groupbox displays one of the
        following three groupboxes depending on the choice selected in the
        combobox:
          a) Periodic Table Elements L{self.regularElementChooser}
          b) PAM5 Atoms  L{self.PAM5Chooser}
          c) PAM3 Atoms  L{self.PAM3Chooser}
        @see: L{self.__updateAtomChooserGroupBoxes}
        """
        self.atomChooserGroupBox = \
            PM_GroupBox(self, title = "Atom Chooser")
        self._loadAtomChooserGroupBox(self.atomChooserGroupBox)

        self._updateAtomChooserGroupBoxes(currentIndex = 0)

    def _addElementChooserGroupBox(self, inPmGroupBox):
        """
        Add the 'Element Chooser' groupbox. (present within the
        Atom Chooser Groupbox)
        """
        if not self.previewGroupBox:
            return

        elementViewer = self.previewGroupBox.elementViewer
        self.regularElementChooser = \
            PM_ElementChooser( inPmGroupBox,
                               parentPropMgr = self,
                               elementViewer = elementViewer)


    def _add_PAM5_AtomChooserGroupBox(self, inPmGroupBox):
        """
        Add the 'PAM5 Atom Chooser' groupbox (present within the
        Atom Chooser Groupbox)
        """
        if not self.previewGroupBox:
            return

        elementViewer = self.previewGroupBox.elementViewer
        self.PAM5Chooser = \
            PM_PAM5_AtomChooser( inPmGroupBox,
                                 parentPropMgr = self,
                                 elementViewer = elementViewer)

    def _add_PAM3_AtomChooserGroupBox(self, inPmGroupBox):
        """
        Add the 'PAM3 Atom Chooser' groupbox (present within the
        Atom Chooser Groupbox)
        """
        if not self.previewGroupBox:
            return

        elementViewer = self.previewGroupBox.elementViewer
        self.PAM3Chooser = \
            PM_PAM3_AtomChooser( inPmGroupBox,
                                 parentPropMgr = self,
                                 elementViewer = elementViewer)

    def _hideAllAtomChooserGroupBoxes(self):
        """
        Hides all Atom Chooser group boxes.
        """
        if self.regularElementChooser:
            self.regularElementChooser.hide()
        if self.PAM5Chooser:
            self.PAM5Chooser.hide()
        if self.PAM3Chooser:
            self.PAM3Chooser.hide()

    def _addBondToolsGroupBox(self):
        """
        Add the 'Bond Tools' groupbox.
        """
        self.bondToolsGroupBox = \
            PM_GroupBox( self, title = "Bond Tools")

        self._loadBondToolsGroupBox(self.bondToolsGroupBox)

    def _addSelectionOptionsGroupBox(self):
        """
        Add 'Selection Options' groupbox
        """
        self.selectionOptionsGroupBox = \
            PM_GroupBox( self, title = "Selection Options" )

        self._loadSelectionOptionsGroupBox(self.selectionOptionsGroupBox)

    def _loadAtomChooserGroupBox(self, inPmGroupBox):
        """
        Load the widgets inside the Atom Chooser groupbox.
        @param inPmGroupBox: The Atom Chooser box in the PM
        @type  inPmGroupBox: L{PM_GroupBox}
        """
        atomChooserChoices = [ "Periodic Table Elements",
                             "PAM5 Atoms",
                             "PAM3 Atoms" ]

        self.atomChooserComboBox = \
            PM_ComboBox( inPmGroupBox,
                         label        = '',
                         choices      = atomChooserChoices,
                         index        = 0,
                         setAsDefault = False,
                         spanWidth    = True )

        #Following fixes bug 2550
        self.atomChooserComboBox.setFocusPolicy(Qt.NoFocus)

        self._addElementChooserGroupBox(inPmGroupBox)
        self._add_PAM5_AtomChooserGroupBox(inPmGroupBox)
        self._add_PAM3_AtomChooserGroupBox(inPmGroupBox)

    def _loadSelectionOptionsGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Selection Options group box.
        @param inPmGroupBox: The Selection Options box in the PM
        @type  inPmGroupBox: L{PM_GroupBox}
        """

        self.selectionFilterCheckBox = \
            PM_CheckBox( inPmGroupBox,
                         text  = "Enable atom selection filter",
                         widgetColumn = 0,
                         state        = Qt.Unchecked  )
        self.selectionFilterCheckBox.setDefaultValue(False)

        self.filterlistLE = PM_LineEdit( inPmGroupBox,
                                         label        = "",
                                         text         = "",
                                         setAsDefault = False,
                                         spanWidth    = True )
        self.filterlistLE.setReadOnly(True)

        if self.selectionFilterCheckBox.isChecked():
            self.filterlistLE.setEnabled(True)
        else:
            self.filterlistLE.setEnabled(False)

        self.showSelectedAtomInfoCheckBox = \
            PM_CheckBox(
                inPmGroupBox,
                text  = "Show Selected Atom Info",
                widgetColumn = 0,
                state        = Qt.Unchecked)

        self.selectedAtomPosGroupBox = \
            PM_GroupBox( inPmGroupBox, title = "")
        self._loadSelectedAtomPosGroupBox(self.selectedAtomPosGroupBox)

        self.toggle_selectedAtomPosGroupBox(show = 0)
        self.enable_or_disable_selectedAtomPosGroupBox( bool_enable = False)

        self.reshapeSelectionCheckBox = \
            PM_CheckBox( inPmGroupBox,
                         text         = 'Dragging reshapes selection',
                         widgetColumn = 0,
                         state        = Qt.Unchecked  )

        connect_checkbox_with_boolean_pref( self.reshapeSelectionCheckBox,
                                            reshapeAtomsSelection_prefs_key )

        env.prefs[reshapeAtomsSelection_prefs_key] = False

        self.waterCheckBox = \
            PM_CheckBox( inPmGroupBox,
                         text         = "Z depth filter (water surface)",
                         widgetColumn = 0,
                         state        = Qt.Unchecked  )

    def _loadSelectedAtomPosGroupBox(self, inPmGroupBox):
        """
        Load the selected Atoms position groupbox It is a sub-gropbox of
        L{self.selectionOptionsGroupBox)
        @param inPmGroupBox: 'The Selected Atom Position Groupbox'
        @type  inPmGroupBox: L{PM_GroupBox}
        """

        self.selectedAtomLineEdit = PM_LineEdit( inPmGroupBox,
                                         label        = "Selected Atom:",
                                         text         = "",
                                         setAsDefault = False,
                                         spanWidth    = False )

        self.selectedAtomLineEdit.setReadOnly(True)
        self.selectedAtomLineEdit.setEnabled(False)

        self.coordinateSpinboxes = PM_CoordinateSpinBoxes(inPmGroupBox)

        # User input to specify x-coordinate
        self.xCoordOfSelectedAtom  =  self.coordinateSpinboxes.xSpinBox
        # User input to specify y-coordinate
        self.yCoordOfSelectedAtom  =  self.coordinateSpinboxes.ySpinBox
        # User input to specify z-coordinate
        self.zCoordOfSelectedAtom  =  self.coordinateSpinboxes.zSpinBox

    def _addAdvancedOptionsGroupBox(self):
        """
        Add 'Advanced Options' groupbox
        """
        self.advancedOptionsGroupBox = \
            PM_GroupBox( self, title = "Advanced Options" )

        self._loadAdvancedOptionsGroupBox(self.advancedOptionsGroupBox)

    def _loadAdvancedOptionsGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Advanced Options group box.
        @param inPmGroupBox: The Advanced Options box in the PM
        @type  inPmGroupBox: L{PM_GroupBox}
        """

        self.autoBondCheckBox = \
            PM_CheckBox( inPmGroupBox,
                         text         = 'Auto bond',
                         widgetColumn = 0,
                         state        = Qt.Checked  )

        self.highlightingCheckBox = \
            PM_CheckBox( inPmGroupBox,
                         text         = "Hover highlighting",
                         widgetColumn = 0,
                         state        = Qt.Checked )

    def _loadBondToolsGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Bond Tools group box.
        @param inPmGroupBox: The Bond Tools box in the PM
        @type  inPmGroupBox: L{PM_GroupBox}
        """
        # Button list to create a toolbutton row.
        # Format:
        # - buttonId,
        # - buttonText ,
        # - iconPath
        # - tooltip
        # - shortcut
        # - column
        BOND_TOOL_BUTTONS = \
                          [ ( "QToolButton", 0,  "SINGLE",    "", "", None, 0),
                            ( "QToolButton", 1,  "DOUBLE",    "", "", None, 1),
                            ( "QToolButton", 2,  "TRIPLE",    "", "", None, 2),
                            ( "QToolButton", 3,  "AROMATIC",  "", "", None, 3),
                            ( "QToolButton", 4,  "GRAPHITIC", "", "", None, 4),
                            ( "QToolButton", 5,  "CUTBONDS",  "", "", None, 5)
                          ]


        self.bondToolButtonRow = \
            PM_ToolButtonRow(
                inPmGroupBox,
                title        = "",
                buttonList   = BOND_TOOL_BUTTONS,
                checkedId    = None,
                setAsDefault = True )

    def _addWhatsThisText(self):
        """
        "What's This" text for widgets in this Property Manager.
        """
        from ne1_ui.WhatsThisText_for_PropertyManagers import whatsThis_BuildAtomsPropertyManager
        whatsThis_BuildAtomsPropertyManager(self)

    def _addToolTipText(self):
        """
        Tool Tip text for widgets in this Property Manager.
        """
        from ne1_ui.ToolTipText_for_PropertyManagers import ToolTip_BuildAtomsPropertyManager
        ToolTip_BuildAtomsPropertyManager(self)

    def toggle_selectedAtomPosGroupBox(self, show = 0):
        """
        Show or hide L{self.selectedAtomPosGroupBox} depending on the state of
        the checkbox (L{self.showSelectedAtomInfoCheckBox})
        @param show: Flag that shows or hides the groupbox (can have values
                     0 or 1
        @type  show: int
        """
        if show:
            self.selectedAtomPosGroupBox.show()
        else:
            self.selectedAtomPosGroupBox.hide()

    def enable_or_disable_selectedAtomPosGroupBox(self, bool_enable = False):
        """
        Enable or disable Selected AtomPosGroupBox present within
        'selection options' and also the checkbox that shows or hide this
        groupbox. These two widgets are enabled when only a single atom is
        selected from the 3D workspace.
        @param bool_enable: Flag that enables or disables widgets
        @type  bool_enable: boolean
        """
        if self.showSelectedAtomInfoCheckBox:
            self.showSelectedAtomInfoCheckBox.setEnabled(bool_enable)
        if self.selectedAtomPosGroupBox:
            self.selectedAtomPosGroupBox.setEnabled(bool_enable)

    def _updateAtomChooserGroupBoxes(self, currentIndex):
        """
        Updates the Atom Chooser Groupbox. It displays one of the
        following three groupboxes depending on the choice selected in the
        combobox:
          a) Periodic Table Elements L{self.regularElementChooser}
          b) PAM5 Atoms  L{self.PAM5Chooser}
          c) PAM3 Atoms  L{self.PAM3Chooser}
        It also sets self.elementChooser to the current active Atom chooser
        and updates the display accordingly in the Preview groupbox.
        """
        self._hideAllAtomChooserGroupBoxes()

        if currentIndex is 0:
            self.elementChooser = self.regularElementChooser
            self.regularElementChooser.show()
        if currentIndex is 1:
            self.elementChooser = self.PAM5Chooser
            self.PAM5Chooser.show()
        if currentIndex is 2:
            self.elementChooser = self.PAM3Chooser
            self.PAM3Chooser.show()

        if self.elementChooser:
            self.elementChooser.updateElementViewer()

        self.updateMessage()


    def updateMessage(self):
        """
        Update the Message groupbox with informative message.
        Subclasses should override this.
        """
        pass
class Ui_MovePropertyManager(Command_PropertyManager):
    
       
    # The title that appears in the Property Manager header        
    title = "Move"
    # The name of this Property Manager. This will be set to
    # the name of the PM_Dialog object via setObjectName().
    pmName = title
    # The relative path to the PNG file that appears in the header
    iconPath = "ui/actions/Properties Manager/Translate_Components.png"
    
    # The title(s) that appear in the property manager header.
    # (these are changed depending on the active group box) 
    translateTitle = "Translate"
    rotateTitle = "Rotate"

    # The full path to PNG file(s) that appears in the header.
    translateIconPath = "ui/actions/Properties Manager/Translate_Components.png"
    rotateIconPath = "ui/actions/Properties Manager/Rotate_Components.png"
    
    def __init__(self, command):  
        _superclass.__init__(self, command)       
        self.showTopRowButtons(PM_DONE_BUTTON | PM_WHATS_THIS_BUTTON)
    
    def _addGroupBoxes(self):
        """
        Add groupboxes to the Property Manager dialog. 
        """
        
        self.translateGroupBox = PM_GroupBox( self, 
                                              title = "Translate",
                                              connectTitleButton = False)
        self.translateGroupBox.titleButton.setShortcut('T')
        self._loadTranslateGroupBox(self.translateGroupBox)
        
        self.rotateGroupBox = PM_GroupBox( self, 
                                           title = "Rotate",
                                           connectTitleButton = False)
        self.rotateGroupBox.titleButton.setShortcut('R')
        self._loadRotateGroupBox(self.rotateGroupBox)
        
        self.translateGroupBox.collapse()
        self.rotateGroupBox.collapse()
            
    # == Begin Translate Group Box =====================
    
    def _loadTranslateGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Translate group box.
        @param inPmGroupBox: The Translate group box in the PM
        @type  inPmGroupBox: L{PM_GroupBox}
        """
        
        translateChoices = [ "Free Drag", 
                             "By Delta XYZ", 
                             "To XYZ Position" ]
        
        self.translateComboBox = \
            PM_ComboBox( inPmGroupBox,
                         label        = '', 
                         choices      = translateChoices, 
                         index        = 0, 
                         setAsDefault = False,
                         spanWidth    = True )
        
        self.freeDragTranslateGroupBox = PM_GroupBox( inPmGroupBox )
        self._loadFreeDragTranslateGroupBox(self.freeDragTranslateGroupBox)
                
        self.byDeltaGroupBox = PM_GroupBox( inPmGroupBox )
        self._loadByDeltaGroupBox(self.byDeltaGroupBox)
        
        self.toPositionGroupBox = PM_GroupBox( inPmGroupBox )
        self._loadToPositionGroupBox(self.toPositionGroupBox)
        
        self.updateTranslateGroupBoxes(0)
    
    def _loadFreeDragTranslateGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Free Drag Translate group box, which is present 
        within the Translate groupbox.
        @param inPmGroupBox: The Free Drag Translate group box in the Translate 
                             group box. 
        @type  inPmGroupBox: L{PM_GroupBox}
        """
        # Button list to create a toolbutton row.
        # Format: 
        # - buttonId, 
        # - buttonText , 
        # - iconPath
        # - tooltip
        # - shortcut
        # - column
        
         
        BUTTON_LIST = [ 
            ( "QToolButton", 1,  "MOVEDEFAULT", 
              "ui/actions/Properties Manager/Move_Free.png", "", "F", 0),
            ( "QToolButton", 2,  "TRANSX", 
              "ui/actions/Properties Manager/TranslateX.png", "", "X", 1),
            ( "QToolButton", 3,  "TRANSY",  
              "ui/actions/Properties Manager/TranslateY.png", "", "Y", 2),
            ( "QToolButton", 4,  "TRANSZ",  
              "ui/actions/Properties Manager/TranslateZ.png", "", "Z", 3),
            ( "QToolButton", 5,  "ROT_TRANS_ALONG_AXIS",  
              "ui/actions/Properties Manager/translate+rotate-A.png", "", \
              "A", 4)
                        
            ]
            
        self.freeDragTranslateButtonGroup = \
            PM_ToolButtonRow( inPmGroupBox, 
                               title        = "",
                               buttonList   = BUTTON_LIST,
                               checkedId    = 1,
                               setAsDefault = True,
                               )
        self.transFreeButton =self.freeDragTranslateButtonGroup.getButtonById(1)
        self.transXButton = self.freeDragTranslateButtonGroup.getButtonById(2)
        self.transYButton = self.freeDragTranslateButtonGroup.getButtonById(3)
        self.transZButton = self.freeDragTranslateButtonGroup.getButtonById(4)
        self.transAlongAxisButton = \
            self.freeDragTranslateButtonGroup.getButtonById(5)
        
        self.moveFromToButton = PM_ToolButton(
                    inPmGroupBox, 
                    text = "Translate from/to",
                    iconPath  = "ui/actions/Properties Manager"\
                    "/Translate_Components.png",
                    spanWidth = True
                    
                    )
        self.moveFromToButton.setCheckable(True)
        self.moveFromToButton.setAutoRaise(True)
        self.moveFromToButton.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        
        
        self.startCoordLineEdit = PM_LineEdit( 
            inPmGroupBox, 
            label        = "ui/actions/Properties Manager"\
                    "/Move_Start_Point.png",
            text         = "Define 'from' and 'to' points",
            setAsDefault = False,
            )
        self.startCoordLineEdit.setReadOnly(True)
        self.startCoordLineEdit.setEnabled(False)
        
    def _loadByDeltaGroupBox(self, inPmGroupBox):
        """
        Load widgets in the translate By Delta group box, which is present 
        within the Translate groupbox.
        @param inPmGroupBox: The Translate By Delta group box in the translate 
                             group box. 
        @type  inPmGroupBox: L{PM_GroupBox}
        """

        self.moveDeltaXSpinBox = \
            PM_DoubleSpinBox( 
                inPmGroupBox, 
                label        = "ui/actions/Properties Manager/Delta_X.png",
                value        = 0.0, 
                setAsDefault = True,
                minimum      = -100.0, 
                maximum      =  100.0, 
                singleStep   = 1.0, 
                decimals     = 3, 
                suffix       = ' Angstroms',
                spanWidth    = False )
        
        self.moveDeltaYSpinBox = \
            PM_DoubleSpinBox( 
                inPmGroupBox, 
                label        = "ui/actions/Properties Manager/Delta_Y.png",
                value        = 0.0, 
                setAsDefault = True,
                minimum      = -100.0, 
                maximum      =  100.0, 
                singleStep   = 1.0, 
                decimals     = 3, 
                suffix       = ' Angstroms',
                spanWidth    = False )
        
        self.moveDeltaZSpinBox = \
            PM_DoubleSpinBox( 
                inPmGroupBox, 
                label        = "ui/actions/Properties Manager/Delta_Z.png",
                value        = 0.0, 
                setAsDefault = True,
                minimum      = -100.0, 
                maximum      =  100.0, 
                singleStep   = 1.0, 
                decimals     = 3, 
                suffix       = ' Angstroms',
                spanWidth    = False )
        
        DELTA_BUTTONS = [
                        ("QToolButton",1,  "Delta Plus", 
                         "ui/actions/Properties Manager/Move_Delta_Plus.png", 
                         "", "+", 0 ),
            
                        ( "QToolButton", 2,  "Delta Minus",  
                          "ui/actions/Properties Manager/Move_Delta_Minus.png", 
                          "", "-", 1 )
                        ]
        
        self.translateDeltaButtonRow = \
            PM_ToolButtonRow( inPmGroupBox, 
                              title        = "",
                              buttonList   = DELTA_BUTTONS,
                              label        = 'Translate:',
                              isAutoRaise  =  True,
                              isCheckable  =  False                           
                            )
        self.transDeltaPlusButton = \
            self.translateDeltaButtonRow.getButtonById(1)
        self.transDeltaMinusButton = \
            self.translateDeltaButtonRow.getButtonById(2)
        
            
    def _loadToPositionGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Translate To a given Position group box, which is 
        present within the Translate groupbox.
        @param inPmGroupBox: Translate To Position group box in the Translate 
                             group box.
        @type  inPmGroupBox: L{PM_GroupBox}
        """
        
        self.toPositionspinboxes = PM_CoordinateSpinBoxes(inPmGroupBox)
        
        self.moveXSpinBox = self.toPositionspinboxes.xSpinBox
        self.moveYSpinBox = self.toPositionspinboxes.ySpinBox
        self.moveZSpinBox = self.toPositionspinboxes.zSpinBox
        
        
        self.moveAbsoluteButton = \
            PM_PushButton( inPmGroupBox,
                           label     = "",
                           text      = "Move Selection",
                           spanWidth = True )
            
    # == Begin Rotate Group Box =====================
    def _loadRotateGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Rotate group box, 
        @param inPmGroupBox: The Rotate GroupBox in the PM
        @type  inPmGroupBox: L{PM_GroupBox}
        """
        
        rotateChoices = [ "Free Drag", "By Specified Angle"]
        
        self.rotateComboBox = \
            PM_ComboBox( inPmGroupBox,
                         label        = '', 
                         choices      = rotateChoices, 
                         index        = 0, 
                         setAsDefault = False,
                         spanWidth    = True )
        
        self.rotateAsUnitCB = \
            PM_CheckBox( inPmGroupBox,
                         text         = 'Rotate as a unit' ,
                         widgetColumn = 0,
                         state        = Qt.Checked )
        
               
        self.freeDragRotateGroupBox = PM_GroupBox( inPmGroupBox )
        self._loadFreeDragRotateGroupBox(self.freeDragRotateGroupBox)
        
        self.bySpecifiedAngleGroupBox = PM_GroupBox( inPmGroupBox )
        self._loadBySpecifiedAngleGroupBox(self.bySpecifiedAngleGroupBox)
        
        self.updateRotateGroupBoxes(0)    
        
    def _loadFreeDragRotateGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Free Drag Rotate group box, which is 
        present within the Rotate groupbox.
        @param inPmGroupBox: The Free Drag Rotate group box in the Rotate 
                             group box.
        @type  inPmGroupBox: L{PM_GroupBox}
        """
        # Button list to create a toolbutton row.
        # Format: 
        # - buttonId, 
        # - buttonText , 
        # - iconPath
        # - tooltip
        # - shortcut
        # - column
        
        BUTTON_LIST = [ 
            ( "QToolButton", 1,  "ROTATEDEFAULT", 
              "ui/actions/Properties Manager/Rotate_Free.png", "", "F", 0 ),
            
            ( "QToolButton", 2,  "ROTATEX", 
              "ui/actions/Properties Manager/RotateX.png", "", "X", 1 ),
            
            ( "QToolButton", 3,  "ROTATEY",  
              "ui/actions/Properties Manager/RotateY.png", "", "Y", 2 ),
            
            ( "QToolButton", 4,  "ROTATEZ",  
              "ui/actions/Properties Manager/RotateZ.png", "", "Z", 3 ),
            
            ( "QToolButton", 5,  "ROT_TRANS_ALONG_AXIS",  
              "ui/actions/Properties Manager/translate+rotate-A.png", "", \
              "A", 4 )
                        
            ]
            
        self.freeDragRotateButtonGroup = \
            PM_ToolButtonRow( inPmGroupBox, 
                               title        = "",
                               buttonList   = BUTTON_LIST,
                               spanWidth = True,
                               checkedId    = 1,
                               setAsDefault = True,
                            )
                
        self.rotateFreeButton = self.freeDragRotateButtonGroup.getButtonById(1)
        self.rotateXButton    = self.freeDragRotateButtonGroup.getButtonById(2)
        self.rotateYButton    = self.freeDragRotateButtonGroup.getButtonById(3)
        self.rotateZButton    = self.freeDragRotateButtonGroup.getButtonById(4)
        self.rotAlongAxisButton = \
            self.freeDragRotateButtonGroup.getButtonById(5)
        
        inPmGroupBox.setStyleSheet(
            self.freeDragRotateButtonGroup._getStyleSheet())
                
        X_ROW_LABELS = [("QLabel", "Delta Theta X:", 0),
                        ("QLabel", "", 1),
                        ("QLabel", "0.00", 2),
                        ("QLabel", "Degrees", 3)]
        
        Y_ROW_LABELS = [("QLabel", "Delta Theta Y:", 0),
                        ("QLabel", "", 1),
                        ("QLabel", "0.00", 2),
                        ("QLabel", "Degrees", 3)]
        
        Z_ROW_LABELS = [("QLabel", "Delta Theta Z:", 0),
                        ("QLabel", "", 1),
                        ("QLabel", "0.00", 2),
                        ("QLabel", "Degrees", 3)]
        
        self.rotateXLabelRow = PM_LabelRow( inPmGroupBox,
                                            title = "",
                                            labelList = X_ROW_LABELS )  
        self.deltaThetaX_lbl = self.rotateXLabelRow.labels[2]
                                           
        self.rotateYLabelRow = PM_LabelRow( inPmGroupBox,
                                            title = "",
                                            labelList = Y_ROW_LABELS )
        self.deltaThetaY_lbl = self.rotateYLabelRow.labels[2]
                                          
        self.rotateZLabelRow = PM_LabelRow( inPmGroupBox,
                                            title = "",
                                            labelList = Z_ROW_LABELS )  
        self.deltaThetaZ_lbl = self.rotateZLabelRow.labels[2]    
        
        self.rotateAboutPointButton = PM_ToolButton(
                    inPmGroupBox, 
                    text = "Rotate selection about a point",
                    iconPath  = "ui/actions/Properties Manager"\
                    "/Rotate_Components.png",
                    spanWidth = True                    
                    )
        self.rotateAboutPointButton.setCheckable(True)
        self.rotateAboutPointButton.setAutoRaise(True)
        self.rotateAboutPointButton.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        
        
        self.rotateStartCoordLineEdit = PM_LineEdit( 
            inPmGroupBox, 
            label        = "ui/actions/Properties Manager"\
                    "/Move_Start_Point.png",
            text         = "Define 3 points",
            setAsDefault = False,
            )
        self.rotateStartCoordLineEdit.setReadOnly(True)
        self.rotateStartCoordLineEdit.setEnabled(False)
            
            
    def _loadBySpecifiedAngleGroupBox(self, inPmGroupBox):
        """
        Load widgets in the Rotate By Specified Angle group box, which is 
        present within the Rotate groupbox.
        @param inPmGroupBox: Rotate By Specified Angle group box in the Rotate 
                             group box.
        @type  inPmGroupBox: L{PM_GroupBox}
        """
        # Button list to create a toolbutton row.
        # Format: 
        # - buttonId, 
        # - buttonText , 
        # - iconPath
        # - tooltip
        # - shortcut
        # - column
        
        BUTTON_LIST = [ 
            ( "QToolButton", 1,  "ROTATEX", 
              "ui/actions/Properties Manager/RotateX.png", 
              "Rotate about X axis", "X", 0 ),
            
            ( "QToolButton", 2,  "ROTATEY",  
              "ui/actions/Properties Manager/RotateY.png", 
              "Rotate about Y axis", "Y", 1 ),
            
            ( "QToolButton", 3,  "ROTATEZ",  
              "ui/actions/Properties Manager/RotateZ.png", 
              "Rotate about Z axis","Z", 2 ),
            ]
        
        
        
        self.rotateAroundAxisButtonRow = \
            PM_ToolButtonRow( inPmGroupBox, 
                              title        = "",
                              buttonList   = BUTTON_LIST,
                              alignment    = 'Right',
                              label        = 'Rotate Around:'
                            )
        self.rotXaxisButton = \
            self.rotateAroundAxisButtonRow.getButtonById(1)
        
        self.rotYaxisButton = \
            self.rotateAroundAxisButtonRow.getButtonById(2)
        
        self.rotZaxisButton = \
            self.rotateAroundAxisButtonRow.getButtonById(3)
        
        

        self.rotateThetaSpinBox = \
            PM_DoubleSpinBox(inPmGroupBox,
                             label        = "Rotate By:",
                             value        = 0.0, 
                             setAsDefault = True,
                             minimum      = 0, 
                             maximum      = 360.0,
                             singleStep   = 1.0, 
                             decimals     = 2, 
                             suffix       = ' Degrees')
        
        
        THETA_BUTTONS = [ 
            ( "QToolButton", 1,  "Theta Plus", 
              "ui/actions/Properties Manager/Move_Theta_Plus.png", "", "+", 0 ),
            
            ( "QToolButton", 2,  "Theta Minus",  
              "ui/actions/Properties Manager/Move_Theta_Minus.png", "", "-", 1 )
            ]
        
        self.rotateThetaButtonRow = \
            PM_ToolButtonRow( inPmGroupBox, 
                              title        = "",
                              buttonList   = THETA_BUTTONS,
                              label        = 'Direction:',
                              isAutoRaise  =  True,
                              isCheckable  =  False                           
                            )
        self.rotateThetaPlusButton =  self.rotateThetaButtonRow.getButtonById(1)
        self.rotateThetaMinusButton = self.rotateThetaButtonRow.getButtonById(2)
    
    # == End Rotate Group Box =====================
        
    # == Slots for Translate group box
    def _hideAllTranslateGroupBoxes(self):
        """
        Hides all Translate group boxes.
        """
        self.toPositionGroupBox.hide()
        self.byDeltaGroupBox.hide()
        self.freeDragTranslateGroupBox.hide()
            
    def updateTranslateGroupBoxes(self, id):
        """
        Update the translate group boxes displayed based on the translate
        option selected.
        @param id: Integer value corresponding to the combobox item in the 
                   Translate group box. 
        @type  id: int
        """
        self._hideAllTranslateGroupBoxes()
        
        if id is 0:
            self.freeDragTranslateGroupBox.show()
                               
        if id is 1:
            self.byDeltaGroupBox.show()                    
        if id is 2:
            self.toPositionGroupBox.show()
           
        self.updateMessage()
    
    def changeMoveOption(self, button):
        """
        Subclasses should reimplement this method.
        
        @param button: QToolButton that decides the type of translate operation 
        to be set.
        @type  button: QToolButton 
                       L{http://doc.trolltech.com/4.2/qtoolbutton.html}
        @see: B{MovePropertyManager.changeMoveOption} which overrides this
              method
        """
        pass
    
    # == Slots for Rotate group box
    def updateRotateGroupBoxes(self, id):
        """
        Update the translate group boxes displayed based on the translate
        option selected.
        @param id: Integer value corresponding to the combobox item in the 
                   Rotate group box. 
        @type  id: int
        """
        if id is 0:
            self.bySpecifiedAngleGroupBox.hide()
            self.freeDragRotateGroupBox.show()   
        if id is 1:
            self.freeDragRotateGroupBox.hide()
            self.bySpecifiedAngleGroupBox.show()
            
        self.updateMessage()
            
    def changeRotateOption(self, button):
        """
        Subclasses should reimplement this method. 
        
        @param button: QToolButton that decides the type of rotate operation 
        to be set.
        @type  button: QToolButton 
                       L{http://doc.trolltech.com/4.2/qtoolbutton.html}
        @see: B{MovePropertyManage.changeRotateOption} which overrides this 
             method
        """
        pass
    
    def _addWhatsThisText(self):
        """
        What's This text for some of the widgets in this Property Manager.  

        """
        from ne1_ui.WhatsThisText_for_PropertyManagers import whatsThis_MovePropertyManager
        whatsThis_MovePropertyManager(self)
        
    def _addToolTipText(self):
        """
        Tool Tip text for widgets in this Property Manager.  
        """
        from ne1_ui.ToolTipText_for_PropertyManagers import ToolTip_MovePropertyManager
        ToolTip_MovePropertyManager(self)
class InsertNanotube_PropertyManager( DnaOrCnt_PropertyManager):
    """
    The InsertNanotube_PropertyManager class provides a Property Manager
    for the B{Build > Nanotube > CNT} command.

    @ivar title: The title that appears in the property manager header.
    @type title: str

    @ivar pmName: The name of this property manager. This is used to set
                  the name of the PM_Dialog object via setObjectName().
    @type name: str

    @ivar iconPath: The relative path to the PNG file that contains a
                    22 x 22 icon image that appears in the PM header.
    @type iconPath: str
    """

    title         =  "Insert Nanotube"
    pmName        =  title
    iconPath      =  "ui/actions/Tools/Build Structures/InsertNanotube.png"

    def __init__( self, win, editCommand ):
        """
        Constructor for the Nanotube property manager.
        """
        self.endPoint1 = None
        self.endPoint2 = None

        self.nanotube = Nanotube() # A 5x5 CNT.

        _superclass.__init__( self,
                                 win,
                                 editCommand)

        self.showTopRowButtons( PM_DONE_BUTTON | \
                                PM_CANCEL_BUTTON | \
                                PM_WHATS_THIS_BUTTON)

    def connect_or_disconnect_signals(self, isConnect):
        """
        Connect or disconnect widget signals sent to their slot methods.
        This can be overridden in subclasses. By default it does nothing.
        @param isConnect: If True the widget will send the signals to the slot
                          method.
        @type  isConnect: boolean
        """
        if isConnect:
            change_connect = self.win.connect
        else:
            change_connect = self.win.disconnect

        change_connect( self.ntTypeComboBox,
                      SIGNAL("currentIndexChanged(const QString&)"),
                      self._ntTypeComboBoxChanged )

        change_connect(self.chiralityNSpinBox,
                       SIGNAL("valueChanged(int)"),
                       self._chiralityFixup)

        change_connect(self.chiralityMSpinBox,
                       SIGNAL("valueChanged(int)"),
                       self._chiralityFixup)

        change_connect(self.endingsComboBox,
                       SIGNAL("currentIndexChanged(const QString&)"),
                       self._endingsComboBoxChanged )

        # This spin box is currently hidden.
        change_connect(self.bondLengthDoubleSpinBox,
                       SIGNAL("valueChanged(double)"),
                       self._bondLengthChanged)

        change_connect(self.showCursorTextCheckBox,
                       SIGNAL('stateChanged(int)'),
                       self._update_state_of_cursorTextGroupBox)

    def ok_btn_clicked(self):
        """
        Slot for the OK button
        """
        if self.editCommand:
            self.editCommand.preview_or_finalize_structure(previewing = False)
            ##env.history.message(self.editCommand.logMessage)
        self.win.toolsDone()

    def cancel_btn_clicked(self):
        """
        Slot for the Cancel button.
        """
        if self.editCommand:
            self.editCommand.cancelStructure()
        self.win.toolsCancel()


    def _update_widgets_in_PM_before_show(self):
        """
        Update various widgets in this Property manager.
        Overrides MotorPropertyManager._update_widgets_in_PM_before_show.
        The various  widgets , (e.g. spinboxes) will get values from the
        structure for which this propMgr is constructed for
        (self.editcCntroller.struct)

        @see: MotorPropertyManager._update_widgets_in_PM_before_show
        @see: self.show where it is called.
        """
        pass

    def getFlyoutActionList(self):
        """
        Returns custom actionlist that will be used in a specific mode
        or editing a feature etc Example: while in movie mode,
        the _createFlyoutToolBar method calls this.
        """
        #'allActionsList' returns all actions in the flyout toolbar
        #including the subcontrolArea actions
        allActionsList = []

        #Action List for  subcontrol Area buttons.
        #In this mode there is really no subcontrol area.
        #We will treat subcontrol area same as 'command area'
        #(subcontrol area buttons will have an empty list as their command area
        #list). We will set  the Comamnd Area palette background color to the
        #subcontrol area.

        subControlAreaActionList =[]

        self.exitEditCommandAction.setChecked(True)
        subControlAreaActionList.append(self.exitEditCommandAction)

        separator = QAction(self.w)
        separator.setSeparator(True)
        subControlAreaActionList.append(separator)


        allActionsList.extend(subControlAreaActionList)

        #Empty actionlist for the 'Command Area'
        commandActionLists = []

        #Append empty 'lists' in 'commandActionLists equal to the
        #number of actions in subControlArea
        for i in range(len(subControlAreaActionList)):
            lst = []
            commandActionLists.append(lst)

        params = (subControlAreaActionList, commandActionLists, allActionsList)

        return params

    def _addGroupBoxes( self ):
        """
        Add the Insert Nanotube Property Manager group boxes.
        """

        self._pmGroupBox1 = PM_GroupBox( self, title = "Endpoints" )
        self._loadGroupBox1( self._pmGroupBox1 )
        self._pmGroupBox1.hide()

        self._pmGroupBox2 = PM_GroupBox( self, title = "Parameters" )
        self._loadGroupBox2( self._pmGroupBox2 )

        self._displayOptionsGroupBox = PM_GroupBox( self,
                                                    title = "Display Options" )
        self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )

        self._pmGroupBox3 = PM_GroupBox( self, title = "Nanotube Distortion" )
        self._loadGroupBox3( self._pmGroupBox3 )
        self._pmGroupBox3.hide() #@ Temporary.

        self._pmGroupBox4 = PM_GroupBox( self, title = "Multi-Walled CNTs" )
        self._loadGroupBox4( self._pmGroupBox4 )
        self._pmGroupBox4.hide() #@ Temporary.

        self._pmGroupBox5 = PM_GroupBox( self, title = "Advanced Options" )
        self._loadGroupBox5( self._pmGroupBox5 )
        self._pmGroupBox5.hide() #@ Temporary.

    def _loadGroupBox1(self, pmGroupBox):
        """
        Load widgets in group box 1.
        """
        #Following toolbutton facilitates entering a temporary NanotubeLineMode
        #to create a CNT using endpoints of the specified line.
        self.specifyCntLineButton = PM_ToolButton(
            pmGroupBox,
            text = "Specify Endpoints",
            iconPath  = "ui/actions/Properties Manager/Pencil.png",
            spanWidth = True
        )
        self.specifyCntLineButton.setCheckable(True)
        self.specifyCntLineButton.setAutoRaise(True)
        self.specifyCntLineButton.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)

        #EndPoint1 and endPoint2 coordinates. These widgets are hidden
        # as of 2007- 12 - 05
        self._endPoint1SpinBoxes = PM_CoordinateSpinBoxes(pmGroupBox,
                                                label = "End Point 1")
        self.x1SpinBox = self._endPoint1SpinBoxes.xSpinBox
        self.y1SpinBox = self._endPoint1SpinBoxes.ySpinBox
        self.z1SpinBox = self._endPoint1SpinBoxes.zSpinBox

        self._endPoint2SpinBoxes = PM_CoordinateSpinBoxes(pmGroupBox,
                                                label = "End Point 2")
        self.x2SpinBox = self._endPoint2SpinBoxes.xSpinBox
        self.y2SpinBox = self._endPoint2SpinBoxes.ySpinBox
        self.z2SpinBox = self._endPoint2SpinBoxes.zSpinBox

        self._endPoint1SpinBoxes.hide()
        self._endPoint2SpinBoxes.hide()

    def _loadGroupBox2(self, pmGroupBox):
        """
        Load widgets in group box 2.
        """

        _ntTypeChoices = ['Carbon',
                          'Boron Nitride']
        self.ntTypeComboBox  = \
            PM_ComboBox( pmGroupBox,
                         label         =  "Type:",
                         choices       =  _ntTypeChoices,
                         setAsDefault  =  True)

        self.ntRiseDoubleSpinBox  =  \
            PM_DoubleSpinBox( pmGroupBox,
                              label         =  "Rise:",
                              value         =  self.nanotube.getRise(),
                              setAsDefault  =  True,
                              minimum       =  2.0,
                              maximum       =  4.0,
                              decimals      =  3,
                              singleStep    =  0.01 )

        self.ntRiseDoubleSpinBox.hide()

        # Nanotube Length
        self.ntLengthLineEdit  =  \
            PM_LineEdit( pmGroupBox,
                         label         =  "Nanotube Length: ",
                         text          =  "0.0 Angstroms",
                         setAsDefault  =  False)

        self.ntLengthLineEdit.setDisabled(True)
        self.ntLengthLineEdit.hide()

        # Nanotube diameter
        self.ntDiameterLineEdit  =  \
            PM_LineEdit( pmGroupBox,
                         label         =  "Diameter: ",
                         setAsDefault  =  False)

        self.ntDiameterLineEdit.setDisabled(True)
        self.updateNanotubeDiameter()

        self.chiralityNSpinBox = \
            PM_SpinBox( pmGroupBox,
                        label        = "Chirality (n):",
                        value        = self.nanotube.getChiralityN(),
                        minimum      =  2,
                        maximum      =  100,
                        setAsDefault = True )

        self.chiralityMSpinBox = \
            PM_SpinBox( pmGroupBox,
                        label        = "Chirality (m):",
                        value        = self.nanotube.getChiralityM(),
                        minimum      =  0,
                        maximum      =  100,
                        setAsDefault = True )

        # How about having user prefs for CNT and BNNT bond lengths?
        # I'm guessing that if the user wants to set these values, they will
        # do it once and would like those bond length values persist forever.
        # Need to discuss with others to determine if this spinbox comes out.
        # --Mark 2008-03-29
        self.bondLengthDoubleSpinBox = \
            PM_DoubleSpinBox( pmGroupBox,
                              label        = "Bond length:",
                              value        = self.nanotube.getBondLength(),
                              setAsDefault = True,
                              minimum      = 1.0,
                              maximum      = 3.0,
                              singleStep   = 0.1,
                              decimals     = 3,
                              suffix       = " Angstroms" )

        #self.bondLengthDoubleSpinBox.hide()

        endingChoices = ["Hydrogen", "None"] # Removed:, "Nitrogen"]

        self.endingsComboBox= \
            PM_ComboBox( pmGroupBox,
                         label        = "Endings:",
                         choices      = endingChoices,
                         index        = 0,
                         setAsDefault = True,
                         spanWidth    = False )

    def _loadGroupBox3(self, inPmGroupBox):
        """
        Load widgets in group box 3.
        """

        self.zDistortionDoubleSpinBox = \
            PM_DoubleSpinBox( inPmGroupBox,
                              label        = "Z-distortion:",
                              value        = 0.0,
                              setAsDefault = True,
                              minimum      = 0.0,
                              maximum      = 10.0,
                              singleStep   = 0.1,
                              decimals     = 3,
                              suffix       = " Angstroms" )

        self.xyDistortionDoubleSpinBox = \
            PM_DoubleSpinBox( inPmGroupBox,
                              label        = "XY-distortion:",
                              value        = 0.0,
                              setAsDefault = True,
                              minimum      = 0.0,
                              maximum      = 2.0,
                              singleStep   = 0.1,
                              decimals     = 3,
                              suffix       = " Angstroms" )

        self.twistSpinBox = \
            PM_SpinBox( inPmGroupBox,
                        label        = "Twist:",
                        value        = 0,
                        setAsDefault = True,
                        minimum      = 0,
                        maximum      = 100, # What should maximum be?
                        suffix       = " deg/A" )

        self.bendSpinBox = \
            PM_SpinBox( inPmGroupBox,
                        label        = "Bend:",
                        value        = 0,
                        setAsDefault = True,
                        minimum      = 0,
                        maximum      = 360,
                        suffix       = " deg" )

    def _loadGroupBox4(self, inPmGroupBox):
        """
        Load widgets in group box 4.
        """

        # "Number of Nanotubes" SpinBox
        self.mwntCountSpinBox = \
            PM_SpinBox( inPmGroupBox,
                        label        = "Number:",
                        value        = 1,
                        setAsDefault = True,
                        minimum      = 1,
                        maximum      = 10,
                        suffix       = " nanotubes" )

        self.mwntCountSpinBox.setSpecialValueText("SWNT")

        # "Spacing" lineedit.
        self.mwntSpacingDoubleSpinBox = \
            PM_DoubleSpinBox( inPmGroupBox,
                              label        = "Spacing:",
                              value        = 2.46,
                              setAsDefault = True,
                              minimum      = 1.0,
                              maximum      = 10.0,
                              singleStep   = 0.1,
                              decimals     = 3,
                              suffix       = " Angstroms" )

    def _loadGroupBox5(self, pmGroupBox):
        """
        Load widgets in group box 5.
        """
        self._rubberbandLineGroupBox = PM_GroupBox(
            pmGroupBox,
            title = 'Rubber band Line:')

        ntLineChoices = ['Ladder']
        self.ntRubberBandLineDisplayComboBox = \
            PM_ComboBox( self._rubberbandLineGroupBox ,
                         label         =  " Display as:",
                         choices       =  ntLineChoices,
                         setAsDefault  =  True)

        self.lineSnapCheckBox = \
            PM_CheckBox(self._rubberbandLineGroupBox ,
                        text         = 'Enable line snap' ,
                        widgetColumn = 1,
                        state        = Qt.Checked
                        )


    def _connect_showCursorTextCheckBox(self):
        """
        Connect the show cursor text checkbox with user prefs_key.
        Overrides
        DnaOrCnt_PropertyManager._connect_showCursorTextCheckBox
        """
        connect_checkbox_with_boolean_pref(
            self.showCursorTextCheckBox ,
            insertNanotubeEditCommand_showCursorTextCheckBox_prefs_key )


    def _params_for_creating_cursorTextCheckBoxes(self):
        """
        Returns params needed to create various cursor text checkboxes connected
        to prefs_keys  that allow custom cursor texts.
        @return: A list containing tuples in the following format:
                ('checkBoxTextString' , preference_key). PM_PrefsCheckBoxes
                uses this data to create checkboxes with the the given names and
                connects them to the provided preference keys. (Note that
                PM_PrefsCheckBoxes puts thes within a GroupBox)
        @rtype: list
        @see: PM_PrefsCheckBoxes
        @see: self._loadDisplayOptionsGroupBox where this list is used.
        @see: Superclass method which is overridden here --
        DnaOrCnt_PropertyManager._params_for_creating_cursorTextCheckBoxes()
        """
        params = \
               [  #Format: (" checkbox text", prefs_key)

                   ("Nanotube length",
                    insertNanotubeEditCommand_cursorTextCheckBox_length_prefs_key ),

                    ("Angle",
                     insertNanotubeEditCommand_cursorTextCheckBox_angle_prefs_key )
                 ]

        return params


    def _addToolTipText(self):
        """
        Tool Tip text for widgets in the Insert Nanotube Property Manager.
        """
        pass

    def _setEndPoints(self):
        """
        Set the two endpoints of the nanotube using the values from the
        X, Y, Z coordinate spinboxes in the property manager.

        @note: The group box containing the 2 sets of XYZ spin boxes are
        currently hidden.
        """
        # First endpoint (origin) of nanotube
        x1 = self.x1SpinBox.value()
        y1 = self.y1SpinBox.value()
        z1 = self.z1SpinBox.value()

        # Second endpoint (direction vector/axis) of nanotube.
        x2 = self.x2SpinBox.value()
        y2 = self.y2SpinBox.value()
        z2 = self.z2SpinBox.value()

        if not self.endPoint1:
            self.endPoint1 = V(x1, y1, z1)
        if not self.endPoint2:
            self.endPoint2 = V(x2, y2, z2)

        self.nanotube.setEndPoints(self.endPoint1, self.endPoint2)
            # Need arg "recompute=True", which will recompute the second
            # endpoint (endPoint2) using the nanotube rise.

    def getParameters(self):
        """
        Return the parameters from this property manager to be used to create
        the nanotube.

        @return: A nanotube instance with its attrs set to the current
                 parameters in the property manager.
        @rtype: L{Nanotube}

        @see: L{InsertNanotube_EditCommand._gatherParameters} where this is used
        """
        self._setEndPoints()
        return (self.nanotube)

    def _ntTypeComboBoxChanged( self, type ):
        """
        Slot for the Type combobox. It is called whenever the
        Type choice is changed.

        @param inIndex: The new index.
        @type  inIndex: int
        """
        self.nanotube.setType(str(type))
        print "Bond Length =", self.nanotube.getBondLength()
        self.bondLengthDoubleSpinBox.setValue(self.nanotube.getBondLength())
        #self.bondLengthDoubleSpinBox.setValue(ntBondLengths[inIndex])

    def _bondLengthChanged(self, bondLength):
        """
        Slot for the B{Bond Length} spinbox.
        """
        self.nanotube.setBondLength(bondLength)
        self.updateNanotubeDiameter()
        return

    def _chiralityFixup(self, spinBoxValueJunk = None):
        """
        Slot for several validators for different parameters.
        This gets called whenever the user changes the n, m chirality values.

        @param spinBoxValueJunk: This is the Spinbox value from the valueChanged
                                 signal. It is not used. We just want to know
                                 that the spinbox value has changed.
        @type  spinBoxValueJunk: double or None
        """
        _n, _m = self.nanotube.setChirality(self.chiralityNSpinBox.value(),
                                            self.chiralityMSpinBox.value())

        #self.n, self.m = self.nanotube.getChirality()

        self.connect_or_disconnect_signals(isConnect = False)
        self.chiralityNSpinBox.setValue(_n)
        self.chiralityMSpinBox.setValue(_m)
        self.connect_or_disconnect_signals(isConnect = True)

        self.updateNanotubeDiameter()

    def updateNanotubeDiameter(self):
        """
        Update the nanotube Diameter lineEdit widget.
        """
        diameterText = "%-7.4f Angstroms" %  (self.nanotube.getDiameter())
        self.ntDiameterLineEdit.setText(diameterText)

        # ntRiseDoubleSpinBox is currently hidden.
        self.ntRiseDoubleSpinBox.setValue(self.nanotube.getRise())

    def _endingsComboBoxChanged(self, endings):
        """
        Slot for the B{Ending} combobox.

        @param endings: The option's text.
        @type  endings: string
        """
        self.nanotube.setEndings(str(endings))
        return

    def _addWhatsThisText(self):
        """
        What's This text for widgets in this Property Manager.
        """
        whatsThis_InsertNanotube_PropertyManager(self)
        return
    def __init__(self,
                 parentWidget,
                 title = "Message"
                 ):
        """
        PM_MessageGroupBox constructor.

        @param parentWidget: the PM_Dialog containing this message groupbox.
        @type  parentWidget: PM_Dialog

        @param title: The title on the collapse button
        @type  title: str
        """

        PM_GroupBox.__init__(self, parentWidget, title)

        self.vBoxLayout.setMargin(0)
        self.vBoxLayout.setSpacing(0)

        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)


        self.MessageTextEdit = PM_TextEdit(self,
                                           label='',
                                           spanWidth = True,
                                           addToParent = False,
                                           ##cursorPosition = 'beginning'
                                       )
            # We pass addToParent = False to suppress the usual call by
            # PM_TextEdit.__init__ of self.addPmWidget(new textedit widget),
            # since we need to add it to self in a different way (below).
            # [bruce 071103 refactored this from what used to be a special case
            #  in PM_TextEdit.__init__ based on self being an instance of
            #  PM_MessageGroupBox.]

        # Needed for Intel MacOS. Otherwise, the horizontal scrollbar
        # is displayed in the MessageGroupBox. Mark 2007-05-24.
        # Shouldn't be needed with _setHeight() in PM_TextEdit.

        #Note 2008-06-17: We now permit a vertical scrollbar in message groupbox
        #--Ninad

        self.MessageTextEdit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        # Add self.MessageTextEdit to self's vBoxLayout.
        self.vBoxLayout.addWidget(self.MessageTextEdit)
        # We should be calling the PM's getMessageTextEditPalette() method,
        # but that will take some extra work which I will do soon. Mark 2007-06-21
        self.MessageTextEdit.setPalette(getPalette( None,
                                                    QPalette.Base,
                                                    pmMessageBoxColor))
        self.MessageTextEdit.setReadOnly(True)
        #@self.MessageTextEdit.labelWidget = None # Never has one. Mark 2007-05-31
        self._widgetList.append(self.MessageTextEdit)
        self._rowCount += 1


        # wrapWrapMode seems to be set to QTextOption.WrapAnywhere on MacOS,
        # so let's force it here. Mark 2007-05-22.
        self.MessageTextEdit.setWordWrapMode(QTextOption.WordWrap)

        parentWidget.MessageTextEdit = self.MessageTextEdit

        # These two policies very important. Mark 2007-05-22
        self.setSizePolicy(
            QSizePolicy(QSizePolicy.Policy(QSizePolicy.Preferred),
                        QSizePolicy.Policy(QSizePolicy.Fixed)))

        self.MessageTextEdit.setSizePolicy(
            QSizePolicy(QSizePolicy.Policy(QSizePolicy.Preferred),
                        QSizePolicy.Policy(QSizePolicy.Fixed)))

        self.setWhatsThis("""<b>Messages</b>
                          <p>This prompts the user for a requisite operation and/or displays
helpful messages to the user.</p>""")

        # Hide until insertHtmlMessage() loads a message.
        self.hide()
class DnaStrand_PropertyManager( DnaOrCnt_PropertyManager):
    """
    The DnaStrand_PropertyManager class provides a Property Manager
    for the DnaStrand_EditCommand.

    @ivar title: The title that appears in the property manager header.
    @type title: str

    @ivar pmName: The name of this property manager. This is used to set
                  the name of the PM_Dialog object via setObjectName().
    @type name: str

    @ivar iconPath: The relative path to the PNG file that contains a
                    22 x 22 icon image that appears in the PM header.
    @type iconPath: str
    """

    title         =  "DnaStrand Properties"
    iconPath      =  "ui/actions/Properties Manager/Strand.png"

    def __init__( self, command ):
        """
        Constructor for the Build DNA property manager.
        """

        self.sequenceEditor = None

        self._numberOfBases = 0
        self._conformation = 'B-DNA'
        self.dnaModel = 'PAM3'

        _superclass.__init__( self, command)

        self.showTopRowButtons( PM_DONE_BUTTON | \
                                PM_WHATS_THIS_BUTTON)
        return

    def _addGroupBoxes( self ):
        """
        Add group boxes to this PM.
        """

        self._pmGroupBox1 = PM_GroupBox( self, title = "Parameters" )
        self._loadGroupBox1( self._pmGroupBox1 )
        self._displayOptionsGroupBox = PM_GroupBox( self,
                                                    title = "Display Options" )
        self._loadDisplayOptionsGroupBox( self._displayOptionsGroupBox )

        #Sequence Editor. This is NOT a groupbox, needs cleanup. Doing it here
        #so that the sequence editor gets connected! Perhaps
        #superclass should define _loadAdditionalWidgets. -- Ninad2008-10-03
        self._loadSequenceEditor()
        return

    def _loadGroupBox1(self, pmGroupBox):
        """
        Load widgets in group box 1.
        """

        self.nameLineEdit = PM_LineEdit( pmGroupBox,
                         label         =  "Name:",
                         text          =  "",
                         setAsDefault  =  False)

        self.numberOfBasesSpinBox = \
            PM_SpinBox( pmGroupBox,
                        label         =  "Number of bases:",
                        value         =  self._numberOfBases,
                        setAsDefault  =  False,
                        minimum       =  2,
                        maximum       =  10000 )

        self.disableStructHighlightingCheckbox = \
            PM_CheckBox( pmGroupBox,
                         text         = "Don't highlight while editing DNA",
                         widgetColumn  = 0,
                         state        = Qt.Unchecked,
                         setAsDefault = True,
                         spanWidth = True
                         )

        #As of 2008-03-31, the properties such as number of bases will be
        #editable only by using the resize handles.
        self.numberOfBasesSpinBox.setEnabled(False)
        return

    def _loadSequenceEditor(self):
        """
        Temporary code  that shows the Sequence editor ..a doc widget docked
        at the bottom of the mainwindow. The implementation is going to change
        before 'rattleSnake' product release.
        As of 2007-11-20: This feature (sequence editor) is waiting
        for the ongoing dna model work to complete.
        """
        self.sequenceEditor = self.win.createDnaSequenceEditorIfNeeded()
        self.sequenceEditor.hide()
        return

    def _loadDisplayOptionsGroupBox(self, pmGroupBox):
        """
        Overrides superclass method.
        Also loads the color chooser widget.
        """
        self._loadColorChooser(pmGroupBox)
        _superclass._loadDisplayOptionsGroupBox(self, pmGroupBox)
        return

    def _connect_showCursorTextCheckBox(self):
        """
        Connect the show cursor text checkbox with user prefs_key.
        Overrides
        DnaOrCnt_PropertyManager._connect_showCursorTextCheckBox
        """
        connect_checkbox_with_boolean_pref(
            self.showCursorTextCheckBox ,
            dnaStrandEditCommand_showCursorTextCheckBox_prefs_key)
        return


    def _params_for_creating_cursorTextCheckBoxes(self):
        """
        Returns params needed to create various cursor text checkboxes connected
        to prefs_keys  that allow custom cursor texts.
        @return: A list containing tuples in the following format:
                ('checkBoxTextString' , preference_key). PM_PrefsCheckBoxes
                uses this data to create checkboxes with the the given names and
                connects them to the provided preference keys. (Note that
                PM_PrefsCheckBoxes puts thes within a GroupBox)
        @rtype: list
        @see: PM_PrefsCheckBoxes
        @see: self._loadDisplayOptionsGroupBox where this list is used.
        @see: Superclass method which is overridden here --
        DnaOrCnt_PropertyManager._params_for_creating_cursorTextCheckBoxes()
        """
        params = \
               [  #Format: (" checkbox text", prefs_key)
                  ("Number of bases",
                   dnaStrandEditCommand_cursorTextCheckBox_numberOfBases_prefs_key),

                  ("Number of bases to be changed",
                   dnaStrandEditCommand_cursorTextCheckBox_changedBases_prefs_key)
                 ]

        return params


    def getParameters(self):
        name = self.nameLineEdit.text()
        numberOfBases = self.numberOfBasesSpinBox.value()
        dnaForm  = self._conformation
        dnaModel = self.dnaModel
        color = self._colorChooser.getColor()

        return (numberOfBases,
                dnaForm,
                dnaModel,
                color,
                name
                )

    def setParameters(self, params):
        """
        This is usually called when you are editing an existing structure.
        It also gets called when selecting a new strand (within this command).
        Some property manager ui elements then display the information
        obtained from the object being edited.
        TODO:
        - Make this a EditCommand_PM API method?
        - See also the routines GraphicsMode.setParams or object.setProps
        ..better to name them all in one style?
        """
        numberOfBases, \
            dnaForm, \
            dnaModel, \
            color, \
            name = params

        if numberOfBases is not None:
            self.numberOfBasesSpinBox.setValue(numberOfBases)
        if dnaForm is not None:
            self._conformation = dnaForm
        if dnaModel is not None:
            self.dnaModel = dnaModel

        if color is not None:
            self._colorChooser.setColor(color)

        if name:  # Minimal test. Should add a validator. --Mark 2008-12-16
            self.nameLineEdit.setText(name)

        # This gets called when we enter the command *and* when selecting a new
        # strand. In either case, we must update the sequence in the sequenece
        # editor. Fixes bug 2951. --Mark 2008-12-16
        if self.command and self.command.hasValidStructure():
            #print "setParameters(): loading sequence in sequence editor for ", name
            self.updateSequence(strand = self.command.struct)
        return

    def connect_or_disconnect_signals(self, isConnect):
        """
        Connect or disconnect widget signals sent to their slot methods.
        This can be overridden in subclasses. By default it does nothing.
        @param isConnect: If True the widget will send the signals to the slot
                          method.
        @type  isConnect: boolean
        """
        #TODO: This is a temporary fix for a bug. When you invoke a temporary
        # mode Entering such a temporary mode keeps the signals of
        #PM from the previous mode connected (
        #but while exiting that temporary mode and reentering the
        #previous mode, it atucally reconnects the signal! This gives rise to
        #lots  of bugs. This needs more general fix in Temporary mode API.
        # -- Ninad 2008-01-09 (similar comment exists in MovePropertyManager.py

        if isConnect and self.isAlreadyConnected:
            if debug_flags.atom_debug:
                print_compact_stack("warning: attempt to connect widgets"\
                                    "in this PM that are already connected." )
            return

        if not isConnect and self.isAlreadyDisconnected:
            if debug_flags.atom_debug:
                print_compact_stack("warning: attempt to disconnect widgets"\
                                    "in this PM that are already disconnected.")
            return

        self.isAlreadyConnected = isConnect
        self.isAlreadyDisconnected = not isConnect

        if isConnect:
            change_connect = self.win.connect
        else:
            change_connect = self.win.disconnect


        if self.sequenceEditor:
            self.sequenceEditor.connect_or_disconnect_signals(isConnect)

        _superclass.connect_or_disconnect_signals(self, isConnect)


        change_connect(self.disableStructHighlightingCheckbox,
                       SIGNAL('stateChanged(int)'),
                       self.change_struct_highlightPolicy)

        change_connect(self.showCursorTextCheckBox,
                       SIGNAL('stateChanged(int)'),
                       self._update_state_of_cursorTextGroupBox)

        change_connect(self.nameLineEdit,
                       SIGNAL("editingFinished()"),
                       self._nameChanged)
        return

    def _update_UI_do_updates(self):
        """
        @see: Command_PropertyManager. _update_UI_do_updates()
        @see: DnaStrand_EditCommand.command_update_UI()
        @see: DnaStrand_EditCommand.hasResizableStructure()
        """
        if not self.command.hasValidStructure():
            print "DnaStrand not a valid structure."
            self._pmGroupBox1.setEnabled(False)
            self._displayOptionsGroupBox.setEnabled(False)
            self.sequenceEditor.updateSequence(strand = " ")
            self.sequenceEditor.setEnabled(False)
            self.nameLineEdit.setText("")
            self.numberOfBasesSpinBox.setValue(0)
            return
        else:
            self._pmGroupBox1.setEnabled(True)
            self._displayOptionsGroupBox.setEnabled(True)
            self.sequenceEditor.setEnabled(True)

        isStructResizable, why_not = self.command.hasResizableStructure()
        if not isStructResizable:
            #disable all widgets
            if self._pmGroupBox1.isEnabled():
                self._pmGroupBox1.setEnabled(False)
                msg1 = ("Attention: ") % (self.command.struct.name)
                msg2 = redmsg("DnaStrand <b>%s</b> is not resizable. Reason: %s" % \
                              (self.command.struct.name, why_not))
                self.updateMessage(msg1 + msg2)
        else:
            if not self._pmGroupBox1.isEnabled():
                self._pmGroupBox1.setEnabled(True)
            msg1 = ("Editing <b>%s</b>. ") % (self.command.struct.name)
            msg2 = "Use resize handles to resize the strand. "\
                 "Use the <i>Sequence Editor</i> to edit the sequence."
            self.updateMessage(msg1 + msg2)
        return

    def close(self):
        """
        Close this property manager.
        Also sets the name of the self.command's structure to the one
        displayed in the line edit field.
        @see self.show()
        @see: DnaSegment_EditCommand.setStructureName
        """
        if self.command is not None:
            name = str(self.nameLineEdit.text())
            self.command.setStructureName(name)

        if self.sequenceEditor:
            self.sequenceEditor.close()

        _superclass.close(self)
        return

    def updateSequence(self, strand = None):
        """
        Public method provided for convenience. If any callers outside of this
        command need to update the sequence in the sequence editor, they can simply
        do DnaStrand_ProprtyManager.updateSequence() rather than
        DnaStrand_ProprtyManager.sequenceEditor.updateSequence()
        @see: Ui_DnaSequenceEditor.updateSequence()
        """
        if self.sequenceEditor:
            self.sequenceEditor.updateSequence(strand = strand)
        return

    def change_struct_highlightPolicy(self,checkedState = False):
        """
        Change the 'highlight policy' of the structure being edited
        (i.e. self.command.struct) .
        @param checkedState: The checked state of the checkbox that says
                             'Don't highlight while editing DNA'. So, it
                             its True, the structure being edited won't get
                             highlighted.
        @see: DnaStrand.setHighlightPolicy for more comments
        """
        if self.command and self.command.hasValidStructure():
            highlight = not checkedState
            self.command.struct.setHighlightPolicy(highlight = highlight)
        return

    def _addWhatsThisText(self):
        """
        Add what's this text.
        Abstract method.
        """
        pass

    def _nameChanged(self): # Added by Mark. 2008-12-16
        """
        Slot for "Name" field. Changes the name of the strand if the user types
        in a new name.

        @warning: this lacks a validator. User can type in a name with invalid
                  characters.
        """
        if not self.command.hasValidStructure():
            return

        name = str(self.nameLineEdit.text())

        if not name: # Minimal test. Should add a validator. Ask Bruce for example validator code somewhere. --Mark 2008-12-16
            if self.command.hasValidStructure():
                self.nameLineEdit.setText(self.command.getStructureName())

            return

        self.command.setStructureName(name)

        self._update_UI_do_updates() # Updates the message box.

        return