Пример #1
0
class TracebackWidget(QWidget):
    """
    Represents a python traceback
    """
    def __init__(self, traceback_msg):
        QWidget.__init__(self)
        vbox = QVBoxLayout(self)
        self._editor = QPlainTextEdit()
        vbox.addWidget(QLabel(translations.TR_TRACEBACK))
        vbox.addWidget(self._editor)
        self._editor.setReadOnly(True)
        self._editor.setLineWrapMode(0)
        self._editor.insertPlainText(traceback_msg)
        self._editor.selectAll()
Пример #2
0
class TracebackWidget(QWidget):
    """
    Represents a python traceback
    """

    def __init__(self, traceback_msg):
        QWidget.__init__(self)
        vbox = QVBoxLayout(self)
        self._editor = QPlainTextEdit()
        vbox.addWidget(QLabel(translations.TR_TRACEBACK))
        vbox.addWidget(self._editor)
        self._editor.setReadOnly(True)
        self._editor.setLineWrapMode(0)
        self._editor.insertPlainText(traceback_msg)
        self._editor.selectAll()
Пример #3
0
class TagHelpViewer( QWidget ):
    """ The tag help viewer widget """

    def __init__( self, parent = None ):
        QWidget.__init__( self, parent )

        self.__isEmpty = True
        self.__copyAvailable = False
        self.__clearButton = None
        self.__textEdit = None
        self.__header = None
        self.__copyButton = None
        self.__selectAllButton = None
        self.__createLayout( parent )

        # create the context menu
        self.__menu = QMenu( self )
        self.__selectAllMenuItem = self.__menu.addAction(
                            PixmapCache().getIcon( 'selectall.png' ),
                            'Select All', self.__textEdit.selectAll )
        self.__copyMenuItem = self.__menu.addAction(
                            PixmapCache().getIcon( 'copytoclipboard.png' ),
                            'Copy', self.__textEdit.copy )
        self.__menu.addSeparator()
        self.__clearMenuItem = self.__menu.addAction(
                            PixmapCache().getIcon( 'trash.png' ),
                            'Clear', self.__clear )

        self.__textEdit.setContextMenuPolicy( Qt.CustomContextMenu )
        self.__textEdit.customContextMenuRequested.connect(
                                                self.__handleShowContextMenu )
        self.__textEdit.copyAvailable.connect( self.__onCopyAvailable )

        self.__updateToolbarButtons()
        return

    def __createLayout( self, parent ):
        " Helper to create the viewer layout "

        # __textEdit list area
        self.__textEdit = QPlainTextEdit( parent )
        self.__textEdit.setLineWrapMode( QPlainTextEdit.NoWrap )
        self.__textEdit.setFont( QFont( GlobalData().skin.baseMonoFontFace ) )
        self.__textEdit.setReadOnly( True )

        # Default font size is good enough for most of the systems.
        # 12.0 might be good only in case of the XServer on PC (Xming).
        # self.__textEdit.setFontPointSize( 12.0 )

        # Buttons
        self.__selectAllButton = QAction(
            PixmapCache().getIcon( 'selectall.png' ),
            'Select all', self )
        self.__selectAllButton.triggered.connect(self.__textEdit.selectAll )
        self.__copyButton = QAction(
            PixmapCache().getIcon( 'copytoclipboard.png' ),
            'Copy to clipboard', self )
        self.__copyButton.triggered.connect( self.__textEdit.copy )
        spacer = QWidget()
        spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding )
        self.__clearButton = QAction(
            PixmapCache().getIcon( 'trash.png' ),
            'Clear all', self )
        self.__clearButton.triggered.connect( self.__clear )

        # Toolbar
        toolbar = QToolBar()
        toolbar.setOrientation( Qt.Vertical )
        toolbar.setMovable( False )
        toolbar.setAllowedAreas( Qt.LeftToolBarArea )
        toolbar.setIconSize( QSize( 16, 16 ) )
        toolbar.setFixedWidth( 28 )
        toolbar.setContentsMargins( 0, 0, 0, 0 )
        toolbar.addAction( self.__selectAllButton )
        toolbar.addAction( self.__copyButton )
        toolbar.addWidget( spacer )
        toolbar.addAction( self.__clearButton )

        self.__header = QLabel( "Signature: none" )
        self.__header.setFrameStyle( QFrame.StyledPanel )
        self.__header.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Fixed )
        self.__header.setAutoFillBackground( True )
        headerPalette = self.__header.palette()
        headerBackground = headerPalette.color( QPalette.Background )
        headerBackground.setRgb( min( headerBackground.red() + 30, 255 ),
                                 min( headerBackground.green() + 30, 255 ),
                                 min( headerBackground.blue() + 30, 255 ) )
        headerPalette.setColor( QPalette.Background, headerBackground )
        self.__header.setPalette( headerPalette )
        verticalLayout = QVBoxLayout()
        verticalLayout.setContentsMargins( 2, 2, 2, 2 )
        verticalLayout.setSpacing( 2 )
        verticalLayout.addWidget( self.__header )
        verticalLayout.addWidget( self.__textEdit )

        # layout
        layout = QHBoxLayout()
        layout.setContentsMargins( 0, 0, 0, 0 )
        layout.setSpacing( 0 )
        layout.addWidget( toolbar )
        layout.addLayout( verticalLayout )

        self.setLayout( layout )
        return

    def __handleShowContextMenu( self, coord ):
        """ Show the context menu """

        self.__selectAllMenuItem.setEnabled( not self.__isEmpty )
        self.__copyMenuItem.setEnabled( self.__copyAvailable )
        self.__clearMenuItem.setEnabled( not self.__isEmpty )

        self.__menu.popup( QCursor.pos() )
        return

    def __calltipDisplayable( self, calltip ):
        " True if calltip is displayable "
        if calltip is None:
            return False
        if calltip.strip() == "":
            return False
        return True

    def __docstringDisplayable( self, docstring ):
        " True if docstring is displayable "
        if docstring is None:
            return False
        if isinstance( docstring, dict ):
            if docstring[ "docstring" ].strip() == "":
                return False
            return True
        if docstring.strip() == "":
            return False
        return True

    def display( self, calltip, docstring ):
        " Displays the given help information "

        calltipDisplayable = self.__calltipDisplayable( calltip )
        docstringDisplayable = self.__docstringDisplayable( docstring )
        self.__isEmpty = True
        if calltipDisplayable or docstringDisplayable:
            self.__isEmpty = False

        if calltipDisplayable:
            if '\n' in calltip:
                calltip = calltip.split( '\n' )[ 0 ]
            self.__header.setText( "Signature: " + calltip.strip() )
        else:
            self.__header.setText( "Signature: n/a" )

        self.__textEdit.clear()
        if docstringDisplayable:
            if isinstance( docstring, dict ):
                docstring = docstring[ "docstring" ]
            self.__textEdit.insertPlainText( docstring )

        self.__updateToolbarButtons()
        QApplication.processEvents()
        return

    def __updateToolbarButtons( self ):
        " Contextually updates toolbar buttons "

        self.__selectAllButton.setEnabled( not self.__isEmpty )
        self.__copyButton.setEnabled( self.__copyAvailable )
        self.__clearButton.setEnabled( not self.__isEmpty )
        return

    def __clear( self ):
        " Triggers when the clear function is selected "
        self.__isEmpty = True
        self.__copyAvailable = False
        self.__header.setText( "Signature: none" )
        self.__textEdit.clear()
        self.__updateToolbarButtons()
        return

    def __onCopyAvailable( self, isAvailable ):
        " Triggers on the copyAvailable signal "
        self.__copyAvailable = isAvailable
        self.__updateToolbarButtons()
        return
