Exemplo n.º 1
0
 def addSection(self, section):
     """
     Adds a section to this menu.  A section will create a label for the
     menu to separate sections of the menu out.
     
     :param      section | <str>
     """
     label = QLabel(section, self)
     label.setMinimumHeight(self.titleHeight())
     
     # setup font
     font = label.font()
     font.setBold(True)
     
     # setup palette
     palette = label.palette()
     palette.setColor(palette.WindowText, palette.color(palette.Mid))
     
     # setup label
     label.setFont(font)
     label.setAutoFillBackground(True)
     label.setPalette(palette)
     
     # create the widget action
     action = QWidgetAction(self)
     action.setDefaultWidget(label)
     self.addAction(action)
     
     return action
Exemplo n.º 2
0
    def __createScoreLabel( self, score, previousScore,
                            showFileName, fileName ):
        " Creates the score label "

        txt = "Score: " + str( score )
        if previousScore != "":
            txt += " / Previous score: " + str( previousScore )
        if not showFileName:
            txt += " for " + os.path.basename( fileName )

        scoreLabel = QLabel( txt )
        scoreLabel.setFrameShape( QFrame.StyledPanel )
        scoreLabel.setFont( self.__headerFont )
        scoreLabel.setAutoFillBackground( True )
        palette = scoreLabel.palette()

        if score < self.BadLimit:
            palette.setColor( QPalette.Background, QColor( 255, 127, 127 ) )
            palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) )
        elif score > self.GoodLimit:
            palette.setColor( QPalette.Background, QColor( 220, 255, 220 ) )
            palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) )
        else:
            palette.setColor( QPalette.Background, QColor( 255, 255, 127 ) )
            palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) )

        scoreLabel.setPalette( palette )
        return scoreLabel
Exemplo n.º 3
0
    def __createScoreLabel(self, score, previousScore, showFileName, fileName):
        " Creates the score label "

        txt = "Score: " + str(score)
        if previousScore != "":
            txt += " / Previous score: " + str(previousScore)
        if not showFileName:
            txt += " for " + os.path.basename(fileName)

        scoreLabel = QLabel(txt)
        scoreLabel.setFrameShape(QFrame.StyledPanel)
        scoreLabel.setFont(self.__headerFont)
        scoreLabel.setAutoFillBackground(True)
        palette = scoreLabel.palette()

        if score < self.BadLimit:
            palette.setColor(QPalette.Background, QColor(255, 127, 127))
            palette.setColor(QPalette.Foreground, QColor(0, 0, 0))
        elif score > self.GoodLimit:
            palette.setColor(QPalette.Background, QColor(220, 255, 220))
            palette.setColor(QPalette.Foreground, QColor(0, 0, 0))
        else:
            palette.setColor(QPalette.Background, QColor(255, 255, 127))
            palette.setColor(QPalette.Foreground, QColor(0, 0, 0))

        scoreLabel.setPalette(palette)
        return scoreLabel
class Option(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        Layout = QHBoxLayout(self)
        Layout.setMargin(0)
        
        self.button = Button(self)
        palette = QPalette(self.button.palette())
        palette.setColor(QPalette.Button, QColor('grey').dark(150))
        self.button.setPalette(palette)
        QObject.connect(self.button, SIGNAL('clicked()'), self.clicked)
        Layout.addWidget(self.button)
        
        self.label = QLabel(self)
        self.label.setFrameShape(QLabel.Panel)
        self.label.setFixedHeight(self.button.height())
        self.label.setAutoFillBackground(True)
        self.label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        palette = QPalette(self.label.palette())
        palette.setColor(QPalette.Window, QColor(151, 169, 0))
        self.label.setPalette(palette)
        Layout.addWidget(self.label)

    def clicked(self):
        self.emit(SIGNAL('selected(QString &)'), self.label.text())
Exemplo n.º 5
0
    def __createLayout( self ):
        " Creates the widget layout "
        totalCalls = self.__stats.total_calls
        totalPrimitiveCalls = self.__stats.prim_calls  # The calls were not induced via recursion
        totalTime = self.__stats.total_tt

        txt = "<b>Script:</b> " + self.__script + " " + self.__params.arguments + "<br>" \
              "<b>Run at:</b> " + self.__reportTime + "<br>" + \
              str( totalCalls ) + " function calls (" + \
              str( totalPrimitiveCalls ) + " primitive calls) in " + \
              FLOAT_FORMAT % totalTime + " CPU seconds"
        summary = QLabel( txt )
        summary.setToolTip( txt )
        summary.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Fixed )
        summary.setFrameStyle( QFrame.StyledPanel )
        summary.setAutoFillBackground( True )
        summaryPalette = summary.palette()
        summaryBackground = summaryPalette.color( QPalette.Background )
        summaryBackground.setRgb( min( summaryBackground.red() + 30, 255 ),
                                  min( summaryBackground.green() + 30, 255 ),
                                  min( summaryBackground.blue() + 30, 255 ) )
        summaryPalette.setColor( QPalette.Background, summaryBackground )
        summary.setPalette( summaryPalette )

        self.__scene = QGraphicsScene()
        self.__viewer = DiagramWidget()
        self.__viewer.escapePressed.connect( self.__onESC )

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins( 0, 0, 0, 0 )
        vLayout.setSpacing( 0 )
        vLayout.addWidget( summary )
        vLayout.addWidget( self.__viewer )

        self.setLayout( vLayout )
        return
Exemplo n.º 6
0
    def __createLayout(self):
        " Creates the widget layout "
        totalCalls = self.__stats.total_calls
        totalPrimitiveCalls = self.__stats.prim_calls  # The calls were not induced via recursion
        totalTime = self.__stats.total_tt

        txt = "<b>Script:</b> " + self.__script + " " + self.__params.arguments + "<br>" \
              "<b>Run at:</b> " + self.__reportTime + "<br>" + \
              str( totalCalls ) + " function calls (" + \
              str( totalPrimitiveCalls ) + " primitive calls) in " + \
              FLOAT_FORMAT % totalTime + " CPU seconds"
        summary = QLabel(txt)
        summary.setToolTip(txt)
        summary.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        summary.setFrameStyle(QFrame.StyledPanel)
        summary.setAutoFillBackground(True)
        summaryPalette = summary.palette()
        summaryBackground = summaryPalette.color(QPalette.Background)
        summaryBackground.setRgb(min(summaryBackground.red() + 30, 255),
                                 min(summaryBackground.green() + 30, 255),
                                 min(summaryBackground.blue() + 30, 255))
        summaryPalette.setColor(QPalette.Background, summaryBackground)
        summary.setPalette(summaryPalette)

        self.__scene = QGraphicsScene()
        self.__viewer = DiagramWidget()
        self.__viewer.escapePressed.connect(self.__onESC)

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins(0, 0, 0, 0)
        vLayout.setSpacing(0)
        vLayout.addWidget(summary)
        vLayout.addWidget(self.__viewer)

        self.setLayout(vLayout)
        return
Exemplo n.º 7
0
class ProjectXively(QWidget):

    qtcb_update_illuminance = pyqtSignal(float)
    qtcb_update_air_pressure = pyqtSignal(float)
    qtcb_update_temperature = pyqtSignal(float)
    qtcb_update_humidity = pyqtSignal(float)
    qtcb_button_pressed = pyqtSignal(int)

    lcdwidget = None

    xively_host = "api.xively.com"
    xively_agent = "Tinkerforge Starter Kit Weather Station Demo"
    xively_channel = "Enter Feed ID here"
    xively_api_key = "Enter API Key here"

    xively_items = {}
    xively_headers = None
    xively_params = ""
    xively_update_rate = 5 # in minutes

    text_agent = None
    text_channel = None
    text_api_key = None
    number_update_rate = None

    save_button = None

    xively_timer = None

    error_message = None

    label_upload_active = None

    last_upload = None

    def __init__(self, parent, app):
        super(QWidget, self).__init__()

        self.lcdwidget = LCDWidget(self, app)
        self.lcdwidget.hide()

        self.text_agent = QLineEdit(self)
        self.text_agent.setText(self.xively_agent)
        
        self.text_channel = QLineEdit(self)
        self.text_channel.setText(self.xively_channel)
        
        self.text_api_key = QLineEdit(self)
        self.text_api_key.setText(self.xively_api_key)
        
        self.number_update_rate = QSpinBox(self)
        self.number_update_rate.setRange(1, 1440)
        self.number_update_rate.setSuffix(' min')
        self.number_update_rate.setValue(self.xively_update_rate)

        layout1 = QHBoxLayout()
        layout2 = QVBoxLayout()
        
        layout1.addStretch()
        layout1.addLayout(layout2)
        layout1.addStretch()
        
        layout2.addSpacerItem(QSpacerItem(LCDWidget.FIXED_WIDGTH, 0))

        label = QLabel(self)
        label.setText("Project: <b>Connect to Xively</b>. This project uploads the measured values to Xively. Please find documentation how to configure it and program sources in Python <a href=\"http://www.tinkerforge.com/en/doc/Kits/WeatherStation/WeatherStation.html#connect-to-xively\">here</a>.<br>")
        label.setTextFormat(Qt.RichText)
        label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        label.setOpenExternalLinks(True)
        label.setWordWrap(True)
        label.setAlignment(Qt.AlignJustify)

        layout2.addSpacing(10)
        layout2.addWidget(label)
        layout2.addSpacing(10)

        layout3a = QHBoxLayout()
        label = QLabel("Agent Description:")
        label.setMinimumWidth(150)
        layout3a.addWidget(label)
        layout3a.addWidget(self.text_agent, 1)

        layout2.addLayout(layout3a)
        layout2.addSpacing(10)

        layout3b = QHBoxLayout()
        label = QLabel("Feed:")
        label.setMinimumWidth(150)
        layout3b.addWidget(label)
        layout3b.addWidget(self.text_channel, 1)

        layout2.addLayout(layout3b)
        layout2.addSpacing(10)

        layout3c = QHBoxLayout()
        label = QLabel("API Key:")
        label.setMinimumWidth(150)
        layout3c.addWidget(label)
        layout3c.addWidget(self.text_api_key, 1)

        layout2.addLayout(layout3c)
        layout2.addSpacing(10)

        layout3d = QHBoxLayout()
        label = QLabel("Update Rate:")
        label.setMinimumWidth(150)
        layout3d.addWidget(label)
        layout3d.addWidget(self.number_update_rate, 1)

        layout2.addLayout(layout3d)
        layout2.addSpacing(10)

        self.label_upload_active = QLabel("Not Active", self)
        self.label_upload_active.setMinimumWidth(150)
        font = QFont()
        font.setPixelSize(20)
        self.label_upload_active.setFont(font)
        self.set_active_label(False)

        self.save_button = QPushButton("Save/Activate")

        layout4 = QHBoxLayout()
        layout4.addWidget(self.label_upload_active)
        layout4.addWidget(self.save_button, 1)

        layout2.addLayout(layout4)
        layout2.addStretch()

        self.setLayout(layout1)

        self.qtcb_update_illuminance.connect(self.update_illuminance_data_slot)
        self.qtcb_update_air_pressure.connect(self.update_air_pressure_data_slot)
        self.qtcb_update_temperature.connect(self.update_temperature_data_slot)
        self.qtcb_update_humidity.connect(self.update_humidity_data_slot)
        self.qtcb_button_pressed.connect(self.button_pressed_slot)
        self.save_button.clicked.connect(self.save_configuration)

        self.lcdwidget.clear(self)

        self.error_message = QErrorMessage(self)

    def set_active_label(self, value):
        palette = self.label_upload_active.palette()
        if value:
            palette.setColor(self.foregroundRole(), Qt.darkGreen)
            self.label_upload_active.setText("Active")
        else:
            palette.setColor(self.foregroundRole(), Qt.red)
            self.label_upload_active.setText("Not Active")

        self.label_upload_active.setPalette(palette)

    def save_configuration(self):
        try:
            self.xively_agent = str(self.text_agent.text()).decode('ascii')
            self.xively_channel = str(self.text_channel.text()).decode('ascii')
            self.xively_api_key = str(self.text_api_key.text()).decode('ascii')
        except:
            self.error_message.showMessage('Agent, Feed and API Key can only contain ASCII characters')
            return

        self.xively_update_rate = self.number_update_rate.value()

        self.xively_headers = {
            "Content-Type"  : "application/x-www-form-urlencoded",
            "X-ApiKey"      : self.xively_api_key,
            "User-Agent"    : self.xively_agent,
        }
        self.xively_params = "/v2/feeds/" + self.xively_channel

        if self.xively_timer is None:
            self.xively_timer = QTimer(self)
            self.xively_timer.timeout.connect(self.update_xively)
            self.xively_timer.start(self.xively_update_rate*60*1000)

        self.set_active_label(True)
        self.update_xively()

    def write_lcd(self):
        if self.last_upload == None:
            tmp = "Last: Never"
        else:
            tmp = "Last: " + self.last_upload

        self.lcdwidget.write_line(0, 0, "Xively Upload", self)
        self.lcdwidget.write_line(2, 0, tmp, self)

    def update_xively(self):
        if len(self.xively_items) == 0:
            return

        stream_items = []
        for identifier, value in self.xively_items.items():
            stream_items.append({'id': identifier,
                                 'current_value': value[0],
                                 'min_value': value[1],
                                 'max_value': value[2]})

        data = {'version': '1.0.0',
                    'datastreams': stream_items}
        self.xively_items = {}
        body = json.dumps(data)

        try:
            http = httplib.HTTPSConnection(self.xively_host)
            http.request('PUT', self.xively_params, body, self.xively_headers)
            response = http.getresponse()
            http.close()

            if response.status != 200:
                self.error_message.showMessage('Could not upload to xively -> Response:' +
                          str(response.status) + ': ' + response.reason + '. Check your configuration.')
                self.xively_timer.stop()
                self.xively_timer = None
                self.set_active_label(False)
                return
        except Exception as e:
            self.error_message.showMessage('HTTP error: ' + str(e))
            self.xively_timer.stop()
            self.xively_timer = None
            self.set_active_label(False)
            return

        # set upload time if upload was a success
        self.last_upload = time.strftime("%H:%M:%S")


    def put(self, identifier, value):
        self.write_lcd()
        try:
            _, min_value, max_value = self.xively_items[identifier]
            if value < min_value:
                min_value = value
            if value > max_value:
                max_value = value
            self.xively_items[identifier] = (value, min_value, max_value)
        except:
            self.xively_items[identifier] = (value, value, value)

    def update_illuminance_data_slot(self, illuminance):
        self.put('AmbientLight', illuminance/10.0)

    def update_illuminance(self, illuminance):
        self.qtcb_update_illuminance.emit(illuminance)

    def update_humidity_data_slot(self, humidity):
        self.put('Humidity', humidity/10.0)
    
    def update_humidity(self, humidity):
        self.qtcb_update_humidity.emit(humidity)

    def update_air_pressure_data_slot(self, air_pressure):
        self.put('AirPressure', air_pressure/1000.0)
    
    def update_air_pressure(self, air_pressure):
        self.qtcb_update_air_pressure.emit(air_pressure)

    def update_temperature_data_slot(self, temperature):
        self.put('Temperature', temperature/100.0)

    def update_temperature(self, temperature):
        self.qtcb_update_temperature.emit(temperature)

    def button_pressed_slot(self, button):
        pass

    def button_pressed(self, button):
        self.qtcb_button_pressed.emit(button)
Exemplo n.º 8
0
    def __createLayout(self, scriptName, name, code, reportTime):
        " Creates the toolbar and layout "

        # Buttons
        self.__printButton = QAction(PixmapCache().getIcon('printer.png'),
                                     'Print', self)
        self.__printButton.triggered.connect(self.__onPrint)
        self.__printButton.setEnabled(False)
        self.__printButton.setVisible(False)

        self.__printPreviewButton = QAction(
            PixmapCache().getIcon('printpreview.png'), 'Print preview', self)
        self.__printPreviewButton.triggered.connect(self.__onPrintPreview)
        self.__printPreviewButton.setEnabled(False)
        self.__printPreviewButton.setVisible(False)

        # Zoom buttons
        self.__zoomInButton = QAction(PixmapCache().getIcon('zoomin.png'),
                                      'Zoom in (Ctrl+=)', self)
        self.__zoomInButton.triggered.connect(self.onZoomIn)

        self.__zoomOutButton = QAction(PixmapCache().getIcon('zoomout.png'),
                                       'Zoom out (Ctrl+-)', self)
        self.__zoomOutButton.triggered.connect(self.onZoomOut)

        self.__zoomResetButton = QAction(
            PixmapCache().getIcon('zoomreset.png'), 'Zoom reset (Ctrl+0)',
            self)
        self.__zoomResetButton.triggered.connect(self.onZoomReset)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # Toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(28)
        toolbar.setContentsMargins(0, 0, 0, 0)

        toolbar.addAction(self.__printPreviewButton)
        toolbar.addAction(self.__printButton)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.__zoomInButton)
        toolbar.addAction(self.__zoomOutButton)
        toolbar.addAction(self.__zoomResetButton)

        summary = QLabel("<b>Script:</b> " + scriptName + "<br>"
                         "<b>Name:</b> " + name + "<br>"
                         "<b>Disassembled at:</b> " + reportTime)
        summary.setFrameStyle(QFrame.StyledPanel)
        summary.setAutoFillBackground(True)
        summaryPalette = summary.palette()
        summaryBackground = summaryPalette.color(QPalette.Background)
        summaryBackground.setRgb(min(summaryBackground.red() + 30, 255),
                                 min(summaryBackground.green() + 30, 255),
                                 min(summaryBackground.blue() + 30, 255))
        summaryPalette.setColor(QPalette.Background, summaryBackground)
        summary.setPalette(summaryPalette)

        self.__text = DisasmWidget(self)
        self.__text.setAcceptRichText(False)
        self.__text.setLineWrapMode(QTextEdit.NoWrap)
        self.__text.setFont(GlobalData().skin.nolexerFont)
        self.zoomTo(Settings().zoom)
        self.__text.setReadOnly(True)
        self.__text.setPlainText(code)

        vLayout = QVBoxLayout()
        vLayout.addWidget(summary)
        vLayout.addWidget(self.__text)

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)
        hLayout.addLayout(vLayout)
        hLayout.addWidget(toolbar)

        self.setLayout(hLayout)
        return
Exemplo n.º 9
0
class OutsideChangeWidget(QFrame):
    " Frameless dialogue to deal with outside changes "

    reloadRequest = pyqtSignal()
    reloadAllNonModifiedRequest = pyqtSignal()

    def __init__(self, parent):
        QFrame.__init__(self, parent)

        # Make the frame nice looking
        panelColor = QColor(170, 17, 17)
        palette = self.palette()
        palette.setColor(self.backgroundRole(), panelColor)
        self.setPalette(palette)

        self.setFrameShape(QFrame.StyledPanel)
        self.setLineWidth(2)
        self.setAutoFillBackground(True)

        # Keep pylint happy
        self.__messageLabel = None
        self.__leaveAsIsButton = None
        self.__reloadButton = None
        self.__reloadAllNonChangedButton = None

        self.__markers = []
        self.__createLayout()

        for item in self.__markers:
            item.hide()
        return

    def __createLayout(self):
        " Creates the widget layout "

        self.__messageLabel = QLabel("This file has been modified "
                                     "outside of codimension. What "
                                     "would you like to do?")
        self.__messageLabel.setWordWrap(True)
        self.__messageLabel.setAlignment(Qt.AlignHCenter)
        palette = self.__messageLabel.palette()
        palette.setColor(self.foregroundRole(), QColor(255, 255, 255, 255))
        self.__messageLabel.setPalette(palette)

        self.__leaveAsIsButton = QPushButton("Continue editing", self)
        self.__leaveAsIsButton.setToolTip("ESC")
        self.__leaveAsIsButton.clicked.connect(self.hide)

        self.__reloadButton = QPushButton(self)
        self.__reloadButton.clicked.connect(self.__reload)

        txt = "Reload all non-modified buffers"
        self.__reloadAllNonChangedButton = QPushButton(txt, self)
        self.__reloadAllNonChangedButton.clicked.connect(
            self.__reloadAllNonModified)

        # This will prevent the buttons growing wider than necessary
        fontMetrics = QFontMetrics(self.__reloadAllNonChangedButton.font())
        buttonWidth = fontMetrics.width(txt) + 20
        self.__reloadAllNonChangedButton.setFixedWidth(buttonWidth)

        gridLayout = QGridLayout(self)
        gridLayout.setMargin(3)

        gridLayout.addWidget(self.__messageLabel, 0, 0, 1, 1)
        gridLayout.addWidget(self.__leaveAsIsButton, 0, 1, 1, 1)
        gridLayout.addWidget(self.__reloadButton, 1, 1, 1, 1)
        gridLayout.addWidget(self.__reloadAllNonChangedButton, 2, 1, 1, 1)

        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.move(5, 5)

        self.__markers.append(QFrame(self.parent()))
        self.__markers.append(QFrame(self.parent()))
        self.__markers.append(QFrame(self.parent()))
        self.__markers.append(QFrame(self.parent()))

        markerColor = QColor(224, 0, 0, 255)
        for item in self.__markers:
            pal = item.palette()
            pal.setColor(item.backgroundRole(), markerColor)
            item.setPalette(pal)
            item.setFrameShape(QFrame.StyledPanel)
            item.setLineWidth(1)
            item.setAutoFillBackground(True)
            item.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        return

    def resize(self):
        " Resizes the dialogue to match the editor size "

        vscroll = self.parent().verticalScrollBar()
        if vscroll.isVisible():
            scrollWidth = vscroll.width()
        else:
            scrollWidth = 0

        hscroll = self.parent().horizontalScrollBar()
        if hscroll.isVisible():
            scrollHeight = hscroll.height()
        else:
            scrollHeight = 0

        # Dialogue
        width = self.parent().width()
        height = self.parent().height()
        widgetWidth = width - scrollWidth - 10 - 1

        self.setFixedWidth(widgetWidth)

        # Marker
        self.__markers[0].move(1, 1)
        self.__markers[0].setFixedWidth(width - scrollWidth - 4)
        self.__markers[0].setFixedHeight(3)

        self.__markers[1].move(width - scrollWidth - 5, 1)
        self.__markers[1].setFixedWidth(3)
        self.__markers[1].setFixedHeight(height - scrollHeight - 4)

        self.__markers[2].move(1, height - scrollHeight - 5)
        self.__markers[2].setFixedWidth(width - scrollWidth - 4)
        self.__markers[2].setFixedHeight(3)

        self.__markers[3].move(1, 1)
        self.__markers[3].setFixedWidth(3)
        self.__markers[3].setFixedHeight(height - scrollHeight - 4)
        return

    def showChoice(self, modified, allEnabled):
        " Brings up the panel with the correct text and buttons "
        if modified:
            self.__reloadButton.setText("Reload losing changes")
        else:
            self.__reloadButton.setText("Reload")
        self.__reloadAllNonChangedButton.setEnabled(allEnabled)

        QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

        self.resize()
        self.show()
        for item in self.__markers:
            item.show()
        self.__leaveAsIsButton.setFocus()
        self.parent().setReadOnly(True)
        return

    def setFocus(self):
        " Passes the focus to the default button "
        self.__leaveAsIsButton.setFocus()
        return

    def keyPressEvent(self, event):
        " Handles the key press events "
        if event.key() == Qt.Key_Escape:
            editorsManager = GlobalData().mainWindow.editorsManager()
            activeWindow = editorsManager.currentWidget()
            if activeWindow:
                activeWindow.setFocus()
            event.accept()
            self.hide()
        return

    def hide(self):
        " Handles the hiding of the panel and markers "
        for item in self.__markers:
            item.hide()
        QFrame.hide(self)
        self.parent().setReadOnly(False)
        self.parent().setFocus()
        return

    def __reload(self):
        " Reloads the file from the disk "
        self.reloadRequest.emit()
        return

    def __reloadAllNonModified(self):
        " Reloads all the non-modified buffers "
        self.reloadAllNonModifiedRequest.emit()
        return
