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
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
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())
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
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
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)
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
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
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
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
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)
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)
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
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
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
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()
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
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
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
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)
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( "&", "&" ) \ .replace( ">", ">" ) \ .replace( "<", "<" ) 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
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")
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
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
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()
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)
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
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)
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()
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
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
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
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
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( "&", "&" ) \ .replace( ">", ">" ) \ .replace( "<", "<" ) 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
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