Example #1
0
 def on_actionShow_logfiles_triggered(self):
     self._item.setText(3, '')
     try:
         loglines = self._client.getServiceLogs(self._service,
                                                self._instance)
     except ClientError as err:
         self._item.setText(3, str(err))
         return
     if not loglines:
         self._item.setText(3, 'Service does not return logs')
         return
     dlg = QDialog(self)
     loadUi(dlg, 'details.ui')
     dlg.tabber.clear()
     logs = []
     for logline in loglines:
         filename, content = logline.split(':', 1)
         if not logs or filename != logs[-1][0]:
             logs.append((filename, []))
         logs[-1][1].append(content)
     for filename, content in logs:
         widget = QPlainTextEdit(dlg)
         font = widget.font()
         font.setFamily('Monospace')
         widget.setFont(font)
         widget.setPlainText(''.join(content))
         dlg.tabber.addTab(widget, filename)
     dlg.exec_()
Example #2
0
    def setFont(self, font):
        pass # suppress dockstring for non-public method
        """Set font and update tab stop width
        """
        QPlainTextEdit.setFont(self, font)
        self._updateTabStopWidth()

        # text on line numbers may overlap, if font is bigger, than code font
        self._lineNumberArea.setFont(font)
class ConfigFile(object):
    def __init__(self, display_name, absolute_name, tab, deletable=True):
        self.display_name   = display_name # is unique
        self.absolute_name  = absolute_name # is also unique
        self.tab            = tab
        self.deletable      = deletable
        self.index          = -1
        self.modified       = False
        self.content        = None
        self.edit           = QPlainTextEdit()

        font = QFont('monospace')
        font.setStyleHint(QFont.TypeWriter)

        self.edit.setWordWrapMode(QTextOption.NoWrap)
        self.edit.setFont(font)
        self.edit.textChanged.connect(self.check_content)

    def check_content(self):
        self.set_modified(self.content != self.edit.toPlainText())

    def set_modified(self, modified):
        if self.modified == modified:
            return

        self.modified = modified

        self.tab.combo_config.setItemText(self.index, self.get_combo_item())
        self.tab.update_ui_state()

    def set_content(self, content):
        # FIXME: QPlainTextEdit does not preserve the original line endings, but
        #        converts all line endings to \n. this results in a difference
        #        between self.content and the content stored in the QPlainTextEdit
        #        even if the user did not edit the content. avoid this problem
        #        by converting all line endings to \n before setting the content
        #        of the QPlainTextEdit
        content = content.replace('\r\n', '\n')

        if self.content == None:
            self.edit.setPlainText(content)

        self.content = content

        self.check_content()

    def get_combo_item(self):
        if self.modified:
            return self.display_name + ' (modified)'
        else:
            return self.display_name

    def discard_changes(self):
        self.edit.setPlainText(self.content)
        self.set_modified(False)
Example #4
0
    def __init__(self, settings, name, filename, plain_text=False, parent=None):
        super().__init__(parent=parent)
        splitty = QSplitter(self)
        self.setWidget(splitty)
        self.setWindowTitle(os.path.basename(name))
        self.setFloating(True)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.plain_text = plain_text
        self.notePath = settings.notePath

        fh = QFile(filename)
        try:
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(fh.errorString())
        except IOError as e:
            QMessageBox.warning(self, self.tr("Read Error"),
                                self.tr("Failed to open %s: %s") % (filename, e))
        finally:
            if fh is not None:
                noteBody = QTextStream(fh).readAll()
                fh.close()
                self.tocw = TocTree(self)
                splitty.addWidget(self.tocw)

                strip_math_for_header_parsing = False
                strip_fence_for_header_parsing = False

                self.tocw.itemClicked.connect(self.tocNavigate)
                if 'asciimathml' in settings.extensions:
                    stuff=JSCRIPT_TPL.format(settings.mathjax)
                    strip_math_for_header_parsing = True
                else:
                    stuff=''
                if 'fenced_code' in settings.extensions or 'extra' in settings.extensions:
                    strip_fence_for_header_parsing = True
                if plain_text:
                    note_view = QPlainTextEdit(self)
                    qfnt = QFont()
                    qfnt.setFamily('monospace')
                    note_view.setFont(qfnt)
                    note_view.setPlainText(noteBody)
                else:
                    note_view = QWebView(self)
                    note_view.setHtml(settings.md.reset().convert(noteBody)+stuff)
                    note_view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
                    note_view.linkClicked.connect(self.linkClicked)
                    note_view.settings().setUserStyleSheetUrl( 
                     QUrl('file://'+self.parent().settings.cssfile))
                self.note_view = note_view
                splitty.addWidget(note_view)
                self.tocw.updateToc(os.path.basename(name), 
                    parseHeaders(noteBody, strip_fenced_block=strip_fence_for_header_parsing,
                        strip_ascii_math=strip_math_for_header_parsing))