Exemplo n.º 10
0
class PymetricsViewer(QWidget):
    " Pymetrics tab widget "

    # Limits to colorize the McCabe score
    LittleRiskLimit = 10
    ModerateRiskLimit = 20
    HighRiskLimit = 50

    # Options of providing a report
    SingleFile = 0
    DirectoryFiles = 1
    ProjectFiles = 2
    SingleBuffer = 3

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

        self.__reportUUID = ""
        self.__reportFileName = ""
        self.__reportOption = -1
        self.__reportShown = False
        self.__report = None

        # Prepare members for reuse
        self.__noneLabel = QLabel("\nNo results available")

        self.__noneLabel.setFrameShape(QFrame.StyledPanel)
        self.__noneLabel.setAlignment(Qt.AlignHCenter)
        self.__headerFont = self.__noneLabel.font()
        self.__headerFont.setPointSize(self.__headerFont.pointSize() + 4)
        self.__noneLabel.setFont(self.__headerFont)
        self.__noneLabel.setAutoFillBackground(True)
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor(QPalette.Background,
                                  GlobalData().skin.nolexerPaper)
        self.__noneLabel.setPalette(noneLabelPalette)

        self.__createLayout(parent)

        self.__updateButtonsStatus()
        return

    def __createLayout(self, parent):
        " Creates the toolbar and layout "

        # Buttons
        self.__mcCabeButton = QAction(PixmapCache().getIcon('tableview.png'),
                                      'Switch to McCabe only table view', self)
        self.__mcCabeButton.setCheckable(True)
        self.connect(self.__mcCabeButton, SIGNAL('toggled(bool)'),
                     self.__onMcCabe)

        self.printButton = QAction(PixmapCache().getIcon('printer.png'),
                                   'Print', self)
        #printButton.setShortcut( 'Ctrl+' )
        self.connect(self.printButton, SIGNAL('triggered()'), self.__onPrint)
        self.printButton.setVisible(False)

        self.printPreviewButton = QAction(
            PixmapCache().getIcon('printpreview.png'), 'Print preview', self)
        #printPreviewButton.setShortcut( 'Ctrl+' )
        self.connect(self.printPreviewButton, SIGNAL('triggered()'),
                     self.__onPrintPreview)
        self.printPreviewButton.setVisible(False)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.clearButton = QAction(PixmapCache().getIcon('trash.png'), 'Clear',
                                   self)
        self.connect(self.clearButton, SIGNAL('triggered()'), self.__clear)

        # The toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.__mcCabeButton)
        self.toolbar.addAction(self.printPreviewButton)
        self.toolbar.addAction(self.printButton)
        self.toolbar.addWidget(spacer)
        self.toolbar.addAction(self.clearButton)

        self.__totalResultsTree = QTreeWidget()
        self.__totalResultsTree.setAlternatingRowColors(True)
        self.__totalResultsTree.setRootIsDecorated(True)
        self.__totalResultsTree.setItemsExpandable(True)
        self.__totalResultsTree.setUniformRowHeights(True)
        self.__totalResultsTree.setItemDelegate(NoOutlineHeightDelegate(4))
        headerLabels = ["Path / name", "Value", ""]
        self.__totalResultsTree.setHeaderLabels(headerLabels)
        self.connect(self.__totalResultsTree,
                     SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
                     self.__allItemActivated)
        self.connect(self.__totalResultsTree,
                     SIGNAL("itemExpanded(QTreeWidgetItem *)"),
                     self.__onResultsExpanded)
        self.__totalResultsTree.setColumnHidden(2, True)
        self.__totalResultsTree.hide()

        self.__mcCabeTable = QTreeWidget()
        self.__mcCabeTable.setAlternatingRowColors(True)
        self.__mcCabeTable.setRootIsDecorated(False)
        self.__mcCabeTable.setItemsExpandable(False)
        self.__mcCabeTable.setSortingEnabled(True)
        self.__mcCabeTable.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__mcCabeTable.setUniformRowHeights(True)
        headerLabels = ["", "File name", "Object", "McCabe Complexity"]
        self.__mcCabeTable.setHeaderLabels(headerLabels)
        self.connect(self.__mcCabeTable,
                     SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
                     self.__mcCabeActivated)
        self.__mcCabeTable.hide()

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addWidget(self.__totalResultsTree)
        self.__hLayout.addWidget(self.__mcCabeTable)

        self.setLayout(self.__hLayout)
        return

    def getTotalResultsWidget(self):
        " Provides a reference to the total results widget "
        return self.__totalResultsTree

    def getMcCabeResultsWidget(self):
        " Provides a reference to the McCabe results widget "
        return self.__mcCabeTable

    def __updateButtonsStatus(self):
        " Updates the buttons status "
        self.__mcCabeButton.setEnabled(self.__reportShown)
        self.printButton.setEnabled(self.__reportShown)
        self.printPreviewButton.setEnabled(self.__reportShown)
        self.clearButton.setEnabled(self.__reportShown)
        return

    def __onResultsExpanded(self, item):
        " An item has been expanded, so the column width should be adjusted "
        self.__totalResultsTree.header().resizeSections(
            QHeaderView.ResizeToContents)
        return

    def __onPrint(self):
        " Triggered when the print button is pressed "
        pass

    def __onPrintPreview(self):
        " triggered when the print preview button is pressed "
        pass

    def __onMcCabe(self, state):
        " Triggered when the metrics view is switched "

        if not self.__reportShown:
            return

        if state:
            self.__totalResultsTree.hide()
            self.__mcCabeTable.show()
            self.__mcCabeButton.setIcon(PixmapCache().getIcon('treeview.png'))
            self.__mcCabeButton.setToolTip("Switch to complete "
                                           "results tree view")
        else:
            self.__mcCabeTable.hide()
            self.__totalResultsTree.show()
            self.__mcCabeButton.setIcon(PixmapCache().getIcon('tableview.png'))
            self.__mcCabeButton.setToolTip("Switch to McCabe only table view")
        return

    def setFocus(self):
        " Overridden setFocus "
        self.__hLayout.setFocus()
        return

    def __clear(self):
        " Clears the content of the vertical layout "
        if not self.__reportShown:
            return

        self.__totalResultsTree.clear()
        self.__totalResultsTree.hide()
        self.__mcCabeTable.clear()
        self.__mcCabeTable.hide()
        self.__noneLabel.show()

        self.__report = None
        self.__reportShown = False
        self.__updateButtonsStatus()
        #        self.resizeEvent()
        self.__mcCabeButton.setIcon(PixmapCache().getIcon('tableview.png'))
        self.__mcCabeButton.setToolTip("Switch to McCabe only table view")
        self.__mcCabeButton.setChecked(False)

        self.__updateTooltip()
        return

    def __updateTooltip(self):
        " Generates a signal with appropriate string message "
        if not self.__reportShown:
            tooltip = "No metrics available"
        elif self.__reportOption == self.DirectoryFiles:
            tooltip = "Metrics generated for directory: " + \
                      self.__reportFileName
        elif self.__reportOption == self.ProjectFiles:
            tooltip = "Metrics generated for the whole project"
        elif self.__reportOption == self.SingleFile:
            tooltip = "Metrics generated for file: " + self.__reportFileName
        elif self.__reportOption == self.SingleBuffer:
            tooltip = "Metrics generated for unsaved file: " + \
                      self.__reportFileName
        else:
            tooltip = ""
        self.emit(SIGNAL('updatePymetricsTooltip'), tooltip)
        return

    @staticmethod
    def __shouldShowFileName(table, column):
        " Checks if the file name is the same "

        size = table.topLevelItemCount()
        if size == 0:
            return False

        index = size - 1
        firstName = table.topLevelItem(index).text(column)
        index -= 1
        while index >= 0:
            if table.topLevelItem(index).text(column) != firstName:
                return True
            index -= 1
        return False

    def showReport(self, metrics, reportOption, fileName, uuid):
        " Shows the pymetrics results "
        self.__clear()
        self.__noneLabel.hide()

        self.__report = metrics
        self.__reportUUID = uuid
        self.__reportFileName = fileName
        self.__reportOption = reportOption

        if len(metrics.report) > 1:
            accumulatedBasic = self.__accumulateBasicMetrics()
            accItem = QTreeWidgetItem(["Cumulative basic metrics"])
            self.__totalResultsTree.addTopLevelItem(accItem)
            for key in accumulatedBasic:
                bmItem = [
                    BasicMetrics.metricsOfInterest[key],
                    splitThousands(str(accumulatedBasic[key]))
                ]
                basicMetric = QTreeWidgetItem(bmItem)
                accItem.addChild(basicMetric)

        # Add the complete information
        for fileName in metrics.report:
            if reportOption == self.SingleBuffer:
                fileItem = QTreeWidgetItem(["Editor buffer"])
            else:
                fileItem = QTreeWidgetItem([fileName])
                info = GlobalData().briefModinfoCache.get(fileName)
                if info.docstring is not None:
                    fileItem.setToolTip(0, info.docstring.text)
                else:
                    fileItem.setToolTip(0, "")
            self.__totalResultsTree.addTopLevelItem(fileItem)

            # Messages part
            messages = metrics.report[fileName].messages
            if len(messages) > 0:
                messagesItem = QTreeWidgetItem(["Messages"])
                fileItem.addChild(messagesItem)
                for message in messages:
                    mItem = [message, "", "E"]
                    messagesItem.addChild(QTreeWidgetItem(mItem))

            # Basic metrics part
            basicItem = QTreeWidgetItem(["Basic metrics"])
            fileItem.addChild(basicItem)
            basic = metrics.report[fileName].basicMetrics
            for key in basic.metrics:
                bmItem = [
                    BasicMetrics.metricsOfInterest[key],
                    str(basic.metrics[key])
                ]
                basicMetric = QTreeWidgetItem(bmItem)
                basicItem.addChild(basicMetric)

            # McCabe part
            mccabeItem = QTreeWidgetItem(["McCabe metrics"])
            fileItem.addChild(mccabeItem)
            mccabe = metrics.report[fileName].mcCabeMetrics.metrics
            for objName in mccabe:
                objItem = [objName, str(mccabe[objName]), "M"]
                mccabeMetric = QTreeWidgetItem(objItem)
                mccabeItem.addChild(mccabeMetric)

            # COCOMO 2 part
            cocomo = [
                "COCOMO 2",
                str(metrics.report[fileName].cocomo2Metrics.value)
            ]
            cocomoItem = QTreeWidgetItem(cocomo)
            fileItem.addChild(cocomoItem)

        # Resizing the table
        self.__totalResultsTree.header().resizeSections(
            QHeaderView.ResizeToContents)

        # Add McCabe complexity information
        for fileName in metrics.report:
            mccabe = metrics.report[fileName].mcCabeMetrics.metrics
            for objName in mccabe:
                values = ["", fileName, objName, str(mccabe[objName])]
                self.__mcCabeTable.addTopLevelItem(McCabeTableItem(values))

        if not self.__shouldShowFileName(self.__mcCabeTable, 1):
            self.__mcCabeTable.setColumnHidden(1, True)

        # Resizing and sorting the table
        self.__mcCabeTable.header().setSortIndicator(3, Qt.DescendingOrder)
        self.__mcCabeTable.sortItems(
            3,
            self.__mcCabeTable.header().sortIndicatorOrder())
        self.__mcCabeTable.header().resizeSections(
            QHeaderView.ResizeToContents)

        # Show the complete information
        self.__mcCabeTable.hide()
        self.__totalResultsTree.show()

        self.__reportShown = True
        self.__updateButtonsStatus()
        self.__updateTooltip()

        # It helps, but why do I have flickering?
        QApplication.processEvents()
        return

    def __accumulateBasicMetrics(self):
        " Accumulates basic metrics for all the processed files "
        basic = {}
        for fileName in self.__report.report:
            singleBasic = self.__report.report[fileName].basicMetrics.metrics
            for key in singleBasic:
                if not key.startswith('num'):
                    continue
                if key in basic:
                    basic[key] += int(singleBasic[key])
                else:
                    basic[key] = int(singleBasic[key])
        return basic

    def __mcCabeActivated(self, item, column):
        " Handles the double click (or Enter) on the mccabe table item "

        objName = str(item.text(2))
        if self.__reportOption == self.SingleBuffer:
            if os.path.isabs(self.__reportFileName):
                fileName = self.__reportFileName
            else:
                fileName = ""
        else:
            fileName = str(item.text(1))
        self.__onMcCabeObject(objName, fileName)
        return

    def __allItemActivated(self, item, column):
        " Handles the double click (or Enter) in the total results tree "

        # We process only the error messages and McCabe items
        hiddenColumnText = str(item.text(2))
        if not hiddenColumnText in ["M", "E"]:
            return

        fileName = self.__getTreeItemFileName(item)
        lineNumber = 0
        if hiddenColumnText == "M":
            # This is McCabe item
            objName = str(item.text(0))
            self.__onMcCabeObject(objName, fileName)
            return
        elif hiddenColumnText == "E":
            # This is an error message
            message = str(item.text(0))
            pos = message.find("at line")
            if pos == -1:
                logging.error("Unknown format of the message. "
                              "Please inform the developers.")
                return
            parts = message[pos:].split()
            try:
                lineNumber = int(parts[2].replace(',', ''))
            except:
                logging.error("Unknown format of the message. "
                              "Please inform the developers.")
                return

            if fileName == "":
                # This is an unsaved buffer, try to find the editor by UUID
                mainWindow = GlobalData().mainWindow
                widget = mainWindow.getWidgetByUUID(self.__reportUUID)
                if widget is None:
                    logging.error("The unsaved buffer has been closed")
                    return
                # The widget was found, so jump to the required
                editor = widget.getEditor()
                editor.gotoLine(lineNumber)
                editor.setFocus()
                return

        GlobalData().mainWindow.openFile(fileName, lineNumber)
        return

    def __getTreeItemFileName(self, item):
        " Identifies the tree view item file name "
        if self.__reportOption == self.SingleBuffer:
            if os.path.isabs(self.__reportFileName):
                return self.__reportFileName
            return ""

        # The file name is always two levels up
        fileItem = item.parent().parent()
        return str(fileItem.text(0))

    def __onMcCabeObject(self, objName, fileName):
        " Called when the user activated McCabe item "

        info = None

        mainWindow = GlobalData().mainWindow
        widget = mainWindow.getWidgetByUUID(self.__reportUUID)
        if widget is None:
            if fileName == "":
                logging.error("The unsaved buffer has been closed")
                return
            # No widget, but we know the file name
            info = getBriefModuleInfoFromFile(fileName)
        else:
            # The widget was found
            editor = widget.getEditor()
            # The editor content has been modified, so re-parse the buffer
            info = getBriefModuleInfoFromMemory(editor.text())

        parts = objName.split('.')
        currentIndex = 0
        functionsContainer = info.functions
        classesContainer = info.classes
        line = -1

        if objName == "__main__" and len(parts) == 1:
            # Special case - global file scope
            line = 1
            currentIndex = 1

        while currentIndex < len(parts):
            found = False
            for func in functionsContainer:
                if func.name == parts[currentIndex]:
                    if currentIndex == len(parts) - 1:
                        # Found, jump to the line
                        line = func.line
                        break
                    functionsContainer = func.functions
                    classesContainer = func.classes
                    found = True
                    break
            if line != -1:
                break
            if found:
                currentIndex += 1
                continue
            for klass in classesContainer:
                if klass.name == parts[currentIndex]:
                    if currentIndex == len(parts) - 1:
                        # Found, jump to the line
                        line = klass.line
                        break
                    functionsContainer = klass.functions
                    classesContainer = klass.classes
                    found = True
            if line != -1:
                break
            if found:
                currentIndex += 1
                continue

            # Not found
            logging.error("Cannot find the " + objName)
            return

        # Here we have the line number
        if widget is None:
            GlobalData().mainWindow.openFile(fileName, line)
        else:
            editor = widget.getEditor()
            editor.gotoLine(line)
            editor.setFocus()
        return

    def onFileUpdated(self, fileName, uuid):
        " Called when a buffer is saved or saved as "

        if not self.__reportShown:
            return
        if self.__reportUUID != uuid:
            return

        # Currently shown report is for the saved buffer
        # File name is expected being absolute
        self.__reportFileName = fileName
        self.emit(SIGNAL('updatePymetricsTooltip'),
                  "Metrics generated for buffer saved as " + fileName)
        return
Exemplo n.º 11
0
class FindInFilesViewer(QWidget):
    " Find in files viewer tab widget "

    lastEntered = None

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

        global searchTooltip
        searchTooltip = Tooltip()

        self.__reportRegexp = None
        self.__reportResults = []
        self.__reportShown = False
        self.__bufferChangeconnected = False

        # Prepare members for reuse
        self.__noneLabel = QLabel("\nNo results available")

        self.__noneLabel.setFrameShape(QFrame.StyledPanel)
        self.__noneLabel.setAlignment(Qt.AlignHCenter)
        self.__headerFont = self.__noneLabel.font()
        self.__headerFont.setPointSize(self.__headerFont.pointSize() + 4)
        self.__noneLabel.setFont(self.__headerFont)
        self.__noneLabel.setAutoFillBackground(True)
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor(QPalette.Background, GlobalData().skin.nolexerPaper)
        self.__noneLabel.setPalette(noneLabelPalette)

        # Keep pylint happy
        self.printButton = None
        self.clearButton = None
        self.printPreviewButton = None

        self.__createLayout(parent)

        self.__updateButtonsStatus()

        GlobalData().project.projectChanged.connect(self.__onProjectChanged)
        return

    def __createLayout(self, parent):
        " Creates the toolbar and layout "

        # Buttons
        self.printButton = QAction(PixmapCache().getIcon("printer.png"), "Print", self)
        # printButton.setShortcut( 'Ctrl+' )
        self.printButton.triggered.connect(self.__onPrint)
        self.printButton.setVisible(False)

        self.printPreviewButton = QAction(PixmapCache().getIcon("printpreview.png"), "Print preview", self)
        # printPreviewButton.setShortcut( 'Ctrl+' )
        self.printPreviewButton.triggered.connect(self.__onPrintPreview)
        self.printPreviewButton.setVisible(False)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.clearButton = QAction(PixmapCache().getIcon("trash.png"), "Clear", self)
        self.clearButton.triggered.connect(self.__clear)

        # The toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.printPreviewButton)
        self.toolbar.addAction(self.printButton)
        self.toolbar.addWidget(spacer)
        self.toolbar.addAction(self.clearButton)

        self.__resultsTree = FindResultsTreeWidget()
        self.__resultsTree.setAlternatingRowColors(True)
        self.__resultsTree.setRootIsDecorated(True)
        self.__resultsTree.setItemsExpandable(True)
        self.__resultsTree.setUniformRowHeights(True)
        self.__resultsTree.setItemDelegate(NoOutlineHeightDelegate(4))
        headerLabels = ["File name / line", "Text"]
        self.__resultsTree.setHeaderLabels(headerLabels)
        self.__resultsTree.itemActivated.connect(self.__resultActivated)
        self.__resultsTree.itemClicked.connect(self.__resultClicked)
        self.__resultsTree.setMouseTracking(True)
        self.__resultsTree.itemEntered.connect(self.__itemEntered)
        self.__resultsTree.hide()

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addWidget(self.__resultsTree)

        self.setLayout(self.__hLayout)
        return

    def getResultsTree(self):
        " Provides a reference to the results tree "
        return self.__resultsTree

    def __updateButtonsStatus(self):
        " Updates the buttons status "
        self.printButton.setEnabled(self.__reportShown)
        self.printPreviewButton.setEnabled(self.__reportShown)
        self.clearButton.setEnabled(self.__reportShown)
        return

    def __onPrint(self):
        " Triggered when the print button is pressed "
        pass

    def __onPrintPreview(self):
        " triggered when the print preview button is pressed "
        pass

    def setFocus(self):
        " Overridden setFocus "
        self.__hLayout.setFocus()
        return

    def __onProjectChanged(self, what):
        " Triggered when a project is changed "
        if what == CodimensionProject.CompleteProject:
            self.__clear()
        return

    def __clear(self):
        " Clears the content of the vertical layout "
        if not self.__reportShown:
            return

        # Disconnect the buffer change signal if it is connected
        if self.__bufferChangeconnected:
            self.__bufferChangeconnected = False
            mainWindow = GlobalData().mainWindow
            editorsManager = mainWindow.editorsManagerWidget.editorsManager
            editorsManager.bufferModified.disconnect(self.__resultsTree.onBufferModified)

        self.__resultsTree.resetCache()
        self.__resultsTree.clear()
        self.__resultsTree.hide()
        self.__noneLabel.show()

        self.__reportRegexp = None
        self.__reportResults = []
        self.__reportShown = False
        self.__updateButtonsStatus()
        return

    def showReport(self, regexp, results):
        " Shows the find in files results "
        self.__clear()
        self.__noneLabel.hide()

        self.__reportRegexp = regexp
        self.__reportResults = results

        # Add the complete information
        totalMatched = 0
        for item in results:
            matched = len(item.matches)
            totalMatched += matched
            if matched == 1:
                matchText = " (1 match)"
            else:
                matchText = " (" + str(matched) + " matches)"
            columns = [item.fileName, matchText]
            fileItem = MatchTableFileItem(columns, item.bufferUUID)
            fileItem.setIcon(0, getFileIcon(detectFileType(item.fileName)))
            if item.tooltip != "":
                fileItem.setToolTip(0, item.tooltip)
            self.__resultsTree.addTopLevelItem(fileItem)

            # Matches
            for match in item.matches:
                columns = [str(match.line), match.text]
                matchItem = MatchTableItem(columns, match.tooltip)
                fileItem.addChild(matchItem)
            fileItem.setExpanded(True)

        # Update the header with the total number of matches
        headerLabels = [
            "File name / line (total files: " + str(len(results)) + ")",
            "Text (total matches: " + str(totalMatched) + ")",
        ]
        self.__resultsTree.setHeaderLabels(headerLabels)

        # Resizing the table
        self.__resultsTree.header().resizeSections(QHeaderView.ResizeToContents)

        # Show the complete information
        self.__resultsTree.show()
        self.__resultsTree.buildCache()

        self.__reportShown = True
        self.__updateButtonsStatus()

        # Connect the buffer change signal if not connected yet
        if not self.__bufferChangeconnected:
            self.__bufferChangeconnected = True
            mainWindow = GlobalData().mainWindow
            editorsManager = mainWindow.editorsManagerWidget.editorsManager
            editorsManager.bufferModified.connect(self.__resultsTree.onBufferModified)
        return

    def __resultClicked(self, item, column):
        " Handles the single click "
        hideSearchTooltip()
        return

    def __resultActivated(self, item, column):
        " Handles the double click (or Enter) on a match "
        if type(item) == MatchTableItem:
            fileName = str(item.parent().data(0, Qt.DisplayRole).toString())
            lineNumber = int(item.data(0, Qt.DisplayRole).toString())
            GlobalData().mainWindow.openFile(fileName, lineNumber)
            hideSearchTooltip()
            return

    def __itemEntered(self, item, column):
        " Triggered when the mouse cursor entered a row "

        if type(item) != MatchTableItem:
            self.lastEntered = item
            hideSearchTooltip()
            return

        if column != 1:
            # Show the tooltip only for the column with results
            self.lastEntered = None
            hideSearchTooltip()
            return

        # Memorize the row height for proper tooltip displaying later
        global cellHeight
        cellHeight = self.__resultsTree.visualItemRect(item).height()

        if self.lastEntered != item or not inside:
            item.itemEntered()
            self.lastEntered = item
        return
