class Ui_ProteinSequenceEditor(PM_DockWidget):
    """
    The Ui_DnaSequenceEditor class defines UI elements for the Sequence Editor
    object. The sequence editor is usually visible while in DNA edit mode.
    It is a DockWidget that is doced at the bottom of the MainWindow
    """
    _title         =  "Sequence Editor"
    _groupBoxCount = 0
    _lastGroupBox = None

    def __init__(self, win):
        """
        Constructor for the Ui_DnaSequenceEditor 
        @param win: The parentWidget (MainWindow) for the sequence editor 
        """
        
        self.win = win
        # Should parentWidget for a docwidget always be win? 
        #Not necessary but most likely it will be the case.        
        parentWidget = win 
        
        _superclass.__init__(self, parentWidget, title = self._title)
        
        #A flag used to restore the state of the Reports dock widget 
        #(which can be accessed through View  >  Reports) see self.show() and
        #self.closeEvent() for more details. 
        self._reportsDockWidget_closed_in_show_method = False
        self.setFixedHeight(90)

    def show(self):
        """
        Shows the sequence editor. While doing this, it also closes the reports
        dock widget (if visible) the state of the reports dockwidget will be
        restored when the sequence editor is closed. 
        @see:self.closeEvent()
        """
        self._reportsDockWidget_closed_in_show_method = False
        
        if self.win.viewFullScreenAction.isChecked() or \
           self.win.viewSemiFullScreenAction.isChecked():
            pass
        else:
            if self.win.reportsDockWidget.isVisible():
                self.win.reportsDockWidget.close()
                self._reportsDockWidget_closed_in_show_method = True

        _superclass.show(self)  
        
    def closeEvent(self, event):
        """
        Overrides close event. Makes sure that the visible state of the reports
        widgetis restored when the sequence editor is closed. 
        @see: self.show()
        """
        _superclass.closeEvent(self, event)
       
        if self.win.viewFullScreenAction.isChecked() or \
           self.win.viewSemiFullScreenAction.isChecked():
            pass
        else:
            if self._reportsDockWidget_closed_in_show_method:
                self.win.viewReportsAction.setChecked(True) 
                self._reportsDockWidget_closed_in_show_method = False

    def _loadWidgets(self):
        """
        Overrides PM.PM_DockWidget._loadWidgets. Loads the widget in this
        dockwidget.
        """
        self._loadMenuWidgets()
        self._loadTextEditWidget()


    def _loadMenuWidgets(self):
        """
        Load the various menu widgets (e.g. Open, save sequence options, 
        Find and replace widgets etc. 
        """
        #Note: Find and replace widgets might be moved to their own class.

        self.loadSequenceButton = PM_ToolButton(
            self,
            iconPath = "ui/actions/Properties Manager/Open.png")  

        self.saveSequenceButton = PM_ToolButton(
            self, 
            iconPath = "ui/actions/Properties Manager/Save_Strand_Sequence.png") 

        self.loadSequenceButton.setAutoRaise(True)
        self.saveSequenceButton.setAutoRaise(True)

        
        #Find and replace widgets --
        self.findLineEdit = \
            PM_LineEdit( self, 
                         label        = "",
                         spanWidth    = False)
        self.findLineEdit.setMaximumWidth(60)


        self.replaceLineEdit = \
            PM_LineEdit( self, 
                         label        = "",
                         spanWidth    = False)
        self.replaceLineEdit.setMaximumWidth(60)

        self.findOptionsToolButton = PM_ToolButton(self)
        self.findOptionsToolButton.setMaximumWidth(12)
        self.findOptionsToolButton.setAutoRaise(True)

        self.findOptionsToolButton.setPopupMode(QToolButton.MenuButtonPopup)

        self._setFindOptionsToolButtonMenu()

        self.findNextToolButton = PM_ToolButton(
            self,
            iconPath = "ui/actions/Properties Manager/Find_Next.png")
        self.findNextToolButton.setAutoRaise(True)

        self.findPreviousToolButton = PM_ToolButton(
            self,
            iconPath = "ui/actions/Properties Manager/Find_Previous.png")
        self.findPreviousToolButton.setAutoRaise(True)

        self.replacePushButton = PM_PushButton(self, text = "Replace")

        self.warningSign = QLabel(self)
        self.warningSign.setPixmap(
            getpixmap('ui/actions/Properties Manager/Warning.png'))
        self.warningSign.hide()

        self.phraseNotFoundLabel = QLabel(self)
        self.phraseNotFoundLabel.setText("Sequence Not Found")
        self.phraseNotFoundLabel.hide()

        

        #Widgets to include in the widget row. 
        widgetList = [('PM_ToolButton', self.loadSequenceButton, 0),
                      ('PM_ToolButton', self.saveSequenceButton, 1),
                      ('QLabel', "     Find:", 4),
                      ('PM_LineEdit', self.findLineEdit, 5),
                      ('PM_ToolButton', self.findOptionsToolButton, 6),
                      ('PM_ToolButton', self.findPreviousToolButton, 7),
                      ('PM_ToolButton', self.findNextToolButton, 8), 
                      ('QLabel', "     Replace:", 9),
                      ('PM_TextEdit', self.replaceLineEdit, 10), 
                      ('PM_PushButton', self.replacePushButton, 11),
                      ('PM_Label', self.warningSign, 12),
                      ('PM_Label', self.phraseNotFoundLabel, 13),
                      ('QSpacerItem', 5, 5, 14) ]

        widgetRow = PM_WidgetRow(self,
                                 title     = '',
                                 widgetList = widgetList,
                                 label = "",
                                 spanWidth = True )
        
        

    def _loadTextEditWidget(self):
        """
        Load the SequenceTexteditWidgets.         
        """        
        self.aaRulerTextEdit = \
            PM_TextEdit( self, 
                         label = "", 
                         spanWidth = False,
                         permit_enter_keystroke = False) 
        
        palette = getPalette(None, 
                             QPalette.Base, 
                             pmGrpBoxColor)
        self.aaRulerTextEdit.setPalette(palette)     
        self.aaRulerTextEdit.setWordWrapMode( QTextOption.WrapAnywhere )
        self.aaRulerTextEdit.setFixedHeight(20)
        self.aaRulerTextEdit.setReadOnly(True)
        
        self.sequenceTextEdit = \
            PM_TextEdit( self, 
                         label = " Sequence: ", 
                         spanWidth = False,
                         permit_enter_keystroke = False) 
        
        
        self.sequenceTextEdit.setCursorWidth(2)
        self.sequenceTextEdit.setWordWrapMode( QTextOption.WrapAnywhere )
        self.sequenceTextEdit.setFixedHeight(20)
        
        self.secStrucTextEdit = \
            PM_TextEdit( self, 
                         label = " Secondary structure: ", 
                         spanWidth = False,
                         permit_enter_keystroke = False) 
        
        palette = getPalette(None, 
                             QPalette.Base, 
                             sequenceEditStrandMateBaseColor)
        self.secStrucTextEdit.setPalette(palette)     
        self.secStrucTextEdit.setWordWrapMode( QTextOption.WrapAnywhere )
        self.secStrucTextEdit.setFixedHeight(20)
        self.secStrucTextEdit.setReadOnly(True)

        #Important to make sure that the horizontal and vertical scrollbars 
        #for these text edits are never displayed. 
        
        self.sequenceTextEdit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.sequenceTextEdit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.secStrucTextEdit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.secStrucTextEdit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.aaRulerTextEdit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.aaRulerTextEdit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

    def _getFindLineEditStyleSheet(self):
        """
        Return the style sheet for the findLineEdit. This sets the following 
        properties only:
         - background-color

        This style is set whenever the searchStrig can't be found (sets
        a light red color background to the lineedit when this happens)   

        @return: The line edit style sheet.
        @rtype:  str

        """
        styleSheet = \
                   "QLineEdit {\
                   background-color: rgb(255, 102, 102)\
                   }"
        #Not used:
        #  background-color: rgb(217, 255, 216)\       

        return styleSheet

    def _setFindOptionsToolButtonMenu(self):
        """
        Sets the menu for the findOptionstoolbutton that appears a small 
        menu button next to the findLineEdit.
        """
        self.findOptionsMenu = QMenu(self.findOptionsToolButton)

        self.caseSensitiveFindAction = QAction(self.findOptionsToolButton)
        self.caseSensitiveFindAction.setText('Match Case')
        self.caseSensitiveFindAction.setCheckable(True)
        self.caseSensitiveFindAction.setChecked(False)

        self.findOptionsMenu.addAction(self.caseSensitiveFindAction)
        self.findOptionsMenu.addSeparator()

        self.findOptionsToolButton.setMenu(self.findOptionsMenu)

    def _addToolTipText(self):
        """
            What's Tool Tip text for widgets in this Property Manager.  
            """ 
        pass

    def _addWhatsThisText(self):
        """
            What's This text for widgets in this Property Manager.  

            """
        pass