class SystemLog(object):
    def __init__(self, display_name, source_name):
        self.display_name   = display_name
        self.source_name    = source_name # FIXME: need to handle rotated logs
        self.last_filename  = os.path.join(get_home_path(), display_name)
        self.content        = ''
        self.edit           = QPlainTextEdit()
        self.normal_font    = self.edit.font()
        self.monospace_font = QFont('monospace')

        self.edit.setUndoRedoEnabled(False)
        self.edit.setReadOnly(True)
        self.edit.setWordWrapMode(QTextOption.NoWrap)
        self.edit.setPlainText('Click "Refresh" to download {0}.'.format(display_name))

        self.monospace_font.setStyleHint(QFont.TypeWriter)

    def log(self, message, bold=False, pre=False):
        if bold:
            self.edit.appendHtml(u'<b>{0}</b>'.format(Qt.escape(message)))
        elif pre:
            self.edit.appendHtml(u'<pre>{0}</pre>'.format(message))
        else:
            self.edit.appendPlainText(message)

    def reset(self):
        self.content = None

        self.edit.setPlainText('')
        self.edit.setFont(self.normal_font)

    def set_content(self, content):
        self.content = content

        self.edit.setPlainText('')
        self.edit.setFont(self.monospace_font)
        self.edit.setPlainText(content)