Exemplo n.º 12
0
 def createGUIElements(self):
     ''' Build the GUI based on the parameters for the tool '''
     for i, param in enumerate(self.tooltypearray):
         # print 'creatgui element %d, %s' %(i, param)
         #Swap in the passed params if they exist... loop through each passed
         #param and see if it matches... if so swap it in
         if self.optional_params.has_key(str(param[0])):
             param[2] = self.optional_params[str(param[0])]
         #print "Key: %s , Val: %s" % (param[0],param[1])
         widgetTemp = QWidget(self.variableBox)
         widgetTemp.setObjectName(QString("test_widget").append(QString(i)))
         self.test_widget.append(widgetTemp)
         hlayout = QHBoxLayout(widgetTemp)
         self.hboxlayout.append(hlayout)
         hlayout.setMargin(4)
         hlayout.setSpacing(4)
         hlayout.setObjectName(QString("hboxlayout").append(QString(i)))
         test_text = QLabel(widgetTemp)
         self.test_text.append(test_text)
         test_text.setObjectName(QString("test_text").append(QString(i)))
         paramName = param[0].strip()
         if param[2].strip() == "Required":
             palette = test_text.palette()
             palette.setColor(QPalette.WindowText,Qt.red)
             test_text.setPalette(palette)
         test_text.setText(paramName)
         test_text_type = QLabel(widgetTemp)
         self.test_text_type.append(test_text_type)
         test_text_type.setObjectName(QString("test_text_type").append(QString(i)))
         paramName = param[1].strip()
         test_text_type.setText(QString("(").append(paramName).append(QString(")")))
         hlayout.addWidget(test_text)
         hlayout.addWidget(test_text_type)
         if param[1] == 'db_connection_hook':
             test_line = QComboBox(widgetTemp)
             db_connection_choices = get_db_connection_names()
             for i in db_connection_choices:
                 test_line.addItem(QString(i))
             self.test_line.append(test_line)
             test_line.setEnabled(True)
             test_line.setMinimumSize(QSize(200,0))
             test_line.setObjectName(QString("test_line").append(QString(i)))
             index = test_line.findText(param[2], Qt.MatchExactly)
             test_line.setCurrentIndex(index)
         else:
             test_line = QLineEdit(widgetTemp)
             self.test_line.append(test_line)
             test_line.setEnabled(True)
             test_line.setMinimumSize(QSize(200,0))
             test_line.setObjectName(QString("test_line").append(QString(i)))
             test_line.setText(QString(param[2]))
         hlayout.addWidget(test_line)
         # If we have a dir_path or file_path add a select button
         if (paramName == QString('dir_path')) or (paramName == QString('file_path')):
             pbnSelect = QPushButton(widgetTemp)
             pbnSelect.setObjectName(QString('pbnSelect').append(QString(i)))
             pbnSelect.setText(QString("Select..."))
             pbnSelectDelegate = FileDialogSignal(typeName=paramName,param=test_line)
             QObject.connect(pbnSelectDelegate.o, SIGNAL("buttonPressed(PyQt_PyObject,PyQt_PyObject)"),
                             self.on_pbnSelect_released)
             QObject.connect(pbnSelect, SIGNAL("released()"), pbnSelectDelegate.relayButtonSignal)
             self.test_line_delegates.append(pbnSelectDelegate)
             self.test_line_buttons.append(pbnSelect)
             hlayout.addWidget(pbnSelect)
         self.vboxlayout.addWidget(widgetTemp)
         self.adjustSize()
     # Jesse adding help text from opusHelp
     tool_path = self.optional_params.get('tool_path','')
     try:
         exec_stmt = 'from %s.%s import opusHelp' % (tool_path, self.module_name)
         exec exec_stmt
         help = QString(opusHelp())
         self.toolhelpEdit.insertPlainText(help)
     except Exception, e:
         help = 'could not find opusHelp function in tool module'
         self.toolhelpEdit.insertPlainText(help)
Exemplo n.º 13
0
class ProjectXively(QWidget):
    qtcb_update_illuminance = pyqtSignal(float)
    qtcb_update_air_pressure = pyqtSignal(float)
    qtcb_update_temperature = pyqtSignal(float)
    qtcb_update_humidity = pyqtSignal(float)
    qtcb_button_pressed = pyqtSignal(int)

    lcdwidget = None

    xively_host = "api.xively.com"
    xively_agent = "Tinkerforge Starter Kit Weather Station Demo"
    xively_channel = "Enter Feed ID here"
    xively_api_key = "Enter API Key here"

    xively_items = {}
    xively_headers = None
    xively_params = ""
    xively_update_rate = 5  # in minutes

    text_agent = None
    text_channel = None
    text_api_key = None
    number_update_rate = None

    save_button = None

    xively_timer = None

    error_message = None

    label_upload_active = None

    last_upload = None

    def __init__(self, parent, app):
        super(QWidget, self).__init__()

        self.lcdwidget = LCDWidget(self, app)
        self.lcdwidget.hide()

        self.text_agent = QLineEdit(self)
        self.text_agent.setText(self.xively_agent)

        self.text_channel = QLineEdit(self)
        self.text_channel.setText(self.xively_channel)

        self.text_api_key = QLineEdit(self)
        self.text_api_key.setText(self.xively_api_key)

        self.number_update_rate = QSpinBox(self)
        self.number_update_rate.setRange(1, 1440)
        self.number_update_rate.setSuffix(' min')
        self.number_update_rate.setValue(self.xively_update_rate)

        layout1 = QHBoxLayout()
        layout2 = QVBoxLayout()

        layout1.addStretch()
        layout1.addLayout(layout2)
        layout1.addStretch()

        layout2.addSpacerItem(QSpacerItem(LCDWidget.FIXED_WIDGTH, 0))

        label = QLabel(self)
        label.setText(
            "Project: <b>Connect to Xively</b>. This project uploads the measured values to Xively. Please find documentation how to configure it and program sources in Python <a href=\"http://www.tinkerforge.com/en/doc/Kits/WeatherStation/WeatherStation.html#connect-to-xively\">here</a>.<br>"
        )
        label.setTextFormat(Qt.RichText)
        label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        label.setOpenExternalLinks(True)
        label.setWordWrap(True)
        label.setAlignment(Qt.AlignJustify)

        layout2.addSpacing(10)
        layout2.addWidget(label)
        layout2.addSpacing(10)

        layout3a = QHBoxLayout()
        label = QLabel("Agent Description:")
        label.setMinimumWidth(150)
        layout3a.addWidget(label)
        layout3a.addWidget(self.text_agent, 1)

        layout2.addLayout(layout3a)
        layout2.addSpacing(10)

        layout3b = QHBoxLayout()
        label = QLabel("Feed:")
        label.setMinimumWidth(150)
        layout3b.addWidget(label)
        layout3b.addWidget(self.text_channel, 1)

        layout2.addLayout(layout3b)
        layout2.addSpacing(10)

        layout3c = QHBoxLayout()
        label = QLabel("API Key:")
        label.setMinimumWidth(150)
        layout3c.addWidget(label)
        layout3c.addWidget(self.text_api_key, 1)

        layout2.addLayout(layout3c)
        layout2.addSpacing(10)

        layout3d = QHBoxLayout()
        label = QLabel("Update Rate:")
        label.setMinimumWidth(150)
        layout3d.addWidget(label)
        layout3d.addWidget(self.number_update_rate, 1)

        layout2.addLayout(layout3d)
        layout2.addSpacing(10)

        self.label_upload_active = QLabel("Not Active", self)
        self.label_upload_active.setMinimumWidth(150)
        font = QFont()
        font.setPixelSize(20)
        self.label_upload_active.setFont(font)
        self.set_active_label(False)

        self.save_button = QPushButton("Save/Activate")

        layout4 = QHBoxLayout()
        layout4.addWidget(self.label_upload_active)
        layout4.addWidget(self.save_button, 1)

        layout2.addLayout(layout4)
        layout2.addStretch()

        self.setLayout(layout1)

        self.qtcb_update_illuminance.connect(self.update_illuminance_data_slot)
        self.qtcb_update_air_pressure.connect(
            self.update_air_pressure_data_slot)
        self.qtcb_update_temperature.connect(self.update_temperature_data_slot)
        self.qtcb_update_humidity.connect(self.update_humidity_data_slot)
        self.qtcb_button_pressed.connect(self.button_pressed_slot)
        self.save_button.clicked.connect(self.save_configuration)

        self.lcdwidget.clear(self)

        self.error_message = QErrorMessage(self)

    def set_active_label(self, value):
        palette = self.label_upload_active.palette()
        if value:
            palette.setColor(self.foregroundRole(), Qt.darkGreen)
            self.label_upload_active.setText("Active")
        else:
            palette.setColor(self.foregroundRole(), Qt.red)
            self.label_upload_active.setText("Not Active")

        self.label_upload_active.setPalette(palette)

    def save_configuration(self):
        try:
            self.xively_agent = str(self.text_agent.text()).decode('ascii')
            self.xively_channel = str(self.text_channel.text()).decode('ascii')
            self.xively_api_key = str(self.text_api_key.text()).decode('ascii')
        except:
            self.error_message.showMessage(
                'Agent, Feed and API Key can only contain ASCII characters')
            return

        self.xively_update_rate = self.number_update_rate.value()

        self.xively_headers = {
            "Content-Type": "application/x-www-form-urlencoded",
            "X-ApiKey": self.xively_api_key,
            "User-Agent": self.xively_agent,
        }
        self.xively_params = "/v2/feeds/" + self.xively_channel

        if self.xively_timer is None:
            self.xively_timer = QTimer(self)
            self.xively_timer.timeout.connect(self.update_xively)
            self.xively_timer.start(self.xively_update_rate * 60 * 1000)

        self.set_active_label(True)
        self.update_xively()

    def write_lcd(self):
        if self.last_upload == None:
            tmp = "Last: Never"
        else:
            tmp = "Last: " + self.last_upload

        self.lcdwidget.write_line(0, 0, "Xively Upload", self)
        self.lcdwidget.write_line(2, 0, tmp, self)

    def update_xively(self):
        if len(self.xively_items) == 0:
            return

        stream_items = []
        for identifier, value in self.xively_items.items():
            stream_items.append({
                'id': identifier,
                'current_value': value[0],
                'min_value': value[1],
                'max_value': value[2]
            })

        data = {'version': '1.0.0', 'datastreams': stream_items}
        self.xively_items = {}
        body = json.dumps(data)

        try:
            http = httplib.HTTPSConnection(self.xively_host)
            http.request('PUT', self.xively_params, body, self.xively_headers)
            response = http.getresponse()
            http.close()

            if response.status != 200:
                self.error_message.showMessage(
                    'Could not upload to xively -> Response:' +
                    str(response.status) + ': ' + response.reason +
                    '. Check your configuration.')
                self.xively_timer.stop()
                self.xively_timer = None
                self.set_active_label(False)
                return
        except Exception as e:
            self.error_message.showMessage('HTTP error: ' + str(e))
            self.xively_timer.stop()
            self.xively_timer = None
            self.set_active_label(False)
            return

        # set upload time if upload was a success
        self.last_upload = time.strftime("%H:%M:%S")

    def put(self, identifier, value):
        self.write_lcd()
        try:
            _, min_value, max_value = self.xively_items[identifier]
            if value < min_value:
                min_value = value
            if value > max_value:
                max_value = value
            self.xively_items[identifier] = (value, min_value, max_value)
        except:
            self.xively_items[identifier] = (value, value, value)

    def update_illuminance_data_slot(self, illuminance):
        self.put('AmbientLight', illuminance)

    def update_illuminance(self, illuminance):
        self.qtcb_update_illuminance.emit(illuminance)

    def update_humidity_data_slot(self, humidity):
        self.put('Humidity', humidity)

    def update_humidity(self, humidity):
        self.qtcb_update_humidity.emit(humidity)

    def update_air_pressure_data_slot(self, air_pressure):
        self.put('AirPressure', air_pressure)

    def update_air_pressure(self, air_pressure):
        self.qtcb_update_air_pressure.emit(air_pressure)

    def update_temperature_data_slot(self, temperature):
        self.put('Temperature', temperature)

    def update_temperature(self, temperature):
        self.qtcb_update_temperature.emit(temperature)

    def button_pressed_slot(self, button):
        pass

    def button_pressed(self, button):
        self.qtcb_button_pressed.emit(button)
Exemplo n.º 14
0
class OutsideChangeWidget( QFrame ):
    " Frameless dialogue to deal with outside changes "

    reloadRequest = pyqtSignal()
    reloadAllNonModifiedRequest = pyqtSignal()

    def __init__( self, parent ):
        QFrame.__init__( self, parent )

        # Make the frame nice looking
        panelColor = QColor( 170, 17, 17 )
        palette = self.palette()
        palette.setColor( self.backgroundRole(), panelColor )
        self.setPalette( palette )

        self.setFrameShape( QFrame.StyledPanel )
        self.setLineWidth( 2 )
        self.setAutoFillBackground( True )

        # Keep pylint happy
        self.__messageLabel = None
        self.__leaveAsIsButton = None
        self.__reloadButton = None
        self.__reloadAllNonChangedButton = None

        self.__markers = []
        self.__createLayout()

        for item in self.__markers:
            item.hide()
        return

    def __createLayout( self ):
        " Creates the widget layout "

        self.__messageLabel = QLabel( "This file has been modified "
                                      "outside of codimension. What "
                                      "would you like to do?" )
        self.__messageLabel.setWordWrap( True )
        self.__messageLabel.setAlignment( Qt.AlignHCenter )
        palette = self.__messageLabel.palette()
        palette.setColor( self.foregroundRole(), QColor( 255, 255, 255, 255 ) )
        self.__messageLabel.setPalette( palette )

        self.__leaveAsIsButton = QPushButton( "Continue editing", self )
        self.__leaveAsIsButton.setToolTip( "ESC" )
        self.__leaveAsIsButton.clicked.connect( self.hide )

        self.__reloadButton = QPushButton( self )
        self.__reloadButton.clicked.connect( self.__reload )

        txt = "Reload all non-modified buffers"
        self.__reloadAllNonChangedButton = QPushButton( txt, self )
        self.__reloadAllNonChangedButton.clicked.connect(
                                                self.__reloadAllNonModified )

        # This will prevent the buttons growing wider than necessary
        fontMetrics = QFontMetrics( self.__reloadAllNonChangedButton.font() )
        buttonWidth = fontMetrics.width( txt ) + 20
        self.__reloadAllNonChangedButton.setFixedWidth( buttonWidth )

        gridLayout = QGridLayout( self )
        gridLayout.setMargin( 3 )

        gridLayout.addWidget( self.__messageLabel, 0, 0, 1, 1 )
        gridLayout.addWidget( self.__leaveAsIsButton, 0, 1, 1, 1 )
        gridLayout.addWidget( self.__reloadButton, 1, 1, 1, 1 )
        gridLayout.addWidget( self.__reloadAllNonChangedButton, 2, 1, 1, 1 )

        self.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed )
        self.move( 5, 5 )


        self.__markers.append( QFrame( self.parent() ) )
        self.__markers.append( QFrame( self.parent() ) )
        self.__markers.append( QFrame( self.parent() ) )
        self.__markers.append( QFrame( self.parent() ) )

        markerColor = QColor( 224, 0, 0, 255 )
        for item in self.__markers:
            pal = item.palette()
            pal.setColor( item.backgroundRole(), markerColor )
            item.setPalette( pal )
            item.setFrameShape( QFrame.StyledPanel )
            item.setLineWidth( 1 )
            item.setAutoFillBackground( True )
            item.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed )
        return

    def resize( self ):
        " Resizes the dialogue to match the editor size "

        vscroll = self.parent().verticalScrollBar()
        if vscroll.isVisible():
            scrollWidth = vscroll.width()
        else:
            scrollWidth = 0

        hscroll = self.parent().horizontalScrollBar()
        if hscroll.isVisible():
            scrollHeight = hscroll.height()
        else:
            scrollHeight = 0

        # Dialogue
        width = self.parent().width()
        height = self.parent().height()
        widgetWidth = width - scrollWidth - 10 - 1

        self.setFixedWidth( widgetWidth )

        # Marker
        self.__markers[ 0 ].move( 1, 1 )
        self.__markers[ 0 ].setFixedWidth( width - scrollWidth - 4 )
        self.__markers[ 0 ].setFixedHeight( 3 )

        self.__markers[ 1 ].move( width - scrollWidth - 5, 1 )
        self.__markers[ 1 ].setFixedWidth( 3 )
        self.__markers[ 1 ].setFixedHeight( height - scrollHeight - 4 )

        self.__markers[ 2 ].move( 1, height - scrollHeight - 5 )
        self.__markers[ 2 ].setFixedWidth( width - scrollWidth - 4 )
        self.__markers[ 2 ].setFixedHeight( 3 )

        self.__markers[ 3 ].move( 1, 1 )
        self.__markers[ 3 ].setFixedWidth( 3 )
        self.__markers[ 3 ].setFixedHeight( height - scrollHeight - 4 )
        return

    def showChoice( self, modified, allEnabled ):
        " Brings up the panel with the correct text and buttons "
        if modified:
            self.__reloadButton.setText( "Reload losing changes" )
        else:
            self.__reloadButton.setText( "Reload" )
        self.__reloadAllNonChangedButton.setEnabled( allEnabled )

        QApplication.processEvents( QEventLoop.ExcludeUserInputEvents )

        self.resize()
        self.show()
        for item in self.__markers:
            item.show()
        self.__leaveAsIsButton.setFocus()
        self.parent().setReadOnly( True )
        return

    def setFocus( self ):
        " Passes the focus to the default button "
        self.__leaveAsIsButton.setFocus()
        return

    def keyPressEvent( self, event ):
        " Handles the key press events "
        if event.key() == Qt.Key_Escape:
            editorsManager = GlobalData().mainWindow.editorsManager()
            activeWindow = editorsManager.currentWidget()
            if activeWindow:
                activeWindow.setFocus()
            event.accept()
            self.hide()
        return

    def hide( self ):
        " Handles the hiding of the panel and markers "
        for item in self.__markers:
            item.hide()
        QFrame.hide( self )
        self.parent().setReadOnly( False )
        self.parent().setFocus()
        return

    def __reload( self ):
        " Reloads the file from the disk "
        self.reloadRequest.emit()
        return

    def __reloadAllNonModified( self ):
        " Reloads all the non-modified buffers "
        self.reloadAllNonModifiedRequest.emit()
        return
Exemplo n.º 15
0
    def __addSimilarity(self, similarity, titleText):
        " Adds a similarity "

        # Label
        title = QLabel(titleText)
        title.setFont(self.__headerFont)

        self.__vLayout.addWidget(title)
        self.__widgets.append(title)

        # List of files
        simTable = QTreeWidget(self.bodyWidget)
        simTable.setAlternatingRowColors(True)
        simTable.setRootIsDecorated(False)
        simTable.setItemsExpandable(False)
        simTable.setSortingEnabled(False)
        simTable.setItemDelegate(NoOutlineHeightDelegate(4))
        simTable.setUniformRowHeights(True)
        simTable.itemActivated.connect(self.__similarityActivated)
        simTable.setHeaderLabels(["File name", "Line"])

        for item in similarity.files:
            values = [item[0], str(item[1])]
            simTable.addTopLevelItem(QTreeWidgetItem(values))

        # Resizing
        simTable.header().resizeSections(QHeaderView.ResizeToContents)
        simTable.header().setStretchLastSection(True)

        # Height
        self.__setTableHeight(simTable)

        self.__vLayout.addWidget(simTable)
        self.__widgets.append(simTable)

        # The fragment itself
        if len(similarity.fragment) > 10:
            # Take first 9 lines
            text = "\n".join(similarity.fragment[:9]) + "\n ..."
            toolTip = "\n".join(similarity.fragment)
        else:
            text = "\n".join(similarity.fragment)
            toolTip = ""
        fragmentLabel = QLabel("<pre>" + self.__htmlEncode(text) + "</pre>")
        if toolTip != "":
            fragmentLabel.setToolTip("<pre>" + self.__htmlEncode(toolTip) +
                                     "</pre>")
        palette = fragmentLabel.palette()
        palette.setColor(QPalette.Background, QColor(250, 250, 175))
        palette.setColor(QPalette.Foreground, QColor(0, 0, 0))
        fragmentLabel.setPalette(palette)
        fragmentLabel.setFrameShape(QFrame.StyledPanel)
        fragmentLabel.setAutoFillBackground(True)

        labelFont = fragmentLabel.font()
        labelFont.setFamily(GlobalData().skin.baseMonoFontFace)
        fragmentLabel.setFont(labelFont)

        self.__vLayout.addWidget(fragmentLabel)
        self.__widgets.append(fragmentLabel)
        return
Exemplo n.º 16
0
    def __createLayout( self, scriptName, name, code, reportTime ):
        " Creates the toolbar and layout "

        # Buttons
        self.__printButton = QAction( PixmapCache().getIcon( 'printer.png' ),
                                      'Print', self )
        self.__printButton.triggered.connect( self.__onPrint )
        self.__printButton.setEnabled( False )
        self.__printButton.setVisible( False )

        self.__printPreviewButton = QAction(
                PixmapCache().getIcon( 'printpreview.png' ),
                'Print preview', self )
        self.__printPreviewButton.triggered.connect( self.__onPrintPreview )
        self.__printPreviewButton.setEnabled( False )
        self.__printPreviewButton.setVisible( False )

        # Zoom buttons
        self.__zoomInButton = QAction( PixmapCache().getIcon( 'zoomin.png' ),
                                       'Zoom in (Ctrl+=)', self )
        self.__zoomInButton.triggered.connect( self.onZoomIn )

        self.__zoomOutButton = QAction( PixmapCache().getIcon( 'zoomout.png' ),
                                        'Zoom out (Ctrl+-)', self )
        self.__zoomOutButton.triggered.connect( self.onZoomOut )

        self.__zoomResetButton = QAction( PixmapCache().getIcon( 'zoomreset.png' ),
                                          'Zoom reset (Ctrl+0)', self )
        self.__zoomResetButton.triggered.connect( self.onZoomReset )

        spacer = QWidget()
        spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding )

        # Toolbar
        toolbar = QToolBar( self )
        toolbar.setOrientation( Qt.Vertical )
        toolbar.setMovable( False )
        toolbar.setAllowedAreas( Qt.RightToolBarArea )
        toolbar.setIconSize( QSize( 16, 16 ) )
        toolbar.setFixedWidth( 28 )
        toolbar.setContentsMargins( 0, 0, 0, 0 )

        toolbar.addAction( self.__printPreviewButton )
        toolbar.addAction( self.__printButton )
        toolbar.addWidget( spacer )
        toolbar.addAction( self.__zoomInButton )
        toolbar.addAction( self.__zoomOutButton )
        toolbar.addAction( self.__zoomResetButton )

        summary = QLabel( "<b>Script:</b> " + scriptName + "<br>"
                          "<b>Name:</b> " + name + "<br>"
                          "<b>Disassembled at:</b> " + reportTime )
        summary.setFrameStyle( QFrame.StyledPanel )
        summary.setAutoFillBackground( True )
        summaryPalette = summary.palette()
        summaryBackground = summaryPalette.color( QPalette.Background )
        summaryBackground.setRgb( min( summaryBackground.red() + 30, 255 ),
                                  min( summaryBackground.green() + 30, 255 ),
                                  min( summaryBackground.blue() + 30, 255 ) )
        summaryPalette.setColor( QPalette.Background, summaryBackground )
        summary.setPalette( summaryPalette )

        self.__text = DisasmWidget( self )
        self.__text.setAcceptRichText( False )
        self.__text.setLineWrapMode( QTextEdit.NoWrap )
        self.__text.setFont( GlobalData().skin.nolexerFont )
        self.zoomTo( Settings().zoom )
        self.__text.setReadOnly( True )
        self.__text.setPlainText( code )

        vLayout = QVBoxLayout()
        vLayout.addWidget( summary )
        vLayout.addWidget( self.__text )

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins( 0, 0, 0, 0 )
        hLayout.setSpacing( 0 )
        hLayout.addLayout( vLayout )
        hLayout.addWidget( toolbar )

        self.setLayout( hLayout )
        return
Exemplo n.º 17
0
class LoaderWidget( QWidget ):
    MOVIE = None
    
    def __init__( self, parent ):
        # initialize the super class
        super(LoaderWidget,self).__init__( parent )
        
        # create the movie
        if ( LoaderWidget.MOVIE == None ):
            LoaderWidget.MOVIE = QMovie(resources.find('img/main/ajax-loader.gif'))
            LoaderWidget.MOVIE.start()
        
        # create the movie label
        self._movieLabel    = QLabel(self)
        self._movieLabel.setMovie(LoaderWidget.MOVIE)
        self._movieLabel.setAlignment(Qt.AlignCenter)
        
        self._messageLabel  = QLabel(self)
        self._messageLabel.setAlignment(Qt.AlignCenter)
        
        palette = self._messageLabel.palette()
        palette.setColor( palette.WindowText, QColor('gray') )
        self._messageLabel.setPalette(palette)
            
        # create the interface
        layout = QVBoxLayout()
        layout.setContentsMargins(0,0,0,0)
        layout.addStretch()
        layout.addWidget( self._movieLabel )
        layout.addWidget( self._messageLabel )
        layout.addStretch()
        
        self.setLayout(layout)
        self.setSizePolicy( QSizePolicy.Preferred, QSizePolicy.Preferred )
        self.resize(0,0)
        self.setMessage('')
        
        # set the default properties
        self.setAutoFillBackground(True)
        self.setBackgroundRole( QPalette.Window )
        
        # create custom properties
        clr = QColor('black')
        clr.setAlpha(150)
        self._backgroundColor = clr
    
    def backgroundColor( self ):
        return self._backgroundColor
    
    def eventFilter( self, object, event ):
        if ( object == self.parent() and event.type() == QEvent.Resize ):
            self.resize(object.size())
        return False
    
    def message( self ):
        return self._messageLabel.text()
    
    def paintEvent( self, event ):
        # make sure we have the proper palette, as if this widget is
        # added to a hierarchy, it may overwrite whats there
        palette = self.palette()
        palette.setColor( QPalette.Window, self._backgroundColor )
        self.setPalette(palette)
        
        super(LoaderWidget,self).paintEvent(event)
    
    def setBackgroundColor( self, clr ):
        self._backgroundColor = QColor(clr)
    
    def setMessage( self, message ):
        self._messageLabel.setText(message)
        self._messageLabel.setVisible(message != '')
    
    @staticmethod
    def start( widget, message = '' ):
        loaders = widget.findChildren(LoaderWidget)
        if ( loaders ):
            loader = loaders[0]
        else:
            loader = LoaderWidget(widget)
            widget.installEventFilter(loader)
            loader.resize(widget.size())
            loader.show()
        
        loader.setMessage(message)
        
        return loader
    
    @staticmethod
    def stop(widget):
        for loader in widget.findChildren(LoaderWidget):
            loader.close()
            loader.setParent(None)
            loader.deleteLater()