Пример #4
0
class BluetoothWindow(QMainWindow):

    def __init__(self, inbuf, outbuf,parent=None):

        super(BluetoothWindow, self).__init__(parent)

        self.sendbuf=outbuf
        self.receivebuf=inbuf
        
        self.output=QPlainTextEdit()

        self.output.setReadOnly(True)
        self.output.setLineWrapMode(QPlainTextEdit.WidgetWidth)
        
        self.hor = QHBoxLayout()
        self.ver = QVBoxLayout()
        
        def updateValue(key, value):
            pidvalues[key] = float(value)
            print key, "updated to", value
        
        for k, v in pidvalues.iteritems():
            label = QLabel(k)
            edit = QLineEdit(str(v))
            button = QPushButton("Update")
            l = QHBoxLayout()
            l.addWidget(label, 2)
            l.addWidget(edit, 5)
            l.addWidget(button, 2)
            self.ver.addLayout(l)   
            button.clicked.connect(lambda clicked, label=label, edit=edit: updateValue(label.text(), edit.text()))        
        
        self.hor.addWidget(self.output)
        self.hor.addLayout(self.ver)
        
        w = QWidget()
        w.setLayout(self.hor)
        self.setCentralWidget(w)
        
        SampleTimeInSec = (pidvalues["PID_SAMPLE_TIME"]) / 1000.0
        
        for i in range(4):
          pid_params.append(pid_params_typedef())
        
        pid_params[pidvalues["PID_THROTTLE"]].kp = pidvalues["KP_THROTTLE"];
        pid_params[pidvalues["PID_THROTTLE"]].ki = pidvalues["KI_THROTTLE"] * SampleTimeInSec;
        pid_params[pidvalues["PID_THROTTLE"]].kd = pidvalues["KD_THROTTLE"] / SampleTimeInSec;
        pid_params[pidvalues["PID_THROTTLE"]].min = pidvalues["MIN_THROTTLE"];
        pid_params[pidvalues["PID_THROTTLE"]].max = pidvalues["MAX_THROTTLE"];

        pid_params[pidvalues["PID_PITCH"]].kp = pidvalues["KP_PITCH"];
        pid_params[pidvalues["PID_PITCH"]].ki = pidvalues["KI_PITCH"] * SampleTimeInSec; 
        pid_params[pidvalues["PID_PITCH"]].kd = pidvalues["KD_PITCH"] / SampleTimeInSec;
        pid_params[pidvalues["PID_PITCH"]].min = pidvalues["MIN_PITCH"];
        pid_params[pidvalues["PID_PITCH"]].max = pidvalues["MAX_PITCH"];

        pid_params[pidvalues["PID_ROLL"]].kp = pidvalues["KP_ROLL"];
        pid_params[pidvalues["PID_ROLL"]].ki = pidvalues["KI_ROLL"] * SampleTimeInSec;
        pid_params[pidvalues["PID_ROLL"]].kd = pidvalues["KD_ROLL"] / SampleTimeInSec;
        pid_params[pidvalues["PID_ROLL"]].min = pidvalues["MIN_ROLL"];
        pid_params[pidvalues["PID_ROLL"]].max = pidvalues["MAX_ROLL"];
        
        pid_params[pidvalues["PID_YAW"]].kp = pidvalues["KP_YAW"];
        pid_params[pidvalues["PID_YAW"]].ki = pidvalues["KI_YAW"] * SampleTimeInSec;
        pid_params[pidvalues["PID_YAW"]].kd = pidvalues["KD_YAW"] / SampleTimeInSec;
        pid_params[pidvalues["PID_YAW"]].min = pidvalues["MIN_YAW"];
        pid_params[pidvalues["PID_YAW"]].max = pidvalues["MAX_YAW"];

        for i in pid_params:
           print i              
 
    def receiveText(self):
          