Example #6
0
class Ui_Form (QWidget):
    '''
    Ui class. Generated with pyuic4.
    '''
    def __init__ (self, parent=None):
        
        QWidget.__init__(self, parent)
        self.timer = QTimer (self)
        
        self.image    = QImage (720, 450, QImage.Format_RGB888)
        
        self.__engine = REngineThread ()
        self.__model  = Model ()
        self.__fsm    = DebugStateMachine (self)
    
        
    def wireEngineUp (self):
        '''
        this method connects the REngine's signals.
        '''
        self.connect (self.__engine, SIGNAL ("update (float)"), self.updateImage)
        self.connect (self.__engine, SIGNAL ("thread_completed()"), self.__fsm.finaliseRender)
        self.connect (self.__engine, SIGNAL ("inters_created (PyQt_PyObject, PyQt_PyObject)"), self.widget.addIntersection)
        self.connect (self.__engine, SIGNAL ("vector_created (PyQt_PyObject, PyQt_PyObject, QString)"), self.widget.addArrow)
        self.connect (self.__engine, SIGNAL ("line_created   (PyQt_PyObject, PyQt_PyObject, QString)"), self.widget.addLine)
    
    def wireOGLViewerUp (self):
        '''
        this method connects the REngine's signals.
        '''
        self.widget.setModel (self.__model)
        
        QObject.connect (self.widget, SIGNAL ("MatrixChanged (PyQt_PyObject)"), self.displayGLMatrix)

        # call the function run regularly when the focus is on it. (60 FPS if interval = 20)
        QObject.connect (self.timer, SIGNAL ('timeout()'), self.widget.run)
    
    def freezeGLFrameRate (self):
        
        self.timer.stop ()
    
    def speedUpGLFrameRate (self):
        
        self.timer.start ()
        self.timer.setInterval (20)
        
    def setupUi (self, Form):
        
        font = QFont ()
        font.setPointSize (9)
        font.setBold (False)
        font.setWeight (50)
        
        sizePolicy = QSizePolicy (QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch (0)
        sizePolicy.setVerticalStretch (0)
        
        Form.setObjectName (_fromUtf8("Form"))
        Form.resize (971, 930)
        self.plainTextEdit = QPlainTextEdit (Form)
        self.plainTextEdit.setGeometry (QRect (740, 280, 221, 611))
        self.plainTextEdit.setObjectName (_fromUtf8 ("plainTextEdit"))
        self.plainTextEdit.setFont (font)
        
        self.widget = OGLViewer (Form)
        self.widget.setUi_Form (self)
        self.widget.setGeometry (QRect (10, 10, 720, 450))
        sizePolicy.setHeightForWidth (self.widget.sizePolicy().hasHeightForWidth())
        self.widget.setSizePolicy (sizePolicy)
        self.widget.setObjectName (_fromUtf8 ("widget"))
        
        self.wireOGLViewerUp ()
        self.wireEngineUp ()
        
        self.label_view = QLabel (Form)
        self.label_view.setGeometry  (QRect (10, 470, 720, 450))
        sizePolicy.setHeightForWidth (self.label_view.sizePolicy().hasHeightForWidth())
        self.label_view.setSizePolicy (sizePolicy)
        self.label_view.setObjectName (_fromUtf8 ("label_view"))
        self.initLabel ()          
        self.pixmap_item = self.label_view.setPixmap (QPixmap.fromImage (self.image))
        
        # buttons definitions
        
        self.renderBtn    = QPushButton (Form)
        self.pauseBtn     = QPushButton (Form)
        self.stopBtn      = QPushButton (Form)
        self.upBtn        = QPushButton (Form)
        self.downBtn      = QPushButton (Form)
        self.moreDownBtn  = QPushButton (Form)
        self.moreUpBtn    = QPushButton (Form)
        self.rightBtn     = QPushButton (Form)
        self.moreRightBtn = QPushButton (Form)
        self.leftBtn      = QPushButton (Form)
        self.furtherLeft  = QPushButton (Form)
        self.grid_switch  = QPushButton (Form)
        
        buttons_properties_list = [[self.renderBtn,    True,  QRect (740, 140, 61, 21), "render"],
                                   [self.pauseBtn,     False, QRect (740, 120, 61, 21), "pause"],
                                   [self.stopBtn,      False, QRect (740, 100, 61, 21), "stop"],
                                   [self.upBtn,        False, QRect (820, 120, 21, 21), "one_row_up"],
                                   [self.downBtn,      False, QRect (820, 140, 21, 21), "one_row_down"],
                                   [self.moreDownBtn,  False, QRect (820, 160, 21, 21), "ten_rows_down"],
                                   [self.moreUpBtn,    False, QRect (820, 100, 21, 21), "ten_rows_up"],
                                   [self.rightBtn,     False, QRect (780, 180, 21, 21), "one_column_right"],
                                   [self.moreRightBtn, False, QRect (800, 180, 21, 21), "ten_columns_right"],
                                   [self.leftBtn,      False, QRect (760, 180, 21, 21), "one_column_left"],
                                   [self.furtherLeft,  False, QRect (740, 180, 21, 21), "ten_columns_left"],
                                   [self.grid_switch,  False, QRect (870, 230, 91, 31), "grid_switch"]]
        
        for button in buttons_properties_list:
            button[0].setEnabled  (button[1])
            button[0].setGeometry (button[2])
            button[0].setFont (font)
            button[0].setObjectName (_fromUtf8 (button[3]))
        
        # other UI elements
        
        self.progressBar = QProgressBar (Form)
        self.progressBar.setGeometry (QRect (740, 901, 221, 20))
        self.progressBar.setProperty ("value", 0)
        self.progressBar.setObjectName (_fromUtf8("progressBar"))
        self.progressBar.setMinimum (0)
        self.progressBar.setMaximum (100)
        
        self.slider_label = QLabel (Form)
        self.slider_label.setGeometry (QRect(900, 260, 61, 16))
        self.slider_label.setFont(font)
        self.slider_label.setObjectName (_fromUtf8("slider_label"))
        self.slider_label.setEnabled (True)
        
        self.arrowSizeSlider = QSlider (Form)
        self.arrowSizeSlider.setGeometry (QRect (740, 258, 151, 22))
        self.arrowSizeSlider.setMinimum (2)
        self.arrowSizeSlider.setMaximum (40)
        self.arrowSizeSlider.setSingleStep (1)
        self.arrowSizeSlider.setProperty ("value", 4)
        self.arrowSizeSlider.setOrientation (Qt.Horizontal)
        self.arrowSizeSlider.setObjectName  (_fromUtf8("arrowSizeSlider"))

        self.retranslateUi (Form)
        QMetaObject.connectSlotsByName (Form)
    
    def retranslateUi (self, Form):
        
        Form.setWindowTitle       (_translate ("Form", "RayTracing Debugging Tool", None))
        
        self.renderBtn.setText    (_translate ("Form", "Render", None))
        self.pauseBtn.setText     (_translate ("Form", "Pause",  None))
        self.stopBtn.setText      (_translate ("Form", "Stop",   None))
        self.upBtn.setText        (_translate ("Form", "^",      None))
        self.downBtn.setText      (_translate ("Form", "v",      None))
        self.moreDownBtn.setText  (_translate ("Form", "+",      None))
        self.moreUpBtn.setText    (_translate ("Form", "-",      None))
        self.rightBtn.setText     (_translate ("Form", ">",      None))
        self.moreRightBtn.setText (_translate ("Form", "+",      None))
        self.leftBtn.setText      (_translate ("Form", "<",      None))
        self.furtherLeft.setText  (_translate ("Form", "-",      None))
        
        self.grid_switch.setText  (_translate ("Form", "Grid on/off", None))
        self.slider_label.setText (_translate ("Form", "Arrows size", None))
        
        self.connect (self.renderBtn,       SIGNAL ("clicked()"),        self.__fsm.startRendering)
        self.connect (self.pauseBtn,        SIGNAL ("clicked()"),        self.__fsm.pauseRendering)
        self.connect (self.stopBtn,         SIGNAL ("clicked()"),        self.__fsm.stopRendering)
        self.connect (self.arrowSizeSlider, SIGNAL ("sliderMoved(int)"), self.resizeArrows)
    
    def initLabel (self):
        
        color = QColor (250, 250, 250)
        self.image.fill (color)
        
        '''
        # test init
        for i in range (0, 200, 20):
            for x in range (i, i+20):
                for y in range (i, i+20):
                    self.image.setPixel (x,y, qRgb (0, 0, 0))
        '''
    
    def enableUIButtons (self, boolean_dict):
        '''
        method used by the debug state machine to manage the greyed-out state of buttons.
        '''
        b_dict = dict (boolean_dict)
        
        self.renderBtn.setEnabled    (b_dict['renderBtn'])
        self.pauseBtn.setEnabled     (b_dict['pauseBtn'])
        self.stopBtn.setEnabled      (b_dict['stopBtn'])
        self.upBtn.setEnabled        (b_dict['upBtn'])
        self.downBtn.setEnabled      (b_dict['downBtn'])
        self.moreDownBtn.setEnabled  (b_dict['moreDownBtn'])
        self.moreUpBtn.setEnabled    (b_dict['moreUpBtn'])
        self.rightBtn.setEnabled     (b_dict['rightBtn'])
        self.moreRightBtn.setEnabled (b_dict['moreRightBtn'])
        self.leftBtn.setEnabled      (b_dict['leftBtn'])
        self.furtherLeft.setEnabled  (b_dict['furtherLeft'])
        
        if b_dict['progressBar'] == 'completed':
            self.progressBar.setValue (100)
        elif b_dict['progressBar'] == 'reset':
            self.progressBar.reset ()
    
    def addScreenshot (self):
        '''
        it grabs a screenshot of OpenGL viewer and add it into the QImage instance.
        '''
        self.image = self.widget.grabFrameBuffer ()
        self.pixmap_item = self.label_view.setPixmap (QPixmap.fromImage (self.image))
    
    def prepAndStartEngineUp (self):
        '''
        it preps the engine and start it up.
        '''
        self.__engine.setImage (self.image)
        self.__engine.setCameraNormalMatrix (self.widget.getNormalMatrix(), self.widget.getFovy ())
        self.__engine.setModel (self.__model)
        self.__engine.start ()
    
    def addCamera (self): self.widget.addCamera ()
    def setIsStoppedFlag (self, boo):  self.__engine.setIsStoppedFlag (boo)
    def setIsPausedFlag  (self, boo):  self.__engine.setIsPausedFlag  (boo)
    def changeRenderBtnName (self, title):  self.renderBtn.setText (_translate ("Form", title, None))
    
    # listeners  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    def resizeArrows (self, e):
        self.widget.changeArrowsSize (e*0.5)
    def updateImage (self, e):
        self.pixmap_item = self.label_view.setPixmap (QPixmap.fromImage (self.image))
        self.progressBar.setValue (int(100*e))
    def displayGLMatrix (self, e):
        '''
        this method is registered to the MatrixChanged event fired from the OGLViewer
        component. It prints the model matrix. Only for debugging purposes.
        '''
        pass
class CustomCodeFrame(QFrame):
  poke_code = pyqtSignal(str, int, QByteArray) # code_set_label, code_id, new_bytes
  log = pyqtSignal(str, str) # msg, color

  def __init__(self, code_set, parent=None):
    super(CustomCodeFrame, self).__init__(parent)
    self.cs = code_set

    self.tmr_reset_bg_clr = QTimer(self)
    self.tmr_reset_bg_clr.setInterval(500) # ms
    self.tmr_reset_bg_clr.timeout.connect(self.resetBGColor)

    self.txt_label = QLineEdit(self)
    self.txt_label.setMaximumWidth(160)
    self.txt_label.setPlaceholderText('Label')

    self.txt_codes = QPlainTextEdit(self)
    self.txt_codes.setMaximumHeight(66)
    font = QFont('Monospace')
    font.setStyleHint(QFont.TypeWriter)
    self.txt_codes.setFont(font)
    self.txt_codes.cursorPositionChanged.connect(self.resetBGColor)

    icon_height = self.txt_label.height()*8/15

    self.btn_poke = QPushButton(self)
    self.btn_poke.setIcon(QIcon('img/flaticon/draw39.png'))
    self.btn_poke.setIconSize(QSize(icon_height, icon_height))
    self.btn_poke.setFixedSize(QSize(icon_height*1.5, icon_height*1.5))
    self.btn_poke.setAutoFillBackground(True)
    self.btn_poke.setStyleSheet('background-color: white')
    self.btn_poke.setToolTip('Poke memory')
    self.btn_poke.clicked.connect(self.onPoke)

    self.layout = QHBoxLayout(self)
    self.layout.addWidget(self.txt_label)
    self.layout.setAlignment(self.txt_label, Qt.AlignTop)
    self.layout.addWidget(self.txt_codes)
    self.layout.setAlignment(self.txt_codes, Qt.AlignTop)
    self.layout.addWidget(self.btn_poke)
    self.layout.setAlignment(self.btn_poke, Qt.AlignTop)
    self.layout.setContentsMargins(0, 2, 0, 2)

  def setAlternateBGColor(self):
    self.setStyleSheet('CustomCodeFrame { background-color:rgb(248,248,248) }')

  def setErrorBGColor(self):
    self.txt_codes.setStyleSheet('background-color: rgb(255,128,128)')
    self.tmr_reset_bg_clr.start()

  def resetBGColor(self):
    if self.tmr_reset_bg_clr.isActive():
      self.tmr_reset_bg_clr.stop()
      self.txt_codes.setStyleSheet('background-color: white')

  @pyqtSlot()
  def onPoke(self):
    try:
      parse_custom_codes(self.cs, str(self.txt_codes.toPlainText()))
    except SyntaxError, e:
      self.log.emit(str(e), 'red')
      self.setErrorBGColor()
      return

    if len(self.cs.c) <= 0:
      self.log.emit('POKE failed: no codes found', 'red')
      self.setErrorBGColor()
      return

    # Sequentially poke codes
    for code in self.cs.c:
      raw_bytes = struct.pack('>Q', code.dft_value)[-code.num_bytes:]
      self.poke_code.emit(code.label, code.id, QByteArray(raw_bytes))
Example #8
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
Example #9
0
class CommandWindow(QFrame):
    """Miow main window
    """

    def __init__(self, parent=None):
        super(CommandWindow, self).__init__(parent)
        self.parent = parent
        self.setWindowFlags(QtCore.Qt.Popup)

        self.setFont(QFont("Monospace", 14))
        self.setMinimumWidth(400)
        self.setMinimumHeight(300)
        self.setGeometry(0, 0, 600, 300)


        # create widgets
        layout = QVBoxLayout(self)
        
        self.line_edit = QLineEdit(self)
        layout.addWidget(self.line_edit)

        self.list_widget = QListWidget(self)
        self.list_widget.currentItemChanged.connect(self.on_current_item_changed)
        layout.addWidget(self.list_widget)
        layout.setStretchFactor(self.list_widget, 15)

        layout.setMargin(0)
        layout.setSpacing(0)
        layout.setContentsMargins(0,0,0,0)
        self.setLayout(layout)
        self.line_edit.setFocus()

        self.full_command = QPlainTextEdit(self)
        self.full_command.setFont(QFont("Monospace", 8))
        size_policy = self.full_command.sizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Ignored)
        self.full_command.setSizePolicy(size_policy)
        layout.addWidget(self.full_command)
        layout.setStretchFactor(self.full_command, 3)


        layout2 = QHBoxLayout(self)
        
        self.weight = QLabel(self)
        self.weight.setFont(QFont("Monospace", 8))
        size_policy = self.weight.sizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Ignored)
        self.weight.setSizePolicy(size_policy)
        layout2.addWidget(self.weight)
        layout2.setStretchFactor(self.weight, 1)

        self.labels = QLabel(self)
        self.labels.setFont(QFont("Monospace", 8))
        size_policy = self.labels.sizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Ignored)
        self.labels.setSizePolicy(size_policy)
        layout2.addWidget(self.labels)
        layout2.setStretchFactor(self.labels, 8)

        layout.addLayout(layout2)
        layout.setStretchFactor(layout2, 1)
        
        self.line_edit.textChanged.connect(self.on_text_changed)
        self.list_widget.itemDoubleClicked.connect(self.on_item_double_clicked)

        self.event_selected_command = Event()
        


    def show_hide(self, context):
        if self.isVisible() == False or context is not None:        
            self.command_list = self.parent.get_command_list(context)
            self.filter_commands("")
            self.show()
        else:
            self.hide()

    def showEvent(self, event):
        geom = self.frameGeometry()
        self.line_edit.setFocus()
        self.line_edit.clear()
        #parent_widget = self.parentWidget()
        if self.parent:
            geom.moveCenter(QtCore.QPoint(self.parent.pos().x()+self.parent.width()/2,
                                          self.parent.pos().y()+self.parent.height()/3))
            self.setGeometry(geom)
            super(QFrame, self).showEvent(event)

    def _get_command_from_text(self, text):
        for command_text, tags, weight, command in self.command_list:
            if command_text == text:
                return command
        return None

    def _get_full_command_from_text(self, text):
        for command_text, tags, weight, command in self.command_list:
            if command_text == text:
                return (command_text, tags, weight, command)
        return None
        
    def keyPressEvent(self, event):
        if event.type() == QEvent.KeyPress:
            key_event = QKeyEvent(event)
            if(key_event.key() == Qt.Key_Down
              or key_event.key() == Qt.Key_Up):
                return self.list_widget.keyPressEvent(event)
            elif((event.key() == Qt.Key_Enter  or  event.key() == Qt.Key_Return)
                    and self.list_widget.currentItem()>=0):
                self.hide()
                self.event_selected_command(str(self.full_command.toPlainText()))
        return super(CommandWindow, self).keyPressEvent(event)

    def on_item_double_clicked(self, item):
        self.hide()
        self.event_selected_command(str(self.full_command.toPlainText()))


    def on_current_item_changed(self, prev, current):
        if(self.list_widget.currentItem()):
            command_text, tags, weight, command = self._get_full_command_from_text(
                                        self.list_widget.currentItem().text())
            self.full_command.setPlainText(command)
            self.labels.setText(tags)
            self.weight.setText(str(weight))
        else:
            self.full_command.setPlainText("")
            self.labels.setText("")
            self.weight.setText("")


    def filter_commands(self, text):
        self.list_widget.clear()
        text = str(text).upper()

        def get_item_map_def0(_map, key):
            if(key in _map):
                return _map[key]
            else:
                return 0.

        def get_command_matches(command_list, words):
            result_map = {}
            for command, tags, _, _ in command_list:
                for word in words:
                    located_command_weight = 1
                    located_tag_weight = 0.3
                    if word == '':
                        located_command_weight = 0.
                        located_tag_weight = 0.
                    if command.upper().find(word) != -1:
                        result_map[command] = (get_item_map_def0(result_map,
                                                    command)
                                                    - located_command_weight)
                    for tag in tags.split(" "):
                        if tag.upper().find(word) != -1:
                            result_map[command] = (get_item_map_def0(result_map,
                                                    command)
                                                    - located_tag_weight)
            for command, _, current_weight, _ in command_list:
                if command in result_map:
                    result_map[command] -= current_weight
            return sorted(result_map, key=result_map.get)


        words = str(text).strip().split(" ")
        matches_map = get_command_matches(self.command_list, words)
        for command in matches_map:
            self.list_widget.addItem(command)
        self.list_widget.setCurrentRow(0)


    def on_text_changed(self, text):
        self.filter_commands(text)