Exemplo n.º 18
0
class Tooltip(QFrame):
    " Custom tooltip "

    def __init__(self):
        QFrame.__init__(self)

        # Avoid the border around the window
        self.setWindowFlags(Qt.SplashScreen)

        # Make the frame nice looking
        self.setFrameShape(QFrame.StyledPanel)
        self.setLineWidth(2)

        self.info = None
        self.location = None
        self.__createLayout()

        # The item the tooltip is for
        self.item = None

        # The timer which shows the tooltip. The timer is controlled from
        # outside of the class.
        self.tooltipTimer = QTimer(self)
        self.tooltipTimer.setSingleShot(True)
        self.tooltipTimer.timeout.connect(self.__onTimer)

        self.startPosition = None
        return

    def __createLayout(self):
        " Creates the tooltip layout "
        verticalLayout = QVBoxLayout(self)
        self.info = QLabel()
        self.info.setAutoFillBackground(True)
        font = self.info.font()
        font.setFamily(GlobalData().skin.baseMonoFontFace)
        self.info.setFont(font)
        self.info.setFrameShape(QFrame.StyledPanel)
        verticalLayout.addWidget(self.info)
        verticalLayout.setMargin(0)
        self.location = QLabel()
        verticalLayout.addWidget(self.location)
        return

    def setText(self, text):
        " Sets the tooltip text "
        self.info.setText(text)
        return

    def setLocation(self, text):
        " Sets the file name and line at the bottom "
        self.location.setText(text)
        return

    def setModified(self, status):
        " Sets the required tooltip background "
        palette = self.info.palette()
        if status:
            # Reddish
            palette.setColor(QPalette.Background, QColor(255, 227, 227))
        else:
            # Blueish
            palette.setColor(QPalette.Background, QColor(224, 236, 255))
        self.info.setPalette(palette)
        return

    def setItem(self, item):
        " Sets the item the tooltip is shown for "
        self.item = item
        return

    def __getTooltipPos(self):
        " Calculates the tooltip position - above the row "
        pos = QCursor.pos()
        if pos.x() + self.sizeHint().width() >= screenWidth:
            pos.setX(screenWidth - self.sizeHint().width() - 2)
        pos.setY(pos.y() - cellHeight - 1 - self.sizeHint().height())
        return pos

    def __onTimer(self):
        " Triggered by the show tooltip timer "
        currentPos = QCursor.pos()
        if abs( currentPos.x() - self.startPosition.x() ) <= 2 and \
           abs( currentPos.y() - self.startPosition.y() ) <= 2:
            # No movement since last time, show the tooltip
            self.show()
            return

        # There item has not been changed, but the position within it was
        # So restart the timer, but for shorter
        self.startPosition = currentPos
        self.tooltipTimer.start(400)
        return

    def startShowTimer(self):
        " Memorizes the cursor position and starts the timer "
        self.tooltipTimer.stop()
        self.startPosition = QCursor.pos()
        self.tooltipTimer.start(500)  # 0.5 sec
        return

    def show(self):
        " Shows the tooltip at the proper position "
        QToolTip.hideText()
        QApplication.processEvents()
        if not inside:
            return
        self.move(self.__getTooltipPos())
        self.raise_()
        QFrame.show(self)
        return
Exemplo n.º 19
0
class FindInFilesViewer(QWidget):
    " Find in files viewer tab widget "

    lastEntered = None

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

        global searchTooltip
        searchTooltip = Tooltip()

        self.__reportRegexp = None
        self.__reportResults = []
        self.__reportShown = False
        self.__bufferChangeconnected = False

        # Prepare members for reuse
        self.__noneLabel = QLabel("\nNo results available")

        self.__noneLabel.setFrameShape(QFrame.StyledPanel)
        self.__noneLabel.setAlignment(Qt.AlignHCenter)
        self.__headerFont = self.__noneLabel.font()
        self.__headerFont.setPointSize(self.__headerFont.pointSize() + 4)
        self.__noneLabel.setFont(self.__headerFont)
        self.__noneLabel.setAutoFillBackground(True)
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor(QPalette.Background,
                                  GlobalData().skin.nolexerPaper)
        self.__noneLabel.setPalette(noneLabelPalette)

        # Keep pylint happy
        self.printButton = None
        self.clearButton = None
        self.printPreviewButton = None

        self.__createLayout(parent)

        self.__updateButtonsStatus()

        GlobalData().project.projectChanged.connect(self.__onProjectChanged)
        return

    def __createLayout(self, parent):
        " Creates the toolbar and layout "

        # Buttons
        self.printButton = QAction(PixmapCache().getIcon('printer.png'),
                                   'Print', self)
        #printButton.setShortcut( 'Ctrl+' )
        self.printButton.triggered.connect(self.__onPrint)
        self.printButton.setVisible(False)

        self.printPreviewButton = QAction(
            PixmapCache().getIcon('printpreview.png'), 'Print preview', self)
        #printPreviewButton.setShortcut( 'Ctrl+' )
        self.printPreviewButton.triggered.connect(self.__onPrintPreview)
        self.printPreviewButton.setVisible(False)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.clearButton = QAction(PixmapCache().getIcon('trash.png'), 'Clear',
                                   self)
        self.clearButton.triggered.connect(self.__clear)

        # The toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.printPreviewButton)
        self.toolbar.addAction(self.printButton)
        self.toolbar.addWidget(spacer)
        self.toolbar.addAction(self.clearButton)

        self.__resultsTree = FindResultsTreeWidget()
        self.__resultsTree.setAlternatingRowColors(True)
        self.__resultsTree.setRootIsDecorated(True)
        self.__resultsTree.setItemsExpandable(True)
        self.__resultsTree.setUniformRowHeights(True)
        self.__resultsTree.setItemDelegate(NoOutlineHeightDelegate(4))
        headerLabels = ["File name / line", "Text"]
        self.__resultsTree.setHeaderLabels(headerLabels)
        self.__resultsTree.itemActivated.connect(self.__resultActivated)
        self.__resultsTree.itemClicked.connect(self.__resultClicked)
        self.__resultsTree.setMouseTracking(True)
        self.__resultsTree.itemEntered.connect(self.__itemEntered)
        self.__resultsTree.hide()

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addWidget(self.__resultsTree)

        self.setLayout(self.__hLayout)
        return

    def getResultsTree(self):
        " Provides a reference to the results tree "
        return self.__resultsTree

    def __updateButtonsStatus(self):
        " Updates the buttons status "
        self.printButton.setEnabled(self.__reportShown)
        self.printPreviewButton.setEnabled(self.__reportShown)
        self.clearButton.setEnabled(self.__reportShown)
        return

    def __onPrint(self):
        " Triggered when the print button is pressed "
        pass

    def __onPrintPreview(self):
        " triggered when the print preview button is pressed "
        pass

    def setFocus(self):
        " Overridden setFocus "
        self.__hLayout.setFocus()
        return

    def __onProjectChanged(self, what):
        " Triggered when a project is changed "
        if what == CodimensionProject.CompleteProject:
            self.__clear()
        return

    def __clear(self):
        " Clears the content of the vertical layout "
        if not self.__reportShown:
            return

        # Disconnect the buffer change signal if it is connected
        if self.__bufferChangeconnected:
            self.__bufferChangeconnected = False
            mainWindow = GlobalData().mainWindow
            editorsManager = mainWindow.editorsManagerWidget.editorsManager
            editorsManager.bufferModified.disconnect(
                self.__resultsTree.onBufferModified)

        self.__resultsTree.resetCache()
        self.__resultsTree.clear()
        self.__resultsTree.hide()
        self.__noneLabel.show()

        self.__reportRegexp = None
        self.__reportResults = []
        self.__reportShown = False
        self.__updateButtonsStatus()
        return

    def showReport(self, regexp, results):
        " Shows the find in files results "
        self.__clear()
        self.__noneLabel.hide()

        self.__reportRegexp = regexp
        self.__reportResults = results

        # Add the complete information
        totalMatched = 0
        for item in results:
            matched = len(item.matches)
            totalMatched += matched
            if matched == 1:
                matchText = " (1 match)"
            else:
                matchText = " (" + str(matched) + " matches)"
            columns = [item.fileName, matchText]
            fileItem = MatchTableFileItem(columns, item.bufferUUID)
            fileItem.setIcon(0, getFileIcon(detectFileType(item.fileName)))
            if item.tooltip != "":
                fileItem.setToolTip(0, item.tooltip)
            self.__resultsTree.addTopLevelItem(fileItem)

            # Matches
            for match in item.matches:
                columns = [str(match.line), match.text]
                matchItem = MatchTableItem(columns, match.tooltip)
                fileItem.addChild(matchItem)
            fileItem.setExpanded(True)

        # Update the header with the total number of matches
        headerLabels = [
            "File name / line (total files: " + str(len(results)) + ")",
            "Text (total matches: " + str(totalMatched) + ")"
        ]
        self.__resultsTree.setHeaderLabels(headerLabels)

        # Resizing the table
        self.__resultsTree.header().resizeSections(
            QHeaderView.ResizeToContents)

        # Show the complete information
        self.__resultsTree.show()
        self.__resultsTree.buildCache()

        self.__reportShown = True
        self.__updateButtonsStatus()

        # Connect the buffer change signal if not connected yet
        if not self.__bufferChangeconnected:
            self.__bufferChangeconnected = True
            mainWindow = GlobalData().mainWindow
            editorsManager = mainWindow.editorsManagerWidget.editorsManager
            editorsManager.bufferModified.connect(
                self.__resultsTree.onBufferModified)
        return

    def __resultClicked(self, item, column):
        " Handles the single click "
        hideSearchTooltip()
        return

    def __resultActivated(self, item, column):
        " Handles the double click (or Enter) on a match "
        if type(item) == MatchTableItem:
            fileName = str(item.parent().data(0, Qt.DisplayRole).toString())
            lineNumber = int(item.data(0, Qt.DisplayRole).toString())
            GlobalData().mainWindow.openFile(fileName, lineNumber)
            hideSearchTooltip()
            return

    def __itemEntered(self, item, column):
        " Triggered when the mouse cursor entered a row "

        if type(item) != MatchTableItem:
            self.lastEntered = item
            hideSearchTooltip()
            return

        if column != 1:
            # Show the tooltip only for the column with results
            self.lastEntered = None
            hideSearchTooltip()
            return

        # Memorize the row height for proper tooltip displaying later
        global cellHeight
        cellHeight = self.__resultsTree.visualItemRect(item).height()

        if self.lastEntered != item or not inside:
            item.itemEntered()
            self.lastEntered = item
        return
Exemplo n.º 20
0
class Tooltip(QFrame):
    " Custom tooltip "

    def __init__(self):
        QFrame.__init__(self)

        # Avoid the border around the window
        self.setWindowFlags(Qt.SplashScreen)

        # Make the frame nice looking
        self.setFrameShape(QFrame.StyledPanel)
        self.setLineWidth(2)

        self.info = None
        self.location = None
        self.__createLayout()

        # The item the tooltip is for
        self.item = None

        # The timer which shows the tooltip. The timer is controlled from
        # outside of the class.
        self.tooltipTimer = QTimer(self)
        self.tooltipTimer.setSingleShot(True)
        self.tooltipTimer.timeout.connect(self.__onTimer)

        self.startPosition = None
        return

    def __createLayout(self):
        " Creates the tooltip layout "
        verticalLayout = QVBoxLayout(self)
        self.info = QLabel()
        self.info.setAutoFillBackground(True)
        font = self.info.font()
        font.setFamily(GlobalData().skin.baseMonoFontFace)
        self.info.setFont(font)
        self.info.setFrameShape(QFrame.StyledPanel)
        verticalLayout.addWidget(self.info)
        verticalLayout.setMargin(0)
        self.location = QLabel()
        verticalLayout.addWidget(self.location)
        return

    def setText(self, text):
        " Sets the tooltip text "
        self.info.setText(text)
        return

    def setLocation(self, text):
        " Sets the file name and line at the bottom "
        self.location.setText(text)
        return

    def setModified(self, status):
        " Sets the required tooltip background "
        palette = self.info.palette()
        if status:
            # Reddish
            palette.setColor(QPalette.Background, QColor(255, 227, 227))
        else:
            # Blueish
            palette.setColor(QPalette.Background, QColor(224, 236, 255))
        self.info.setPalette(palette)
        return

    def setItem(self, item):
        " Sets the item the tooltip is shown for "
        self.item = item
        return

    def __getTooltipPos(self):
        " Calculates the tooltip position - above the row "
        pos = QCursor.pos()
        if pos.x() + self.sizeHint().width() >= screenWidth:
            pos.setX(screenWidth - self.sizeHint().width() - 2)
        pos.setY(pos.y() - cellHeight - 1 - self.sizeHint().height())
        return pos

    def __onTimer(self):
        " Triggered by the show tooltip timer "
        currentPos = QCursor.pos()
        if abs(currentPos.x() - self.startPosition.x()) <= 2 and abs(currentPos.y() - self.startPosition.y()) <= 2:
            # No movement since last time, show the tooltip
            self.show()
            return

        # There item has not been changed, but the position within it was
        # So restart the timer, but for shorter
        self.startPosition = currentPos
        self.tooltipTimer.start(400)
        return

    def startShowTimer(self):
        " Memorizes the cursor position and starts the timer "
        self.tooltipTimer.stop()
        self.startPosition = QCursor.pos()
        self.tooltipTimer.start(500)  # 0.5 sec
        return

    def show(self):
        " Shows the tooltip at the proper position "
        QToolTip.hideText()
        QApplication.processEvents()
        if not inside:
            return
        self.move(self.__getTooltipPos())
        self.raise_()
        QFrame.show(self)
        return
Exemplo n.º 21
0
    def toolTypeSelected(self, index):
        #print "Got a new selection"
        #print self.comboBox.itemText(index)

        self.typeSelection = str(self.comboBox.itemText(index))
        for testw in self.test_widget:
            self.vboxlayout.removeWidget(testw)
            testw.hide()
        self.tooltypearray = []
        self.test_widget = []
        self.test_text = []
        self.test_line = []

        # The tool_config will always have tool_config name
        self.tooltypearray.append(["Tool Config Name", "tool_config", ""])

        # Now look up the selected connection type and present to the user...
        # First we start at the tool_library
        tool_name = str(self.typeSelection)
        tool_node = self.tool_nodes[tool_name]
        for param_node in tool_node.find('params'):
            type_val = param_node.get('param_type')
            default_val = param_node.text or ''
            self.tooltypearray.append(
                [param_node.get('name'), type_val, default_val])

        for i, param in enumerate(self.tooltypearray):
            # print "Key: %s , Val: %s" % (param[0],param[1])
            paramName = str(param[0] or '').strip()
            type_val = str(param[1] or '').strip()
            default_val = str(param[2] or '').strip()

            if (i == 0):
                widgetTemp = QFrame(self.variableBox)
                widgetTemp.setFrameStyle(QFrame.Panel | QFrame.Raised)
                widgetTemp.setLineWidth(2)
            else:
                widgetTemp = QWidget(self.variableBox)
            widgetTemp.setObjectName(QString("test_widget").append(QString(i)))
            self.test_widget.append(widgetTemp)
            hlayout = QHBoxLayout(widgetTemp)
            self.hboxlayout.append(hlayout)
            hlayout.setMargin(4)
            hlayout.setSpacing(4)
            hlayout.setObjectName(QString("hboxlayout").append(QString(i)))
            test_text = QLabel(widgetTemp)
            self.test_text.append(test_text)
            test_text.setObjectName(QString("test_text").append(QString(i)))
            if type_val == "Required":
                palette = test_text.palette()
                palette.setColor(QPalette.WindowText, Qt.red)
                test_text.setPalette(palette)
            test_text.setText(paramName)
            test_text_type = QLabel(widgetTemp)
            self.test_text_type.append(test_text_type)
            test_text_type.setObjectName(
                QString("test_text_type").append(QString(i)))
            paramName = type_val
            test_text_type.setText(
                QString("(").append(paramName).append(QString(")")))
            hlayout.addWidget(test_text)
            hlayout.addWidget(test_text_type)
            if type_val == 'db_connection_hook':
                test_line = QComboBox(widgetTemp)
                db_connection_choices = get_db_connection_names()
                for i in db_connection_choices:
                    test_line.addItem(QString(i))
                self.test_line.append(test_line)
                test_line.setEnabled(True)
                test_line.setMinimumSize(QSize(200, 0))
                test_line.setObjectName(
                    QString("test_line").append(QString(i)))
            else:
                test_line = QLineEdit(widgetTemp)
                self.test_line.append(test_line)
                test_line.setEnabled(True)
                test_line.setMinimumSize(QSize(200, 0))
                test_line.setObjectName(
                    QString("test_line").append(QString(i)))
#            test_line = QLineEdit(widgetTemp)
#            self.test_line.append(test_line)
#            test_line.setEnabled(True)
#            test_line.setMinimumSize(QSize(200,0))
#            test_line.setObjectName(QString("test_line").append(QString(i)))
#            test_line.setText(QString(""))
            hlayout.addWidget(test_line)
            self.vboxlayout.addWidget(widgetTemp)