#        | 2-5   | Roll    | [-pi, pi]   |
#        | 6-9   | Pitch   | [-pi, pi]   |
#        | 10-13 | Yaw     | [-pi, pi]   |
#        | 14-17 | Height  | [0, 10m]  |
#        | 18-21 | Battery | [0, 100%] |
        
        rolldata=""
        pitchdata=""
        yawdata=""
        heightdata=""
        batterydata=""
        
        for i in range(4):
            rolldata+=self.receivebuf.pop(0)
        
        for i in range(4):
            pitchdata+=self.receivebuf.pop(0)
        
        for i in range(4):
            yawdata+=self.receivebuf.pop(0)
        
        for i in range(4):
            heightdata+=self.receivebuf.pop(0)
        
        for i in range(4):
            batterydata+=self.receivebuf.pop(0)
        
        roll=struct.unpack('f', rolldata)
        pitch=struct.unpack('f', pitchdata)
        yaw=struct.unpack('f', yawdata)
        
        self.output.appendPlainText("p "+str(pitch[0])+", r "+str(roll[0])+", y "+str(yaw[0]))
        
        ## pids 
        data.pitch = pitch[0]
        data.roll = roll[0]
        data.yaw = yaw[0]
                
        global lastThrottle
                
        pid_output.throttle = self.pid_compute(pidvalues["PID_THROTTLE"], lastThrottle, command.throttle);
        pid_output.pitch = self.pid_compute(pidvalues["PID_PITCH"], data.pitch, command.pitch);
        pid_output.roll = self.pid_compute(pidvalues["PID_ROLL"], data.roll, command.roll);
        pid_output.yaw = self.pid_compute(pidvalues["PID_YAW"], data.yaw, command.yaw);
        
        #Save last throttle value
        lastThrottle = pid_output.throttle * 2 * ( pidvalues["MAX_THROTTLE"] / MOTOR_SPEED_MAX) - pidvalues["MIN_THROTTLE"];
    

        #Add offset to throttle
        pid_output.throttle += MOTOR_SPEED_HALF;
        
        self.motors_pid_apply()
                
        ## update gui
        self.repaint()   

    def motor_name(self, motor):
        if (motor == MOTOR_RIGHT_BACK):
            return "RIGHT__BACK"
        elif (motor == MOTOR_LEFT_BACK):
            return "LEFT___BACK"
        elif (motor == MOTOR_RIGHT_FRONT):
            return "RIGHT_FRONT"
        elif (motor == MOTOR_LEFT_FRONT):
            return "LEFT__FRONT"
        else:
            return "UNKNOWN"

    def motors_set_speed(self, motor, value):
        self.output.appendPlainText("motor "+str(self.motor_name(motor))+", value "+str(int(value)))
        

    def motors_pid_apply(self):
      self.motors_set_speed(MOTOR_RIGHT_FRONT, pid_output.throttle - pid_output.pitch - pid_output.roll - pid_output.yaw);
      self.motors_set_speed(MOTOR_LEFT_FRONT, pid_output.throttle - pid_output.pitch + pid_output.roll + pid_output.yaw);
      self.motors_set_speed(MOTOR_RIGHT_BACK, pid_output.throttle + pid_output.pitch - pid_output.roll + pid_output.yaw);
      self.motors_set_speed(MOTOR_LEFT_BACK, pid_output.throttle + pid_output.pitch + pid_output.roll - pid_output.yaw);
                
                
    def pid_compute(self, index, input, setpoint):
     
      pid = pid_params[index]
      retVal = 0

      #Compute all the working error variables*/
      error = setpoint - input;
      pid.iterm += pid.ki * error;
      if (pid.iterm > pid.max) :
        pid.iterm = pid.max;
      else:
        if (pid.iterm < pid.min):
          pid.iterm = pid.min;
          
      dInput = (input - pid.lastInput);

      #Compute PID Output*/
      retVal = (pid.kp * error + pid.iterm - pid.kd * dInput);
      if (retVal > pid.max):
        retVal = pid.max;
      else:
         if (retVal < pid.min):
           retVal = pid.min;

      #Remember some variables for next time*/
      pid.lastInput = input;
      pid_params[index] = pid
      return retVal        
      
    def reset(self):
        self.output.clear()