Example #10
0
class StripWidget(QWidget):
    timer_timeout = 100

    def __init__(self, device,speed=115200,timeout=1,debug=True):
        super(StripWidget,self).__init__()
        self.device  = device
        self.speed   = speed
        self.timeout = timeout
        self.strip       = Strip()
        self.strip.debug = debug
        self.initGUI()
        self.setInputState(False)
        self.setMinimumSize( 600, 400)
        self.timer = None
        QTimer.singleShot( 500, self.initSerial)
        
    def closeEvent(self,e):
        e.accept()
        self.closeSerial()
            
    def initSerial(self):
        if self.strip.isConnected():
            return
        if not self.device:
            self.device = self.strip.findDevice()
        if not self.device:
            self.printLog("No device found")
            return
        self.printLog("Opening '%s'" % self.device)
        if not self.strip.connect(self.device, self.speed, self.timeout):
            sys.exit(1)
        self.printLog("Opened  '%s' with speed %i" %
                      (self.device, self.strip.baudrate()))
        
        retries = 10
        while retries > 0:
            if self.strip.pingDevice():
                break
            retries -= 1
            QApplication.processEvents()
            time.sleep(1)
        else:
            print "Error connecting to device"
            sys.exit(1)
        self.printLog("Device is READY")
        self.setInputState(True)
        self.timer = self.startTimer(self.timer_timeout)
        self.updateConfig(True)
        
    def closeSerial(self):
        if self.strip.isConnected():
            self.setInputState(False)
            if self.timer:
                self.killTimer(self.timer)
            self.printLog("Disconnecting")
            self.strip.disconnect()
    
    def reconnect(self):
        self.closeSerial()
        self.initSerial()
        
    def printLog(self, s):
        if not s.endswith("\n"): s+="\n"
        self.log.moveCursor( QTextCursor.End)
        self.log.insertPlainText(s)
        self.log.moveCursor( QTextCursor.End)
        self.log.ensureCursorVisible()
    
    def initGUI(self):
        self.inputs = []
        layout = QHBoxLayout()
        
        textLayout = QVBoxLayout()
        self.log = QPlainTextEdit()
        f = QFont("Monospace")
        f.setStyleHint(QFont.TypeWriter)
        self.log.setFont(f)
        self.log.setReadOnly(True)
        textLayout.addWidget( self.log)
        self.input = QLineEdit()
        self.input.returnPressed.connect(self.sendSerial)
        self.setFocusProxy( self.input)
        textLayout.addWidget(self.input)
        self.inputs += [self.input]
        layout.addLayout( textLayout)
 
        buttonLayout = QVBoxLayout()
        p = QPushButton("Reconnect")
        p.clicked.connect(self.reconnect)
        buttonLayout.addWidget(p)
        p = QPushButton("Rainbow")
        p.clicked.connect(
            lambda: self.strip.write( bytearray( [MAGIC,Command.RAINBOW] )))
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("Test")
        p.clicked.connect(
            lambda: self.strip.write( bytearray( [MAGIC,Command.TEST] )))
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("Blank")
        p.clicked.connect(
            lambda: self.strip.write( bytearray( [MAGIC,Command.BLANK] )))
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("UniColor")
        p.clicked.connect( self.openUnicolor )
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("LED State")
        p.clicked.connect( self.getLEDState)
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("Conf")
        p.clicked.connect( lambda: self.updateConfig(True))
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("Debug")
        p.clicked.connect( self.strip.toggleDebug)
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("Reset")
        p.clicked.connect(
            lambda: self.strip.write( bytearray( [MAGIC,Command.RESET] )))
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("Set Size")
        p.clicked.connect( self.setSize)
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("Speed Test")
        p.clicked.connect( self.speedTest)
        buttonLayout.addWidget(p)
        self.inputs += [p]
        p = QPushButton("Free Mem")
        p.clicked.connect( self.freeMemory)
        buttonLayout.addWidget(p)
        self.inputs += [p]
        buttonLayout.addStretch(1)
        p = QPushButton("Quit")
        p.clicked.connect( self.close)
        buttonLayout.addWidget(p)
        layout.addLayout(buttonLayout)
       
        self.setLayout(layout)

    def setInputState(self,state):
        for i in self.inputs:
            i.setEnabled(state)
        if state: self.input.setFocus()
        
    def updateConfig(self, printConfig):
        self.killTimer( self.timer)
        if not self.strip.updateConfig():
            self.printLog( "Error retrieving config: " + str(self.strip.config))
        else:
            if printConfig:
                self.printLog( "Config: " + str(self.strip.config))
        self.timer = self.startTimer( self.timer_timeout)
        
    def speedTest(self):
        self.killTimer(self.timer)
        msg = self.strip.speedTest()
        if not len(msg):
            self.printLog("Error testing serial speed")
        else:
            self.printLog(msg)
        self.timer = self.startTimer(self.timer_timeout)
        
    def sendSerial(self):
        if not len(self.input.text()): return
        try:
            c = [ int(s,16) for s in str(self.input.text()).split(" ") ]
            s = bytearray( c)
            self.printLog( "Sending %s\n" % repr([hex(i) for i in s]))
            self.strip.write(s)
            self.input.selectAll()
        except ValueError:
            self.printLog( "Invalid input")
        
    def tryReadSerial(self,printData=True):
        try:
            s = self.strip.tryReadSerial()
            if printData and len(s):
                self.printLog(s)
        except:
            self.killTimer(self.timer)
            self.setInputState(False)
        
    def timerEvent(self,e):
        e.accept()
        self.tryReadSerial()

    def openUnicolor(self):
        self.killTimer(self.timer)
        debug = False
        if self.strip.config['debug'] == '1':
            self.strip.toggleDebug()
            debug = True
        d = ColorChooserDialog(self.strip,self)
        d.exec_()
        if debug: self.strip.toggleDebug()
        self.timer = self.startTimer(self.timer_timeout)

    def getLEDState(self):
        self.killTimer(self.timer)
        debug = False
        if self.strip.config['debug'] == '1':
            self.strip.toggleDebug()
            debug = True
        d = LEDDialog(self.strip,self)
        d.exec_()
        if debug: self.strip.toggleDebug()
        self.timer = self.startTimer(self.timer_timeout)

    def setSize(self):
        oldsize = int(self.strip.config['nleds'])
        maxsize = int(self.strip.config['nleds_max'])
        newsize = int(QInputDialog.getInt(
            self, "Set Size", "Enter Size (0-%d):" % maxsize, oldsize,
            0, maxsize)[0])
        self.strip.setSize(newsize)

    def freeMemory(self):
        self.killTimer( self.timer)
        self.printLog(self.strip.freeMemory())
        self.timer = self.startTimer( self.timer_timeout)