Example #2
0
class PM_MessageGroupBox(PM_GroupBox):
    """
    The PM_MessageGroupBox widget provides a message box with a 
    collapse/expand button and a title.
    """
    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()

    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)

    def insertHtmlMessage(self,
                          text,
                          setAsDefault=False,
                          minLines=4,
                          maxLines=10,
                          replace=True,
                          scrolltoTop=True):
        """
        Insert text (HTML) into the message box. Displays the message box if it is hidden.

        Arguments:

        @param minLines: the minimum number of lines (of text) to display in the TextEdit.
            if <minLines>=0 the TextEdit will fit its own height to fit <text>. The
            default height is 4 (lines of text).
        @type  minLines: int

        @param maxLines: The maximum number of lines to display in the TextEdit widget.
        @type  maxLines: int

        @param replace: should be set to False if you do not wish to replace 
            the current text. It will append <text> instead.
        @type  replace: int

        @note: Displays the message box if it is hidden.
        """
        self.MessageTextEdit.insertHtml(text,
                                        setAsDefault,
                                        minLines=minLines,
                                        maxLines=maxLines,
                                        replace=True)
        if scrolltoTop:
            cursor = self.MessageTextEdit.textCursor()
            cursor.setPosition(0, QTextCursor.MoveAnchor)
            self.MessageTextEdit.setTextCursor(cursor)
            self.MessageTextEdit.ensureCursorVisible()

            ##self.MessageTextEdit.moveCursor(QTextCursor.Start)
            ##self.MessageTextEdit.ensureCursorVisible()
            #text2 = self.MessageTextEdit.toPlainText()
            #print "***PM = %s, len(text) =%s"%(self.parentWidget, len(text))
            #if len(text2) > 16:
            #anchorText = text2[:16]
            #print "***anchorText =", anchorText
            #self.MessageTextEdit.scrollToAnchor(anchorText)
            #self.MessageTextEdit.ensureCursorVisible()

        self.show()