Exemplo n.º 22
0
class PylintViewer(QWidget):
    " Pylint tab widget "

    # Limits to colorize the final score
    BadLimit = 8.5
    GoodLimit = 9.5

    # Options of providing a report
    SingleFile = 0
    DirectoryFiles = 1
    ProjectFiles = 2
    SingleBuffer = 3

    updatePylintTooltip = pyqtSignal(str)

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

        self.__reportUUID = ""
        self.__reportFileName = ""
        self.__reportOption = -1
        self.__reportShown = False
        self.__report = None

        self.__widgets = []

        # Prepare members for reuse
        if GlobalData().pylintAvailable:
            self.__noneLabel = QLabel("\nNo results available")
        else:
            self.__noneLabel = QLabel("\nPylint is not available")
        self.__noneLabel.setAutoFillBackground(True)
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor(QPalette.Background,
                                  GlobalData().skin.nolexerPaper)
        self.__noneLabel.setPalette(noneLabelPalette)

        self.__noneLabel.setFrameShape(QFrame.StyledPanel)
        self.__noneLabel.setAlignment(Qt.AlignHCenter)
        self.__headerFont = self.__noneLabel.font()
        self.__headerFont.setPointSize(self.__headerFont.pointSize() + 4)
        self.__noneLabel.setFont(self.__headerFont)

        self.__createLayout(parent)

        self.__updateButtonsStatus()
        self.resizeEvent()
        return

    def __createLayout(self, parent):
        " Creates the toolbar and layout "

        # Buttons
        self.printButton = QAction(PixmapCache().getIcon('printer.png'),
                                   'Print', self)
        #printButton.setShortcut( 'Ctrl+' )
        self.printButton.triggered.connect(self.__onPrint)
        self.printButton.setVisible(False)

        self.printPreviewButton = QAction(
            PixmapCache().getIcon('printpreview.png'), 'Print preview', self)
        #printPreviewButton.setShortcut( 'Ctrl+' )
        self.printPreviewButton.triggered.connect(self.__onPrintPreview)
        self.printPreviewButton.setVisible(False)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.clearButton = QAction(PixmapCache().getIcon('trash.png'), 'Clear',
                                   self)
        self.clearButton.triggered.connect(self.__clear)

        # The toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.printPreviewButton)
        self.toolbar.addAction(self.printButton)
        self.toolbar.addWidget(spacer)
        self.toolbar.addAction(self.clearButton)

        self.__vLayout = QVBoxLayout()
        self.__vLayout.setContentsMargins(5, 5, 5, 5)
        self.__vLayout.setSpacing(0)
        self.__vLayout.setSizeConstraint(QLayout.SetFixedSize)

        self.__bodyFrame = QFrame(self)
        #        self.__bodyFrame.setFrameShape( QFrame.StyledPanel )
        self.__bodyFrame.setFrameShape(QFrame.NoFrame)

        #        self.__bodyFrame.setSizePolicy( QSizePolicy.Maximum,
        #                                        QSizePolicy.Expanding )
        self.__bodyFrame.setLayout(self.__vLayout)
        self.bodyWidget = QScrollArea(self)
        self.bodyWidget.setFocusPolicy(Qt.NoFocus)
        self.bodyWidget.setWidget(self.__bodyFrame)
        self.bodyWidget.hide()

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addWidget(self.bodyWidget)

        self.setLayout(self.__hLayout)
        return

    def __updateButtonsStatus(self):
        " Updates the buttons status "
        self.printButton.setEnabled(self.__reportShown)
        self.printPreviewButton.setEnabled(self.__reportShown)
        self.clearButton.setEnabled(self.__reportShown)
        return

    def __onPrint(self):
        " Triggered when the print button is pressed "
        pass

    def __onPrintPreview(self):
        " triggered when the print preview button is pressed "
        pass

    def setFocus(self):
        " Overridden setFocus "
        self.__vLayout.setFocus()
        return

    def __clear(self):
        " Clears the content of the vertical layout "
        if not self.__reportShown:
            return

        self.__removeAll()
        self.bodyWidget.hide()
        self.__noneLabel.show()

        self.__report = None
        self.__reportShown = False
        self.__updateButtonsStatus()
        self.resizeEvent()

        self.__updateTooltip()
        return

    def __removeAll(self):
        " Removes all the items from the report "
        for item in self.__widgets:
            item.hide()
            self.__vLayout.removeWidget(item)
            del item

        self.__widgets = []
        return

    def __createScoreLabel(self, score, previousScore, showFileName, fileName):
        " Creates the score label "

        txt = "Score: " + str(score)
        if previousScore != "":
            txt += " / Previous score: " + str(previousScore)
        if not showFileName:
            txt += " for " + os.path.basename(fileName)

        scoreLabel = QLabel(txt)
        scoreLabel.setFrameShape(QFrame.StyledPanel)
        scoreLabel.setFont(self.__headerFont)
        scoreLabel.setAutoFillBackground(True)
        palette = scoreLabel.palette()

        if score < self.BadLimit:
            palette.setColor(QPalette.Background, QColor(255, 127, 127))
            palette.setColor(QPalette.Foreground, QColor(0, 0, 0))
        elif score > self.GoodLimit:
            palette.setColor(QPalette.Background, QColor(220, 255, 220))
            palette.setColor(QPalette.Foreground, QColor(0, 0, 0))
        else:
            palette.setColor(QPalette.Background, QColor(255, 255, 127))
            palette.setColor(QPalette.Foreground, QColor(0, 0, 0))

        scoreLabel.setPalette(palette)
        return scoreLabel

    @staticmethod
    def __setTableHeight(table):
        " Auxiliary function to set the table height "

        # Height - it is ugly and approximate however I am tired of
        # calculating the proper height. Why is this so hard, huh?
        lastRowHeight = table.itemDelegate().lastHeight
        height = lastRowHeight * (table.topLevelItemCount() + 1) + 10
        table.setFixedHeight(height)
        return

    @staticmethod
    def __shouldShowFileName(messages):
        " Decides if the file name column should be supressed "
        if len(messages) == 0:
            return False
        firstName = messages[0].fileName
        for index in range(1, len(messages)):
            if firstName != messages[index].fileName:
                return True
        return False

    def __addErrorsTable(self, messages, showFileName):
        " Creates the messages table "

        errTable = QTreeWidget(self.bodyWidget)
        errTable.setAlternatingRowColors(True)
        errTable.setRootIsDecorated(False)
        errTable.setItemsExpandable(False)
        errTable.setSortingEnabled(True)
        errTable.setItemDelegate(NoOutlineHeightDelegate(4))
        errTable.setUniformRowHeights(True)
        errTable.itemActivated.connect(self.__errorActivated)

        headerLabels = ["File name", "Line", "Message ID", "Object", "Message"]
        errTable.setHeaderLabels(headerLabels)

        for item in messages:
            if item.position is None:
                lineNumber = str(item.lineNumber)
            else:
                lineNumber = str(item.lineNumber) + ":" + str(item.position)
            values = [
                item.fileName, lineNumber, item.messageID, item.objectName,
                item.message
            ]
            errTable.addTopLevelItem(ErrorTableItem(values, 1))

        # Hide the file name column if required
        if not showFileName:
            errTable.setColumnHidden(0, True)

        # Resizing
        errTable.header().resizeSections(QHeaderView.ResizeToContents)
        errTable.header().setStretchLastSection(True)

        # Sort indicator
        if showFileName:
            sortIndex = 0  # By file names
        else:
            sortIndex = 1  # By line number because this is from the same file
        errTable.header().setSortIndicator(sortIndex, Qt.AscendingOrder)
        errTable.sortItems(sortIndex, errTable.header().sortIndicatorOrder())

        # Height
        self.__setTableHeight(errTable)

        self.__vLayout.addWidget(errTable)
        self.__widgets.append(errTable)
        return

    def __addSimilarity(self, similarity, titleText):
        " Adds a similarity "

        # Label
        title = QLabel(titleText)
        title.setFont(self.__headerFont)

        self.__vLayout.addWidget(title)
        self.__widgets.append(title)

        # List of files
        simTable = QTreeWidget(self.bodyWidget)
        simTable.setAlternatingRowColors(True)
        simTable.setRootIsDecorated(False)
        simTable.setItemsExpandable(False)
        simTable.setSortingEnabled(False)
        simTable.setItemDelegate(NoOutlineHeightDelegate(4))
        simTable.setUniformRowHeights(True)
        simTable.itemActivated.connect(self.__similarityActivated)
        simTable.setHeaderLabels(["File name", "Line"])

        for item in similarity.files:
            values = [item[0], str(item[1])]
            simTable.addTopLevelItem(QTreeWidgetItem(values))

        # Resizing
        simTable.header().resizeSections(QHeaderView.ResizeToContents)
        simTable.header().setStretchLastSection(True)

        # Height
        self.__setTableHeight(simTable)

        self.__vLayout.addWidget(simTable)
        self.__widgets.append(simTable)

        # The fragment itself
        if len(similarity.fragment) > 10:
            # Take first 9 lines
            text = "\n".join(similarity.fragment[:9]) + "\n ..."
            toolTip = "\n".join(similarity.fragment)
        else:
            text = "\n".join(similarity.fragment)
            toolTip = ""
        fragmentLabel = QLabel("<pre>" + self.__htmlEncode(text) + "</pre>")
        if toolTip != "":
            fragmentLabel.setToolTip("<pre>" + self.__htmlEncode(toolTip) +
                                     "</pre>")
        palette = fragmentLabel.palette()
        palette.setColor(QPalette.Background, QColor(250, 250, 175))
        palette.setColor(QPalette.Foreground, QColor(0, 0, 0))
        fragmentLabel.setPalette(palette)
        fragmentLabel.setFrameShape(QFrame.StyledPanel)
        fragmentLabel.setAutoFillBackground(True)

        labelFont = fragmentLabel.font()
        labelFont.setFamily(GlobalData().skin.baseMonoFontFace)
        fragmentLabel.setFont(labelFont)

        self.__vLayout.addWidget(fragmentLabel)
        self.__widgets.append(fragmentLabel)
        return

    @staticmethod
    def __htmlEncode(string):
        " Encodes HTML "
        return string.replace( "&", "&amp;" ) \
                     .replace( ">", "&gt;" ) \
                     .replace( "<", "&lt;" )

    def __addSectionSpacer(self):
        " Adds a fixed height spacer to the VBox layout "
        spacer = QWidget()
        spacer.setFixedHeight(10)
        self.__vLayout.addWidget(spacer)
        self.__widgets.append(spacer)
        return

    def __addGenericTable(self, table):
        " Adds a generic table to the report "

        theTable = QTreeWidget(self.bodyWidget)
        theTable.setAlternatingRowColors(True)
        theTable.setRootIsDecorated(False)
        theTable.setItemsExpandable(False)
        theTable.setSortingEnabled(False)
        theTable.setItemDelegate(NoOutlineHeightDelegate(4))
        theTable.setUniformRowHeights(True)

        headerLabels = []
        for index in range(0, len(table.header)):
            headerLabels.append(table.header[index])
        theTable.setHeaderLabels(headerLabels)

        for item in table.body:
            row = []
            for index in range(0, len(table.header)):
                row.append(item[index])
            theTable.addTopLevelItem(QTreeWidgetItem(row))

        theTable.setFocusPolicy(Qt.NoFocus)

        # Resizing
        theTable.header().resizeSections(QHeaderView.ResizeToContents)
        theTable.header().setStretchLastSection(True)

        # Height
        self.__setTableHeight(theTable)

        self.__vLayout.addWidget(theTable)
        self.__widgets.append(theTable)
        return

    def __addGenericTableTitle(self, table):
        " Adds a generic table title "
        tableTitle = QLabel(table.title)
        tableTitle.setFont(self.__headerFont)

        self.__vLayout.addWidget(tableTitle)
        self.__widgets.append(tableTitle)
        return

    def __updateTooltip(self):
        " Generates a signal with appropriate string message "
        if not self.__reportShown:
            tooltip = "No results available"
        elif self.__reportOption == self.DirectoryFiles:
            tooltip = "Report generated for directory: " + \
                      self.__reportFileName
        elif self.__reportOption == self.ProjectFiles:
            tooltip = "Report generated for the whole project"
        elif self.__reportOption == self.SingleFile:
            tooltip = "Report generated for file: " + self.__reportFileName
        elif self.__reportOption == self.SingleBuffer:
            tooltip = "Report generated for unsaved file: " + \
                      self.__reportFileName
        else:
            tooltip = ""
        self.updatePylintTooltip.emit(tooltip)
        return

    def showReport(self, lint, reportOption, fileName, uuid):
        " Shows the pylint results "
        self.__removeAll()
        self.__noneLabel.hide()

        self.__report = lint
        self.__reportUUID = uuid
        self.__reportFileName = fileName
        self.__reportOption = reportOption

        showFileName = self.__shouldShowFileName(lint.errorMessages)

        scoreLabel = self.__createScoreLabel(lint.score, lint.previousScore,
                                             showFileName, fileName)
        self.__vLayout.addWidget(scoreLabel)
        self.__widgets.append(scoreLabel)

        if len(lint.errorMessages) > 0:
            self.__addSectionSpacer()
            self.__addErrorsTable(lint.errorMessages, showFileName)

        index = 0
        for similarity in lint.similarities:
            self.__addSectionSpacer()
            self.__addSimilarity(similarity, "Similarity #" + str(index))
            index += 1

        for table in lint.tables:
            self.__addSectionSpacer()
            self.__addGenericTableTitle(table)
            self.__addGenericTable(table)

        self.bodyWidget.show()
        self.bodyWidget.ensureVisible(0, 0, 0, 0)
        self.__reportShown = True
        self.__updateButtonsStatus()
        self.__updateTooltip()

        # It helps, but why do I have flickering?
        QApplication.processEvents()
        self.__resizeBodyFrame()
        return

    def __errorActivated(self, item, column):
        " Handles the double click (or Enter) on the item "

        linePos = str(item.text(1))
        if ":" in linePos:
            parts = linePos.split(":")
            lineNumber = int(parts[0])
            pos = int(parts[1])
        else:
            lineNumber = int(linePos)
            pos = 0

        if self.__reportOption in [
                self.SingleFile, self.DirectoryFiles, self.ProjectFiles
        ]:
            fileName = str(item.text(0))
        else:
            # SingleBuffer
            if self.__reportFileName != "":
                if os.path.isabs(self.__reportFileName):
                    fileName = self.__reportFileName
                else:
                    # Could be unsaved buffer, so try to search by the
                    mainWindow = GlobalData().mainWindow
                    widget = mainWindow.getWidgetByUUID(self.__reportUUID)
                    if widget is None:
                        logging.error("The unsaved buffer has been closed")
                        return
                    # The widget was found, so jump to the required
                    editor = widget.getEditor()
                    editor.gotoLine(lineNumber, pos)
                    editor.setFocus()
                    return

        GlobalData().mainWindow.openFile(fileName, lineNumber, pos)
        return

    def __resizeBodyFrame(self):
        " Resizing the frame to occupy all available width "
        size = self.bodyWidget.maximumViewportSize()
        self.__bodyFrame.setMinimumWidth(size.width() - 16)
        self.__bodyFrame.setMinimumHeight(size.height())
        return

    def showEvent(self, showEv=None):
        " Called when the widget is shown "
        self.__resizeBodyFrame()
        return

    def resizeEvent(self, resizeEv=None):
        " Called when the main window gets resized "
        self.__resizeBodyFrame()
        return

    def onFileUpdated(self, fileName, uuid):
        " Called when a buffer is saved or saved as "

        if not self.__reportShown:
            return
        if self.__reportUUID != uuid:
            return

        # Currently shown report is for the saved buffer
        # File name is expected being absolute
        self.__reportFileName = fileName
        self.updatePylintTooltip.emit("Report generated for buffer saved as " +
                                      fileName)
        return

    def __similarityActivated(self, item, column):
        " Triggered when a similarity is activated "
        fileName = str(item.text(0))
        lineNumber = int(item.text(1))
        GlobalData().mainWindow.openFile(fileName, lineNumber)
        return
Exemplo n.º 23
0
    class InfoBoxWidget(QWidget):
        intensity_field = ""
        total_rays_field = ""
        total_good_rays_field = ""
        total_lost_rays_field = ""
        fwhm_h_field = ""
        fwhm_v_field = ""

        def __init__(self, x_scale_factor = 1.0, y_scale_factor = 1.0, is_2d=True):
            super(ShadowPlot.InfoBoxWidget, self).__init__()

            info_box_inner=ShadowGui.widgetBox(self, "Info")
            info_box_inner.setFixedHeight(180*y_scale_factor)
            info_box_inner.setFixedWidth(250*x_scale_factor)

            self.intensity = ShadowGui.lineEdit(info_box_inner, self, "intensity_field", "Intensity", tooltip="Intensity", labelWidth=110, valueType=str, orientation="horizontal")
            self.total_rays = ShadowGui.lineEdit(info_box_inner, self, "total_rays_field", "Total Rays", tooltip="Total Rays", labelWidth=110, valueType=str, orientation="horizontal")
            self.total_good_rays = ShadowGui.lineEdit(info_box_inner, self, "total_good_rays_field", "Total Good Rays", tooltip="Total Good Rays", labelWidth=110, valueType=str, orientation="horizontal")
            self.total_lost_rays = ShadowGui.lineEdit(info_box_inner, self, "total_lost_rays_field", "Total Lost Rays", tooltip="Total Lost Rays", labelWidth=110, valueType=str, orientation="horizontal")

            label_box_1 = ShadowGui.widgetBox(info_box_inner, "", addSpace=False, orientation="horizontal")

            self.label_h = QLabel("FWHM ")
            self.label_h.setFixedWidth(110)
            palette =  QPalette(self.label_h.palette())
            palette.setColor(QPalette.Foreground, QColor('blue'))
            self.label_h.setPalette(palette)
            label_box_1.layout().addWidget(self.label_h)
            self.fwhm_h = ShadowGui.lineEdit(label_box_1, self, "fwhm_h_field", "", tooltip="FWHM", labelWidth=110, valueType=str, orientation="horizontal")

            if is_2d:
                label_box_2 = ShadowGui.widgetBox(info_box_inner, "", addSpace=False, orientation="horizontal")

                self.label_v = QLabel("FWHM ")
                self.label_v.setFixedWidth(110)
                palette =  QPalette(self.label_h.palette())
                palette.setColor(QPalette.Foreground, QColor('red'))
                self.label_v.setPalette(palette)
                label_box_2.layout().addWidget(self.label_v)
                self.fwhm_v = ShadowGui.lineEdit(label_box_2, self, "fwhm_v_field", "", tooltip="FWHM", labelWidth=110, valueType=str, orientation="horizontal")

            self.intensity.setReadOnly(True)
            font = QFont(self.intensity.font())
            font.setBold(True)
            self.intensity.setFont(font)
            palette = QPalette(self.intensity.palette())
            palette.setColor(QPalette.Text, QColor('dark blue'))
            palette.setColor(QPalette.Base, QColor(243, 240, 160))
            self.intensity.setPalette(palette)

            self.total_rays.setReadOnly(True)
            font = QFont(self.total_rays.font())
            font.setBold(True)
            self.total_rays.setFont(font)
            palette = QPalette(self.intensity.palette())
            palette.setColor(QPalette.Text, QColor('dark blue'))
            palette.setColor(QPalette.Base, QColor(243, 240, 160))
            self.total_rays.setPalette(palette)

            self.total_good_rays.setReadOnly(True)
            font = QFont(self.total_good_rays.font())
            font.setBold(True)
            self.total_good_rays.setFont(font)
            palette = QPalette(self.total_good_rays.palette())
            palette.setColor(QPalette.Text, QColor('dark blue'))
            palette.setColor(QPalette.Base, QColor(243, 240, 160))
            self.total_good_rays.setPalette(palette)

            self.total_lost_rays.setReadOnly(True)
            font = QFont(self.total_lost_rays.font())
            font.setBold(True)
            self.total_lost_rays.setFont(font)
            palette = QPalette(self.total_lost_rays.palette())
            palette.setColor(QPalette.Text, QColor('dark blue'))
            palette.setColor(QPalette.Base, QColor(243, 240, 160))
            self.total_lost_rays.setPalette(palette)

            self.fwhm_h.setReadOnly(True)
            font = QFont(self.intensity.font())
            font.setBold(True)
            self.fwhm_h.setFont(font)
            palette = QPalette(self.fwhm_h.palette())
            palette.setColor(QPalette.Text, QColor('dark blue'))
            palette.setColor(QPalette.Base, QColor(243, 240, 160))
            self.fwhm_h.setPalette(palette)

            if is_2d:
                self.fwhm_v.setReadOnly(True)
                font = QFont(self.fwhm_v.font())
                font.setBold(True)
                self.fwhm_v.setFont(font)
                palette = QPalette(self.fwhm_v.palette())
                palette.setColor(QPalette.Text, QColor('dark blue'))
                palette.setColor(QPalette.Base, QColor(243, 240, 160))
                self.fwhm_v.setPalette(palette)

        def clear(self):
            self.intensity.setText("0.0")
            self.total_rays.setText("0")
            self.total_good_rays.setText("0")
            self.total_lost_rays.setText("0")
            self.fwhm_h.setText("0.0000")
            if hasattr(self, "fwhm_v"):  self.fwhm_v.setText("0.0000")
Exemplo n.º 24
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
Exemplo n.º 25
0
class Calltip( QFrame ):
    " Frameless panel with a calltip "

    def __init__( self, parent ):
        QFrame.__init__( self, parent )

        # Make the frame nice looking
        palette = self.palette()
        palette.setColor( self.backgroundRole(),
                          GlobalData().skin.calltipPaper )
        self.setPalette( palette )

        self.setFrameShape( QFrame.StyledPanel )
        self.setLineWidth( 2 )
        self.setAutoFillBackground( True )

        # Keep pylint happy
        self.__calltipLabel = None
        self.__text = None
        self.__paramPositions = None
        self.__highlightedParam = None

        self.__createLayout()
        QFrame.hide( self )
        self.setFocusPolicy( Qt.NoFocus )
        return

    def __createLayout( self ):
        " Creates the widget layout "

        self.__calltipLabel = QLabel( "" )
        self.__calltipLabel.setSizePolicy( QSizePolicy.Ignored,
                                           QSizePolicy.Fixed )
        self.__calltipLabel.setWordWrap( False )
        self.__calltipLabel.setAlignment( Qt.AlignLeft )
        palette = self.__calltipLabel.palette()
        palette.setColor( self.foregroundRole(),
                          GlobalData().skin.calltipColor )
        self.__calltipLabel.setPalette( palette )

        gridLayout = QGridLayout( self )
        gridLayout.setMargin( 3 )
        gridLayout.addWidget( self.__calltipLabel, 0, 0, 1, 1 )

        self.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed )
        return

    def resize( self ):
        " Resizes the dialogue to match the editor size "

        vscroll = self.parent().verticalScrollBar()
        if vscroll.isVisible():
            scrollWidth = vscroll.width()
        else:
            scrollWidth = 0

        hscroll = self.parent().horizontalScrollBar()
        if hscroll.isVisible():
            scrollHeight = hscroll.height()
        else:
            scrollHeight = 0

        # Panel
        width = self.parent().width()
        height = self.parent().height()
        widgetWidth = width - scrollWidth - 6 - 1

        self.setFixedWidth( widgetWidth )

        vPos = height - self.height() - scrollHeight
        self.move( 3, vPos - 3 )
        return

    def showCalltip( self, message, paramNumber ):
        " Brings up the panel with the required text "
        self.__text = message
        self.__calcParamPositions()
        self.highlightParameter( paramNumber )
        QApplication.processEvents( QEventLoop.ExcludeUserInputEvents )

        self.resize()
        self.show()

        # I have to do resize() twice because the self.height() value is
        # calculated in a different way before the frame is shown and after.
        # So the first call moves the widget to the nearly right location
        # and the second to the precise one
        self.resize()
        return

    def highlightParameter( self, number ):
        " Hightlights the given parameter number, 0 - based "
        if number == self.__highlightedParam:
            return
        if self.__paramPositions is None:
            self.__calltipLabel.setText( self.__text )
            return
        if number >= len( self.__paramPositions ):
            self.__calltipLabel.setText( self.__text )
            return
        positions = self.__paramPositions[ number ]
        highlight = self.__text[ 0 : positions[ 0 ] ] + "<font color='" + \
                    GlobalData().skin.calltipHighColor.name() + "'>" + \
                    self.__text[ positions[ 0 ] : positions[ 1 ] + 1 ] + \
                    "</font>" + self.__text[ positions[ 1 ] + 1 : ]
        self.__calltipLabel.setText( highlight )
        return

    def __calcParamPositions( self ):
        " Calculates the parameter positions in the calltip text "
        if self.__text is None or '\n' in self.__text:
            self.__paramPositions = None
            return

        try:
            begin = self.__text.index( '(' ) + 1
        except:
            self.__paramPositions = None
            return

        if self.__text[ begin ] == '.':
            # Special case for f(...)
            self.__paramPositions = None
            return

        self.__paramPositions = []
        lastIndex = len( self.__text ) - 1
        index = begin
        level = 0               # Unconditional skip of commas
        singleQuote = False
        doubleQuote = False
        while index <= lastIndex:
            ch = self.__text[ index ]
            if ch == "'" and singleQuote:
                singleQuote = False
            elif ch == '"' and doubleQuote:
                doubleQuote = False
            elif ch == "'":
                singleQuote = False
            elif ch == '"':
                doubleQuote = False
            elif ch in [ '(', '{' ]:
                level += 1
            elif ch in [ ')', '}' ]:
                level -= 1
                if level == -1:
                    # Closing bracket
                    if index > begin:
                        self.__paramPositions.append( (begin, index - 1) )
                    break
            elif ch == '[':
                if level > 0:
                    index += 1
                    continue
                # if a previous char is '=' then it is a default paam
                checkIndex = index - 1
                while self.__text[ checkIndex ].isspace():
                    checkIndex -= 1
                if self.__text[ checkIndex ] == '=':
                    level += 1
                    index += 1
                    continue

                if self.__text[ checkIndex ] == '(':
                    # The very first round bracket
                    index = index + 1
                    begin = index
                    continue

                # '[' after a parameter name
                if index > begin:
                    self.__paramPositions.append( (begin, index - 1) )
                    # The next meaningfull character is comma or an identifier
                    index += 1
                    while index <= lastIndex and self.__text[ index ].isspace():
                        index += 1
                    if self.__text[ index ] == ',':
                        index += 1
                    index += 1
                    begin = index
                    continue

                # I don't know what it is
                self.__paramPositions = None
                return

            elif ch == ']':
                if level > 0:
                    level -= 1
                    index += 1
                    continue

                # This must be an optional argument closing bracket
                checkIndex = index - 1
                while self.__text[ checkIndex ].isspace():
                    checkIndex -= 1

                if self.__text[ checkIndex ] == ']':
                    index += 1
                    continue

                # Need to add and this is the last parameter
                if index > begin:
                    self.__paramPositions.append( (begin, index - 1) )
                break

            elif ch == ',':
                if level == 0:
                   self.__paramPositions.append( (begin, index - 1) )
                # Skip till the beginning of the next parameter - it must be there
                index += 1
                while index <= lastIndex and self.__text[ index ].isspace():
                    index += 1
                begin = index
                continue

            index += 1

        if len( self.__paramPositions ) == 0:
            self.__paramPositions = None
        return

    def hide( self ):
        " Handles the hiding of the panel and markers "
        QFrame.hide( self )
        self.__text = None
        self.__paramPositions = None
        self.__highlightedParam = None
        self.__calltipLabel.setText( "" )
        return