Example #11
0
class Ui_MainWindow(object):
	def setupUi(self, MainWindow):
		MainWindow.setObjectName(_fromUtf8("MainWindow"))
		MainWindow.resize(300, 270)
		self.centralwidget = QWidget(MainWindow)
		self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
		self.buttonSave = QPushButton(self.centralwidget)
		self.buttonSave.setGeometry(QRect(120, 235, 71, 32))
		self.buttonSave.setObjectName(_fromUtf8("buttonSave"))
		self.inputFolder = QLineEdit(self.centralwidget)
		self.inputFolder.setGeometry(QRect(130, 10, 131, 23))
		self.inputFolder.setObjectName(_fromUtf8("inputFolder"))
		self.buttonSelectFolder = QToolButton(self.centralwidget)
		self.buttonSelectFolder.setGeometry(QRect(263, 10, 27, 23))
		self.buttonSelectFolder.setToolButtonStyle(Qt.ToolButtonIconOnly)
		self.buttonSelectFolder.setAutoRaise(False)
		self.buttonSelectFolder.setArrowType(Qt.NoArrow)
		self.buttonSelectFolder.setObjectName(_fromUtf8("buttonSelectFolder"))
		self.labelFolder = QLabel(self.centralwidget)
		self.labelFolder.setGeometry(QRect(10, 13, 101, 16))
		self.labelFolder.setObjectName(_fromUtf8("labelFolder"))
		self.inputLogin = QLineEdit(self.centralwidget)
		self.inputLogin.setGeometry(QRect(130, 40, 161, 23))
		self.inputLogin.setObjectName(_fromUtf8("inputLogin"))
		self.inputPassword = QLineEdit(self.centralwidget)
		self.inputPassword.setGeometry(QRect(130, 70, 161, 23))
		self.inputPassword.setObjectName(_fromUtf8("inputPassword"))
		self.labelLogin = QLabel(self.centralwidget)
		self.labelLogin.setGeometry(QRect(10, 42, 62, 16))
		self.labelLogin.setObjectName(_fromUtf8("labelLogin"))
		self.labelPassword = QLabel(self.centralwidget)
		self.labelPassword.setGeometry(QRect(10, 72, 62, 16))
		self.labelPassword.setObjectName(_fromUtf8("labelPassword"))
		self.output = QPlainTextEdit(self.centralwidget)
		self.output.setEnabled(True)
		self.output.setGeometry(QRect(10, 100, 281, 131))
		self.output.viewport().setProperty("cursor", QCursor(Qt.IBeamCursor))
		self.output.setReadOnly(True)
		self.output.setObjectName(_fromUtf8("output"))
		font = QApplication.font()
		font.setPointSize(11)
		self.output.setFont(font)
		MainWindow.setCentralWidget(self.centralwidget)

		self.retranslateUi(MainWindow)
		self.connectSignals()
		QMetaObject.connectSlotsByName(MainWindow)

	def retranslateUi(self, MainWindow):
		MainWindow.setWindowTitle(QApplication.translate("MainWindow", "TDS Dropbox setup", None, QApplication.UnicodeUTF8))
		self.buttonSave.setText(QApplication.translate("MainWindow", "Save", None, QApplication.UnicodeUTF8))
		self.buttonSelectFolder.setText(QApplication.translate("MainWindow", "...", None, QApplication.UnicodeUTF8))
		self.labelFolder.setText(QApplication.translate("MainWindow", "Folder to sync", None, QApplication.UnicodeUTF8))
		self.labelLogin.setText(QApplication.translate("MainWindow", "Login", None, QApplication.UnicodeUTF8))
		self.labelPassword.setText(QApplication.translate("MainWindow", "Password", None, QApplication.UnicodeUTF8))

	def connectSignals(self):
		QObject.connect(self.buttonSelectFolder, SIGNAL("clicked()"), self.selectFolder)
		QObject.connect(self.centralwidget, SIGNAL("folderIsSet(PyQt_PyObject)"), self.setFolder)
		QObject.connect(self.buttonSave, SIGNAL("clicked()"), self.validateData)
		

	def selectFolder(self):
		folder = QFileDialog.getExistingDirectory(self.centralwidget, "Choose folder to sync", os.getenv("HOME"))
		QObject.emit(self.centralwidget, SIGNAL("folderIsSet(PyQt_PyObject)"), folder)

	def setFolder(self, folder):
		self.inputFolder.setText(folder)

	def validateData(self):
		validate = True
		if (len(self.inputFolder.text()) == 0):
			self.error("You haven't choose the dir to sync!")
			validate = False
		if (len(self.inputLogin.text()) == 0):
			self.error("You havent enter the login!")
			validate = False
		if (len(self.inputPassword.text()) == 0):
			self.error("You haven't enter the password!")
			validate = False
		if (validate):
			self.lockGui()
			self.out("setup start")
			self.setupSync({"folder": self.inputFolder.text(), "login": self.inputLogin.text(), "password": self.inputPassword.text()})
			self.unlockGui()

	def lockGui(self):
		self.inputFolder.setReadOnly(True)
		self.inputLogin.setReadOnly(True)
		self.inputPassword.setReadOnly(True)
		self.buttonSave.setDisabled(True)
		self.buttonSelectFolder.setDisabled(True)

	def unlockGui(self):
		self.inputFolder.setReadOnly(False)
		self.inputLogin.setReadOnly(False)
		self.inputPassword.setReadOnly(False)
		self.buttonSave.setDisabled(False)
		self.buttonSelectFolder.setDisabled(False)

	def setupSync(self, data):
		p = Popen(["./letssync.sh", "-u%(login)s" % data, "-p%(password)s" % data, "%(folder)s" % data])
		if (p.wait() != 0):
			self.error("an error occuring during setup!")
		else:
			self.out("setup complete!")

	def error(self, message):
		self.out("ERROR: {}".format(message))

	def out(self, message):
		self.output.appendPlainText("{0} :: {1}".format(datetime.now().strftime("%H:%M"), message))
Example #12
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()
Example #13
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