class PM_MessageGroupBox( PM_GroupBox ):
    """
    The PM_MessageGroupBox widget provides a message box with a
    collapse/expand button and a title.
    """

    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()

    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)


    def insertHtmlMessage(self,
                          text,
                          setAsDefault = False,
                          minLines     = 4,
                          maxLines     = 10,
                          replace      = True,
                          scrolltoTop =  True):
        """
        Insert text (HTML) into the message box. Displays the message box if it is hidden.

        Arguments:

        @param minLines: the minimum number of lines (of text) to display in the TextEdit.
            if <minLines>=0 the TextEdit will fit its own height to fit <text>. The
            default height is 4 (lines of text).
        @type  minLines: int

        @param maxLines: The maximum number of lines to display in the TextEdit widget.
        @type  maxLines: int

        @param replace: should be set to False if you do not wish to replace
            the current text. It will append <text> instead.
        @type  replace: int

        @note: Displays the message box if it is hidden.
        """
        self.MessageTextEdit.insertHtml( text,
                                         setAsDefault,
                                         minLines = minLines,
                                         maxLines = maxLines,
                                         replace  = True )
        if scrolltoTop:
            cursor  =  self.MessageTextEdit.textCursor()
            cursor.setPosition( 0,
                                QTextCursor.MoveAnchor )
            self.MessageTextEdit.setTextCursor( cursor )
            self.MessageTextEdit.ensureCursorVisible()

            ##self.MessageTextEdit.moveCursor(QTextCursor.Start)
            ##self.MessageTextEdit.ensureCursorVisible()
            #text2 = self.MessageTextEdit.toPlainText()
            #print "***PM = %s, len(text) =%s"%(self.parentWidget, len(text))
            #if len(text2) > 16:
                #anchorText = text2[:16]
                #print "***anchorText =", anchorText
                #self.MessageTextEdit.scrollToAnchor(anchorText)
                #self.MessageTextEdit.ensureCursorVisible()

        self.show()