Exemplo n.º 26
0
class _QueuedMessageWidget(QWidget):
    
    cleared = pyqtSignal()
    finished = pyqtSignal()
    shown = pyqtSignal()
    closed = pyqtSignal()
    linkActivated = pyqtSignal(unicode)
    linkHovered= pyqtSignal(unicode)
    buttonClicked = pyqtSignal(QAbstractButton)
    
    def __init__(self, *args):
        QWidget.__init__(self, *args)
        self._messages = []
        self._defaultTimeout = 0
        self._defaultPixmap = QPixmap(":/enkiicons/infos.png" )
        self._defaultBackground = QBrush( QColor( 250, 230, 147 ) )
        self._defaultForeground = QBrush( QColor( 0, 0, 0 ) )
        
        # pixmap
        self.lPixmap = QLabel( self )
        self.lPixmap.setAlignment( Qt.AlignCenter )
        self.lPixmap.setSizePolicy( QSizePolicy( QSizePolicy.Maximum, QSizePolicy.Preferred ) )
        
        # message
        self.lMessage = QLabel( self )
        self.lMessage.setAlignment( Qt.AlignVCenter | Qt.AlignLeft )
        self.lMessage.setSizePolicy( QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred ) )
        self.lMessage.setWordWrap( True )
        self.lMessage.setOpenExternalLinks( True )
        self.lMessage.setTextInteractionFlags( Qt.TextBrowserInteraction )
        
        # button
        self.dbbButtons = QDialogButtonBox( self )
        
        # if false - buttons don't have neither text nor icons
        self.dbbButtons.setStyleSheet("dialogbuttonbox-buttons-have-icons: true;")

        self.dbbButtons.setSizePolicy( QSizePolicy( QSizePolicy.Maximum, QSizePolicy.Preferred ) )
        
        self.setSizePolicy( QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Maximum ) )
        
        # layout
        self.hbl = QHBoxLayout( self )
        self.hbl.setMargin( 0 )
        self.hbl.addWidget( self.lPixmap, 0, Qt.AlignCenter )
        self.hbl.addWidget( self.lMessage )
        self.hbl.addWidget( self.dbbButtons, 0, Qt.AlignCenter )
        
        # connections
        self.lMessage.linkActivated.connect(self.linkActivated)
        self.lMessage.linkHovered.connect(self.linkHovered)
        self.dbbButtons.clicked.connect(self.buttonClicked)

    def sizeHint(self):
        return QWidget.minimumSizeHint(self)

    def openExternalLinks(self):
        return self.lMessage.openExternalLinks()

    def defaultTimeout(self):
        return self._defaultTimeout

    def defaultPixmap(self):
        return self._defaultPixmap

    def defaultBackground(self):
        return self._defaultBackground

    def defaultForeground(self):
        return self._defaultForeground

    def currentMessageInformations(self):
        return self.currentMessagePixmap(), self.currentMessageBackground(), self.currentMessageForeground()

    def pendingMessageCount(self):
        return len(self._messages)

    def currentMessage(self):
        return self._messages[0]

    def append(self, message, milliSeconds ):
        msg = _QueuedMessage()
        msg.message = message
        if milliSeconds == -1:
            msg.milliSeconds = self._defaultTimeout
        else:
           msg.milliSeconds = milliSeconds
        msg.pixmap = self._defaultPixmap
        msg.background = self._defaultBackground
        msg.foreground = self._defaultForeground
        
        self._messages.append(msg)
            
        if  len(self._messages) == 1 :
            QTimer.singleShot( 0, self.showMessage)

    def setOpenExternalLinks(self, open ):
        self.lMessage.setOpenExternalLinks( open )

    def setDefaultTimeout(self, timeout ):
        self._defaultTimeout = timeout

    def setDefaultPixmap(self, pixmap ):
        self._defaultPixmap = pixmap

    def setDefaultBackground(self, brush ):
        self._defaultBackground = brush

    def setDefaultForeground(self, brush ):
        self._defaultForeground = brush

    def remove(self, message ):
        raise NotImplemented()  # incorrect port from cpp fresh
        if not self._messages or self._messages.first() == message:
            return

        self._messages.removeOne( message )

    def clear(self):
        self._messages.clear()
        self.lPixmap.clear()
        self.lMessage.clear()
        self.dbbButtons.clear()
        self.cleared.emit()

    def currentMessagePixmap(self):
        msg = self.currentMessage()
        if msg.pixmap.isNull():
            return self._defaultPixmap
        else:
            return msg.pixmap

    def currentMessageBackground(self):
        msg = self.currentMessage()
        if msg.background == QBrush( Qt.NoBrush ):
            return self._defaultBackground
        else:
            return msg.background

    def currentMessageForeground(self):
        msg = self.currentMessage()
        if msg.foreground == QBrush( Qt.NoBrush ):
            return self._defaultForeground
        else:
            return msg.foreground

    def paintEvent(self, event ):
        if  self.pendingMessageCount() == 0 :
            QWidget.paintEvent(self, event )
            return
        
        painter = QPainter( self )
        painter.setPen( Qt.NoPen )
        painter.setBrush( self.currentMessageBackground() )
        painter.drawRect( self.contentsRect() )

    def buttonClicked(self, button ):
        msg = self.currentMessage()
        standardButton = self.dbbButtons.standardButton( button )
        
        if msg.slot is not None:
            msg.slot(standardButton, msg)
        
        self.closeMessage()

    def showMessage(self):
        # get message
        msg = self.currentMessage()
        
        # update palette
        pal = self.lMessage.palette()
        pal.setBrush( self.lMessage.foregroundRole(), self.currentMessageForeground() )
        self.lMessage.setPalette( pal )
        
        # format widget
        self.lPixmap.setPixmap( self.currentMessagePixmap() )
        self.lMessage.setText( msg.message )
        self.lMessage.setToolTip( msg.message )
        self.lMessage.setWhatsThis( msg.message )
        
        # set buttons
        if not msg.buttons:
            msg.buttons[ QDialogButtonBox.Close ] = None

        self.dbbButtons.clear()
        
        for button in msg.buttons.keys():
            pb = self.dbbButtons.addButton( button )
            
            if button in msg.buttons:
                pb.setText( msg.buttons[ button ] )
        
        # auto close if needed
        if msg.milliSeconds == -1:
            timeout = self._defaultTimeout
        else:
            timeout =  msg.milliSeconds
        
        if  timeout > 0:
            QTimer.singleShot( timeout, self.closeMessage )
        
        # signal.emit
        self.shown.emit()

    def closeMessage(self):
        # message.emit
        self.closed.emit()
        
        # remove remove current message from hash
        self._messages = self._messages[1:]
        
        # process next if possible, clear gui
        if self._messages:
            QTimer.singleShot( 0, self.showMessage)
        else:
            QTimer.singleShot( 0, self.clearMessage)
        
        # finished.emit message if needed
        if not self._messages:
            self.finished.emit()

    def clearMessage(self):
        self.lPixmap.clear()
        self.lMessage.clear()
        self.dbbButtons.clear()
Exemplo n.º 27
0
    def toolTypeSelected(self, index):
        #print "Got a new selection"
        #print self.comboBox.itemText(index)

        self.typeSelection = str(self.comboBox.itemText(index))
        for testw in self.test_widget:
            self.vboxlayout.removeWidget(testw)
            testw.hide()
        self.tooltypearray = []
        self.test_widget = []
        self.test_text = []
        self.test_line = []

        # The tool_config will always have tool_config name
        self.tooltypearray.append(["Tool Config Name","tool_config",""])

        # Now look up the selected connection type and present to the user...
        # First we start at the tool_library
        tool_name = str(self.typeSelection)
        tool_node = self.tool_nodes[tool_name]
        for param_node in tool_node.find('params'):
            type_val = param_node.get('param_type')
            default_val = param_node.text or ''
            self.tooltypearray.append([param_node.get('name'), type_val, default_val])

        for i, param in enumerate(self.tooltypearray):
            # print "Key: %s , Val: %s" % (param[0],param[1])
            paramName = str(param[0] or '').strip()
            type_val = str(param[1] or '').strip()
            default_val = str(param[2] or '').strip()

            if (i==0):
                widgetTemp = QFrame(self.variableBox)
                widgetTemp.setFrameStyle(QFrame.Panel | QFrame.Raised)
                widgetTemp.setLineWidth(2)
            else:
                widgetTemp = QWidget(self.variableBox)
            widgetTemp.setObjectName(QString("test_widget").append(QString(i)))
            self.test_widget.append(widgetTemp)
            hlayout = QHBoxLayout(widgetTemp)
            self.hboxlayout.append(hlayout)
            hlayout.setMargin(4)
            hlayout.setSpacing(4)
            hlayout.setObjectName(QString("hboxlayout").append(QString(i)))
            test_text = QLabel(widgetTemp)
            self.test_text.append(test_text)
            test_text.setObjectName(QString("test_text").append(QString(i)))
            if type_val == "Required":
                palette = test_text.palette()
                palette.setColor(QPalette.WindowText,Qt.red)
                test_text.setPalette(palette)
            test_text.setText(paramName)
            test_text_type = QLabel(widgetTemp)
            self.test_text_type.append(test_text_type)
            test_text_type.setObjectName(QString("test_text_type").append(QString(i)))
            paramName = type_val
            test_text_type.setText(QString("(").append(paramName).append(QString(")")))
            hlayout.addWidget(test_text)
            hlayout.addWidget(test_text_type)
            if type_val == 'db_connection_hook':
                test_line = QComboBox(widgetTemp)
                db_connection_choices = get_db_connection_names()
                for i in db_connection_choices:
                    test_line.addItem(QString(i))
                self.test_line.append(test_line)
                test_line.setEnabled(True)
                test_line.setMinimumSize(QSize(200,0))
                test_line.setObjectName(QString("test_line").append(QString(i)))
            else:
                test_line = QLineEdit(widgetTemp)
                self.test_line.append(test_line)
                test_line.setEnabled(True)
                test_line.setMinimumSize(QSize(200,0))
                test_line.setObjectName(QString("test_line").append(QString(i)))
#            test_line = QLineEdit(widgetTemp)
#            self.test_line.append(test_line)
#            test_line.setEnabled(True)
#            test_line.setMinimumSize(QSize(200,0))
#            test_line.setObjectName(QString("test_line").append(QString(i)))
#            test_line.setText(QString(""))
            hlayout.addWidget(test_line)
            self.vboxlayout.addWidget(widgetTemp)
Exemplo n.º 28
0
class PymetricsViewer( QWidget ):
    " Pymetrics tab widget "

    # Limits to colorize the McCabe score
    LittleRiskLimit = 10
    ModerateRiskLimit = 20
    HighRiskLimit = 50

    # Options of providing a report
    SingleFile     = 0
    DirectoryFiles = 1
    ProjectFiles   = 2
    SingleBuffer   = 3

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

        self.__reportUUID = ""
        self.__reportFileName = ""
        self.__reportOption = -1
        self.__reportShown = False
        self.__report = None

        # Prepare members for reuse
        self.__noneLabel = QLabel( "\nNo results available" )

        self.__noneLabel.setFrameShape( QFrame.StyledPanel )
        self.__noneLabel.setAlignment( Qt.AlignHCenter )
        self.__headerFont = self.__noneLabel.font()
        self.__headerFont.setPointSize( self.__headerFont.pointSize() + 4 )
        self.__noneLabel.setFont( self.__headerFont )
        self.__noneLabel.setAutoFillBackground( True )
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor( QPalette.Background,
                                   GlobalData().skin.nolexerPaper )
        self.__noneLabel.setPalette( noneLabelPalette )

        self.__createLayout( parent )

        self.__updateButtonsStatus()
        return

    def __createLayout( self, parent ):
        " Creates the toolbar and layout "

        # Buttons
        self.__mcCabeButton = QAction( PixmapCache().getIcon( 'tableview.png' ),
                                       'Switch to McCabe only table view',
                                       self )
        self.__mcCabeButton.setCheckable( True )
        self.connect( self.__mcCabeButton, SIGNAL( 'toggled(bool)' ),
                      self.__onMcCabe )

        self.printButton = QAction( PixmapCache().getIcon( 'printer.png' ),
                                    'Print', self )
        #printButton.setShortcut( 'Ctrl+' )
        self.connect( self.printButton, SIGNAL( 'triggered()' ),
                      self.__onPrint )
        self.printButton.setVisible( False )

        self.printPreviewButton = QAction(
                PixmapCache().getIcon( 'printpreview.png' ),
                'Print preview', self )
        #printPreviewButton.setShortcut( 'Ctrl+' )
        self.connect( self.printPreviewButton, SIGNAL( 'triggered()' ),
                      self.__onPrintPreview )
        self.printPreviewButton.setVisible( False )

        spacer = QWidget()
        spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding )

        self.clearButton = QAction(
            PixmapCache().getIcon( 'trash.png' ),
            'Clear', self )
        self.connect( self.clearButton, SIGNAL( 'triggered()' ),
                      self.__clear )

        # The toolbar
        self.toolbar = QToolBar( self )
        self.toolbar.setOrientation( Qt.Vertical )
        self.toolbar.setMovable( False )
        self.toolbar.setAllowedAreas( Qt.RightToolBarArea )
        self.toolbar.setIconSize( QSize( 16, 16 ) )
        self.toolbar.setFixedWidth( 28 )
        self.toolbar.setContentsMargins( 0, 0, 0, 0 )

        self.toolbar.addAction( self.__mcCabeButton )
        self.toolbar.addAction( self.printPreviewButton )
        self.toolbar.addAction( self.printButton )
        self.toolbar.addWidget( spacer )
        self.toolbar.addAction( self.clearButton )

        self.__totalResultsTree = QTreeWidget()
        self.__totalResultsTree.setAlternatingRowColors( True )
        self.__totalResultsTree.setRootIsDecorated( True )
        self.__totalResultsTree.setItemsExpandable( True )
        self.__totalResultsTree.setUniformRowHeights( True )
        self.__totalResultsTree.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        headerLabels = [ "Path / name", "Value", "" ]
        self.__totalResultsTree.setHeaderLabels( headerLabels )
        self.connect( self.__totalResultsTree,
                      SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ),
                      self.__allItemActivated )
        self.connect( self.__totalResultsTree,
                      SIGNAL( "itemExpanded(QTreeWidgetItem *)" ),
                      self.__onResultsExpanded )
        self.__totalResultsTree.setColumnHidden( 2, True )
        self.__totalResultsTree.hide()

        self.__mcCabeTable = QTreeWidget()
        self.__mcCabeTable.setAlternatingRowColors( True )
        self.__mcCabeTable.setRootIsDecorated( False )
        self.__mcCabeTable.setItemsExpandable( False )
        self.__mcCabeTable.setSortingEnabled( True )
        self.__mcCabeTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.__mcCabeTable.setUniformRowHeights( True )
        headerLabels = [ "", "File name", "Object", "McCabe Complexity" ]
        self.__mcCabeTable.setHeaderLabels( headerLabels )
        self.connect( self.__mcCabeTable,
                      SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ),
                      self.__mcCabeActivated )
        self.__mcCabeTable.hide()

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins( 0, 0, 0, 0 )
        self.__hLayout.setSpacing( 0 )
        self.__hLayout.addWidget( self.toolbar )
        self.__hLayout.addWidget( self.__noneLabel )
        self.__hLayout.addWidget( self.__totalResultsTree )
        self.__hLayout.addWidget( self.__mcCabeTable )

        self.setLayout( self.__hLayout )
        return

    def getTotalResultsWidget( self ):
        " Provides a reference to the total results widget "
        return self.__totalResultsTree

    def getMcCabeResultsWidget( self ):
        " Provides a reference to the McCabe results widget "
        return self.__mcCabeTable

    def __updateButtonsStatus( self ):
        " Updates the buttons status "
        self.__mcCabeButton.setEnabled( self.__reportShown )
        self.printButton.setEnabled( self.__reportShown )
        self.printPreviewButton.setEnabled( self.__reportShown )
        self.clearButton.setEnabled( self.__reportShown )
        return

    def __onResultsExpanded( self, item ):
        " An item has been expanded, so the column width should be adjusted "
        self.__totalResultsTree.header().resizeSections(
                                            QHeaderView.ResizeToContents )
        return

    def __onPrint( self ):
        " Triggered when the print button is pressed "
        pass

    def __onPrintPreview( self ):
        " triggered when the print preview button is pressed "
        pass

    def __onMcCabe( self, state ):
        " Triggered when the metrics view is switched "

        if not self.__reportShown:
            return

        if state:
            self.__totalResultsTree.hide()
            self.__mcCabeTable.show()
            self.__mcCabeButton.setIcon(
                            PixmapCache().getIcon( 'treeview.png' ) )
            self.__mcCabeButton.setToolTip( "Switch to complete "
                                            "results tree view" )
        else:
            self.__mcCabeTable.hide()
            self.__totalResultsTree.show()
            self.__mcCabeButton.setIcon(
                            PixmapCache().getIcon( 'tableview.png' ) )
            self.__mcCabeButton.setToolTip( "Switch to McCabe only table view" )
        return

    def setFocus( self ):
        " Overridden setFocus "
        self.__hLayout.setFocus()
        return

    def __clear( self ):
        " Clears the content of the vertical layout "
        if not self.__reportShown:
            return

        self.__totalResultsTree.clear()
        self.__totalResultsTree.hide()
        self.__mcCabeTable.clear()
        self.__mcCabeTable.hide()
        self.__noneLabel.show()

        self.__report = None
        self.__reportShown = False
        self.__updateButtonsStatus()
#        self.resizeEvent()
        self.__mcCabeButton.setIcon( PixmapCache().getIcon( 'tableview.png' ) )
        self.__mcCabeButton.setToolTip( "Switch to McCabe only table view" )
        self.__mcCabeButton.setChecked( False )

        self.__updateTooltip()
        return

    def __updateTooltip( self ):
        " Generates a signal with appropriate string message "
        if not self.__reportShown:
            tooltip = "No metrics available"
        elif self.__reportOption == self.DirectoryFiles:
            tooltip = "Metrics generated for directory: " + \
                      self.__reportFileName
        elif self.__reportOption == self.ProjectFiles:
            tooltip = "Metrics generated for the whole project"
        elif self.__reportOption == self.SingleFile:
            tooltip = "Metrics generated for file: " + self.__reportFileName
        elif self.__reportOption == self.SingleBuffer:
            tooltip = "Metrics generated for unsaved file: " + \
                      self.__reportFileName
        else:
            tooltip = ""
        self.emit( SIGNAL( 'updatePymetricsTooltip' ), tooltip )
        return

    @staticmethod
    def __shouldShowFileName( table, column ):
        " Checks if the file name is the same "

        size = table.topLevelItemCount()
        if size == 0:
            return False

        index = size - 1
        firstName = table.topLevelItem( index ).text( column )
        index -= 1
        while index >= 0:
            if table.topLevelItem( index ).text( column ) != firstName:
                return True
            index -= 1
        return False

    def showReport( self, metrics, reportOption, fileName, uuid ):
        " Shows the pymetrics results "
        self.__clear()
        self.__noneLabel.hide()

        self.__report = metrics
        self.__reportUUID = uuid
        self.__reportFileName = fileName
        self.__reportOption = reportOption

        if len( metrics.report ) > 1:
            accumulatedBasic = self.__accumulateBasicMetrics()
            accItem = QTreeWidgetItem( [ "Cumulative basic metrics" ] )
            self.__totalResultsTree.addTopLevelItem( accItem )
            for key in accumulatedBasic:
                bmItem = [ BasicMetrics.metricsOfInterest[ key ],
                           splitThousands( str( accumulatedBasic[ key ] ) ) ]
                basicMetric = QTreeWidgetItem( bmItem )
                accItem.addChild( basicMetric )

        # Add the complete information
        for fileName in metrics.report:
            if reportOption == self.SingleBuffer:
                fileItem = QTreeWidgetItem( [ "Editor buffer" ] )
            else:
                fileItem = QTreeWidgetItem( [ fileName ] )
                info = GlobalData().briefModinfoCache.get( fileName )
                if info.docstring is not None:
                    fileItem.setToolTip( 0, info.docstring.text )
                else:
                    fileItem.setToolTip( 0, "" )
            self.__totalResultsTree.addTopLevelItem( fileItem )

            # Messages part
            messages = metrics.report[ fileName ].messages
            if len( messages ) > 0:
                messagesItem = QTreeWidgetItem( [ "Messages" ] )
                fileItem.addChild( messagesItem )
                for message in messages:
                    mItem = [ message, "", "E" ]
                    messagesItem.addChild( QTreeWidgetItem( mItem ) )

            # Basic metrics part
            basicItem = QTreeWidgetItem( [ "Basic metrics" ] )
            fileItem.addChild( basicItem )
            basic = metrics.report[ fileName ].basicMetrics
            for key in basic.metrics:
                bmItem = [ BasicMetrics.metricsOfInterest[ key ],
                           str( basic.metrics[ key ] ) ]
                basicMetric = QTreeWidgetItem( bmItem )
                basicItem.addChild( basicMetric )

            # McCabe part
            mccabeItem = QTreeWidgetItem( [ "McCabe metrics" ] )
            fileItem.addChild( mccabeItem )
            mccabe = metrics.report[ fileName ].mcCabeMetrics.metrics
            for objName in mccabe:
                objItem = [ objName, str( mccabe[ objName ] ), "M" ]
                mccabeMetric = QTreeWidgetItem( objItem )
                mccabeItem.addChild( mccabeMetric )


            # COCOMO 2 part
            cocomo = [ "COCOMO 2", str( metrics.report[ fileName ].cocomo2Metrics.value ) ]
            cocomoItem = QTreeWidgetItem( cocomo )
            fileItem.addChild( cocomoItem )



        # Resizing the table
        self.__totalResultsTree.header().resizeSections(
                                            QHeaderView.ResizeToContents )


        # Add McCabe complexity information
        for fileName in metrics.report:
            mccabe = metrics.report[ fileName ].mcCabeMetrics.metrics
            for objName in mccabe:
                values = [ "", fileName, objName, str( mccabe[ objName ] ) ]
                self.__mcCabeTable.addTopLevelItem( McCabeTableItem( values ) )

        if not self.__shouldShowFileName( self.__mcCabeTable, 1 ):
            self.__mcCabeTable.setColumnHidden( 1, True )

        # Resizing and sorting the table
        self.__mcCabeTable.header().setSortIndicator( 3, Qt.DescendingOrder )
        self.__mcCabeTable.sortItems( 3,
                          self.__mcCabeTable.header().sortIndicatorOrder() )
        self.__mcCabeTable.header().resizeSections(
                          QHeaderView.ResizeToContents )

        # Show the complete information
        self.__mcCabeTable.hide()
        self.__totalResultsTree.show()

        self.__reportShown = True
        self.__updateButtonsStatus()
        self.__updateTooltip()

        # It helps, but why do I have flickering?
        QApplication.processEvents()
        return

    def __accumulateBasicMetrics( self ):
        " Accumulates basic metrics for all the processed files "
        basic = {}
        for fileName in self.__report.report:
            singleBasic = self.__report.report[ fileName ].basicMetrics.metrics
            for key in singleBasic:
                if not key.startswith( 'num' ):
                    continue
                if key in basic:
                    basic[ key ] += int( singleBasic[ key ] )
                else:
                    basic[ key ] = int( singleBasic[ key ] )
        return basic

    def __mcCabeActivated( self, item, column ):
        " Handles the double click (or Enter) on the mccabe table item "

        objName = str( item.text( 2 ) )
        if self.__reportOption == self.SingleBuffer:
            if os.path.isabs( self.__reportFileName ):
                fileName = self.__reportFileName
            else:
                fileName = ""
        else:
            fileName = str( item.text( 1 ) )
        self.__onMcCabeObject( objName, fileName )
        return

    def __allItemActivated( self, item, column ):
        " Handles the double click (or Enter) in the total results tree "

        # We process only the error messages and McCabe items
        hiddenColumnText = str( item.text( 2 ) )
        if not hiddenColumnText in [ "M", "E" ]:
            return

        fileName = self.__getTreeItemFileName( item )
        lineNumber = 0
        if hiddenColumnText == "M":
            # This is McCabe item
            objName = str( item.text( 0 ) )
            self.__onMcCabeObject( objName, fileName )
            return
        elif hiddenColumnText == "E":
            # This is an error message
            message = str( item.text( 0 ) )
            pos = message.find( "at line" )
            if pos == -1:
                logging.error( "Unknown format of the message. "
                               "Please inform the developers." )
                return
            parts = message[ pos: ].split()
            try:
                lineNumber = int( parts[ 2 ].replace( ',', '' ) )
            except:
                logging.error( "Unknown format of the message. "
                               "Please inform the developers." )
                return

            if fileName == "":
                # This is an unsaved buffer, try to find the editor by UUID
                mainWindow = GlobalData().mainWindow
                widget = mainWindow.getWidgetByUUID( self.__reportUUID )
                if widget is None:
                    logging.error( "The unsaved buffer has been closed" )
                    return
                # The widget was found, so jump to the required
                editor = widget.getEditor()
                editor.gotoLine( lineNumber )
                editor.setFocus()
                return

        GlobalData().mainWindow.openFile( fileName, lineNumber )
        return

    def __getTreeItemFileName( self, item ):
        " Identifies the tree view item file name "
        if self.__reportOption == self.SingleBuffer:
            if os.path.isabs( self.__reportFileName ):
                return self.__reportFileName
            return ""

        # The file name is always two levels up
        fileItem = item.parent().parent()
        return str( fileItem.text( 0 ) )

    def __onMcCabeObject( self, objName, fileName ):
        " Called when the user activated McCabe item "

        info = None

        mainWindow = GlobalData().mainWindow
        widget = mainWindow.getWidgetByUUID( self.__reportUUID )
        if widget is None:
            if fileName == "":
                logging.error( "The unsaved buffer has been closed" )
                return
            # No widget, but we know the file name
            info = getBriefModuleInfoFromFile( fileName )
        else:
            # The widget was found
            editor = widget.getEditor()
            # The editor content has been modified, so re-parse the buffer
            info = getBriefModuleInfoFromMemory( editor.text() )

        parts = objName.split( '.' )
        currentIndex = 0
        functionsContainer = info.functions
        classesContainer = info.classes
        line = -1

        if objName == "__main__" and len( parts ) == 1:
            # Special case - global file scope
            line = 1
            currentIndex = 1

        while currentIndex < len( parts ):
            found = False
            for func in functionsContainer:
                if func.name == parts[ currentIndex ]:
                    if currentIndex == len( parts ) - 1:
                        # Found, jump to the line
                        line = func.line
                        break
                    functionsContainer = func.functions
                    classesContainer = func.classes
                    found = True
                    break
            if line != -1:
                break
            if found:
                currentIndex += 1
                continue
            for klass in classesContainer:
                if klass.name == parts[ currentIndex ]:
                    if currentIndex == len( parts ) - 1:
                        # Found, jump to the line
                        line = klass.line
                        break
                    functionsContainer = klass.functions
                    classesContainer = klass.classes
                    found = True
            if line != -1:
                break
            if found:
                currentIndex += 1
                continue

            # Not found
            logging.error( "Cannot find the " + objName )
            return

        # Here we have the line number
        if widget is None:
            GlobalData().mainWindow.openFile( fileName, line )
        else:
            editor = widget.getEditor()
            editor.gotoLine( line )
            editor.setFocus()
        return

    def onFileUpdated( self, fileName, uuid ):
        " Called when a buffer is saved or saved as "

        if not self.__reportShown:
            return
        if self.__reportUUID != uuid:
            return

        # Currently shown report is for the saved buffer
        # File name is expected being absolute
        self.__reportFileName = fileName
        self.emit( SIGNAL( 'updatePymetricsTooltip' ),
                   "Metrics generated for buffer saved as " + fileName )
        return