Пример #5
0
class LogViewer(QWidget):
    """ The log (+stdout, +stderr) viewer widget """
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.__isEmpty = True
        self.__copyAvailable = False
        self.clearButton = None
        self.messages = None
        self.copyButton = None
        self.selectAllButton = None
        self.__createLayout(parent)

        # create the context menu
        self.__menu = QMenu(self)
        self.__selectAllMenuItem = self.__menu.addAction(
            PixmapCache().getIcon('selectall.png'), 'Select All',
            self.messages.selectAll)
        self.__copyMenuItem = self.__menu.addAction(
            PixmapCache().getIcon('copytoclipboard.png'), 'Copy',
            self.messages.copy)
        self.__menu.addSeparator()
        self.__clearMenuItem = self.__menu.addAction(
            PixmapCache().getIcon('trash.png'), 'Clear', self.__clear)

        self.messages.setContextMenuPolicy(Qt.CustomContextMenu)
        self.messages.customContextMenuRequested.connect(
            self.__handleShowContextMenu)
        self.messages.copyAvailable.connect(self.__onCopyAvailable)

        self.cNormalFormat = self.messages.currentCharFormat()
        self.cErrorFormat = self.messages.currentCharFormat()
        self.cErrorFormat.setForeground(QBrush(QColor(Qt.red)))
        self.__updateToolbarButtons()
        return

    def __createLayout(self, parent):
        " Helper to create the viewer layout "

        # Messages list area
        self.messages = QPlainTextEdit(parent)
        self.messages.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.messages.setFont(QFont(GlobalData().skin.baseMonoFontFace))
        self.messages.setReadOnly(True)
        self.messages.setMaximumBlockCount(MAX_LINES)

        # Default font size is good enough for most of the systems.
        # 12.0 might be good only in case of the XServer on PC (Xming).
        # self.messages.setFontPointSize( 12.0 )

        # Buttons
        self.selectAllButton = QAction(PixmapCache().getIcon('selectall.png'),
                                       'Select all', self)
        self.selectAllButton.triggered.connect(self.messages.selectAll)
        self.copyButton = QAction(PixmapCache().getIcon('copytoclipboard.png'),
                                  'Copy to clipboard', self)
        self.copyButton.triggered.connect(self.messages.copy)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.clearButton = QAction(PixmapCache().getIcon('trash.png'),
                                   'Clear all', self)
        self.clearButton.triggered.connect(self.__clear)

        # Toolbar
        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.LeftToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.selectAllButton)
        self.toolbar.addAction(self.copyButton)
        self.toolbar.addWidget(spacer)
        self.toolbar.addAction(self.clearButton)

        # layout
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self.toolbar)
        layout.addWidget(self.messages)

        self.setLayout(layout)
        return

    def __handleShowContextMenu(self, coord):
        """ Show the context menu """

        self.__selectAllMenuItem.setEnabled(not self.__isEmpty)
        self.__copyMenuItem.setEnabled(self.__copyAvailable)
        self.__clearMenuItem.setEnabled(not self.__isEmpty)

        self.__menu.popup(QCursor.pos())
        return

    def __appendText(self, txt, isError):
        " Append the text "

        if len(txt) == 0:
            return

        self.__isEmpty = False
        cursor = self.messages.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.messages.setTextCursor(cursor)
        if isError:
            self.messages.setCurrentCharFormat(self.cErrorFormat)
        else:
            self.messages.setCurrentCharFormat(self.cNormalFormat)
        self.messages.insertPlainText(txt)
        self.messages.insertPlainText('\n')
        self.messages.ensureCursorVisible()
        self.__updateToolbarButtons()
        return

    def appendMessage(self, txt):
        " Append the regular message "

        self.__appendText(txt, False)
        #QApplication.processEvents()
        return

    def appendError(self, txt):
        " Append the error message "

        self.__appendText(txt, True)
        #QApplication.processEvents()
        return

    def append(self, txt):
        " Decides what the message is - error or not - and append it then "

        if txt.startswith( 'CRITICAL' ) or \
           txt.startswith( 'ERROR' ) or \
           txt.startswith( 'WARNING' ):
            self.appendError(txt)
        else:
            self.appendMessage(txt)
        return

    def __updateToolbarButtons(self):
        " Contextually updates toolbar buttons "

        self.selectAllButton.setEnabled(not self.__isEmpty)
        self.copyButton.setEnabled(self.__copyAvailable)
        self.clearButton.setEnabled(not self.__isEmpty)
        return

    def __clear(self):
        " Triggers when the clear function is selected "
        self.__isEmpty = True
        self.__copyAvailable = False
        self.messages.clear()
        self.__updateToolbarButtons()
        return

    def __onCopyAvailable(self, isAvailable):
        " Triggers on the copyAvailable signal "
        self.__copyAvailable = isAvailable
        self.__updateToolbarButtons()
        return

    def getText(self):
        " Provides the content as a plain text "
        return self.messages.toPlainText()