Exemplo n.º 29
0
 def createGUIElements(self):
     ''' Build the GUI based on the parameters for the tool '''
     for i, param in enumerate(self.tooltypearray):
         # print 'creatgui element %d, %s' %(i, param)
         #Swap in the passed params if they exist... loop through each passed
         #param and see if it matches... if so swap it in
         if self.optional_params.has_key(str(param[0])):
             param[2] = self.optional_params[str(param[0])]
         #print "Key: %s , Val: %s" % (param[0],param[1])
         widgetTemp = QWidget(self.variableBox)
         widgetTemp.setObjectName(QString("test_widget").append(QString(i)))
         self.test_widget.append(widgetTemp)
         hlayout = QHBoxLayout(widgetTemp)
         self.hboxlayout.append(hlayout)
         hlayout.setMargin(4)
         hlayout.setSpacing(4)
         hlayout.setObjectName(QString("hboxlayout").append(QString(i)))
         test_text = QLabel(widgetTemp)
         self.test_text.append(test_text)
         test_text.setObjectName(QString("test_text").append(QString(i)))
         paramName = param[0].strip()
         if param[2].strip() == "Required":
             palette = test_text.palette()
             palette.setColor(QPalette.WindowText, Qt.red)
             test_text.setPalette(palette)
         test_text.setText(paramName)
         test_text_type = QLabel(widgetTemp)
         self.test_text_type.append(test_text_type)
         test_text_type.setObjectName(
             QString("test_text_type").append(QString(i)))
         paramName = param[1].strip()
         test_text_type.setText(
             QString("(").append(paramName).append(QString(")")))
         hlayout.addWidget(test_text)
         hlayout.addWidget(test_text_type)
         if param[1] == 'db_connection_hook':
             test_line = QComboBox(widgetTemp)
             db_connection_choices = get_db_connection_names()
             for i in db_connection_choices:
                 test_line.addItem(QString(i))
             self.test_line.append(test_line)
             test_line.setEnabled(True)
             test_line.setMinimumSize(QSize(200, 0))
             test_line.setObjectName(
                 QString("test_line").append(QString(i)))
             index = test_line.findText(param[2], Qt.MatchExactly)
             test_line.setCurrentIndex(index)
         else:
             test_line = QLineEdit(widgetTemp)
             self.test_line.append(test_line)
             test_line.setEnabled(True)
             test_line.setMinimumSize(QSize(200, 0))
             test_line.setObjectName(
                 QString("test_line").append(QString(i)))
             test_line.setText(QString(param[2]))
         hlayout.addWidget(test_line)
         # If we have a dir_path or file_path add a select button
         if (paramName == QString('dir_path')) or (paramName
                                                   == QString('file_path')):
             pbnSelect = QPushButton(widgetTemp)
             pbnSelect.setObjectName(
                 QString('pbnSelect').append(QString(i)))
             pbnSelect.setText(QString("Select..."))
             pbnSelectDelegate = FileDialogSignal(typeName=paramName,
                                                  param=test_line)
             QObject.connect(
                 pbnSelectDelegate.o,
                 SIGNAL("buttonPressed(PyQt_PyObject,PyQt_PyObject)"),
                 self.on_pbnSelect_released)
             QObject.connect(pbnSelect, SIGNAL("released()"),
                             pbnSelectDelegate.relayButtonSignal)
             self.test_line_delegates.append(pbnSelectDelegate)
             self.test_line_buttons.append(pbnSelect)
             hlayout.addWidget(pbnSelect)
         self.vboxlayout.addWidget(widgetTemp)
         self.adjustSize()
     # Jesse adding help text from opusHelp
     tool_path = self.optional_params.get('tool_path', '')
     try:
         exec_stmt = 'from %s.%s import opusHelp' % (tool_path,
                                                     self.module_name)
         exec exec_stmt
         help = QString(opusHelp())
         self.toolhelpEdit.insertPlainText(help)
     except Exception, e:
         help = 'could not find opusHelp function in tool module'
         self.toolhelpEdit.insertPlainText(help)
Exemplo n.º 30
0
class LoaderWidget(QWidget):
    MOVIE = None

    def __init__(self, parent):
        # initialize the super class
        super(LoaderWidget, self).__init__(parent)

        # create the movie
        if (LoaderWidget.MOVIE == None):
            LoaderWidget.MOVIE = QMovie(
                resources.find('img/main/ajax-loader.gif'))
            LoaderWidget.MOVIE.start()

        # create the movie label
        self._movieLabel = QLabel(self)
        self._movieLabel.setMovie(LoaderWidget.MOVIE)
        self._movieLabel.setAlignment(Qt.AlignCenter)

        self._messageLabel = QLabel(self)
        self._messageLabel.setAlignment(Qt.AlignCenter)

        palette = self._messageLabel.palette()
        palette.setColor(palette.WindowText, QColor('gray'))
        self._messageLabel.setPalette(palette)

        # create the interface
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addStretch()
        layout.addWidget(self._movieLabel)
        layout.addWidget(self._messageLabel)
        layout.addStretch()

        self.setLayout(layout)
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.resize(0, 0)
        self.setMessage('')

        # set the default properties
        self.setAutoFillBackground(True)
        self.setBackgroundRole(QPalette.Window)

        # create custom properties
        clr = QColor('black')
        clr.setAlpha(150)
        self._backgroundColor = clr

    def backgroundColor(self):
        return self._backgroundColor

    def eventFilter(self, object, event):
        if (object == self.parent() and event.type() == QEvent.Resize):
            self.resize(object.size())
        return False

    def message(self):
        return self._messageLabel.text()

    def paintEvent(self, event):
        # make sure we have the proper palette, as if this widget is
        # added to a hierarchy, it may overwrite whats there
        palette = self.palette()
        palette.setColor(QPalette.Window, self._backgroundColor)
        self.setPalette(palette)

        super(LoaderWidget, self).paintEvent(event)

    def setBackgroundColor(self, clr):
        self._backgroundColor = QColor(clr)

    def setMessage(self, message):
        self._messageLabel.setText(message)
        self._messageLabel.setVisible(message != '')

    @staticmethod
    def start(widget, message=''):
        loaders = widget.findChildren(LoaderWidget)
        if (loaders):
            loader = loaders[0]
        else:
            loader = LoaderWidget(widget)
            widget.installEventFilter(loader)
            loader.resize(widget.size())
            loader.show()

        loader.setMessage(message)

        return loader

    @staticmethod
    def stop(widget):
        for loader in widget.findChildren(LoaderWidget):
            loader.close()
            loader.setParent(None)
            loader.deleteLater()
Exemplo n.º 31
0
    def __init__( self, scriptName, params, reportTime,
                        dataFile, stats, parent = None ):
        QWidget.__init__( self, parent )

        self.__table = ProfilerTreeWidget( self )
        self.__table.escapePressed.connect( self.__onEsc )

        self.__script = scriptName
        self.__stats = stats
        project = GlobalData().project
        if project.isLoaded():
            self.__projectPrefix = os.path.dirname( project.fileName )
        else:
            self.__projectPrefix = os.path.dirname( scriptName )
        if not self.__projectPrefix.endswith( os.path.sep ):
            self.__projectPrefix += os.path.sep

        self.__table.setAlternatingRowColors( True )
        self.__table.setRootIsDecorated( False )
        self.__table.setItemsExpandable( False )
        self.__table.setSortingEnabled( True )
        self.__table.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.__table.setUniformRowHeights( True )
        self.__table.setSelectionMode( QAbstractItemView.SingleSelection )
        self.__table.setSelectionBehavior( QAbstractItemView.SelectRows )

        headerLabels = [ "", "Calls", "Total time", "Per call",
                         "Cum. time", "Per call", "File name:line",
                         "Function", "Callers", "Callees" ]
        self.__table.setHeaderLabels( headerLabels )

        headerItem = self.__table.headerItem()
        headerItem.setToolTip( 0, "Indication if it is an outside function" )
        headerItem.setToolTip( 1, "Actual number of calls/primitive calls "
                                  "(not induced via recursion)" )
        headerItem.setToolTip( 2, "Total time spent in function "
                                  "(excluding time made in calls "
                                  "to sub-functions)" )
        headerItem.setToolTip( 3, "Total time divided by number "
                                  "of actual calls" )
        headerItem.setToolTip( 4, "Total time spent in function and all "
                                  "subfunctions (from invocation till exit)" )
        headerItem.setToolTip( 5, "Cumulative time divided by number "
                                  "of primitive calls" )
        headerItem.setToolTip( 6, "Function location" )
        headerItem.setToolTip( 7, "Function name" )
        headerItem.setToolTip( 8, "Function callers" )
        headerItem.setToolTip( 9, "Function callees" )

        self.__table.itemActivated.connect( self.__activated )

        totalCalls = self.__stats.total_calls
        totalPrimitiveCalls = self.__stats.prim_calls  # The calls were not induced via recursion
        totalTime = self.__stats.total_tt

        txt = "<b>Script:</b> " + self.__script + " " + params.arguments + "<br>" \
              "<b>Run at:</b> " + reportTime + "<br>" + \
              str( totalCalls ) + " function calls (" + \
              str( totalPrimitiveCalls ) + " primitive calls) in " + \
              FLOAT_FORMAT % totalTime + " CPU seconds"
        summary = QLabel( txt )
        summary.setToolTip( txt )
        summary.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Fixed )
        summary.setFrameStyle( QFrame.StyledPanel )
        summary.setAutoFillBackground( True )
        summaryPalette = summary.palette()
        summaryBackground = summaryPalette.color( QPalette.Background )
        summaryBackground.setRgb( min( summaryBackground.red() + 30, 255 ),
                                  min( summaryBackground.green() + 30, 255 ),
                                  min( summaryBackground.blue() + 30, 255 ) )
        summaryPalette.setColor( QPalette.Background, summaryBackground )
        summary.setPalette( summaryPalette )

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins( 0, 0, 0, 0 )
        vLayout.setSpacing( 0 )
        vLayout.addWidget( summary )
        vLayout.addWidget( self.__table )

        self.setLayout( vLayout )
        self.__createContextMenu()

        self.__populate( totalTime )
        return
Exemplo n.º 32
0
    def __addSimilarity( self, similarity, titleText ):
        " Adds a similarity "

        # Label
        title = QLabel( titleText )
        title.setFont( self.__headerFont )

        self.__vLayout.addWidget( title )
        self.__widgets.append( title )

        # List of files
        simTable = QTreeWidget( self.bodyWidget )
        simTable.setAlternatingRowColors( True )
        simTable.setRootIsDecorated( False )
        simTable.setItemsExpandable( False )
        simTable.setSortingEnabled( False )
        simTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        simTable.setUniformRowHeights( True )
        simTable.itemActivated.connect( self.__similarityActivated )
        simTable.setHeaderLabels( [ "File name", "Line" ] )

        for item in similarity.files:
            values = [ item[ 0 ], str( item[ 1 ] ) ]
            simTable.addTopLevelItem( QTreeWidgetItem( values )  )

        # Resizing
        simTable.header().resizeSections( QHeaderView.ResizeToContents )
        simTable.header().setStretchLastSection( True )

        # Height
        self.__setTableHeight( simTable )

        self.__vLayout.addWidget( simTable )
        self.__widgets.append( simTable )

        # The fragment itself
        if len( similarity.fragment ) > 10:
            # Take first 9 lines
            text = "\n".join( similarity.fragment[ : 9 ] ) + "\n ..."
            toolTip = "\n".join( similarity.fragment )
        else:
            text = "\n".join( similarity.fragment )
            toolTip = ""
        fragmentLabel = QLabel( "<pre>" + self.__htmlEncode( text ) + "</pre>" )
        if toolTip != "":
            fragmentLabel.setToolTip( "<pre>" + self.__htmlEncode( toolTip ) +
                                      "</pre>" )
        palette = fragmentLabel.palette()
        palette.setColor( QPalette.Background, QColor( 250, 250, 175 ) )
        palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) )
        fragmentLabel.setPalette( palette )
        fragmentLabel.setFrameShape( QFrame.StyledPanel )
        fragmentLabel.setAutoFillBackground( True )

        labelFont = fragmentLabel.font()
        labelFont.setFamily( GlobalData().skin.baseMonoFontFace )
        fragmentLabel.setFont( labelFont )

        self.__vLayout.addWidget( fragmentLabel )
        self.__widgets.append( fragmentLabel )
        return
Exemplo n.º 33
0
class Calltip(QFrame):
    " Frameless panel with a calltip "

    def __init__(self, parent):
        QFrame.__init__(self, parent)

        # Make the frame nice looking
        palette = self.palette()
        palette.setColor(self.backgroundRole(), GlobalData().skin.calltipPaper)
        self.setPalette(palette)

        self.setFrameShape(QFrame.StyledPanel)
        self.setLineWidth(2)
        self.setAutoFillBackground(True)

        # Keep pylint happy
        self.__calltipLabel = None
        self.__text = None
        self.__paramPositions = None
        self.__highlightedParam = None

        self.__createLayout()
        QFrame.hide(self)
        self.setFocusPolicy(Qt.NoFocus)
        return

    def __createLayout(self):
        " Creates the widget layout "

        self.__calltipLabel = QLabel("")
        self.__calltipLabel.setSizePolicy(QSizePolicy.Ignored,
                                          QSizePolicy.Fixed)
        self.__calltipLabel.setWordWrap(False)
        self.__calltipLabel.setAlignment(Qt.AlignLeft)
        palette = self.__calltipLabel.palette()
        palette.setColor(self.foregroundRole(), GlobalData().skin.calltipColor)
        self.__calltipLabel.setPalette(palette)

        gridLayout = QGridLayout(self)
        gridLayout.setMargin(3)
        gridLayout.addWidget(self.__calltipLabel, 0, 0, 1, 1)

        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        return

    def resize(self):
        " Resizes the dialogue to match the editor size "

        vscroll = self.parent().verticalScrollBar()
        if vscroll.isVisible():
            scrollWidth = vscroll.width()
        else:
            scrollWidth = 0

        hscroll = self.parent().horizontalScrollBar()
        if hscroll.isVisible():
            scrollHeight = hscroll.height()
        else:
            scrollHeight = 0

        # Panel
        width = self.parent().width()
        height = self.parent().height()
        widgetWidth = width - scrollWidth - 6 - 1

        self.setFixedWidth(widgetWidth)

        vPos = height - self.height() - scrollHeight
        self.move(3, vPos - 3)
        return

    def showCalltip(self, message, paramNumber):
        " Brings up the panel with the required text "
        self.__text = message
        self.__calcParamPositions()
        self.highlightParameter(paramNumber)
        QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

        self.resize()
        self.show()

        # I have to do resize() twice because the self.height() value is
        # calculated in a different way before the frame is shown and after.
        # So the first call moves the widget to the nearly right location
        # and the second to the precise one
        self.resize()
        return

    def highlightParameter(self, number):
        " Hightlights the given parameter number, 0 - based "
        if number == self.__highlightedParam:
            return
        if self.__paramPositions is None:
            self.__calltipLabel.setText(self.__text)
            return
        if number >= len(self.__paramPositions):
            self.__calltipLabel.setText(self.__text)
            return
        positions = self.__paramPositions[number]
        highlight = self.__text[ 0 : positions[ 0 ] ] + "<font color='" + \
                    GlobalData().skin.calltipHighColor.name() + "'>" + \
                    self.__text[ positions[ 0 ] : positions[ 1 ] + 1 ] + \
                    "</font>" + self.__text[ positions[ 1 ] + 1 : ]
        self.__calltipLabel.setText(highlight)
        return

    def __calcParamPositions(self):
        " Calculates the parameter positions in the calltip text "
        if self.__text is None or '\n' in self.__text:
            self.__paramPositions = None
            return

        try:
            begin = self.__text.index('(') + 1
        except:
            self.__paramPositions = None
            return

        if self.__text[begin] == '.':
            # Special case for f(...)
            self.__paramPositions = None
            return

        self.__paramPositions = []
        lastIndex = len(self.__text) - 1
        index = begin
        level = 0  # Unconditional skip of commas
        singleQuote = False
        doubleQuote = False
        while index <= lastIndex:
            ch = self.__text[index]
            if ch == "'" and singleQuote:
                singleQuote = False
            elif ch == '"' and doubleQuote:
                doubleQuote = False
            elif ch == "'":
                singleQuote = False
            elif ch == '"':
                doubleQuote = False
            elif ch in ['(', '{']:
                level += 1
            elif ch in [')', '}']:
                level -= 1
                if level == -1:
                    # Closing bracket
                    if index > begin:
                        self.__paramPositions.append((begin, index - 1))
                    break
            elif ch == '[':
                if level > 0:
                    index += 1
                    continue
                # if a previous char is '=' then it is a default paam
                checkIndex = index - 1
                while self.__text[checkIndex].isspace():
                    checkIndex -= 1
                if self.__text[checkIndex] == '=':
                    level += 1
                    index += 1
                    continue

                if self.__text[checkIndex] == '(':
                    # The very first round bracket
                    index = index + 1
                    begin = index
                    continue

                # '[' after a parameter name
                if index > begin:
                    self.__paramPositions.append((begin, index - 1))
                    # The next meaningfull character is comma or an identifier
                    index += 1
                    while index <= lastIndex and self.__text[index].isspace():
                        index += 1
                    if self.__text[index] == ',':
                        index += 1
                    index += 1
                    begin = index
                    continue

                # I don't know what it is
                self.__paramPositions = None
                return

            elif ch == ']':
                if level > 0:
                    level -= 1
                    index += 1
                    continue

                # This must be an optional argument closing bracket
                checkIndex = index - 1
                while self.__text[checkIndex].isspace():
                    checkIndex -= 1

                if self.__text[checkIndex] == ']':
                    index += 1
                    continue

                # Need to add and this is the last parameter
                if index > begin:
                    self.__paramPositions.append((begin, index - 1))
                break

            elif ch == ',':
                if level == 0:
                    self.__paramPositions.append((begin, index - 1))
                # Skip till the beginning of the next parameter - it must be there
                index += 1
                while index <= lastIndex and self.__text[index].isspace():
                    index += 1
                begin = index
                continue

            index += 1

        if len(self.__paramPositions) == 0:
            self.__paramPositions = None
        return

    def hide(self):
        " Handles the hiding of the panel and markers "
        QFrame.hide(self)
        self.__text = None
        self.__paramPositions = None
        self.__highlightedParam = None
        self.__calltipLabel.setText("")
        return
Exemplo n.º 34
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
Exemplo n.º 35
0
class PylintViewer( QWidget ):
    " Pylint tab widget "

    # Limits to colorize the final score
    BadLimit = 8.5
    GoodLimit = 9.5

    # Options of providing a report
    SingleFile     = 0
    DirectoryFiles = 1
    ProjectFiles   = 2
    SingleBuffer   = 3

    updatePylintTooltip = pyqtSignal( str )

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

        self.__reportUUID = ""
        self.__reportFileName = ""
        self.__reportOption = -1
        self.__reportShown = False
        self.__report = None

        self.__widgets = []

        # Prepare members for reuse
        if GlobalData().pylintAvailable:
            self.__noneLabel = QLabel( "\nNo results available" )
        else:
            self.__noneLabel = QLabel( "\nPylint is not available" )
        self.__noneLabel.setAutoFillBackground( True )
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor( QPalette.Background,
                                   GlobalData().skin.nolexerPaper )
        self.__noneLabel.setPalette( noneLabelPalette )

        self.__noneLabel.setFrameShape( QFrame.StyledPanel )
        self.__noneLabel.setAlignment( Qt.AlignHCenter )
        self.__headerFont = self.__noneLabel.font()
        self.__headerFont.setPointSize( self.__headerFont.pointSize() + 4 )
        self.__noneLabel.setFont( self.__headerFont )

        self.__createLayout( parent )

        self.__updateButtonsStatus()
        self.resizeEvent()
        return

    def __createLayout( self, parent ):
        " Creates the toolbar and layout "

        # Buttons
        self.printButton = QAction( PixmapCache().getIcon( 'printer.png' ),
                                    'Print', self )
        #printButton.setShortcut( 'Ctrl+' )
        self.printButton.triggered.connect( self.__onPrint )
        self.printButton.setVisible( False )

        self.printPreviewButton = QAction(
                PixmapCache().getIcon( 'printpreview.png' ),
                'Print preview', self )
        #printPreviewButton.setShortcut( 'Ctrl+' )
        self.printPreviewButton.triggered.connect( self.__onPrintPreview )
        self.printPreviewButton.setVisible( False )

        spacer = QWidget()
        spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding )

        self.clearButton = QAction(
            PixmapCache().getIcon( 'trash.png' ),
            'Clear', self )
        self.clearButton.triggered.connect( self.__clear )

        # The toolbar
        self.toolbar = QToolBar( self )
        self.toolbar.setOrientation( Qt.Vertical )
        self.toolbar.setMovable( False )
        self.toolbar.setAllowedAreas( Qt.RightToolBarArea )
        self.toolbar.setIconSize( QSize( 16, 16 ) )
        self.toolbar.setFixedWidth( 28 )
        self.toolbar.setContentsMargins( 0, 0, 0, 0 )

        self.toolbar.addAction( self.printPreviewButton )
        self.toolbar.addAction( self.printButton )
        self.toolbar.addWidget( spacer )
        self.toolbar.addAction( self.clearButton )

        self.__vLayout = QVBoxLayout()
        self.__vLayout.setContentsMargins( 5, 5, 5, 5 )
        self.__vLayout.setSpacing( 0 )
        self.__vLayout.setSizeConstraint( QLayout.SetFixedSize )

        self.__bodyFrame = QFrame( self )
#        self.__bodyFrame.setFrameShape( QFrame.StyledPanel )
        self.__bodyFrame.setFrameShape( QFrame.NoFrame )

#        self.__bodyFrame.setSizePolicy( QSizePolicy.Maximum,
#                                        QSizePolicy.Expanding )
        self.__bodyFrame.setLayout( self.__vLayout )
        self.bodyWidget = QScrollArea( self )
        self.bodyWidget.setFocusPolicy( Qt.NoFocus )
        self.bodyWidget.setWidget( self.__bodyFrame )
        self.bodyWidget.hide()

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins( 0, 0, 0, 0 )
        self.__hLayout.setSpacing( 0 )
        self.__hLayout.addWidget( self.toolbar )
        self.__hLayout.addWidget( self.__noneLabel )
        self.__hLayout.addWidget( self.bodyWidget )

        self.setLayout( self.__hLayout )
        return

    def __updateButtonsStatus( self ):
        " Updates the buttons status "
        self.printButton.setEnabled( self.__reportShown )
        self.printPreviewButton.setEnabled( self.__reportShown )
        self.clearButton.setEnabled( self.__reportShown )
        return

    def __onPrint( self ):
        " Triggered when the print button is pressed "
        pass

    def __onPrintPreview( self ):
        " triggered when the print preview button is pressed "
        pass

    def setFocus( self ):
        " Overridden setFocus "
        self.__vLayout.setFocus()
        return

    def __clear( self ):
        " Clears the content of the vertical layout "
        if not self.__reportShown:
            return

        self.__removeAll()
        self.bodyWidget.hide()
        self.__noneLabel.show()

        self.__report = None
        self.__reportShown = False
        self.__updateButtonsStatus()
        self.resizeEvent()

        self.__updateTooltip()
        return

    def __removeAll( self ):
        " Removes all the items from the report "
        for item in self.__widgets:
            item.hide()
            self.__vLayout.removeWidget( item )
            del item

        self.__widgets = []
        return

    def __createScoreLabel( self, score, previousScore,
                            showFileName, fileName ):
        " Creates the score label "

        txt = "Score: " + str( score )
        if previousScore != "":
            txt += " / Previous score: " + str( previousScore )
        if not showFileName:
            txt += " for " + os.path.basename( fileName )

        scoreLabel = QLabel( txt )
        scoreLabel.setFrameShape( QFrame.StyledPanel )
        scoreLabel.setFont( self.__headerFont )
        scoreLabel.setAutoFillBackground( True )
        palette = scoreLabel.palette()

        if score < self.BadLimit:
            palette.setColor( QPalette.Background, QColor( 255, 127, 127 ) )
            palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) )
        elif score > self.GoodLimit:
            palette.setColor( QPalette.Background, QColor( 220, 255, 220 ) )
            palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) )
        else:
            palette.setColor( QPalette.Background, QColor( 255, 255, 127 ) )
            palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) )

        scoreLabel.setPalette( palette )
        return scoreLabel

    @staticmethod
    def __setTableHeight( table ):
        " Auxiliary function to set the table height "

        # Height - it is ugly and approximate however I am tired of
        # calculating the proper height. Why is this so hard, huh?
        lastRowHeight = table.itemDelegate().lastHeight
        height = lastRowHeight * ( table.topLevelItemCount() + 1 ) + 10
        table.setFixedHeight( height )
        return

    @staticmethod
    def __shouldShowFileName( messages ):
        " Decides if the file name column should be supressed "
        if len( messages ) == 0:
            return False
        firstName = messages[ 0 ].fileName
        for index in range( 1, len( messages ) ):
            if firstName != messages[ index ].fileName:
                return True
        return False

    def __addErrorsTable( self, messages, showFileName ):
        " Creates the messages table "

        errTable = QTreeWidget( self.bodyWidget )
        errTable.setAlternatingRowColors( True )
        errTable.setRootIsDecorated( False )
        errTable.setItemsExpandable( False )
        errTable.setSortingEnabled( True )
        errTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        errTable.setUniformRowHeights( True )
        errTable.itemActivated.connect( self.__errorActivated )

        headerLabels = [ "File name", "Line", "Message ID", "Object", "Message" ]
        errTable.setHeaderLabels( headerLabels )

        for item in messages:
            if item.position is None:
                lineNumber = str( item.lineNumber )
            else:
                lineNumber = str( item.lineNumber ) + ":" + str( item.position )
            values = [ item.fileName, lineNumber, item.messageID,
                       item.objectName, item.message ]
            errTable.addTopLevelItem( ErrorTableItem( values, 1 ) )

        # Hide the file name column if required
        if not showFileName:
            errTable.setColumnHidden( 0, True )

        # Resizing
        errTable.header().resizeSections( QHeaderView.ResizeToContents )
        errTable.header().setStretchLastSection( True )

        # Sort indicator
        if showFileName:
            sortIndex = 0   # By file names
        else:
            sortIndex = 1   # By line number because this is from the same file
        errTable.header().setSortIndicator( sortIndex, Qt.AscendingOrder )
        errTable.sortItems( sortIndex, errTable.header().sortIndicatorOrder() )

        # Height
        self.__setTableHeight( errTable )

        self.__vLayout.addWidget( errTable )
        self.__widgets.append( errTable )
        return

    def __addSimilarity( self, similarity, titleText ):
        " Adds a similarity "

        # Label
        title = QLabel( titleText )
        title.setFont( self.__headerFont )

        self.__vLayout.addWidget( title )
        self.__widgets.append( title )

        # List of files
        simTable = QTreeWidget( self.bodyWidget )
        simTable.setAlternatingRowColors( True )
        simTable.setRootIsDecorated( False )
        simTable.setItemsExpandable( False )
        simTable.setSortingEnabled( False )
        simTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        simTable.setUniformRowHeights( True )
        simTable.itemActivated.connect( self.__similarityActivated )
        simTable.setHeaderLabels( [ "File name", "Line" ] )

        for item in similarity.files:
            values = [ item[ 0 ], str( item[ 1 ] ) ]
            simTable.addTopLevelItem( QTreeWidgetItem( values )  )

        # Resizing
        simTable.header().resizeSections( QHeaderView.ResizeToContents )
        simTable.header().setStretchLastSection( True )

        # Height
        self.__setTableHeight( simTable )

        self.__vLayout.addWidget( simTable )
        self.__widgets.append( simTable )

        # The fragment itself
        if len( similarity.fragment ) > 10:
            # Take first 9 lines
            text = "\n".join( similarity.fragment[ : 9 ] ) + "\n ..."
            toolTip = "\n".join( similarity.fragment )
        else:
            text = "\n".join( similarity.fragment )
            toolTip = ""
        fragmentLabel = QLabel( "<pre>" + self.__htmlEncode( text ) + "</pre>" )
        if toolTip != "":
            fragmentLabel.setToolTip( "<pre>" + self.__htmlEncode( toolTip ) +
                                      "</pre>" )
        palette = fragmentLabel.palette()
        palette.setColor( QPalette.Background, QColor( 250, 250, 175 ) )
        palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) )
        fragmentLabel.setPalette( palette )
        fragmentLabel.setFrameShape( QFrame.StyledPanel )
        fragmentLabel.setAutoFillBackground( True )

        labelFont = fragmentLabel.font()
        labelFont.setFamily( GlobalData().skin.baseMonoFontFace )
        fragmentLabel.setFont( labelFont )

        self.__vLayout.addWidget( fragmentLabel )
        self.__widgets.append( fragmentLabel )
        return

    @staticmethod
    def __htmlEncode( string ):
        " Encodes HTML "
        return string.replace( "&", "&amp;" ) \
                     .replace( ">", "&gt;" ) \
                     .replace( "<", "&lt;" )

    def __addSectionSpacer( self ):
        " Adds a fixed height spacer to the VBox layout "
        spacer = QWidget()
        spacer.setFixedHeight( 10 )
        self.__vLayout.addWidget( spacer )
        self.__widgets.append( spacer )
        return

    def __addGenericTable( self, table ):
        " Adds a generic table to the report "

        theTable = QTreeWidget( self.bodyWidget )
        theTable.setAlternatingRowColors( True )
        theTable.setRootIsDecorated( False )
        theTable.setItemsExpandable( False )
        theTable.setSortingEnabled( False )
        theTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        theTable.setUniformRowHeights( True )

        headerLabels = []
        for index in range( 0, len( table.header ) ):
            headerLabels.append( table.header[ index ] )
        theTable.setHeaderLabels( headerLabels )

        for item in table.body:
            row = []
            for index in range( 0, len( table.header ) ):
                row.append( item[ index ] )
            theTable.addTopLevelItem( QTreeWidgetItem( row ) )

        theTable.setFocusPolicy( Qt.NoFocus )

        # Resizing
        theTable.header().resizeSections( QHeaderView.ResizeToContents )
        theTable.header().setStretchLastSection( True )

        # Height
        self.__setTableHeight( theTable )

        self.__vLayout.addWidget( theTable )
        self.__widgets.append( theTable )
        return

    def __addGenericTableTitle( self, table ):
        " Adds a generic table title "
        tableTitle = QLabel( table.title )
        tableTitle.setFont( self.__headerFont )

        self.__vLayout.addWidget( tableTitle )
        self.__widgets.append( tableTitle )
        return

    def __updateTooltip( self ):
        " Generates a signal with appropriate string message "
        if not self.__reportShown:
            tooltip = "No results available"
        elif self.__reportOption == self.DirectoryFiles:
            tooltip = "Report generated for directory: " + \
                      self.__reportFileName
        elif self.__reportOption == self.ProjectFiles:
            tooltip = "Report generated for the whole project"
        elif self.__reportOption == self.SingleFile:
            tooltip = "Report generated for file: " + self.__reportFileName
        elif self.__reportOption == self.SingleBuffer:
            tooltip = "Report generated for unsaved file: " + \
                      self.__reportFileName
        else:
            tooltip = ""
        self.updatePylintTooltip.emit( tooltip )
        return

    def showReport( self, lint, reportOption, fileName, uuid ):
        " Shows the pylint results "
        self.__removeAll()
        self.__noneLabel.hide()

        self.__report = lint
        self.__reportUUID = uuid
        self.__reportFileName = fileName
        self.__reportOption = reportOption

        showFileName = self.__shouldShowFileName( lint.errorMessages )

        scoreLabel = self.__createScoreLabel( lint.score, lint.previousScore,
                                              showFileName, fileName )
        self.__vLayout.addWidget( scoreLabel )
        self.__widgets.append( scoreLabel )

        if len( lint.errorMessages ) > 0:
            self.__addSectionSpacer()
            self.__addErrorsTable( lint.errorMessages, showFileName )

        index = 0
        for similarity in lint.similarities:
            self.__addSectionSpacer()
            self.__addSimilarity( similarity, "Similarity #" + str( index ) )
            index += 1

        for table in lint.tables:
            self.__addSectionSpacer()
            self.__addGenericTableTitle( table )
            self.__addGenericTable( table )

        self.bodyWidget.show()
        self.bodyWidget.ensureVisible( 0, 0, 0, 0 )
        self.__reportShown = True
        self.__updateButtonsStatus()
        self.__updateTooltip()

        # It helps, but why do I have flickering?
        QApplication.processEvents()
        self.__resizeBodyFrame()
        return

    def __errorActivated( self, item, column ):
        " Handles the double click (or Enter) on the item "

        linePos = str( item.text( 1 ) )
        if ":" in linePos:
            parts = linePos.split( ":" )
            lineNumber = int( parts[ 0 ] )
            pos = int( parts[ 1 ] )
        else:
            lineNumber = int( linePos )
            pos = 0

        if self.__reportOption in [ self.SingleFile, self.DirectoryFiles,
                                    self.ProjectFiles ]:
            fileName = str( item.text( 0 ) )
        else:
            # SingleBuffer
            if self.__reportFileName != "":
                if os.path.isabs( self.__reportFileName ):
                    fileName = self.__reportFileName
                else:
                    # Could be unsaved buffer, so try to search by the
                    mainWindow = GlobalData().mainWindow
                    widget = mainWindow.getWidgetByUUID( self.__reportUUID )
                    if widget is None:
                        logging.error( "The unsaved buffer has been closed" )
                        return
                    # The widget was found, so jump to the required
                    editor = widget.getEditor()
                    editor.gotoLine( lineNumber, pos )
                    editor.setFocus()
                    return

        GlobalData().mainWindow.openFile( fileName, lineNumber, pos )
        return

    def __resizeBodyFrame( self ):
        " Resizing the frame to occupy all available width "
        size = self.bodyWidget.maximumViewportSize()
        self.__bodyFrame.setMinimumWidth( size.width() - 16 )
        self.__bodyFrame.setMinimumHeight( size.height() )
        return

    def showEvent( self, showEv = None ):
        " Called when the widget is shown "
        self.__resizeBodyFrame()
        return

    def resizeEvent( self, resizeEv = None ):
        " Called when the main window gets resized "
        self.__resizeBodyFrame()
        return

    def onFileUpdated( self, fileName, uuid ):
        " Called when a buffer is saved or saved as "

        if not self.__reportShown:
            return
        if self.__reportUUID != uuid:
            return

        # Currently shown report is for the saved buffer
        # File name is expected being absolute
        self.__reportFileName = fileName
        self.updatePylintTooltip.emit( "Report generated for buffer saved as " +
                                       fileName )
        return

    def __similarityActivated( self, item, column ):
        " Triggered when a similarity is activated "
        fileName = str( item.text( 0 ) )
        lineNumber = int( item.text( 1 ) )
        GlobalData().mainWindow.openFile( fileName, lineNumber )
        return
Exemplo n.º 36
0
class FileOutlineViewer( QWidget ):
    """ The file outline viewer widget """

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

        self.__editorsManager = editorsManager
        self.__mainWindow = parent
        self.__editorsManager.currentChanged.connect( self.__onTabChanged )
        self.connect( self.__editorsManager, SIGNAL( "tabClosed" ),
                      self.__onTabClosed )
        self.connect( self.__editorsManager, SIGNAL( 'bufferSavedAs' ),
                      self.__onSavedBufferAs )
        self.connect( self.__editorsManager, SIGNAL( 'fileTypeChanged' ),
                      self.__onFileTypeChanged )

        self.__outlineBrowsers = {}  # UUID -> OutlineAttributes
        self.__currentUUID = None
        self.__updateTimer = QTimer( self )
        self.__updateTimer.setSingleShot( True )
        self.__updateTimer.timeout.connect( self.__updateView )

        self.findButton = None
        self.outlineViewer = None
        self.toolbar = None
        self.__createLayout()

        self.__modifiedFormat = Settings().modifiedFormat

        # create the context menu
        self.__menu = QMenu( self )
        self.__findMenuItem = self.__menu.addAction(
                                PixmapCache().getIcon( 'findusage.png' ),
                                'Find where used', self.__findWhereUsed )
        return

    def setTooltips( self, switchOn ):
        " Sets the tooltips mode "
        for key in self.__outlineBrowsers:
            self.__outlineBrowsers[ key ].browser.setTooltips( switchOn )
        return

    def __connectOutlineBrowser( self, browser ):
        " Connects a new buffer signals "
        browser.setContextMenuPolicy( Qt.CustomContextMenu )
        browser.customContextMenuRequested.connect( self.__handleShowContextMenu )

        self.connect( browser,
                      SIGNAL( "selectionChanged" ),
                      self.__selectionChanged )
        return

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

        # Toolbar part - buttons
        self.findButton = QAction(
                PixmapCache().getIcon( 'findusage.png' ),
                'Find where highlighted item is used', self )
        self.findButton.setVisible( False )
        self.findButton.triggered.connect( self.__findWhereUsed )
        self.showParsingErrorsButton = QAction(
                PixmapCache().getIcon( 'showparsingerrors.png' ),
                'Show lexer/parser errors', self )
        self.showParsingErrorsButton.triggered.connect( self.__showParserError )
        self.showParsingErrorsButton.setEnabled( False )

        self.toolbar = QToolBar( self )
        self.toolbar.setMovable( False )
        self.toolbar.setAllowedAreas( Qt.TopToolBarArea )
        self.toolbar.setIconSize( QSize( 16, 16 ) )
        self.toolbar.setFixedHeight( 28 )
        self.toolbar.setContentsMargins( 0, 0, 0, 0 )
        self.toolbar.addAction( self.findButton )
        self.toolbar.addAction( self.showParsingErrorsButton )

        # Prepare members for reuse
        self.__noneLabel = QLabel( "\nNot a python file" )
        self.__noneLabel.setFrameShape( QFrame.StyledPanel )
        self.__noneLabel.setAlignment( Qt.AlignHCenter )
        headerFont = self.__noneLabel.font()
        headerFont.setPointSize( headerFont.pointSize() + 2 )
        self.__noneLabel.setFont( headerFont )
        self.__noneLabel.setAutoFillBackground( True )
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor( QPalette.Background,
                                   GlobalData().skin.nolexerPaper )
        self.__noneLabel.setPalette( noneLabelPalette )

        self.__layout = QVBoxLayout()
        self.__layout.setContentsMargins( 0, 0, 0, 0 )
        self.__layout.setSpacing( 0 )
        self.__layout.addWidget( self.toolbar )
        self.__layout.addWidget( self.__noneLabel )

        self.setLayout( self.__layout )
        return

    def __selectionChanged( self, index ):
        " Handles the changed selection "
        if index is None:
            self.__outlineBrowsers[ self.__currentUUID ].contentItem = None
        else:
            self.__outlineBrowsers[ self.__currentUUID ].contentItem = \
                self.__outlineBrowsers[
                        self.__currentUUID ].browser.model().item( index )

        self.__updateButtons()
        return

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

        browser = self.__outlineBrowsers[ self.__currentUUID ].browser
        index = browser.indexAt( coord )
        if not index.isValid():
            return

        # This will update the contextItem
        self.__selectionChanged( index )

        contextItem = self.__outlineBrowsers[ self.__currentUUID ].contentItem
        if contextItem is None:
            return

        self.__findMenuItem.setEnabled( self.findButton.isEnabled() )

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

    def __goToDefinition( self ):
        " Jump to definition context menu handler "
        contextItem = self.__outlineBrowsers[ self.__currentUUID ].contentItem
        if contextItem is not None:
            self.__outlineBrowsers[
                        self.__currentUUID ].browser.openItem( contextItem )
        return

    def __findWhereUsed( self ):
        """ Find where used context menu handler """
        contextItem = self.__outlineBrowsers[ self.__currentUUID ].contentItem
        if contextItem is not None:
            GlobalData().mainWindow.findWhereUsed(
                    contextItem.getPath(),
                    contextItem.sourceObj )
        return

    def __updateButtons( self ):
        " Updates the toolbar buttons depending on what is selected "

        self.findButton.setEnabled( False )

        contextItem = self.__outlineBrowsers[ self.__currentUUID ].contentItem
        if contextItem is None:
            return

        if contextItem.itemType in [ FunctionItemType, ClassItemType,
                                     AttributeItemType, GlobalItemType ]:
            self.findButton.setEnabled( True )
        return

    def __onTabChanged( self, index ):
        " Triggered when another tab becomes active "

        # If the timer is still active that means the tab was switched before
        # the handler had a chance to work. Therefore update the previous tab
        # first if so.
        if self.__updateTimer.isActive():
            self.__updateTimer.stop()
            self.__updateView()

        # Now, switch the outline browser to the new tab
        if index == -1:
            widget = self.__editorsManager.currentWidget()
        else:
            widget = self.__editorsManager.getWidgetByIndex( index )
        if widget is None:
            if self.__currentUUID is not None:
                self.__outlineBrowsers[ self.__currentUUID ].browser.hide()
                self.__currentUUID = None
            self.__noneLabel.show()
            self.showParsingErrorsButton.setEnabled( False )
            return
        if widget.getType() not in [ MainWindowTabWidgetBase.PlainTextEditor,
                                     MainWindowTabWidgetBase.VCSAnnotateViewer ]:
            if self.__currentUUID is not None:
                self.__outlineBrowsers[ self.__currentUUID ].browser.hide()
                self.__currentUUID = None
            self.__noneLabel.show()
            self.showParsingErrorsButton.setEnabled( False )
            return

        # This is text editor, detect the file type
        if widget.getFileType() not in [ PythonFileType, Python3FileType ]:
            if self.__currentUUID is not None:
                self.__outlineBrowsers[ self.__currentUUID ].browser.hide()
                self.__currentUUID = None
            self.__noneLabel.show()
            self.showParsingErrorsButton.setEnabled( False )
            return


        # This is a python file, check if we already have the parsed info in
        # the cache
        uuid = widget.getUUID()
        if uuid in self.__outlineBrowsers:
            # We have it, hide the current and show the existed
            if self.__currentUUID is not None:
                self.__outlineBrowsers[ self.__currentUUID ].browser.hide()
                self.__currentUUID = None
            else:
                self.__noneLabel.hide()
            self.__currentUUID = uuid
            self.__outlineBrowsers[ self.__currentUUID ].browser.show()

            info = self.__outlineBrowsers[ self.__currentUUID ].info
            self.showParsingErrorsButton.setEnabled( info.isOK != True )
            return

        # It is first time we are here, create a new
        editor = widget.getEditor()
        editor.SCEN_CHANGE.connect( self.__onBufferChanged )
        editor.cursorPositionChanged.connect( self.__cursorPositionChanged )
        info = getBriefModuleInfoFromMemory( editor.text() )

        self.showParsingErrorsButton.setEnabled( info.isOK != True )

        shortFileName = widget.getShortName()
        browser = OutlineBrowser( uuid, shortFileName, info, self )
        browser.setHeaderHighlight( info.isOK != True )
        self.__connectOutlineBrowser( browser )
        self.__layout.addWidget( browser )
        if self.__currentUUID is not None:
            self.__outlineBrowsers[ self.__currentUUID ].browser.hide()
            self.__currentUUID = None
        else:
            self.__noneLabel.hide()

        self.__currentUUID = uuid
        attributes = OutlineAttributes()
        attributes.browser = browser
        attributes.contextItem = None
        attributes.info = info
        attributes.shortFileName = shortFileName
        attributes.changed = False
        self.__outlineBrowsers[ self.__currentUUID ] = attributes
        self.__outlineBrowsers[ self.__currentUUID ].browser.show()
        return

    def getCurrentUsedInfo( self ):
        " Provides the info used to show the current outline window "
        if self.__currentUUID in self.__outlineBrowsers:
            return self.__outlineBrowsers[ self.__currentUUID ].info
        return None

    def __cursorPositionChanged( self, xpos, ypos ):
        " Triggered when a cursor position is changed "
        if self.__updateTimer.isActive():
            # If a file is very large and the cursor is moved
            # straight after changes this will delay the update till
            # the real pause.
            self.__updateTimer.stop()
            self.__updateTimer.start( 1500 )
        return

    def __onBufferChanged( self ):
        " Triggered when a change in the buffer is identified "
        if self.__currentUUID is None:
            return
        widget = self.__editorsManager.getWidgetByUUID(
                                        self.__currentUUID )
        if widget is None:
            return
        if widget.getEditor().ignoreBufferChangedSignal:
            return
        if self.__mainWindow.debugMode:
            return

        self.__updateTimer.stop()
        if self.__currentUUID in self.__outlineBrowsers:
            if self.__outlineBrowsers[ self.__currentUUID ].changed == False:
                self.__outlineBrowsers[ self.__currentUUID ].changed = True
                browser = self.__outlineBrowsers[ self.__currentUUID ].browser
                fName = self.__outlineBrowsers[ self.__currentUUID ].shortFileName
                title = self.__modifiedFormat % fName
                browser.model().sourceModel().updateRootData( 0, title )
        self.__updateTimer.start( 1500 )
        return

    def __updateView( self ):
        " Updates the view when a file is changed "
        self.__updateTimer.stop()
        info = self.getCurrentBufferInfo()
        if info is None:
            return

        self.showParsingErrorsButton.setEnabled( info.isOK != True )
        browser = self.__outlineBrowsers[ self.__currentUUID ].browser
        fName = self.__outlineBrowsers[ self.__currentUUID ].shortFileName
        browser.setHeaderHighlight( info.isOK != True )

        if not info.isOK:
            title = self.__modifiedFormat % fName
            browser.model().sourceModel().updateRootData( 0, title )
            return

        browser.model().sourceModel().updateRootData( 0, fName )
        self.__outlineBrowsers[ self.__currentUUID ].changed = False

        browser.updateFileItem( browser.model().sourceModel().rootItem, info )
        self.__outlineBrowsers[ self.__currentUUID ].info = info

        return

    def getCurrentBufferInfo( self ):
        " Provides the current buffer parsed info "
        if self.__currentUUID is None:
            return None
        widget = self.__editorsManager.getWidgetByUUID( self.__currentUUID )
        if widget is None:
            return None

        editor = widget.getEditor()
        info = getBriefModuleInfoFromMemory( editor.text() )
        return info

    def __onTabClosed( self, uuid ):
        " Triggered when a tab is closed "

        if uuid in self.__outlineBrowsers:
            del self.__outlineBrowsers[ uuid ]
        return

    def __onSavedBufferAs( self, fileName, uuid ):
        " Triggered when a file is saved with a new name "

        if uuid in self.__outlineBrowsers:

            baseName = os.path.basename( fileName )
            if detectFileType( fileName ) not in [ PythonFileType,
                                                   Python3FileType ]:
                # It's not a python file anymore
                if uuid == self.__currentUUID:
                    self.__outlineBrowsers[ uuid ].browser.hide()
                    self.__noneLabel.show()
                    self.__currentUUID = None

                del self.__outlineBrowsers[ uuid ]
                self.showParsingErrorsButton.setEnabled( False )
                self.findButton.setEnabled( False )
                return

            # Still python file with a different name
            browser = self.__outlineBrowsers[ uuid ].browser
            self.__outlineBrowsers[ uuid ].shortFileName = baseName
            if self.__outlineBrowsers[ uuid ].changed:
                title = self.__modifiedFormat % baseName
            else:
                title = baseName
            browser.model().sourceModel().updateRootData( 0, title )
        return

    def __onFileTypeChanged( self, fileName, uuid, newFileType ):
        " Triggered when the current buffer file type is changed, e.g. .cgi "
        if newFileType in [ PythonFileType, Python3FileType ]:
            # The file became a python one
            if uuid not in self.__outlineBrowsers:
                self.__onTabChanged( -1 )
        else:
            if uuid in self.__outlineBrowsers:
                # It's not a python file any more
                if uuid == self.__currentUUID:
                    self.__outlineBrowsers[ uuid ].browser.hide()
                    self.__noneLabel.show()
                    self.__currentUUID = None

                del self.__outlineBrowsers[ uuid ]
                self.showParsingErrorsButton.setEnabled( False )
                self.findButton.setEnabled( False )
        return

    def __showParserError( self ):
        " Shows the parser errors window "
        if self.__currentUUID is None:
            return

        try:
            fName = self.__outlineBrowsers[ self.__currentUUID ].shortFileName

            widget = self.__editorsManager.getWidgetByUUID( self.__currentUUID )
            if widget is None:
                return

            editor = widget.getEditor()
            info = getBriefModuleInfoFromMemory( editor.text() )
            dialog = ParserErrorsDialog( fName, info )
            dialog.exec_()
        except Exception, ex:
            logging.error( str( ex ) )
        return