Пример #6
0
class LogViewer( QWidget ):
    """ The log (+stdout, +stderr) viewer widget """

    def __init__( self, parent = None ):
        QWidget.__init__( self, parent )

        self.__isEmpty = True
        self.__copyAvailable = False
        self.clearButton = None
        self.messages = None
        self.copyButton = None
        self.selectAllButton = None
        self.__createLayout( parent )

        # create the context menu
        self.__menu = QMenu( self )
        self.__selectAllMenuItem = self.__menu.addAction(
                            PixmapCache().getIcon( 'selectall.png' ),
                            'Select All', self.messages.selectAll )
        self.__copyMenuItem = self.__menu.addAction(
                            PixmapCache().getIcon( 'copytoclipboard.png' ),
                            'Copy', self.messages.copy )
        self.__menu.addSeparator()
        self.__clearMenuItem = self.__menu.addAction(
                            PixmapCache().getIcon( 'trash.png' ),
                            'Clear', self.__clear )

        self.messages.setContextMenuPolicy( Qt.CustomContextMenu )
        self.messages.customContextMenuRequested.connect(
                                                self.__handleShowContextMenu )
        self.messages.copyAvailable.connect( self.__onCopyAvailable )

        self.cNormalFormat = self.messages.currentCharFormat()
        self.cErrorFormat = self.messages.currentCharFormat()
        self.cErrorFormat.setForeground( QBrush( QColor( Qt.red ) ) )
        self.__updateToolbarButtons()
        return

    def __createLayout( self, parent ):
        " Helper to create the viewer layout "

        # Messages list area
        self.messages = QPlainTextEdit( parent )
        self.messages.setLineWrapMode( QPlainTextEdit.NoWrap )
        self.messages.setFont( QFont( GlobalData().skin.baseMonoFontFace ) )
        self.messages.setReadOnly( True )
        self.messages.setMaximumBlockCount( MAX_LINES )

        # Default font size is good enough for most of the systems.
        # 12.0 might be good only in case of the XServer on PC (Xming).
        # self.messages.setFontPointSize( 12.0 )

        # Buttons
        self.selectAllButton = QAction(
            PixmapCache().getIcon( 'selectall.png' ),
            'Select all', self )
        self.selectAllButton.triggered.connect( self.messages.selectAll )
        self.copyButton = QAction(
            PixmapCache().getIcon( 'copytoclipboard.png' ),
            'Copy to clipboard', self )
        self.copyButton.triggered.connect( self.messages.copy )
        spacer = QWidget()
        spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding )
        self.clearButton = QAction(
            PixmapCache().getIcon( 'trash.png' ),
            'Clear all', self )
        self.clearButton.triggered.connect( self.__clear )

        # Toolbar
        self.toolbar = QToolBar()
        self.toolbar.setOrientation( Qt.Vertical )
        self.toolbar.setMovable( False )
        self.toolbar.setAllowedAreas( Qt.LeftToolBarArea )
        self.toolbar.setIconSize( QSize( 16, 16 ) )
        self.toolbar.setFixedWidth( 28 )
        self.toolbar.setContentsMargins( 0, 0, 0, 0 )
        self.toolbar.addAction( self.selectAllButton )
        self.toolbar.addAction( self.copyButton )
        self.toolbar.addWidget( spacer )
        self.toolbar.addAction( self.clearButton )

        # layout
        layout = QHBoxLayout()
        layout.setContentsMargins( 0, 0, 0, 0 )
        layout.setSpacing( 0 )
        layout.addWidget( self.toolbar )
        layout.addWidget( self.messages )

        self.setLayout( layout )
        return

    def __handleShowContextMenu( self, coord ):
        """ Show the context menu """

        self.__selectAllMenuItem.setEnabled( not self.__isEmpty )
        self.__copyMenuItem.setEnabled( self.__copyAvailable )
        self.__clearMenuItem.setEnabled( not self.__isEmpty )

        self.__menu.popup( QCursor.pos() )
        return

    def __appendText( self, txt, isError ):
        " Append the text "

        if len( txt ) == 0:
            return

        self.__isEmpty = False
        cursor = self.messages.textCursor()
        cursor.movePosition( QTextCursor.End )
        self.messages.setTextCursor( cursor )
        if isError:
            self.messages.setCurrentCharFormat( self.cErrorFormat )
        else:
            self.messages.setCurrentCharFormat( self.cNormalFormat )
        self.messages.insertPlainText( txt )
        self.messages.insertPlainText( '\n' )
        self.messages.ensureCursorVisible()
        self.__updateToolbarButtons()
        return

    def appendMessage( self, txt ):
        " Append the regular message "

        self.__appendText( txt, False )
        #QApplication.processEvents()
        return

    def appendError( self, txt ):
        " Append the error message "

        self.__appendText( txt, True )
        #QApplication.processEvents()
        return

    def append( self, txt ):
        " Decides what the message is - error or not - and append it then "

        if txt.startswith( 'CRITICAL' ) or \
           txt.startswith( 'ERROR' ) or \
           txt.startswith( 'WARNING' ):
            self.appendError( txt )
        else:
            self.appendMessage( txt )
        return

    def __updateToolbarButtons( self ):
        " Contextually updates toolbar buttons "

        self.selectAllButton.setEnabled( not self.__isEmpty )
        self.copyButton.setEnabled( self.__copyAvailable )
        self.clearButton.setEnabled( not self.__isEmpty )
        return

    def __clear( self ):
        " Triggers when the clear function is selected "
        self.__isEmpty = True
        self.__copyAvailable = False
        self.messages.clear()
        self.__updateToolbarButtons()
        return

    def __onCopyAvailable( self, isAvailable ):
        " Triggers on the copyAvailable signal "
        self.__copyAvailable = isAvailable
        self.__updateToolbarButtons()
        return

    def getText( self ):
        " Provides the content as a plain text "
        return self.messages.toPlainText()
Пример #7
0
class TagHelpViewer(QWidget):
    """ The tag help viewer widget """
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.__isEmpty = True
        self.__copyAvailable = False
        self.__clearButton = None
        self.__textEdit = None
        self.__header = None
        self.__copyButton = None
        self.__selectAllButton = None
        self.__createLayout(parent)

        # create the context menu
        self.__menu = QMenu(self)
        self.__selectAllMenuItem = self.__menu.addAction(
            PixmapCache().getIcon('selectall.png'), 'Select All',
            self.__textEdit.selectAll)
        self.__copyMenuItem = self.__menu.addAction(
            PixmapCache().getIcon('copytoclipboard.png'), 'Copy',
            self.__textEdit.copy)
        self.__menu.addSeparator()
        self.__clearMenuItem = self.__menu.addAction(
            PixmapCache().getIcon('trash.png'), 'Clear', self.__clear)

        self.__textEdit.setContextMenuPolicy(Qt.CustomContextMenu)
        self.__textEdit.customContextMenuRequested.connect(
            self.__handleShowContextMenu)
        self.__textEdit.copyAvailable.connect(self.__onCopyAvailable)

        self.__updateToolbarButtons()
        return

    def __createLayout(self, parent):
        " Helper to create the viewer layout "

        # __textEdit list area
        self.__textEdit = QPlainTextEdit(parent)
        self.__textEdit.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.__textEdit.setFont(QFont(GlobalData().skin.baseMonoFontFace))
        self.__textEdit.setReadOnly(True)

        # Default font size is good enough for most of the systems.
        # 12.0 might be good only in case of the XServer on PC (Xming).
        # self.__textEdit.setFontPointSize( 12.0 )

        # Buttons
        self.__selectAllButton = QAction(
            PixmapCache().getIcon('selectall.png'), 'Select all', self)
        self.__selectAllButton.triggered.connect(self.__textEdit.selectAll)
        self.__copyButton = QAction(
            PixmapCache().getIcon('copytoclipboard.png'), 'Copy to clipboard',
            self)
        self.__copyButton.triggered.connect(self.__textEdit.copy)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.__clearButton = QAction(PixmapCache().getIcon('trash.png'),
                                     'Clear all', self)
        self.__clearButton.triggered.connect(self.__clear)

        # Toolbar
        toolbar = QToolBar()
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.LeftToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(28)
        toolbar.setContentsMargins(0, 0, 0, 0)
        toolbar.addAction(self.__selectAllButton)
        toolbar.addAction(self.__copyButton)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.__clearButton)

        self.__header = QLabel("Signature: none")
        self.__header.setFrameStyle(QFrame.StyledPanel)
        self.__header.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        self.__header.setAutoFillBackground(True)
        headerPalette = self.__header.palette()
        headerBackground = headerPalette.color(QPalette.Background)
        headerBackground.setRgb(min(headerBackground.red() + 30, 255),
                                min(headerBackground.green() + 30, 255),
                                min(headerBackground.blue() + 30, 255))
        headerPalette.setColor(QPalette.Background, headerBackground)
        self.__header.setPalette(headerPalette)
        verticalLayout = QVBoxLayout()
        verticalLayout.setContentsMargins(2, 2, 2, 2)
        verticalLayout.setSpacing(2)
        verticalLayout.addWidget(self.__header)
        verticalLayout.addWidget(self.__textEdit)

        # layout
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(toolbar)
        layout.addLayout(verticalLayout)

        self.setLayout(layout)
        return

    def __handleShowContextMenu(self, coord):
        """ Show the context menu """

        self.__selectAllMenuItem.setEnabled(not self.__isEmpty)
        self.__copyMenuItem.setEnabled(self.__copyAvailable)
        self.__clearMenuItem.setEnabled(not self.__isEmpty)

        self.__menu.popup(QCursor.pos())
        return

    def __calltipDisplayable(self, calltip):
        " True if calltip is displayable "
        if calltip is None:
            return False
        if calltip.strip() == "":
            return False
        return True

    def __docstringDisplayable(self, docstring):
        " True if docstring is displayable "
        if docstring is None:
            return False
        if isinstance(docstring, dict):
            if docstring["docstring"].strip() == "":
                return False
            return True
        if docstring.strip() == "":
            return False
        return True

    def display(self, calltip, docstring):
        " Displays the given help information "

        calltipDisplayable = self.__calltipDisplayable(calltip)
        docstringDisplayable = self.__docstringDisplayable(docstring)
        self.__isEmpty = True
        if calltipDisplayable or docstringDisplayable:
            self.__isEmpty = False

        if calltipDisplayable:
            if '\n' in calltip:
                calltip = calltip.split('\n')[0]
            self.__header.setText("Signature: " + calltip.strip())
        else:
            self.__header.setText("Signature: n/a")

        self.__textEdit.clear()
        if docstringDisplayable:
            if isinstance(docstring, dict):
                docstring = docstring["docstring"]
            self.__textEdit.insertPlainText(docstring)

        self.__updateToolbarButtons()
        QApplication.processEvents()
        return

    def __updateToolbarButtons(self):
        " Contextually updates toolbar buttons "

        self.__selectAllButton.setEnabled(not self.__isEmpty)
        self.__copyButton.setEnabled(self.__copyAvailable)
        self.__clearButton.setEnabled(not self.__isEmpty)
        return

    def __clear(self):
        " Triggers when the clear function is selected "
        self.__isEmpty = True
        self.__copyAvailable = False
        self.__header.setText("Signature: none")
        self.__textEdit.clear()
        self.__updateToolbarButtons()
        return

    def __onCopyAvailable(self, isAvailable):
        " Triggers on the copyAvailable signal "
        self.__copyAvailable = isAvailable
        self.__updateToolbarButtons()
        return