class ActiveLabel(HelpedWidget): """Label shows a string. The model must be a TextModelMixin""" def __init__(self, model, label="", help_link=""): HelpedWidget.__init__(self, label, help_link) assert isinstance(model, BasicModelMixin) self.model = model self.model.observable().attach(BasicModelMixin.VALUE_CHANGED_EVENT, self.modelChanged) self.active_label = QLabel() self.addWidget(self.active_label) font = self.active_label.font() font.setWeight(QFont.Bold) self.active_label.setFont(font) self.modelChanged() def modelChanged(self): """Retrieves data from the model and inserts it into the edit line""" self_get_from_model = self.model.getValue() if self_get_from_model is None: self_get_from_model = "" self.active_label.setText(str(self_get_from_model))
def addMenuLine(self, parent, text, box, header = False): aLabel = QLabel(text, parent) if header: aLabel.setAlignment(Qt.AlignCenter) oldFont = aLabel.font() aLabel.setFont(QFont(oldFont.family(), 13, QFont.Bold)) box.addWidget(aLabel, 0, Qt.AlignBottom)
def __init__(self, patts_version, parent=None): super().__init__(parent) okButton = QPushButton(_('OK')) okButton.clicked.connect(self.accept) layout = QVBoxLayout() title = QLabel('patts-qt v{}'.format(__version__)) title_font = title.font() title_font.setPointSize(20) title_font.setBold(True) title.setFont(title_font) versions = ('patts module v{}'.format(patts_version), 'libpatts v{}'.format(get_c_library_version()), 'patts db v{}'.format(get_db_version())) layout.addWidget(title) layout.addWidget(QLabel('(' + ', '.join(versions) + ')')) holders = ',\n\t'.join([holder for holder in _COPYRIGHT_HOLDERS]) layout.addWidget(QLabel(_('About.copyright') + ' ' + holders)) layout.addWidget(QLabel(_('About.license'))) layout.addWidget(okButton) self.setLayout(layout) self.setWindowTitle(_('About.title'))
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
class ActiveLabel(HelpedWidget): """Label shows a string. The model must be a TextModelMixin""" def __init__(self, model, label="", help_link=""): HelpedWidget.__init__(self, label, help_link) assert isinstance(model, BasicModelMixin) self.model = model self.model.observable().attach(BasicModelMixin.VALUE_CHANGED_EVENT, self.modelChanged) self.active_label = QLabel() self.addWidget(self.active_label) font = self.active_label.font() font.setWeight(QFont.Bold) self.active_label.setFont(font) self.modelChanged() def modelChanged(self): """Retrieves data from the model and inserts it into the edit line""" self_get_from_model = self.model.getValue() if self_get_from_model is None: self_get_from_model = "" self.active_label.setText(str(self_get_from_model))
def addMenuLine(self, parent, text, box, header=False): aLabel = QLabel(text, parent) if header: aLabel.setAlignment(Qt.AlignCenter) oldFont = aLabel.font() aLabel.setFont(QFont(oldFont.family(), 13, QFont.Bold)) box.addWidget(aLabel, 0, Qt.AlignBottom)
def __init__(self, patts_version, parent=None): super().__init__(parent) okButton = QPushButton(_('OK')) okButton.clicked.connect(self.accept) layout = QVBoxLayout() title = QLabel('patts-qt v{}'.format(__version__)) title_font = title.font() title_font.setPointSize(20) title_font.setBold(True) title.setFont(title_font) versions = ( 'patts module v{}'.format(patts_version), 'libpatts v{}'.format(get_c_library_version()), 'patts db v{}'.format(get_db_version()) ) layout.addWidget(title) layout.addWidget(QLabel('(' + ', '.join(versions) + ')')) holders = ',\n\t'.join([holder for holder in _COPYRIGHT_HOLDERS]) layout.addWidget(QLabel(_('About.copyright') + ' ' + holders)) layout.addWidget(QLabel(_('About.license'))) layout.addWidget(okButton) self.setLayout(layout) self.setWindowTitle(_('About.title'))
def populateMenuFromSettings(self, menu): """ :type menu: QMenu """ actions = menu.actions() before = actions[0] if actions else None title = QWidgetAction(menu) label = QLabel("Hosts") font = label.font() px = font.pointSize() font.setBold(True) font.setPointSize(px * 1.5) label.setFont(font) label.setMargin(4) label.setIndent(10) # label.setStyleSheet("font-weight: bold; margin: 4px 2px; border-bottom: 2px solid black") title.setDefaultWidget(label) menu.insertAction(before, title) self.menuServers.append(title) servers = self.settings.beginReadArray("servers") for d in range(servers): self.settings.setArrayIndex(d) server = Server.fromSettings(self.settings) action = QAction(QIcon("res/server.png"), server.alias, menu) menu.insertAction(before, action) action.setData(server) action.triggered.connect(self.wakeFromMenu) self.menuServers.append(action) self.settings.endArray()
def __init__(self, data, summary, parent=None): super().__init__(parent) layout = QVBoxLayout() types = [] patts.connect() try: info = self._title_info(data) self._title_string = _('Reports.summaryFor').format(info) titleLabel = QLabel(self._title_string) titleLabelFont = titleLabel.font() titleLabelFont.setBold(True) titleLabel.setFont(titleLabelFont) layout.addWidget(titleLabel) sort_types(list(summary.keys()), types) for type in types: if type not in summary: continue type_info = patts.get_type_byid(type) resultBox = QHBoxLayout() resultBox.addWidget(QLabel(type_info['displayName'] + ':')) resultBox.addStretch(1) resultBox.addWidget(QLabel(result_stamp(summary[type]))) layout.addLayout(resultBox) finally: patts.close() self.setWindowTitle(_('Reports.summaryResults')) self.setLayout(layout)
class TimerWidget(QLabel): def __init__(self,ressource_directory, dim: QSize, clock_dim_ratio: tuple=(0.9, 0.35), clock_color="#FFFFFF", dev_mode=False): super().__init__() self.setMaximumSize(dim) self.setMinimumSize(dim) self.font_color = clock_color # Setup clock background self._load_timer_picture(ressource_directory) #self.setPixmap(self.fond_pixmap.scaled(dim, Qt.KeepAspectRatio)) self.setPixmap(self.fond_pixmap.scaled(QSize(dim.width()-5,dim.height()-5), Qt.KeepAspectRatio)) self.setContentsMargins((dim.width() - self.pixmap().width()) * 0.5, (dim.height() - self.pixmap().height()) * 0.5, (dim.width() - self.pixmap().width()) * 0.5, (dim.height() - self.pixmap().height()) * 0.5) if dev_mode: self.setStyleSheet("background-color:yellow") else: self.setAttribute(Qt.WA_TranslucentBackground, True) # Setup clock foreground self.clock_layout = QtGui.QGridLayout() self.setLayout(self.clock_layout) self.clock_layout.setContentsMargins(0,0,0,0) self.clock_label = QLabel() self.clock_layout.addWidget(self.clock_label) self.clock_label.setAlignment(Qt.AlignCenter) #self.default_font = self.font() #TODO set custom font font = self.clock_label.font() font.setBold(True) self.clock_label.setFont(font) bound = self.clock_label.fontMetrics().boundingRect("00") font_size_ratio = min(dim.width() * clock_dim_ratio[0] / bound.width() * 0.5, dim.height() * clock_dim_ratio[1] / bound.height()) font.setPointSizeF(font_size_ratio * self.clock_label.font().pointSize()+10) self.clock_label.setFont(font) self.clock_label.setAttribute(Qt.WA_TranslucentBackground, True) self.set_timer_value(0) # TODO def adjustSize , to resize the widget def set_timer_value(self, new_val): self.clock_label.setText("<font color=" + self.font_color + ">" + str(new_val) + "</font>") def _load_timer_picture(self, ressource_directory): """Load les Pixelmap des images du timer Utile a l'initialisation """ # Image de fond self.fond_pixmap = QtGui.QPixmap(ressource_directory + "fond_timer.png")
def createGPSLabel(self, form, key, value): lbl = QLabel(self.canMonitor) lbl.setMinimumHeight(50) font = lbl.font() font.setPointSize(14) lbl.setFont(font) lbl.setText(key) lbl2 = QLabel(self.canMonitor) lbl2.setMinimumHeight(50) font = lbl2.font() font.setPointSize(14) lbl2.setFont(font) lbl2.setText(value) self.valueLabelList.append(lbl2) form.addRow(lbl, lbl2)
def _addLabel(self, v, cnt): label = QLabel(v.name + ':') f = QFont(label.font().family()) f.setPointSizeF(11) label.setFont(f) label.setMinimumWidth(80) label.setAlignment(Qt.AlignRight) self.layout.addWidget(label, cnt, 0)
def _addLabel(self, v, cnt): label = QLabel(v.name + ':') f = QFont(label.font().family()) f.setPointSizeF(11) label.setFont(f) label.setMinimumWidth(80) label.setAlignment(Qt.AlignRight) self.layout.addWidget(label, cnt, 0)
def _createTitleLabel(text, size=sectionFontSize): label = QLabel(text) font = QFont(label.font()) font.setPointSize(size) font.setWeight(75) font.setBold(True) label.setFont(font) label.setWordWrap(True) return label
def widgetLabel(widget, label="", labelWidth=None, **misc): lbl = QLabel(label, widget) if labelWidth: lbl.setFixedSize(labelWidth, lbl.sizeHint().height()) orange_gui.miscellanea(lbl, None, widget, **misc) font = lbl.font() font.setPointSize(current_module.gui_point_size) lbl.setFont(font) return lbl
class WidgetProgress(QWidget): def __init__(self,parent = None): super(WidgetProgress,self).__init__(parent) #self.setFixedWidth(300) self.setFixedSize(500,300) self.tipLabel = QLabel(self.tr("downloading...")) self.setStyleSheet("background-color:rgba(5,5,255,0);") self.tipLabel.setStyleSheet( "background-color:rgba(5,5,255,255);" "QToolTip{" "background-color:rgba(5,255,55,255)" "};" ) labelLayout = QHBoxLayout(self) labelLayout.addStretch() labelLayout.addWidget(self.tipLabel) labelLayout.addStretch() self.test() def test(self): s = "win7_32 test1 test2 test3 test4" text = self.tr("course ") + s + u" downloading..." text_2 = self.__getElidedText(self.tipLabel.font(),text, 150) self.tipLabel.setText(text_2) #text = "<html style=\"background:rgb(255,255,255);" \ # "border:0px\"" \ # ">" \ # "<font color=red>%s</font>" \ # "</html>" % text self.setToolTip(text) def __getElidedText(self,font,s,maxWidth): ''' ''' fontWidth = QFontMetrics(font) width = fontWidth.width(s) if width >= maxWidth: s = fontWidth.elidedText(s,Qt.ElideRight,maxWidth) return s
def warningDialog(self, parent, title='FPS', msg='Adjusting frame rate,\n please wait...'): from cross3d.migrate import Window # Tell the user what is going on and that they should wait for it to complete. # Because of the this system works it can not block keyboard and mouse input to Max # TODO: Re-build this in a generic non-blurdev specific way. if Window: from PyQt4.QtGui import QLabel self.uiWarningWND = Window() self.uiWarningWND.setWindowTitle(title) x,y,w,h = GetWindowRect(parent) self.uiWarningWND.setGeometry(x+15, y+40, 303, 80) lbl = QLabel(self.uiWarningWND) fnt = lbl.font() fnt.setPointSize(20) lbl.setGeometry(0,0,300,86) lbl.setFont(fnt) lbl.setText(msg) self.uiWarningWND.show()
class FoldableTable(QFrame): def __init__(self, parent = None): QFrame.__init__(self, parent) self.setFrameStyle(QFrame.Box | QFrame.Raised); self.setupWidget() self.folded = False self.connect(self.folding_button, SIGNAL("clicked()"), self.toggleVisible) self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) def setupWidget(self): self.plus_icon = QIcon() self.plus_icon.addPixmap(QPixmap(":/icons/add.png")) self.minus_icon = QIcon() self.minus_icon.addPixmap(QPixmap(":/icons/moins.png")) self.layout = QGridLayout(self) self.folding_button = QPushButton(self.minus_icon, "", self) self.folding_button.setMaximumSize(QSize(30,30)) self.layout.addWidget(self.folding_button, 0, 0) self.label = QLabel("") self.layout.addWidget(self.label, 0, 1) self.table = QTableWidget(self) self.layout.addWidget(self.table, 1, 1) self.table.horizontalHeader().setStretchLastSection(1) self.font = self.label.font() self.font.setBold(True) self.font.setPointSize(self.font.pointSize() * 1.5) self.label.setFont(self.font) ## resize table to contents ## set column stretch to ensure first column won't expand when table ## is hidden self.layout.setColumnStretch(1, 10) def toggleVisible(self): self.folded = not self.folded if self.folded: self.folding_button.setIcon(self.plus_icon) self.table.hide() else: self.folding_button.setIcon(self.minus_icon) self.table.show() def setLabel(self, text): self.label.setText(text)
def createCANIdEntry(self, form, canId, subId, label, mode): # hbox = QHBoxLayout() lbl = QLabel(self) lbl.setMinimumHeight(50) font = lbl.font() font.setPointSize(14) lbl.setFont(font) if label!=None: lbl.setText(label) # hbox.addWidget(lbl) lcd = self.createLCD(mode) # hbox.addWidget(lcd) form.addRow(lbl, lcd) self.addLCD(lcd, canId, subId)
def warningDialog(self, parent, title='FPS', msg='Adjusting frame rate,\n please wait...'): from cross3d.migrate import Window # Tell the user what is going on and that they should wait for it to complete. # Because of the this system works it can not block keyboard and mouse input to Max # TODO: Re-build this in a generic non-blurdev specific way. if Window: from PyQt4.QtGui import QLabel self.uiWarningWND = Window() self.uiWarningWND.setWindowTitle(title) x, y, w, h = GetWindowRect(parent) self.uiWarningWND.setGeometry(x + 15, y + 40, 303, 80) lbl = QLabel(self.uiWarningWND) fnt = lbl.font() fnt.setPointSize(20) lbl.setGeometry(0, 0, 300, 86) lbl.setFont(fnt) lbl.setText(msg) self.uiWarningWND.show()
def createCANIdEntrySingleLine(self, form, canId, subIdList, label, mode): # hbox = QHBoxLayout() lbl = QLabel(self) lbl.setMinimumHeight(50) font = lbl.font() font.setPointSize(14) lbl.setFont(font) if label!=None: lbl.setText(label) # hbox.addWidget(lbl) hbox2=QHBoxLayout(); for i in range(len(subIdList)): subId=subIdList[i] lcd = self.createLCD(mode) hbox2.addWidget(lcd) self.addLCD(lcd, canId, subId) form.addRow(lbl, hbox2)
class ReportStepWidget(QWidget): reportStepTimeSelected = pyqtSignal(int) def __init__(self): QWidget.__init__(self) layout = QVBoxLayout() self.setLayout(layout) def converter(item): return "%s" % (str(item.date())) self.__items = ReportStepsModel().getList() self.__time_spinner = ListSpinBox(self.__items) self.__time_spinner.valueChanged[int].connect(self.valueSelected) self.__time_spinner.setStringConverter(converter) layout.addWidget(self.__time_spinner) self.__label = QLabel("Report Step") layout.addWidget(self.__label, 0, Qt.AlignHCenter) layout.addStretch() def valueSelected(self, index): self.reportStepTimeSelected.emit(self.__items[index]) def getSelectedValue(self): """ @rtype: CTime """ index = self.__time_spinner.value() return self.__items[index] def setFontSize(self, size): font = self.__time_spinner.font() font.setPointSize(size) self.__time_spinner.setFont(font) font = self.__label.font() font.setPointSize(size) self.__label.setFont(font)
class ReportStepWidget(QWidget): reportStepTimeSelected = pyqtSignal(int) def __init__(self): QWidget.__init__(self) layout = QVBoxLayout() self.setLayout(layout) def converter(item): return "%s" % (str(item.date())) self.__items = ReportStepsModel().getList() self.__time_spinner = ListSpinBox(self.__items) self.__time_spinner.valueChanged[int].connect(self.valueSelected) self.__time_spinner.setStringConverter(converter) layout.addWidget(self.__time_spinner) self.__label = QLabel("Report Step") layout.addWidget(self.__label, 0, Qt.AlignHCenter) layout.addStretch() def valueSelected(self, index): self.reportStepTimeSelected.emit(self.__items[index]) def getSelectedValue(self): """ @rtype: CTime """ index = self.__time_spinner.value() return self.__items[index] def setFontSize(self, size): font = self.__time_spinner.font() font.setPointSize(size) self.__time_spinner.setFont(font) font = self.__label.font() font.setPointSize(size) self.__label.setFont(font)
def __init__(self,parent): QToolBar.__init__(self,parent) self.parent = parent self.action_NewProject = QAction(Icons.newprj, 'Project', self) self.action_NewProject.triggered.connect(self.parent.treeWidget.newProject) self.action_NewProject.setToolTip("Create a New Project") self.action_Open = QAction(Icons.open, 'Open', self) self.action_Open.triggered.connect(self.parent.fileOpen) self.action_Open.setToolTip("Open File") self.action_Save = QAction(Icons.save, 'Save', self) self.action_Save.setShortcut('Ctrl+S') self.action_Save.triggered.connect(self.parent.fileSave) self.action_Save.setToolTip("Save Current File") self.action_SaveAll = QAction(Icons.saveall, 'SaveAll', self) self.action_SaveAll.setShortcut('Ctrl+A') self.action_SaveAll.triggered.connect(self.parent.fileSaveAll) self.action_SaveAll.setToolTip("Save All Files") self.action_Build = QAction(Icons.thread_view, 'Build', self) self.action_Build.setShortcut('Ctrl+B') self.action_Build.triggered.connect(self.parent.build_project) self.action_Debug = QAction(Icons.debug_exec, 'Debug', self) self.action_Refresh = QAction(Icons.refresh_tab, 'Refresh', self) self.action_Refresh.triggered.connect(self.parent.treeWidget.refreshCurrentProject) self.action_Run = QAction(Icons.run, 'Run', self) self.action_Run.setShortcut('Ctrl+R') self.action_Run.triggered.connect(self.parent.adb.run) self.action_RunFile = QAction(Icons.go, 'Cmd', self) self.action_RunFile.triggered.connect(self.parent.openCommand) self.parent.runButton.clicked.connect(self.parent.command.setCmdLine) self.action_Stop = QAction(Icons.stop, 'Stop', self) self.action_Stop.setShortcut('Ctrl+Q') self.action_Stop.triggered.connect(self.parent.adb.stop) self.action_Design = QAction(Icons.color_palette, 'Design', self) self.action_Design.triggered.connect(self.parent.design) self.action_Level = QAction(Icons.cmpC_pal, 'Level', self) self.action_Level.triggered.connect(self.parent.level) self.action_Todo = QAction(Icons.task_set, 'Todo', self) self.action_Todo.triggered.connect(self.parent.todo) self.action_Help = QAction(Icons.toc_open, 'Help', self) self.action_Help.triggered.connect(self.parent.help) men = QMenu() #Threshold Slider self.threshSlider = QSlider() self.threshSlider.setTickPosition(QSlider.TicksLeft) self.threshSlider.setOrientation(Qt.Horizontal) self.threshSlider.setValue(config.thresh()) self.threshSlider.setMinimum(0) self.threshSlider.setMaximum(5) self.threshSlider.valueChanged.connect(self.parent.setThreshold) self.threshSliderAction = QWidgetAction(men) self.threshSliderAction.setDefaultWidget(self.threshSlider) #TabsWidth Slider self.tabsSlider = QSlider() self.tabsSlider.setTickPosition(QSlider.TicksLeft) self.tabsSlider.setOrientation(Qt.Horizontal) self.tabsSlider.setValue(config.tabwidth()) self.tabsSlider.setMinimum(0) self.tabsSlider.setMaximum(8) self.tabsSlider.valueChanged.connect(self.parent.setTabWidth) self.tabsSliderAction = QWidgetAction(men) self.tabsSliderAction.setDefaultWidget(self.tabsSlider) #iconSize Slider self.iconSlider = QSlider() self.iconSlider.setTickPosition(QSlider.TicksLeft) self.iconSlider.setOrientation(Qt.Horizontal) self.iconSlider.setValue(config.iconSize()) self.iconSlider.setMinimum(16) self.iconSlider.setMaximum(32) self.iconSlider.setSingleStep(2) self.iconSlider.valueChanged.connect(self.setIcon) self.iconSliderAction = QWidgetAction(men) self.iconSliderAction.setDefaultWidget(self.iconSlider) '''Font Button''' self.fontCombo = QFontComboBox() self.fontCombo.currentFontChanged.connect(self.parent.setFont) self.fontCombo.setCurrentFont(QFont(config.fontName())) self.fontComboMenu = QWidgetAction(men) self.fontComboMenu.setDefaultWidget(self.fontCombo) '''Font Size''' self.fontSizeCombo = QComboBox() for size in range(1,40): self.fontSizeCombo.addItem(str(size)) self.fontSizeCombo.setCurrentIndex(config.fontSize()) self.fontSizeCombo.currentIndexChanged.connect(self.parent.setFontSize) self.fontSizeComboMenu = QWidgetAction(men) self.fontSizeComboMenu.setDefaultWidget(self.fontSizeCombo) action_explorer = QAction("Show Explorer",self) action_explorer.triggered.connect(self.parent.exp) action_console = QAction("Show Console",self) action_console.triggered.connect(self.parent.cmd) action_designer = QAction("Show Designer",self) action_designer.triggered.connect(self.parent.design) action_Indentation = QAction("Indentation Guides",self) action_Indentation.triggered.connect(self.parent.setIndent) action_WhiteSpace = QAction("Show WhiteSpace",self) action_WhiteSpace.triggered.connect(self.parent.setWhiteSpace) action_EndLine = QAction("Show End of Lines",self) action_EndLine.triggered.connect(self.parent.setEndLine) action_Margin = QAction("Line Numbers",self) action_Margin.triggered.connect(self.parent.setMargin) action_ToolLabel = QAction("Tool Labels",self) action_ToolLabel.triggered.connect(self.setToolLabel) action_Android = QAction(Icons.android,'Android', self) action_Android.triggered.connect(self.parent.android) action_Ant = QAction(Icons.ant_view,'Ant', self) action_Ant.triggered.connect(self.parent.antt) action_Squirrel = QAction(Icons.nut,'Squirrel', self) action_Squirrel.triggered.connect(self.parent.squirrel) action_Ios1 = QAction(Icons.ios,'iOS', self) action_Update = QAction("Update",self) action_Update.triggered.connect(self.parent.update) '''Encoding''' encodingGroup = QActionGroup(self) encodingGroup.setExclusive(True) action_Ascii = QAction("Ascii",encodingGroup) action_Ascii.setCheckable(True) action_Unicode = QAction("Unicode",encodingGroup) action_Unicode.setCheckable(True) encodingGroup.addAction(action_Ascii) encodingGroup.addAction(action_Unicode) encodingGroup.selected.connect(self.parent.setEncoding) if(config.encoding() == Encoding.ASCII): action_Ascii.setChecked(True) else: action_Unicode.setChecked(True) men.addAction(action_Android) men.addAction(action_Ant) men.addAction(action_Squirrel) men.addAction(action_Ios1) men.addAction(action_Update) men.addSeparator() men.addAction(action_explorer) men.addAction(action_console) men.addAction(action_designer) men.addAction(action_Indentation) men.addAction(action_WhiteSpace) men.addAction(action_EndLine) men.addAction(action_Margin) men.addAction(action_ToolLabel) men.addSeparator() men.addActions(encodingGroup.actions()) men.addSeparator() head_font = QLabel("Font---------------------") fnt = head_font.font() fnt.setBold(True) head_font.setFont(fnt) head_fontWidgetAction = QWidgetAction(men) head_fontWidgetAction.setDefaultWidget(head_font) men.addAction(head_fontWidgetAction) men.addAction(self.fontComboMenu) men.addAction(self.fontSizeComboMenu) men.addSeparator() men.addAction(QAction("TabWidth",self)) men.addAction(self.tabsSliderAction) men.addSeparator() men.addAction(QAction("Threshold",self)) men.addAction(self.threshSliderAction) #men.addAction(QAction("Icon Size",self)) #men.addAction(self.iconSliderAction) self.action_Options = QAction(Icons.emblem_system, 'Options', self) self.action_Options.setMenu(men) self.action_Full = QAction(Icons.fullscreen, 'Full', self) self.action_Full.setShortcut('Shift+Enter') self.action_Full.triggered.connect(self.parent.full) self.modeGroup = QActionGroup(self) self.modeGroup.setExclusive(True) self.modeGroup.selected.connect(self.parent.setMode) self.action_Squirrel = QAction(Icons.nut, 'Squ', self.modeGroup) self.action_Squirrel.setCheckable(True) self.action_Emo = QAction(Icons.emo, 'Emo', self.modeGroup) self.action_Emo.setCheckable(True) self.action_And = QAction(Icons.android, 'Android', self.modeGroup) self.action_And.setCheckable(True) self.action_Ios = QAction(Icons.ios, 'ios', self.modeGroup) self.action_Ios.setCheckable(True) self.modeGroup.addAction(self.action_Squirrel) self.modeGroup.addAction(self.action_Emo) self.modeGroup.addAction(self.action_And) self.modeGroup.addAction(self.action_Ios) self.action_Style = QAction(Icons.style, 'Style', self) men1 = QMenu() self.styleslist = [] self.style1 = QAction("All Hallow's Eve",self) self.style1.triggered.connect(lambda:self.parent.style_clicked(1)) self.style1.setCheckable(True) self.style2 = QAction("Amy",self) self.style2.triggered.connect(lambda:self.parent.style_clicked(2)) self.style2.setCheckable(True) self.style3 = QAction("Aptana Studio",self) self.style3.triggered.connect(lambda:self.parent.style_clicked(3)) self.style3.setCheckable(True) self.style4 = QAction("Bespin",self) self.style4.triggered.connect(lambda:self.parent.style_clicked(4)) self.style4.setCheckable(True) self.style5 = QAction("Blackboard",self) self.style5.triggered.connect(lambda:self.parent.style_clicked(5)) self.style5.setCheckable(True) self.style6 = QAction("Choco",self) self.style6.triggered.connect(lambda:self.parent.style_clicked(6)) self.style6.setCheckable(True) self.style7 = QAction("Cobalt",self) self.style7.triggered.connect(lambda:self.parent.style_clicked(7)) self.style7.setCheckable(True) self.style8 = QAction("Dawn",self) self.style8.triggered.connect(lambda:self.parent.style_clicked(8)) self.style8.setCheckable(True) self.style9 = QAction("Eclipse",self) self.style9.triggered.connect(lambda:self.parent.style_clicked(9)) self.style9.setCheckable(True) self.styleslist.append(self.style1) self.styleslist.append(self.style2) self.styleslist.append(self.style3) self.styleslist.append(self.style4) self.styleslist.append(self.style5) self.styleslist.append(self.style6) self.styleslist.append(self.style7) self.styleslist.append(self.style8) self.styleslist.append(self.style9) men1.addActions(self.styleslist) self.action_Style.setMenu(men1) self.styleslist[self.parent.styleIndex].setChecked(True) self.action_Stop.setDisabled(True) self.setToolLabel() self.setAllowedAreas(Qt.AllToolBarAreas) #self.setFixedHeight(40) #self.setIconSize(QSize(config.iconSize(),config.iconSize())) self.addAction(self.action_NewProject) self.addAction(self.action_Open) self.addAction(self.action_Save) self.addAction(self.action_SaveAll) #self.addAction(self.action_Refresh) self.addSeparator() self.addAction(self.action_Build) self.addAction(self.action_Run) self.addAction(self.action_RunFile) self.addAction(self.action_Stop) self.addAction(self.action_Debug) self.addSeparator() self.addAction(self.action_Design) self.addAction(self.action_Level) self.addAction(self.action_Todo) self.addAction(self.action_Options) self.addAction(self.action_Style) self.addSeparator() self.addAction(self.action_Help) self.addAction(self.action_Full) self.addSeparator() self.addActions(self.modeGroup.actions()) if(config.mode() == 0): self.action_Squirrel.setChecked(True) elif(config.mode() == 1): self.action_Emo.setChecked(True) elif(config.mode() == 2): self.action_And.setChecked(True) elif(config.mode() == 3): self.action_Ios.setChecked(True)
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 CImprovedButton(QToolButton): def __init__(self, parent=None): QToolButton.__init__(self, parent) #TESTO ALTERNATIVO #Spesso se il pulsante ha icona troppo grossa e quando per ragioni di spazio o altro non si può spostare #o ridimensionare il pulsante stesso, la label ha posizioni assurde e schifose. Aggiungerne una "+ controllabile" #è l'unico modo.. self.__fixed_label = QLabel("alternative label", self) self.__fixed_label.move(0, self.geometry().height() - 35) self.__fixed_label.resize(self.geometry().width(), self.__fixed_label.geometry().height()) self.__fixed_label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) self.__font = QtGui.QFont("Arial", 10) self.__fixed_label.setFont(self.__font) self.__fixed_label.show() #INDICATORE STILE iOS self.__indicator = QLabel("0", self) self.__indicator.setStyleSheet( "border-image: url(':/images/backgrounds/indicator.png'); padding-right:1px; color: white;" ) self.__indicator.geometry().setWidth(25) self.__indicator.geometry().setHeight(20) self.__indicator.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) self.__indicator.setVisible(False) self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0)) #default top-right corner #Quando il pulsante viene ridimensionato (designer o meno) devo anche sistemare la label di conseguenza self.resizeEvent = self.__onResize self.__indicator.resizeEvent = self.__on_indicator_Resize self.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) self.clicked.connect(self.stopAllAnimations) #BLINK self.__blink_timer = QTimer(parent) self.__blink_timer.timeout.connect(self.__on_blink_timer) self.__blink_timer_interval = 1000 #FADING self.__opacity_effect = QGraphicsOpacityEffect() self.__fading_timer = QTimer(parent) self.__fading_timer.timeout.connect(self.__on_fading_timer) self.__FADE_TYPE = Enum("IN", "OUT") self.__fade_time = 20 self.__opacity = 1.0 self.__opacity_fading_coefficient = 0.02 self.__selected_fade_type = self.__FADE_TYPE.IN # ANIMAZIONI GROW self.__animationGrow = QPropertyAnimation(self, "iconSize", self) self.__animationGrow.setDuration(1000) self.__animationGrow.setEasingCurve(QEasingCurve.Linear) self.__animationGrow.finished.connect(self.__on_growed) self.__animationShrink = QPropertyAnimation(self, "iconSize", self) self.__animationShrink.setDuration(1000) self.__animationShrink.setEasingCurve(QEasingCurve.Linear) self.__animationShrink.finished.connect(self.__on_shrinked) self.__defaultIconDimension = 60 self.__iconGrowsBy = 40 self.__growing = False # ANIMAZIONI BOUNCE self.__animationUp = QPropertyAnimation(self, "pos", self) self.__animationUp.setDuration(200) self.__animationUp.setEasingCurve(QEasingCurve.Linear) self.__animationUp.finished.connect(self.__on_top_reached) self.__animationBounce = QPropertyAnimation(self, "pos", self) self.__animationBounce.setDuration(1000) self.__animationBounce.setEasingCurve(QEasingCurve.OutBounce) self.__animationBounce.finished.connect(self.__on_bounce_finished) self.__bouncing = False self.__startPos = QPoint(self.pos().x(), self.pos().y()) #PIXMAP & MASCHERA self.__pmap = QPixmap(self.size()) self.__pmap_fname = "" self.__show_mask_preview = False def setDefaultIconSize(self, value): """ Sets default icon size when growing stops. @param value: size (both width and height) @type value: int """ self.__defaultIconDimension = value def getDefaultIconSize(self): return self.__defaultIconDimension defaultIconSize = QtCore.pyqtProperty("int", getDefaultIconSize, setDefaultIconSize) def setFixetTextVisibility(self, bool): """ Sets if fixed text is visible or not. @param bool: visible or not @type bool: bool """ self.__fixed_label.setVisible(bool) def getFixetTextVisibility(self): return self.__fixed_label.isVisible() fixetTextVisibility = QtCore.pyqtProperty("bool", fget=getFixetTextVisibility, fset=setFixetTextVisibility) def setFixedText(self, txt): """ Sets text on the button. @param txt: text @type txt: string """ self.__fixed_label.setText(txt) def getFixedText(self): return self.__fixed_label.text() fixedText = QtCore.pyqtProperty("QString", getFixedText, setFixedText) def setFixedTextPos(self, qpoint): """ Sets text position in the button. @param qpoint: Position RELATIVE. 0,0 is top left corner of the button. @type qpoint: QPoint """ self.__fixed_label.move(qpoint) def getFixedTextPos(self): return self.__fixed_label.pos() fixedTextPos = QtCore.pyqtProperty("QPoint", getFixedTextPos, setFixedTextPos) def setFixedTextFont(self, font): """ Sets text font. @param font: Font for fixed text. @type font: QFont """ self.__font = font self.__fixed_label.setFont(self.__font) def getFixedTextFont(self): return self.__font fixedTextFont = QtCore.pyqtProperty("QFont", getFixedTextFont, setFixedTextFont) #FUNZIONI INDICATORE def setIndicatorVisibility(self, bool): """ Sets if indicator is visible or not. @param bool: visible or not @type bool: bool """ self.__indicator.setVisible(bool) def getIndicatorVisibility(self): return self.__indicator.isVisible() indicatorVisibility = QtCore.pyqtProperty("bool", fget=getIndicatorVisibility, fset=setIndicatorVisibility) def setIndicatorPos(self, qpoint): """ Sets indicator position in the button. @param qpoint: Position RELATIVE. 0,0 is top left corner of the button. @type qpoint: QPoint """ self.__indicator.move(qpoint) def getIndicatorPos(self): return self.__indicator.pos() indicatorPos = QtCore.pyqtProperty("QPoint", getIndicatorPos, setIndicatorPos) def setIndicatorSize(self, size): """ Sets indicator size. @param size: Size @type size: QSize """ self.__indicator.resize(size) def getIndicatorSize(self): return self.__indicator.size() indicatorSize = QtCore.pyqtProperty("QSize", getIndicatorSize, setIndicatorSize) def setIndicatorFont(self, font): """ Sets indicator text font. @param font: Font for indicator text. @type font: QFont """ self.__indicator.setFont(font) def getIndicatorFont(self): return self.__indicator.font() indicatorFont = QtCore.pyqtProperty("QFont", getIndicatorFont, setIndicatorFont) ## FUNZIONI PER BLINK def __on_blink_timer(self): self.setVisible(not (self.isVisible())) def setBlinking(self, blink): """ Sets if the button have to blink or not. @param blink: blinking or not @type blink: bool """ if blink: self.__blink_timer.setInterval(self.__blink_timer_interval) self.__blink_timer.start() else: self.__blink_timer.stop() self.setVisible(True) def setBlinkInterval(self, value): """ Sets blink interval. @param blink: blink interval (msec) @type blink: int """ self.__blink_timer_interval = value def getBlinkInterval(self): return self.__blink_timer_interval blinkInterval = QtCore.pyqtProperty("int", getBlinkInterval, setBlinkInterval) ##FUNZIONI PER FADING def fadeIn(self): """ Button fades in from completely invisible to completely visible. """ self.__opacity = 0.0 self.__selected_fade_type = self.__FADE_TYPE.IN self.__fading_timer.start(self.__fade_time) def fadeOut(self): """ Button fades out from completely visible to completely invisible. """ self.__selected_fade_type = self.__FADE_TYPE.OUT self.__fading_timer.start(self.__fade_time) def setFadeTime(self, value): """ Sets fading time. Everytime interval is reached, alpha is increased (or decreased) by __opacity_fading_coefficient. @param value: fade time (msec) @type value: int """ self.__fade_time = value def getFadeTime(self): return self.__fade_time fadeInterval = QtCore.pyqtProperty("int", getFadeTime, setFadeTime) def setFadeCoefficient(self, value): """ Sets fading coefficient. Alpha is increased (or decreased) by this value. @param value: coefficient (min 0.0 - max 1.0) @type value: float """ self.__opacity_fading_coefficient = value def getFadeCoefficient(self): return self.__opacity_fading_coefficient fadeCoefficient = QtCore.pyqtProperty("double", getFadeCoefficient, setFadeCoefficient) def __on_fading_timer(self): if self.__selected_fade_type == self.__FADE_TYPE.OUT: if self.__opacity > 0: self.__opacity -= self.__opacity_fading_coefficient self.__opacity_effect.setOpacity(self.__opacity) self.setGraphicsEffect(self.__opacity_effect) else: self.__fading_timer.stop() if self.__selected_fade_type == self.__FADE_TYPE.IN: if self.__opacity <= 1.0: self.__opacity += self.__opacity_fading_coefficient self.__opacity_effect.setOpacity(self.__opacity) self.setGraphicsEffect(self.__opacity_effect) else: self.__fading_timer.stop() # FUNZIONI PER GROW\SHRINK def __on_growed(self): self.__animationShrink.setStartValue( QSize(self.iconSize().width(), self.iconSize().height())) self.__animationShrink.setEndValue( QSize(self.iconSize().width() - self.__iconGrowsBy, self.iconSize().height() - self.__iconGrowsBy)) self.__animationShrink.start() def __on_shrinked(self): self.__animationGrow.setStartValue( QSize(self.iconSize().width(), self.iconSize().height())) self.__animationGrow.setEndValue( QSize(self.iconSize().width() + self.__iconGrowsBy, self.iconSize().height() + self.__iconGrowsBy)) self.__animationGrow.start() def startGrow(self): """ Button ICON starts to grow and shrink to standard value when maximum size (configured) is reached """ if self.__growing: return self.__animationGrow.setStartValue( QSize(self.iconSize().width(), self.iconSize().height())) self.__animationGrow.setEndValue( QSize(self.iconSize().width() + self.__iconGrowsBy, self.iconSize().height() + self.__iconGrowsBy)) self.__animationGrow.start() self.__growing = True def stopGrow(self): if self.__animationGrow.startValue().toSize() != QSize( 0, 0) and self.__animationShrink.startValue().toSize() != QPoint( 0, 0): self.__animationGrow.stop() self.__animationShrink.stop() self.setIconSize( QSize(self.__defaultIconDimension, self.__defaultIconDimension)) self.__growing = False #FUNZIONI PER BOUNCE def startBounce(self): """ Button starts to bounce requiring attention. """ if self.__bouncing: return self.__startPos = QPoint(self.pos().x(), self.pos().y()) self.__animationUp.setStartValue( QPoint(self.__startPos.x(), self.__startPos.y())) self.__animationUp.setEndValue( QPoint(self.__startPos.x(), self.__startPos.y() - self.geometry().height())) self.__animationUp.start() self.__bouncing = True def stopBounce(self): if self.__animationUp.startValue().toPoint() != QPoint( 0, 0) and self.__animationBounce.startValue().toPoint() != QPoint( 0, 0): self.__animationBounce.stop() self.__animationUp.stop() self.setGeometry(self.__startPos.x(), self.__startPos.y(), self.geometry().width(), self.geometry().height()) self.__bouncing = False def __on_top_reached(self): self.__animationBounce.setStartValue( QPoint(self.pos().x(), self.pos().y())) self.__animationBounce.setEndValue( QPoint(self.__startPos.x(), self.__startPos.y())) self.__animationBounce.start() def __on_bounce_finished(self): self.__animationUp.start() def stopAllAnimations(self): self.stopBounce() self.stopGrow() #FUNZIONI PER PIXMAP & MASCHERA def setPixmapFile(self, image_file): self.__pmap = image_file self.__pmap.scaled(self.size()) #NB: Il pixmap deve essere BIANCO e NERO. Con heuristicMask il primo pixel in alto a sinistra (0,0) viene #usato per decidere il colore trasparente, tutto il resto è visibile. def getPixmapFile(self): return self.__pmap pixmapFile = QtCore.pyqtProperty("QPixmap", getPixmapFile, setPixmapFile) def applyMask(self, bool): self.__show_mask_preview = bool if bool: self.setMask( QBitmap(self.__pmap.createHeuristicMask().scaled(self.size()))) else: self.setMask(QBitmap()) def getMask(self): return self.__show_mask_preview appliedMask = QtCore.pyqtProperty("bool", fget=getMask, fset=applyMask) def __onResize(self, event): self.__fixed_label.move(0, self.geometry().height() - 35) self.__fixed_label.resize(self.geometry().width(), self.__fixed_label.geometry().height()) self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0)) self.__pmap.scaled(self.size()) if self.__show_mask_preview: self.setMask( QBitmap(self.__pmap.createHeuristicMask().scaled(self.size()))) def __on_indicator_Resize(self, event): self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0))
class Tooltip(QFrame): " Custom tooltip " def __init__(self): QFrame.__init__(self) # Avoid the border around the window self.setWindowFlags(Qt.SplashScreen) # Make the frame nice looking self.setFrameShape(QFrame.StyledPanel) self.setLineWidth(2) self.info = None self.location = None self.__createLayout() # The item the tooltip is for self.item = None # The timer which shows the tooltip. The timer is controlled from # outside of the class. self.tooltipTimer = QTimer(self) self.tooltipTimer.setSingleShot(True) self.tooltipTimer.timeout.connect(self.__onTimer) self.startPosition = None return def __createLayout(self): " Creates the tooltip layout " verticalLayout = QVBoxLayout(self) self.info = QLabel() self.info.setAutoFillBackground(True) font = self.info.font() font.setFamily(GlobalData().skin.baseMonoFontFace) self.info.setFont(font) self.info.setFrameShape(QFrame.StyledPanel) verticalLayout.addWidget(self.info) verticalLayout.setMargin(0) self.location = QLabel() verticalLayout.addWidget(self.location) return def setText(self, text): " Sets the tooltip text " self.info.setText(text) return def setLocation(self, text): " Sets the file name and line at the bottom " self.location.setText(text) return def setModified(self, status): " Sets the required tooltip background " palette = self.info.palette() if status: # Reddish palette.setColor(QPalette.Background, QColor(255, 227, 227)) else: # Blueish palette.setColor(QPalette.Background, QColor(224, 236, 255)) self.info.setPalette(palette) return def setItem(self, item): " Sets the item the tooltip is shown for " self.item = item return def __getTooltipPos(self): " Calculates the tooltip position - above the row " pos = QCursor.pos() if pos.x() + self.sizeHint().width() >= screenWidth: pos.setX(screenWidth - self.sizeHint().width() - 2) pos.setY(pos.y() - cellHeight - 1 - self.sizeHint().height()) return pos def __onTimer(self): " Triggered by the show tooltip timer " currentPos = QCursor.pos() if abs( currentPos.x() - self.startPosition.x() ) <= 2 and \ abs( currentPos.y() - self.startPosition.y() ) <= 2: # No movement since last time, show the tooltip self.show() return # There item has not been changed, but the position within it was # So restart the timer, but for shorter self.startPosition = currentPos self.tooltipTimer.start(400) return def startShowTimer(self): " Memorizes the cursor position and starts the timer " self.tooltipTimer.stop() self.startPosition = QCursor.pos() self.tooltipTimer.start(500) # 0.5 sec return def show(self): " Shows the tooltip at the proper position " QToolTip.hideText() QApplication.processEvents() if not inside: return self.move(self.__getTooltipPos()) self.raise_() QFrame.show(self) return
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 initOptionsMenu(self): men = QMenu() #Threshold Slider self.threshSlider = QSlider() self.threshSlider.setTickPosition(QSlider.TicksLeft) self.threshSlider.setOrientation(Qt.Horizontal) self.threshSlider.setValue(config.thresh()) self.threshSlider.setMinimum(0) self.threshSlider.setMaximum(5) self.threshSlider.valueChanged.connect(self.parent.setThreshold) self.threshSliderAction = QWidgetAction(men) self.threshSliderAction.setDefaultWidget(self.threshSlider) #TabsWidth Slider self.tabsSlider = QSlider() self.tabsSlider.setTickPosition(QSlider.TicksLeft) self.tabsSlider.setOrientation(Qt.Horizontal) self.tabsSlider.setValue(config.tabwidth()) self.tabsSlider.setMinimum(0) self.tabsSlider.setMaximum(8) self.tabsSlider.valueChanged.connect(self.parent.setTabWidth) self.tabsSliderAction = QWidgetAction(men) self.tabsSliderAction.setDefaultWidget(self.tabsSlider) #iconSize Slider self.iconSlider = QSlider() self.iconSlider.setTickPosition(QSlider.TicksLeft) self.iconSlider.setOrientation(Qt.Horizontal) self.iconSlider.setValue(config.iconSize()) self.iconSlider.setMinimum(16) self.iconSlider.setMaximum(32) self.iconSlider.setSingleStep(2) self.iconSlider.valueChanged.connect(self.setIcon) self.iconSliderAction = QWidgetAction(men) self.iconSliderAction.setDefaultWidget(self.iconSlider) '''Font Button''' self.fontCombo = QFontComboBox() self.fontCombo.currentFontChanged.connect(self.parent.setFont) self.fontCombo.setCurrentFont(QFont(config.fontName())) self.fontComboMenu = QWidgetAction(men) self.fontComboMenu.setDefaultWidget(self.fontCombo) '''Font Size''' self.fontSizeCombo = QComboBox() for size in range(1,40): self.fontSizeCombo.addItem(str(size)) self.fontSizeCombo.setCurrentIndex(config.fontSize()) self.fontSizeCombo.currentIndexChanged.connect(self.parent.setFontSize) self.fontSizeComboMenu = QWidgetAction(men) self.fontSizeComboMenu.setDefaultWidget(self.fontSizeCombo) action_Android = QAction(Icons.android,'Android', self) action_Android.triggered.connect(self.parent.android) action_Ant = QAction(Icons.ant_view,'Ant', self) action_Ant.triggered.connect(self.parent.antt) action_Squirrel = QAction(Icons.nut,'Squirrel', self) action_Squirrel.triggered.connect(self.parent.squirrel) action_Ios1 = QAction(Icons.ios,'iOS', self) action_Update = QAction(Icons.update,"Update",self) action_Update.triggered.connect(self.parent.update) action_explorer = QAction("Explorer",self) action_explorer.triggered.connect(self.parent.exp) action_explorer.setCheckable(True) action_explorer.setChecked(True) action_console = QAction("Console",self) action_console.triggered.connect(self.parent.cmd) action_console.setCheckable(True) action_console.setChecked(False) #action_designer = QAction("Designer",self) #action_designer.triggered.connect(self.parent.design) action_Indentation = QAction("Indentation Guides",self) action_Indentation.triggered.connect(self.parent.setIndent) action_Indentation.setCheckable(True) action_Indentation.setChecked(config.indent()) action_WhiteSpace = QAction("WhiteSpace",self) action_WhiteSpace.triggered.connect(self.parent.setWhiteSpace) action_WhiteSpace.setCheckable(True) action_WhiteSpace.setChecked(config.whiteSpace()) action_EndLine = QAction("End of Lines",self) action_EndLine.triggered.connect(self.parent.setEndLine) action_EndLine.setCheckable(True) action_Margin = QAction("Line Numbers",self) action_Margin.triggered.connect(self.parent.setMargin) action_Margin.setCheckable(True) action_Margin.setChecked(config.margin()) action_ToolLabel = QAction("Tool Labels",self) action_ToolLabel.triggered.connect(self.setToolLabel) action_ToolLabel.setCheckable(True) #action_ToolLabel.setChecked(config.toolLabel()) '''Encoding''' encodingGroup = QActionGroup(self) encodingGroup.setExclusive(True) action_Ascii = QAction("Ascii",encodingGroup) action_Ascii.setCheckable(True) action_Unicode = QAction("Unicode",encodingGroup) action_Unicode.setCheckable(False) encodingGroup.addAction(action_Ascii) encodingGroup.addAction(action_Unicode) encodingGroup.selected.connect(self.parent.setEncoding) if(config.encoding() == Encoding.ASCII): action_Ascii.setChecked(True) else: action_Unicode.setChecked(True) men.addAction(action_Update) men.addAction(self.action_Help) men.addAction(self.action_Full) men.addSeparator() men.addAction(action_Android) men.addAction(action_Ant) men.addAction(action_Squirrel) men.addAction(action_Ios1) men.addSeparator() men.addAction(action_explorer) men.addAction(action_console) #men.addAction(action_designer) men.addSeparator() men.addAction(action_Indentation) men.addAction(action_WhiteSpace) men.addAction(action_EndLine) men.addAction(action_Margin) men.addAction(action_ToolLabel) men.addSeparator() men.addActions(encodingGroup.actions()) men.addSeparator() head_font = QLabel("Font---------------------") fnt = head_font.font() fnt.setBold(True) head_font.setFont(fnt) head_fontWidgetAction = QWidgetAction(men) head_fontWidgetAction.setDefaultWidget(head_font) men.addAction(head_fontWidgetAction) men.addAction(self.fontComboMenu) men.addAction(self.fontSizeComboMenu) men.addSeparator() men.addAction(QAction("TabWidth",self)) men.addAction(self.tabsSliderAction) men.addSeparator() men.addAction(QAction("Threshold",self)) men.addAction(self.threshSliderAction) #men.addAction(QAction("Icon Size",self)) #men.addAction(self.iconSliderAction) self.action_Options = QAction(Icons.emblem_system, 'Options', self) self.action_Options.setMenu(men) self.addAction(self.action_Options)
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 __init__(self, parent, enable_replace=False): QWidget.__init__(self, parent) self.enable_replace = enable_replace self.editor = None glayout = QGridLayout() glayout.setContentsMargins(0, 0, 0, 0) self.setLayout(glayout) self.close_button = create_toolbutton(self, triggered=self.hide, icon=get_std_icon("DialogCloseButton")) glayout.addWidget(self.close_button, 0, 0) # Find layout self.search_text = PatternComboBox(self, tip=self.tr("Search string"), adjust_to_minimum=False) self.connect(self.search_text, SIGNAL("editTextChanged(QString)"), self.text_has_changed) self.previous_button = create_toolbutton(self, text=self.tr("Previous"), triggered=self.find_previous, icon=get_std_icon("ArrowBack")) self.next_button = create_toolbutton(self, text=self.tr("Next"), triggered=self.find_next, icon=get_std_icon("ArrowForward")) self.connect(self.next_button, SIGNAL('clicked()'), self.update_search_combo) self.connect(self.previous_button, SIGNAL('clicked()'), self.update_search_combo) self.case_check = QCheckBox(self.tr("Case Sensitive")) self.connect(self.case_check, SIGNAL("stateChanged(int)"), self.find) self.words_check = QCheckBox(self.tr("Whole words")) self.connect(self.words_check, SIGNAL("stateChanged(int)"), self.find) hlayout = QHBoxLayout() self.widgets = [self.close_button, self.search_text, self.previous_button, self.next_button, self.case_check, self.words_check] for widget in self.widgets[1:]: hlayout.addWidget(widget) glayout.addLayout(hlayout, 0, 1) # Replace layout replace_with1 = QLabel(self.tr("Replace")) replace_with2 = QLabel() font = replace_with2.font() font.setBold(True) replace_with2.setFont(font) replace_with3 = QLabel(self.tr("with:")) self.replace_text = PatternComboBox(self, adjust_to_minimum=False, tip=self.tr("Replace string")) self.replace_button = create_toolbutton(self, text=self.tr("Replace/find"), triggered=self.replace_find, icon=get_std_icon("DialogApplyButton")) self.connect(self.replace_button, SIGNAL('clicked()'), self.update_replace_combo) self.connect(self.replace_button, SIGNAL('clicked()'), self.update_search_combo) self.all_check = QCheckBox(self.tr("Replace all")) self.replace_layout = QHBoxLayout() widgets = [replace_with1, replace_with2, replace_with3, self.replace_text, self.replace_button, self.all_check] for widget in widgets: self.replace_layout.addWidget(widget) self.connect(self.search_text, SIGNAL("editTextChanged(QString)"), replace_with2, SLOT("setText(QString)")) glayout.addLayout(self.replace_layout, 1, 1) self.widgets.extend(widgets) self.replace_widgets = widgets self.hide_replace() self.search_text.setTabOrder(self.search_text, self.replace_text) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
class PlotScalesWidget(QWidget): plotScaleChanged = pyqtSignal() def __init__(self, type_key, title, select_min_time_value=False): QWidget.__init__(self) self.__type_key = type_key self.__type = None self.__double_spinner = self.createDoubleSpinner(minimum=-999999999.0, maximum=999999999.0) self.__integer_spinner = self.createIntegerSpinner(minimum=0, maximum=999999999) self.__time_map = ReportStepsModel().getList() self.__time_index_map = {} for index in range(len(self.__time_map)): time = self.__time_map[index] self.__time_index_map[time] = index self.__time_spinner = self.createTimeSpinner( select_minimum_value=select_min_time_value) layout = QVBoxLayout() self.setLayout(layout) self.__label = QLabel(title) self.__label.setAlignment(Qt.AlignHCenter) self.__stack = QStackedWidget() self.__stack.setSizePolicy(QSizePolicy(QSizePolicy.Preferred)) self.__stack.addWidget(self.__integer_spinner) self.__stack.addWidget(self.__double_spinner) self.__stack.addWidget(self.__time_spinner) layout.addWidget(self.__stack) layout.addWidget(self.__label) self.setLayout(layout) def createDoubleSpinner(self, minimum, maximum): spinner = QDoubleSpinBox() spinner.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) spinner.setMinimumWidth(105) spinner.setRange(minimum, maximum) spinner.setKeyboardTracking(False) spinner.setDecimals(8) spinner.editingFinished.connect(self.plotScaleChanged) spinner.valueChanged.connect(self.plotScaleChanged) return spinner def createIntegerSpinner(self, minimum, maximum): spinner = QSpinBox() spinner.setMinimumWidth(75) spinner.setRange(minimum, maximum) spinner.setKeyboardTracking(False) spinner.editingFinished.connect(self.plotScaleChanged) spinner.valueChanged.connect(self.plotScaleChanged) return spinner def createTimeSpinner(self, select_minimum_value): def converter(item): return "%s" % (str(item.date())) spinner = ListSpinBox(self.__time_map) spinner.setMinimumWidth(75) if select_minimum_value: spinner.setValue(0) spinner.valueChanged[int].connect(self.plotScaleChanged) spinner.editingFinished.connect(self.plotScaleChanged) spinner.setStringConverter(converter) return spinner def getValue(self): if self.__type is int: return self.__integer_spinner.value() elif self.__type is float: return self.__double_spinner.value() elif self.__type is CTime: index = self.__time_spinner.value() return self.__time_map[index] else: raise TypeError("Unsupported spinner type: %s" % self.__type) def setValue(self, value): if value is not None: if self.__type is int: self.__integer_spinner.setValue(int(value)) elif self.__type is float: self.__double_spinner.setValue(value) elif self.__type is CTime: index = self.__time_index_map[value] self.__time_spinner.setValue(index) else: raise TypeError("Unsupported spinner type: %s" % self.__type) def setFontSize(self, size): font = self.__double_spinner.font() font.setPointSize(size) self.__double_spinner.setFont(font) font = self.__integer_spinner.font() font.setPointSize(size) self.__integer_spinner.setFont(font) font = self.__time_spinner.font() font.setPointSize(size) self.__time_spinner.setFont(font) font = self.__label.font() font.setPointSize(size) self.__label.setFont(font) def setType(self, spinner_type): self.__type = spinner_type if spinner_type is int: self.__stack.setCurrentWidget(self.__integer_spinner) elif spinner_type is float: self.__stack.setCurrentWidget(self.__double_spinner) elif spinner_type is CTime: self.__stack.setCurrentWidget(self.__time_spinner) else: raise TypeError("Unsupported spinner type: %s" % spinner_type) def getType(self): return self.__type
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
class SliceSelectorHud(QFrame): """ Heads up display for slice selection. Compact widget that shows a name, a spinbox and its maximum value explicitly. A background color can be set. """ @property def maximum(self): return self._maximum @property def minimum(self): return self._minimum @maximum.setter def maximum(self, m): self._maximum = m self.coordLabel.setText("of %d" % self._maximum) self.sliceSelector.setRange(self._minimum, self._maximum) @minimum.setter def minimum(self, m): self._minimum = m self.sliceSelector.setRange(self._minimum, self._maximum) @property def label(self): return self._label @label.setter def label(self, l): self._label = l self.dimLabel.setText(l) @property def bgColor(self): return self._bgColor @bgColor.setter def bgColor(self, color): self._bgColor = color palette = self.palette(); palette.setColor(self.backgroundRole(), color); self.setAutoFillBackground(True); self.setPalette(palette) def __init__(self, parent = None): super(SliceSelectorHud, self).__init__(parent) # init properties self._minimum = 0 self._maximum = 1 self._label = '' self._bgColor = QColor(255,255,255) # configure self # # a border-radius of >0px to make the Hud appear rounded # does not work together with an QGLWidget, the corners just appear black # instead of transparent #self.setStyleSheet("QFrame {background-color: white; color: black; border-radius: 0px;}") self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.setLayout(QHBoxLayout()) self.layout().setContentsMargins(3,1,3,1) # dimension label self.dimLabel = QLabel(self) font = self.dimLabel.font() font.setBold(True) self.dimLabel.setFont(font) self.layout().addWidget(self.dimLabel) # coordinate selection self.sliceSelector = QSpinBox() self.sliceSelector.setButtonSymbols(QAbstractSpinBox.NoButtons) self.sliceSelector.setAlignment(Qt.AlignRight) self.sliceSelector.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.layout().addWidget(self.sliceSelector) # coordinate label self.coordLabel = QLabel() self.layout().addWidget(self.coordLabel)
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
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 MainWindow(QMainWindow): SHUTDOWN_MENU = "&Shutdown" HELP_MENU = "&Help" SOFT_EXIT = "&Soft Exit" PHONE_HOME = "Pho&ne Home" ADD_MENU = "Add &Pattern" DELETE_MENU = "&Delete" VERSION_MENU = "&Version" ABOUT_MENU = "&About" ## __init__ --------------------------------------------------------- def __init__(self, Log = None): # Make Main window QMainWindow.__init__(self, None) self.setWindowTitle("Lightbox") self.resize(800, 480) # Screen Size self.__log = Log self.CALLING_CLASS = "MainWindow" if self.__log == None: print "No Log File" self.close() # Create main layout for window mainWidget = QWidget(self) self.__mainLayout = QVBoxLayout(mainWidget) mainWidget.setLayout(self.__mainLayout) # Selected pattern self.__selectedPattern = None self.__presetPatternForDeleting = None self.__currentIntensity = 4000 self.__loadedPattern = None ## Loaded (Running Pattern) self.__loadedPatternBeforePreset = None self.__CACHED_PRESET = None self.EXECUTION_THREAD = None # Add Menu Bard self.__menu = self.__createMenu() ## Toolbar that is always there->Selected Pattern, Start, Stop, Current State Label self.__statusLayout = self.__createStatusLayout() self.__mainLayout.addLayout(self.__statusLayout) self.__patterns = list() self.__buttons = list() self.__savedPresets = list() self.__presetManager = PresetManager(self.__log) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensitySelectLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() self.__makeDefaultButtons() self.__importPresetsFromFile() # Connect TagPushButton signals self.connect(self, SIGNAL("tagPushButtonClicked(PyQt_PyObject)"), self._tagButtonClicked) self.connect(self,SIGNAL("idPushButtonClicked(PyQt_PyObject)"), self._idButtonClicked) # Make the window knwo what is the main widget self.setCentralWidget(mainWidget) self.ColorIcons = [QIcon(RED_ICON_LOC), QIcon(REDOR_ICON_LOC), QIcon(CYAN_ICON_LOC), QIcon(GREEN_ICON_LOC), QIcon(BLUE_ICON_LOC), QIcon(WHITE_ICON_LOC), \ QIcon(YELLOW_ICON_LOC)] self.__mode = PATTERN_SELECT_MODE self.__lastMode = self.__mode self.__modeBeforeIntensity = None self.__running = False def __createStatusLayout(self): ## Make the currently running, start and stop button, running status self.__currentPatternLabel = QLabel(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) font = self.__currentPatternLabel.font() self.__setFont(self.__currentPatternLabel,CONTROL_LABEL_FONT_SIZE) self.__currentStatusLabel = QLabel(STATUS_PREAMBLE + STOPPED) self.__setFont(self.__currentStatusLabel,CONTROL_LABEL_FONT_SIZE) self.StartButton = QPushButton("Start") self.__setFont(self.StartButton, CONTROL_BUTTON_FONT_SIZE) self.StartButton.setMinimumSize(CONTROL_BUTTON_WIDTH,CONTROL_BUTTON_HEIGHT) startIcon = QIcon(START_ICON_LOC) stopIcon = QIcon(STOP_ICON_LOC) self.StartButton.setIcon(startIcon) self.StopButton = QPushButton("Stop") self.__setFont(self.StopButton, CONTROL_BUTTON_FONT_SIZE) self.StopButton.setIcon(stopIcon) self.StopButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) self.StartButton.clicked.connect(self.__handleStart) self.StopButton.clicked.connect(self.__handleStop) # put on the first row of the left coloumn, first two of the right column controlLayout = QHBoxLayout() leftHandColumn = QVBoxLayout() rightHandColumn = QVBoxLayout() leftHandColumn.addWidget(self.__currentPatternLabel) rightHandColumn.addWidget(self.__currentStatusLabel) startStopLayout = QHBoxLayout() startStopLayout.addWidget(self.StartButton) startStopLayout.addWidget(self.StopButton) rightHandColumn.addLayout(startStopLayout) ## Make Intensity Layout self.__intensityLabel = QLabel(INTENSITY_PREAMBLE + str(self.__currentIntensity)) self.__setFont(self.__intensityLabel,CONTROL_LABEL_FONT_SIZE) self.__intensityButton = QPushButton("Set Intensity...") self.__setFont(self.__intensityButton, CONTROL_BUTTON_FONT_SIZE) self.__intensityButton.setMinimumSize(CONTROL_BUTTON_WIDTH*2, CONTROL_BUTTON_HEIGHT) self.__intensityButton.setMaximumSize(CONTROL_BUTTON_WIDTH*2, CONTROL_BUTTON_HEIGHT) self.__intensityButton.clicked.connect(self.__intensityButtonClicked) intensityIcon = QIcon(INTENSITY_ICON_LOC) self.__intensityButton.setIcon(intensityIcon) intensityLayout = QVBoxLayout() intensityLayout.addWidget(self.__intensityLabel) intensityLayout.addWidget(self.__intensityButton) # add intensity layout to left hand column leftHandColumn.addLayout(intensityLayout) # Add shutdown button self.ShutdownButton = QPushButton("Shutdown") self.__setFont(self.ShutdownButton, CONTROL_BUTTON_FONT_SIZE) self.ShutdownButton.setMinimumSize(160, CONTROL_BUTTON_HEIGHT) shutdownIcon = QIcon(SHUTDOWN_ICON_LOC) self.ShutdownButton.setIcon(shutdownIcon) self.ShutdownButton.clicked.connect(self.__shutdown) rightHandColumn.addWidget(self.ShutdownButton) infoBarLayout = QHBoxLayout() infoBarLayout.addLayout(leftHandColumn) infoBarLayout.addStretch(1) infoBarLayout.addLayout(rightHandColumn) return infoBarLayout def __Log(self,message): self.__log.LOG(self.CALLING_CLASS,message) def __createMenu(self): menu = self.menuBar() ## About Menu ---------------------------------------- aboutMenu = menu.addMenu(MainWindow.ABOUT_MENU) versionAction = QAction(menu) versionAction.setText(MainWindow.VERSION_MENU) versionAction.triggered.connect(self.__showAbout) aboutMenu.addAction(versionAction) ## Shutdown Menu ----------------------------------------- #shutdownMenu = menu.addMenu(MainWindow.SHUTDOWN_MENU) if ADD_PATTERN_ENABLED: newPatternAction = QAction(menu) newPatternAction.setText(MainWindow.ADD_MENU) newPatternAction.triggered.connect(self.__addPattern) deletePatternAction = QAction(menu) deletePatternAction.setText(MainWindow.DELETE_MENU) deletePatternAction.triggered.connect(self.__deletePattern) #shutdownMenu.addAction(newPatternAction) #shutdownMenu.addAction(deletePatternAction) #shutdownAction = QAction(menu) #shutdownAction.setText(MainWindow.SHUTDOWN_MENU) #shutdownAction.triggered.connect(self.__shutdown) #shutdownMenu.addAction(shutdownAction) ## Soft Exit Menu ------------------------------------ helpMenu = menu.addMenu(MainWindow.HELP_MENU) softExitAction = QAction(menu) softExitAction.setText(MainWindow.SOFT_EXIT) softExitAction.triggered.connect(self.__exit) helpMenu.addAction(softExitAction) if PHONE_HOME_ENABLED: phoneHomeAction = QAction(menu) phoneHomeAction.setText(MainWindow.PHONE_HOME) softExitAction.triggered.connect(self.__phoneHome) helpMenu.addAction(phoneHomeAction) def __showAbout(self): ret = QMessageBox.information(self,"Version Info", "Release: July 10, 2014") ## Make the Default pattern Buttons ---------------------------------------------- def __makeDefaultButtons(self): for iter in range(0,NUM_DEFAULT_PATTERNS): self.__Log("Making preset %d"%iter) pattern_params = DEFAULT_PATTERNS[iter] name = pattern_params[pIndex.Name] des = pattern_params[pIndex.Description] default = pattern_params[pIndex.Default] clist = pattern_params[pIndex.ColorList] reqColors = pattern_params[pIndex.RequiredColors] pwm = pattern_params[pIndex.PWM] newPattern = Pattern(name, des, default,clist, reqColors, pwm, self.__log) self.__patterns += [newPattern] self.__drawPatternButtons() def __importPresetsFromFile(self): self.__savedPresets = self.__presetManager.GetPresetPatterns() ## Clear Layouts ------------------------------------------------------------------ def __clearLayout(self, layout): if layout is not None: while layout.count(): item = layout.takeAt(0) widget = item.widget() if widget is not None: widget.hide() else: self.__clearLayout(item.layout()) def __intensityButtonClicked(self): self.__Log("Intensity Button Clicked") self.__lastMode = self.__mode self.__drawIntensityButtons() ## Color Button has been clicked ------------------------------------------------------- def _idButtonClicked(self,ID): ## Currently only Color buttons are using the ID Button self.__Log("ColorID: %d"%ID) if self.__mode == PATTERN_EDIT_MODE: ## Show color select. self.__currentColorSelection = ID - 1 self.__drawColorButtons() elif self.__mode == INTENSITY_SELECT_MODE: # Get the intensity selected self.__intensitySelected(ID) elif self.__mode == PATTERN_PRESET_SELECT_MODE: self.__presetPatternSelectedForStart(ID) #self.__drawPatternButtons() else: self.__Log("Bad Mode") def _tagButtonClicked(self,buttonTag): self.__Log("Button Tag: %s, mode: %s"%(buttonTag, self.__mode)) if self.__mode == PATTERN_SELECT_MODE: self.__patternSelected(buttonTag) elif self.__mode == PATTERN_EDIT_MODE: # Must be the back or OK buttons if buttonTag == "Back": self.__patternEditControlPressed(buttonTag) elif buttonTag == "Save as Preset": self.__savePatternAsPreset() else: self.__colorSelected(buttonTag) elif self.__mode == PATTERN_PRESET_SELECT_MODE: if buttonTag == "Back": if self.__loadedPatternBeforePreset != None and self.__presetPatternForDeleting != None: self.__Log("Both are not none") if self.__loadedPatternBeforePreset.GetName() != self.__presetPatternForDeleting.GetName() and self.__loadedPatternBeforePreset.GetColorString() != self.__presetPatternForDeleting.GetColorString(): self.__Log("Setting preset back to the one it was before") self.__loadedPattern = self.__loadedPatternBeforePreset self.__loadedPatternBeforePreset = None self.__presetPatternForDeleting = None self.__loadedPatternBeforePreset = None self.__drawPatternButtons() if self.__loadedPattern != None: self.__currentPatternLabel.setText(PATTERN_PREAMBLE + self.__loadedPattern.GetName() + ' ' + self.__loadedPattern.GetColorString()) elif buttonTag == "Delete": self.__presetPatternForDeleting = self.__loadedPattern if self.__loadedPatternBeforePreset != None and self.__presetPatternForDeleting != None: self.__Log("Both are not none") if self.__loadedPatternBeforePreset.GetName() == self.__presetPatternForDeleting.GetName() and self.__loadedPatternBeforePreset.GetColorString() == self.__presetPatternForDeleting.GetColorString(): self.__Log("Deleting the currently loaded pattern") self.__loadedPatternBeforePreset = None self.__loadedPattern = None self.__currentPatternLabel.setText(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) else: self.__Log("Setting the loaded pattern back to what it should be before delete occured") self.__loadedPattern = self.__loadedPatternBeforePreset self.__currentPatternLabel.setText(PATTERN_PREAMBLE + self.__loadedPattern.GetName()+ ' ' + self.__loadedPattern.GetColorString()) elif self.__loadedPatternBeforePreset == None: self.__currentPatternLabel.setText(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) self.__loadedPattern = None else: self.__loadedPattern = self.__loadedPatternBeforePreset self.__currentPatternLabel.setText(PATTERN_PREAMBLE + self.__loadedPattern.GetName()+ ' ' + self.__loadedPattern.GetColorString()) self.__deletePresetPattern() if len(self.__savedPresets) > 0: self.__drawPresetPatternsForSelection() else: self.__drawPatternButtons() else: self.__Log("Unknown button") else: self.__Log("Bad Mode") def __presetPatternSelectedForStart(self,ID): self.__Log("Preset pattern selected with ID %d"%ID) if ID >= 0 and ID < len(self.__savedPresets): self.__selectedPattern = self.__savedPresets[ID] self.__currentPatternLabel.setText(PATTERN_PREAMBLE + self.__selectedPattern.GetName() + ' ' + self.__selectedPattern.GetColorString()) self.__loadedPattern = self.__selectedPattern self.__presetDeleteButton.setEnabled(True) self.StartButton.setEnabled(True) return def __intensitySelected(self, ID): ## NOTE: INtensity does not change until the STOP->START is pressed. self.__Log("Got Intensity: %d"%ID) self.__currentIntensity = ID self.__intensityLabel.setText(INTENSITY_PREAMBLE + str(ID)) self.__mode = self.__lastMode self.__redrawMode() def __colorSelected(self, colorTag): self.__Log("Got Color Selected: %s, setting index %d"%(colorTag,self.__currentColorSelection)) presetColorList = list() if (self.__savedPresets != None): for aPreset in self.__savedPresets: self.__Log("Preset Colors:%s"%(",".join(aPreset.GetColorList()))) newList = list() for color in aPreset.GetColorList(): for presetColor in ColorsByIndex: if presetColor == color: newList += [presetColor] break presetColorList += [newList] self.__Log("Preset Colors:%s"%(",".join(newList))) #presetColorList += [aPreset.GetColorList()] self.__selectedPattern.SetColor(self.__currentColorSelection,colorTag) if self.__savedPresets != None: for ind,aPreset in enumerate(self.__savedPresets): self.__Log("Colors: %s"%(",".join(presetColorList[ind]))) aPreset.SetColorList(presetColorList[ind]) self.__Log("Preset Colors:%s"%(",".join(aPreset.GetColorList()))) ## Check to see if this is now valid if self.__selectedPattern.CanStart(): self.__loadedPattern = self.__selectedPattern self.StartButton.setEnabled(True) self.__drawPatternSettings(self.__selectedPattern) def __savePatternAsPreset(self): self.__Log("Save Pattern As Preset") if self.__selectedPattern.CanStart(): self.__Log("%d Presets already made"%len(self.__savedPresets)) for aPreset in self.__savedPresets: self.__Log("Preset Colors:%s"%(",".join(aPreset.GetColorList()))) if len(self.__savedPresets) < MAX_NUM_PRESETS: # Check to see if there is a duplicate of this already newPattern = Pattern() newPattern.SetName(self.__selectedPattern.GetName()) newPattern.SetDescription(self.__selectedPattern.GetDescription()) newPattern.SetLog(self.__log) newPattern.SetPwmSequenceDict(self.__selectedPattern.GetPwmSequenceDict()) newPattern.SetColorList(self.__selectedPattern.GetColorList()) newPattern.SetRequiredColors(self.__selectedPattern.GetRequiredColors()) self.__Log("Colors %s"%(",".join(newPattern.GetColorList()))) for pattern in self.__savedPresets: if pattern.GetName() == newPattern.GetName(): if pattern.GetColorList() == newPattern.GetColorList(): self.__drawPatternSettings(self.__selectedPattern, False, True, PRESET_EXISTS) return self.__savedPresets += [newPattern] self.__CACHED_PRESET = None self.__Log("Saved Pattern.") self.__presetManager.SavePresetPattern(newPattern) self.__drawPatternSettings(self.__selectedPattern, False, True, PRESET_SAVED) def __patternEditControlPressed(self,buttonTag): if buttonTag == "Back": self.__drawPatternButtons() if self.__loadedPattern != None: self.__currentPatternLabel.setText(PATTERN_PREAMBLE + self.__loadedPattern.GetName() + ' ' + self.__loadedPattern.GetColorString()) else: self.__Log("Unknown tag: %s"%buttonTag) def __patternSelected(self,buttonTag): self.__Log("Pattern \'%s\' pressed"%buttonTag) if buttonTag == PRESET_TAG: self.__Log("Preset Button Pressed.") self.__loadedPatternBeforePreset = self.__loadedPattern self.__drawPresetPatternsForSelection() return # Get the actual pattern from the list of patterns for it in range(0,len(self.__patterns)): self.__selectedPattern = self.__patterns[it] if self.__selectedPattern.GetName() == buttonTag: self.__Log("FOUND PATTERN") self.__selectedPattern.ClearColors() self.__drawPatternSettings(self.__selectedPattern) return self.__Log("Didn't find a pattern that matched tag!") def __handleStart(self): self.__Log("START") if self.__loadedPattern != None: if self.__running: if (self.EXECUTION_THREAD != None): self.EXECUTION_THREAD.join() time.sleep(.5) self.__running = True self.__currentStatusLabel.setText(STATUS_PREAMBLE + RUNNING) self.EXECUTION_THREAD = ExecutionThread(self.__loadedPattern,self.__currentIntensity, self.__log) self.EXECUTION_THREAD.start() time.sleep(.5) def __handleStop(self): self.__Log("STOP") if self.__running: self.__running = False #self.__selectedPattern.ClearColors() #self.__currentPatternLabel.setText(PATTERN_PREAMBLE + NO_PATTERN_SELECTED) self.__currentStatusLabel.setText(STATUS_PREAMBLE + STOPPED) # Stop Threading if (self.EXECUTION_THREAD != None): self.EXECUTION_THREAD.join() time.sleep(.5) self.__redrawMode() def __phoneHome(self): if RASPI: os.system("/home/pi/Desktop/Lightbox/util/phoneHome.sh &") def __exit(self): self.__handleStop() self.close() def __shutdown(self): response = QMessageBox.question(self, "Shutdown", "Proceed with shutdown?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if response == QMessageBox.Yes: self.__handleStop() if RASPI: os.system("sudo shutdown -h 0") self.close() ### DISABLED----------------------------------------------------- def __addPattern(self): self.__Log("Add Pattern") newPattern = Pattern() newDescription = "Pattern %d"%(len(self.__patterns)) self.__Log("New description %s"%newDescription) copyPattern = self.__patterns[0] newPattern = copyPattern.CopyPattern(newDescription) self.__patterns += [newPattern] self.__drawPatternButtons() ## Delete a preset pattern -------------------------------------- def __deletePresetPattern(self): self.__Log("Delete Preset Pattern") self.__savedPresets.remove(self.__presetPatternForDeleting) self.__presetManager.DeletePresetPattern(self.__presetPatternForDeleting) def __setFont(self, object, size): font = QFont(object.font()) font.setPointSize(size) object.setFont(font) def __startValid(self): self.__Log("In start Valid") if self.__mode == PATTERN_EDIT_MODE or self.__mode == PATTERN_PRESET_SELECT_MODE: if self.__selectedPattern != None: self.StartButton.setEnabled(self.__selectedPattern.CanStart()) else: self.StartButton.setEnabled(False) self.__Log("In edit mode/preset selection (same state as edit, selectedPattern has to be valid.") elif self.__loadedPattern != None: self.__Log("Looking at loaded pattern") if self.__loadedPattern.CanStart(): self.StartButton.setEnabled(self.__loadedPattern.CanStart()) else: self.StartButton.setEnabled(False) def __redrawMode(self): if self.__mode == PATTERN_EDIT_MODE: self.__drawPatternSettings(self.__selectedPattern) elif self.__mode == PATTERN_SELECT_MODE: self.__drawPatternButtons() elif self.__mode == PATTERN_PRESET_SELECT_MODE: self.__drawPresetPatternsForSelection() elif self.__mode == INTENSITY_SELECT_MODE: if (self.__modeBeforeIntensity != None): if self.__modeBeforeIntensity == PATTERN_EDIT_MODE: self.__drawPatternSettings(self.__selectedPattern) elif self.__mode == PATTERN_SELECT_MODE: self.__drawPatternButtons() elif self.__mode == PATTERN_PRESET_SELECT_MODE: self.__drawPresetPatternsForSelection() else: self.__drawPatternButtons() else: self.__drawPatternButtons() else: self.__Log("No mode to redraw") ## Draw the Premade pattern buttons ------------------------------------------------ def __drawPatternButtons(self): self.__mode = PATTERN_SELECT_MODE self.__startValid() self.__clearLayout(self.__selectedPatternLayout) self.__clearLayout(self.__defaultButtonLayout) self.__clearLayout(self.__intensitySelectLayout) self.__clearLayout(self.__presetButtonLayout) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensityLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() self.__buttons = list() # add label for this screen patternLabelLayout = QHBoxLayout() patternLabelLayout.addStretch(1) patternLabel = QLabel("Temporal Patterns") self.__setFont(patternLabel,PAGE_INFO_LABEL_SIZE) patternLabelLayout.addWidget(patternLabel) patternLabelLayout.addStretch(1) self.__defaultButtonLayout.addLayout(patternLabelLayout) self.__Log("Redrawing Buttons") numOfButtons = len(self.__patterns)# + 1 # One for preset numOfRows = numOfButtons/BUTTONS_PER_ROW lastRowStretch = False if numOfButtons%BUTTONS_PER_ROW != 0: numOfRows += 1 lastRowStretch = True self.__Log("Buttons: %d, Rows: %d"%(numOfButtons, numOfRows)) for i in range(0,numOfRows): #self.__Log("Row %d"%i) newRow = QHBoxLayout() buttonsLeft = numOfButtons - i*BUTTONS_PER_ROW buttonsInRow = BUTTONS_PER_ROW if buttonsLeft < BUTTONS_PER_ROW: buttonsInRow = buttonsLeft newRow.addStretch(1) for j in range(0,buttonsInRow): patternId = i*BUTTONS_PER_ROW + j #print "Pattern ID %d"%patternId pattern = self.__patterns[patternId] name = pattern.GetName() desc = pattern.GetDescription() #print "Name %s"%name newLabel = QLabel(desc) self.__setFont(newLabel,PATTERN_LABEL_FONT_SIZE) newButton = TagPushButton(self,name) newButton.setMinimumSize(MIN_BUTTON_WIDTH,MIN_BUTTON_HEIGHT) self.__setFont(newButton, PATTERN_BUTTON_FONT_SIZE) self.__buttons.append(newButton) newButtonLayout = QVBoxLayout() newButtonLayout.addWidget(newButton) labelLayout = QHBoxLayout() labelLayout.addStretch() labelLayout.addWidget(newLabel) labelLayout.addStretch() newButtonLayout.addLayout(labelLayout) newButtonLayout.addStretch(1) newRow.addLayout(newButtonLayout) # Iflast row and < full, add stretch to left and right side (left done above) if lastRowStretch and i == numOfRows-1: ## Add the preset button here, we know it's there button = TagPushButton(self,PRESET_TAG) self.__setFont(button, PATTERN_BUTTON_FONT_SIZE) button.setMinimumSize(MIN_BUTTON_WIDTH,MIN_BUTTON_HEIGHT) presetLayout = QVBoxLayout() presetLayout.addWidget(button) presetLayout.addStretch(1) newRow.addLayout(presetLayout) newRow.addStretch(1) self.__defaultButtonLayout.addLayout(newRow) self.__mainLayout.addLayout(self.__defaultButtonLayout) ## Draw Settings Window ------------------------------------------------------- def __drawPatternSettings(self, pattern, withColors=False, withLogMessage=False, logMessage=""): self.__mode = PATTERN_EDIT_MODE if pattern.CanStart(): self.__currentPatternLabel.setText(PATTERN_PREAMBLE + pattern.GetName() + ' ' + pattern.GetColorString()) else: self.__currentPatternLabel.setText(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) self.__startValid() self.__Log("Draw pattern settings") self.__Log("Pattern \'%s\' pressed"%pattern.GetName()) self.__Log("Clearing pattern layout.") self.__clearLayout(self.__selectedPatternLayout) self.__clearLayout(self.__defaultButtonLayout) self.__clearLayout(self.__intensitySelectLayout) self.__clearLayout(self.__presetButtonLayout) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensityLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() # Pattern picture patternLayout = QHBoxLayout() patLabel = QLabel(pattern.GetName()) self.__setFont(patLabel,PAGE_INFO_LABEL_SIZE) image = QLabel("ICON HERE") patternLayout.addStretch(1) patternLayout.addWidget(patLabel) patternLayout.addStretch(1) self.__selectedPatternLayout.addLayout(patternLayout) # Color choosing buttons numOfColors = pattern.GetRequiredColors() self.__Log("Number of required colors is %d"%numOfColors) colorButtonLayout = QHBoxLayout() colorButtonLayout.addStretch(1) for x in range(1,numOfColors+1,1): buttonLayout = QVBoxLayout() # Make Button newButton = IDPushButton(self,"Color %d..."%x, x) self.__setFont(newButton,PATTERN_BUTTON_FONT_SIZE) newButton.setMaximumSize(100,100) # Make Label newLabel = QLabel(self.__selectedPattern.GetColorByIndex(x-1)) self.__setFont(newLabel,PATTERN_LABEL_FONT_SIZE) buttonLayout.addWidget(newButton) labelLayout = QHBoxLayout() labelLayout.addStretch(1) labelLayout.addWidget(newLabel) labelLayout.addStretch(1) # Add label to button layout, button layout to color button layout buttonLayout.addLayout(labelLayout) colorButtonLayout.addLayout(buttonLayout) colorButtonLayout.addStretch(1) self.__selectedPatternLayout.addLayout(colorButtonLayout) if withColors: self.__selectedPatternLayout.addLayout(self.__colorButtonChooserLayout) self.__selectedPatternLayout.addStretch(1) # Control buttons controlButtonLayout = QHBoxLayout() controlButtonLayout.addStretch(1) saveButton = TagPushButton(self,"Save as Preset") saveIcon = QIcon(SAVE_ICON_LOC) saveButton.setIcon(saveIcon) backButton = TagPushButton(self,"Back") backIcon = QIcon(BACK_ICON_LOC) backButton.setIcon(backIcon) saveButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) backButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) self.__setFont(saveButton,CONTROL_BUTTON_FONT_SIZE) self.__setFont(backButton,CONTROL_BUTTON_FONT_SIZE) ## If we just saved a preset, show the QLabel that we did. if (withLogMessage and logMessage != ""): logLabel = QLabel(logMessage) self.__setFont(logLabel, CONTROL_LABEL_FONT_SIZE) controlButtonLayout.addWidget(logLabel) ## Check to see if adding a preset is okay? if len(self.__savedPresets) >= MAX_NUM_PRESETS: saveButton.setEnabled(False) presetsFullLabel = QLabel("Presets Full!") self.__setFont(presetsFullLabel,CONTROL_LABEL_FONT_SIZE) controlButtonLayout.addWidget(presetsFullLabel) else: saveButton.setEnabled(self.__selectedPattern.CanStart()) controlButtonLayout.addWidget(saveButton) controlButtonLayout.addWidget(backButton) self.__selectedPatternLayout.addLayout(controlButtonLayout) self.__mainLayout.addLayout(self.__selectedPatternLayout) def __drawColorButtons(self): self.__colorButtonChooserLayout = QHBoxLayout() numOfColors = len(Colors) for i in range(0,numOfColors-1): ## -1 excludes the Empty button = TagPushButton(self,Colors[i]) self.__setFont(button, PATTERN_BUTTON_FONT_SIZE) button.setIcon(self.ColorIcons[i]) self.__colorButtonChooserLayout.addWidget(button) self.__drawPatternSettings(self.__selectedPattern, True) def __drawIntensityButtons(self): self.__modeBeforeIntensity = self.__mode self.__mode = INTENSITY_SELECT_MODE self.__Log("Draw intensity buttons") self.__clearLayout(self.__selectedPatternLayout) self.__clearLayout(self.__defaultButtonLayout) self.__clearLayout(self.__intensitySelectLayout) self.__clearLayout(self.__presetButtonLayout) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensitySelectLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() self.__intensitySelectLayout.addStretch(1) labelLayout = QHBoxLayout() labelLayout.addStretch(1) intensityLabel = QLabel("Intensity Select (candela)") self.__setFont(intensityLabel,PAGE_INFO_LABEL_SIZE) labelLayout.addWidget(intensityLabel) labelLayout.addStretch(1) self.__intensitySelectLayout.addLayout(labelLayout) numOfButtons = len(Intensities) maxButtonsPerRow = 3 numOfRows = numOfButtons/maxButtonsPerRow if numOfButtons%maxButtonsPerRow != 0: numOfRows += 1 for i in range(0, numOfRows): rowLayout = QHBoxLayout() rowLayout.addStretch(1) buttonsLeft = numOfButtons - i*maxButtonsPerRow buttonsInRow = maxButtonsPerRow if buttonsLeft < maxButtonsPerRow: buttonsInRow = buttonsLeft for j in range(0,buttonsInRow): button = IDPushButton(self, str(Intensities[j+(i*maxButtonsPerRow)]), Intensities[j+(i*maxButtonsPerRow)]) self.__setFont(button, INTENSITY_BUTTON_FONT_SIZE) button.setMinimumSize(INTENSITY_BUTTON_MIN_WIDTH, INTENSITY_BUTTON_MIN_HEIGHT) rowLayout.addWidget(button) rowLayout.addStretch(1) self.__intensitySelectLayout.addLayout(rowLayout) self.__mainLayout.addLayout(self.__intensitySelectLayout) def __drawPresetPatternsForSelection(self): if len(self.__savedPresets) > 0: self.__mode = PATTERN_PRESET_SELECT_MODE self.__createPresetPatternLayout() controlLayout = QHBoxLayout() controlLayout.addStretch(1) self.__presetDeleteButton = TagPushButton(self,"Delete") deleteIcon = QIcon(DELETE_ICON_LOC) self.__presetDeleteButton.setIcon(deleteIcon) self.__setFont(self.__presetDeleteButton, CONTROL_BUTTON_FONT_SIZE) self.__presetDeleteButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) self.__presetDeleteButton.setEnabled(False) backButton = TagPushButton(self,"Back") self.__setFont(backButton,CONTROL_BUTTON_FONT_SIZE) backButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) backIcon = QIcon(BACK_ICON_LOC) backButton.setIcon(backIcon) controlLayout.addWidget(self.__presetDeleteButton) controlLayout.addWidget(backButton) self.__presetButtonLayout.addStretch(1) self.__presetButtonLayout.addLayout(controlLayout) self.__mainLayout.addLayout(self.__presetButtonLayout) self.__selectedPattern = None self.__startValid() def __createPresetPatternLayout(self): self.__clearLayout(self.__selectedPatternLayout) self.__clearLayout(self.__defaultButtonLayout) self.__clearLayout(self.__intensitySelectLayout) self.__clearLayout(self.__presetButtonLayout) self.__currentPatternLabel.setText(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensityLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() presetLabelLayout = QHBoxLayout() presetLabelLayout.addStretch(1) presetPatternLabel = QLabel("Preset Patterns") self.__setFont(presetPatternLabel,PAGE_INFO_LABEL_SIZE) presetLabelLayout.addWidget(presetPatternLabel) presetLabelLayout.addStretch(1) self.__presetButtonLayout.addLayout(presetLabelLayout) if len(self.__savedPresets) <= 0: return numOfButtons = len(self.__savedPresets) numOfRows = numOfButtons/BUTTONS_PER_ROW lastRowStretch = False if numOfButtons%BUTTONS_PER_ROW != 0: numOfRows += 1 lastRowStretch = True self.__Log("Buttons: %d, Rows: %d"%(numOfButtons, numOfRows)) for i in range(0,numOfRows): self.__Log("Row %d"%i) newRow = QHBoxLayout() buttonsLeft = numOfButtons - i*BUTTONS_PER_ROW buttonsInRow = BUTTONS_PER_ROW if buttonsLeft < BUTTONS_PER_ROW: buttonsInRow = buttonsLeft newRow.addStretch(1) for j in range(0,buttonsInRow): patternId = i*BUTTONS_PER_ROW + j #print "Pattern ID %d"%patternId pattern = self.__savedPresets[patternId] name = pattern.GetName() desc = ",".join(pattern.GetColorList()) #print "Name %s"%name newLabel = QLabel(desc) self.__setFont(newLabel,PATTERN_LABEL_FONT_SIZE) newButton = IDPushButton(self,name, patternId) newButton.setMinimumSize(MIN_BUTTON_WIDTH,MIN_BUTTON_HEIGHT) self.__setFont(newButton, PATTERN_BUTTON_FONT_SIZE) self.__buttons.append(newButton) newButtonLayout = QVBoxLayout() newButtonLayout.addWidget(newButton) labelLayout = QHBoxLayout() labelLayout.addStretch(1) labelLayout.addWidget(newLabel) labelLayout.addStretch(1) newButtonLayout.addLayout(labelLayout) newRow.addLayout(newButtonLayout) # Iflast row and < full, add stretch to left and right side (left done above) if lastRowStretch and i == numOfRows-1: newRow.addStretch(1) self.__presetButtonLayout.addLayout(newRow)
class FitParam(object): def __init__(self, name, value, mini, maxi, logscale=False, steps=5000, format='%.3f', size_offset=0, unit=''): self.name = name self.value = value self.min = mini if logscale == False else max(1e-120, mini) self.max = maxi self.logscale = logscale self.steps = steps self.format = format self.unit = unit self.prefix_label = None self.lineedit = None self.unit_label = None self.slider = None self.button = None self._widgets = [] self._size_offset = size_offset self._refresh_callback = None self.dataset = FitParamDataSet(title=_("Curve fitting parameter")) def copy(self): """Return a copy of this fitparam""" return self.__class__(self.name, self.value, self.min, self.max, self.logscale, self.steps, self.format, self._size_offset, self.unit) def create_widgets(self, parent, refresh_callback): self._refresh_callback = refresh_callback self.prefix_label = QLabel() font = self.prefix_label.font() font.setPointSize(font.pointSize() + self._size_offset) self.prefix_label.setFont(font) self.button = QPushButton() self.button.setIcon(get_icon('settings.png')) self.button.setToolTip( _("Edit '%s' fit parameter properties") % self.name) QObject.connect(self.button, SIGNAL('clicked()'), lambda: self.edit_param(parent)) self.lineedit = QLineEdit() QObject.connect(self.lineedit, SIGNAL('editingFinished()'), self.line_editing_finished) self.unit_label = QLabel(self.unit) self.slider = QSlider() self.slider.setOrientation(Qt.Horizontal) self.slider.setRange(0, self.steps - 1) QObject.connect(self.slider, SIGNAL("valueChanged(int)"), self.slider_value_changed) self.update(refresh=False) self.add_widgets([ self.prefix_label, self.lineedit, self.unit_label, self.slider, self.button ]) def add_widgets(self, widgets): self._widgets += widgets def get_widgets(self): return self._widgets def set_scale(self, state): self.logscale = state > 0 self.update_slider_value() def set_text(self, fmt=None): style = "<span style=\'color: #444444\'><b>%s</b></span>" self.prefix_label.setText(style % self.name) if self.value is None: value_str = '' else: if fmt is None: fmt = self.format value_str = fmt % self.value self.lineedit.setText(value_str) self.lineedit.setDisabled(self.value == self.min and self.max == self.min) def line_editing_finished(self): try: self.value = float(self.lineedit.text()) except ValueError: self.set_text() self.update_slider_value() self._refresh_callback() def slider_value_changed(self, int_value): if self.logscale: #~ total_delta = np.log10(1+self.max-self.min) #~ self.value = self.min+10**(total_delta*int_value/(self.steps-1))-1 #~ total_delta = np.log10(self.max)-np.log10(self.min) ratio = int_value / (self.steps - 1) self.value = self.max**ratio * self.min**(1 - ratio) else: total_delta = self.max - self.min self.value = self.min + total_delta * int_value / (self.steps - 1) self.set_text() self._refresh_callback() def update_slider_value(self): from numpy import isnan, isinf if (self.value is None or self.min is None or self.max is None): self.slider.setEnabled(False) if self.slider.parent() and self.slider.parent().isVisible(): self.slider.show() elif self.value == self.min and self.max == self.min: self.slider.hide() else: self.slider.setEnabled(True) if self.slider.parent() and self.slider.parent().isVisible(): self.slider.show() if self.logscale: value_delta = max([np.log10(self.value / self.min), 0.]) total_delta = np.log10(self.max / self.min) if not isnan(self.steps * value_delta / total_delta): intval = int(self.steps * value_delta / total_delta) else: intval = int(self.min) else: value_delta = self.value - self.min total_delta = self.max - self.min intval = int(self.steps * value_delta / total_delta) self.slider.blockSignals(True) print intval print sys.stdout.flush() self.slider.setValue(intval) self.slider.blockSignals(False) def edit_param(self, parent): update_dataset(self.dataset, self) if self.dataset.edit(parent=parent): restore_dataset(self.dataset, self) if self.value > self.max: self.max = self.value if self.value < self.min: self.min = self.value self.update(True) def update(self, refresh=True): self.unit_label.setText(self.unit) self.slider.setRange(0, self.steps - 1) self.update_slider_value() self.set_text() if refresh: self._refresh_callback()
class ConnectionStep(Step): """ A connection step which waits for all sensors to have good signal for 10 seconds. """ update_bars_signal = pyqtSignal() end_connection_signal = pyqtSignal() def __init__(self, params): params["next_button"] = True super(ConnectionStep, self).__init__(params) self.time_to_finish = 5 self.f_widget = QWidget() self.f_layout = QVBoxLayout() self.progress_bars = [QProgressBar() for _ in range(4)] self.timers = [QElapsedTimer() for _ in range(4)] for timer in self.timers: timer.invalidate() self.title_label = QLabel("Adjust the headband until all of the bars are full.") font = self.title_label.font() font.setPointSize(28) font.setBold(False) self.title_label.setFont(font) self.title_label.setAlignment(Qt.AlignCenter) self.title_label.setMaximumHeight(100) self.f_layout.addWidget(self.title_label) self.colors = ["#ea6a1f", "#009986", "#555c99", "#d20e8a"] for bar, color in zip(self.progress_bars, self.colors): bar.setMinimum(0) bar.setMaximum(self.time_to_finish * 1000) bar.setTextVisible(False) bar.setStyleSheet( ( u" QProgressBar::chunk {{ background: {0:s}; }}" + u" QProgressBar {{border: 1px solid gray; height: 60px}}" ).format(color) ) self.f_layout.addWidget(bar) self.update_bars_signal.connect(self.update_bars) self.end_connection_signal.connect(self.endStep) self.f_widget.setLayout(self.f_layout) self.grid.addWidget(self.f_widget) def startStep(self, callback): print "starting connection step" muselo.server.register_listener("/muse/elements/horseshoe", self.receive_horseshoe) super(ConnectionStep, self).startStep(callback) def receive_horseshoe(self, path, args): good = 0 for idx, (conn, timer) in enumerate(zip(args, self.timers)): if conn == 1: if not timer.isValid(): timer.start() else: if timer.elapsed() / 1e3 > self.time_to_finish: good += 1 else: timer.invalidate() self.update_bars_signal.emit() if good == 4: self.end_connection_signal.emit() def update_bars(self): for bar, timer in zip(self.progress_bars, self.timers): if timer.isValid(): bar.setValue(timer.elapsed()) # / 10) else: bar.setValue(0) def endStep(self): muselo.server.remove_listener("/muse/elements/horseshoe", self.receive_horseshoe) self.horseshoe.stop() self.f_widget.close() super(ConnectionStep, self).endStep()
def initGui(self): """ Initialize the GUI. """ self.resize(self._init_window_width, self._init_window_height) grid = QGridLayout(self) grid.setSpacing(10) ### Functions. group_func = QGroupBox(self) font = group_func.font() font.setPointSize(self._font_size_groupbox_title) group_func.setFont(font) group_func.resize(400, 100) grid_func = QGridLayout(group_func) grid_func.setSpacing(10) # Some buttons. self._is_bp = self.kwargs.get("bp", True) if self._is_bp: self.bp = QPushButton(group_func) self.bp.setText("Start plotting") self.bp.clicked.connect(self.pushButton) # Some options. label_logscale = QLabel(group_func) label_logscale.setText("Log") self.checkbox_logscale = QCheckBox(group_func) # Construct. if self._is_bp: grid_func.addWidget(self.bp, 0, 0, 1, 1) grid_func.addWidget(label_logscale, 0, 1) grid_func.addWidget(self.checkbox_logscale, 0, 2) ### Coordinate and Value of the mouse pointer. widget_coor_value = QWidget(self) widget_coor_value.resize(self._init_window_width, 30) grid_coor_value = QGridLayout(widget_coor_value) grid_coor_value.setSpacing(10) label_coor_value = QLabel(self) label_coor_value.setText("Coor, Value:") label_coor_value.setAlignment(Qt.AlignRight) # label_coor_value.setFixedWidth(120) font = label_coor_value.font() font.setPointSize(self._font_size_groupbox_title) font.setBold(True) label_coor_value.setFont(font) self.label_coor_value = QLabel(self) # self.label_coor_value.setFixedSize(200, 30) self.label_coor_value.setText("") font = self.label_coor_value.font() font.setPointSize(self._font_size_groupbox_title) font.setBold(True) self.label_coor_value.setFont(font) # Construct. grid_coor_value.addWidget(label_coor_value, 0, 0) grid_coor_value.addWidget(self.label_coor_value, 0, 1, 1, 3) ### Plotting area. self.initPlotArea() ### Construct the layout. grid.addWidget(group_func, 0, 0) grid.addWidget(self.glw, 1, 0) grid.addWidget(widget_coor_value, 1, 0)
class MainWindow(QMainWindow): SHUTDOWN_MENU = "&Shutdown" HELP_MENU = "&Help" SOFT_EXIT = "&Soft Exit" PHONE_HOME = "Pho&ne Home" ADD_MENU = "Add &Pattern" DELETE_MENU = "&Delete" VERSION_MENU = "&Version" ABOUT_MENU = "&About" ## __init__ --------------------------------------------------------- def __init__(self, Log=None): # Make Main window QMainWindow.__init__(self, None) self.setWindowTitle("Lightbox") self.resize(800, 480) # Screen Size self.__log = Log self.CALLING_CLASS = "MainWindow" if self.__log == None: print "No Log File" self.close() # Create main layout for window mainWidget = QWidget(self) self.__mainLayout = QVBoxLayout(mainWidget) mainWidget.setLayout(self.__mainLayout) # Selected pattern self.__selectedPattern = None self.__presetPatternForDeleting = None self.__currentIntensity = 4000 self.__loadedPattern = None ## Loaded (Running Pattern) self.__loadedPatternBeforePreset = None self.__CACHED_PRESET = None self.EXECUTION_THREAD = None # Add Menu Bard self.__menu = self.__createMenu() ## Toolbar that is always there->Selected Pattern, Start, Stop, Current State Label self.__statusLayout = self.__createStatusLayout() self.__mainLayout.addLayout(self.__statusLayout) self.__patterns = list() self.__buttons = list() self.__savedPresets = list() self.__presetManager = PresetManager(self.__log) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensitySelectLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() self.__makeDefaultButtons() self.__importPresetsFromFile() # Connect TagPushButton signals self.connect(self, SIGNAL("tagPushButtonClicked(PyQt_PyObject)"), self._tagButtonClicked) self.connect(self, SIGNAL("idPushButtonClicked(PyQt_PyObject)"), self._idButtonClicked) # Make the window knwo what is the main widget self.setCentralWidget(mainWidget) self.ColorIcons = [QIcon(RED_ICON_LOC), QIcon(REDOR_ICON_LOC), QIcon(CYAN_ICON_LOC), QIcon(GREEN_ICON_LOC), QIcon(BLUE_ICON_LOC), QIcon(WHITE_ICON_LOC), \ QIcon(YELLOW_ICON_LOC)] self.__mode = PATTERN_SELECT_MODE self.__lastMode = self.__mode self.__modeBeforeIntensity = None self.__running = False def __createStatusLayout(self): ## Make the currently running, start and stop button, running status self.__currentPatternLabel = QLabel(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) font = self.__currentPatternLabel.font() self.__setFont(self.__currentPatternLabel, CONTROL_LABEL_FONT_SIZE) self.__currentStatusLabel = QLabel(STATUS_PREAMBLE + STOPPED) self.__setFont(self.__currentStatusLabel, CONTROL_LABEL_FONT_SIZE) self.StartButton = QPushButton("Start") self.__setFont(self.StartButton, CONTROL_BUTTON_FONT_SIZE) self.StartButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) startIcon = QIcon(START_ICON_LOC) stopIcon = QIcon(STOP_ICON_LOC) self.StartButton.setIcon(startIcon) self.StopButton = QPushButton("Stop") self.__setFont(self.StopButton, CONTROL_BUTTON_FONT_SIZE) self.StopButton.setIcon(stopIcon) self.StopButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) self.StartButton.clicked.connect(self.__handleStart) self.StopButton.clicked.connect(self.__handleStop) # put on the first row of the left coloumn, first two of the right column controlLayout = QHBoxLayout() leftHandColumn = QVBoxLayout() rightHandColumn = QVBoxLayout() leftHandColumn.addWidget(self.__currentPatternLabel) rightHandColumn.addWidget(self.__currentStatusLabel) startStopLayout = QHBoxLayout() startStopLayout.addWidget(self.StartButton) startStopLayout.addWidget(self.StopButton) rightHandColumn.addLayout(startStopLayout) ## Make Intensity Layout self.__intensityLabel = QLabel(INTENSITY_PREAMBLE + str(self.__currentIntensity)) self.__setFont(self.__intensityLabel, CONTROL_LABEL_FONT_SIZE) self.__intensityButton = QPushButton("Set Intensity...") self.__setFont(self.__intensityButton, CONTROL_BUTTON_FONT_SIZE) self.__intensityButton.setMinimumSize(CONTROL_BUTTON_WIDTH * 2, CONTROL_BUTTON_HEIGHT) self.__intensityButton.setMaximumSize(CONTROL_BUTTON_WIDTH * 2, CONTROL_BUTTON_HEIGHT) self.__intensityButton.clicked.connect(self.__intensityButtonClicked) intensityIcon = QIcon(INTENSITY_ICON_LOC) self.__intensityButton.setIcon(intensityIcon) intensityLayout = QVBoxLayout() intensityLayout.addWidget(self.__intensityLabel) intensityLayout.addWidget(self.__intensityButton) # add intensity layout to left hand column leftHandColumn.addLayout(intensityLayout) # Add shutdown button self.ShutdownButton = QPushButton("Shutdown") self.__setFont(self.ShutdownButton, CONTROL_BUTTON_FONT_SIZE) self.ShutdownButton.setMinimumSize(160, CONTROL_BUTTON_HEIGHT) shutdownIcon = QIcon(SHUTDOWN_ICON_LOC) self.ShutdownButton.setIcon(shutdownIcon) self.ShutdownButton.clicked.connect(self.__shutdown) rightHandColumn.addWidget(self.ShutdownButton) infoBarLayout = QHBoxLayout() infoBarLayout.addLayout(leftHandColumn) infoBarLayout.addStretch(1) infoBarLayout.addLayout(rightHandColumn) return infoBarLayout def __Log(self, message): self.__log.LOG(self.CALLING_CLASS, message) def __createMenu(self): menu = self.menuBar() ## About Menu ---------------------------------------- aboutMenu = menu.addMenu(MainWindow.ABOUT_MENU) versionAction = QAction(menu) versionAction.setText(MainWindow.VERSION_MENU) versionAction.triggered.connect(self.__showAbout) aboutMenu.addAction(versionAction) ## Shutdown Menu ----------------------------------------- #shutdownMenu = menu.addMenu(MainWindow.SHUTDOWN_MENU) if ADD_PATTERN_ENABLED: newPatternAction = QAction(menu) newPatternAction.setText(MainWindow.ADD_MENU) newPatternAction.triggered.connect(self.__addPattern) deletePatternAction = QAction(menu) deletePatternAction.setText(MainWindow.DELETE_MENU) deletePatternAction.triggered.connect(self.__deletePattern) #shutdownMenu.addAction(newPatternAction) #shutdownMenu.addAction(deletePatternAction) #shutdownAction = QAction(menu) #shutdownAction.setText(MainWindow.SHUTDOWN_MENU) #shutdownAction.triggered.connect(self.__shutdown) #shutdownMenu.addAction(shutdownAction) ## Soft Exit Menu ------------------------------------ helpMenu = menu.addMenu(MainWindow.HELP_MENU) softExitAction = QAction(menu) softExitAction.setText(MainWindow.SOFT_EXIT) softExitAction.triggered.connect(self.__exit) helpMenu.addAction(softExitAction) if PHONE_HOME_ENABLED: phoneHomeAction = QAction(menu) phoneHomeAction.setText(MainWindow.PHONE_HOME) softExitAction.triggered.connect(self.__phoneHome) helpMenu.addAction(phoneHomeAction) def __showAbout(self): ret = QMessageBox.information(self, "Version Info", "Release: July 10, 2014") ## Make the Default pattern Buttons ---------------------------------------------- def __makeDefaultButtons(self): for iter in range(0, NUM_DEFAULT_PATTERNS): self.__Log("Making preset %d" % iter) pattern_params = DEFAULT_PATTERNS[iter] name = pattern_params[pIndex.Name] des = pattern_params[pIndex.Description] default = pattern_params[pIndex.Default] clist = pattern_params[pIndex.ColorList] reqColors = pattern_params[pIndex.RequiredColors] pwm = pattern_params[pIndex.PWM] newPattern = Pattern(name, des, default, clist, reqColors, pwm, self.__log) self.__patterns += [newPattern] self.__drawPatternButtons() def __importPresetsFromFile(self): self.__savedPresets = self.__presetManager.GetPresetPatterns() ## Clear Layouts ------------------------------------------------------------------ def __clearLayout(self, layout): if layout is not None: while layout.count(): item = layout.takeAt(0) widget = item.widget() if widget is not None: widget.hide() else: self.__clearLayout(item.layout()) def __intensityButtonClicked(self): self.__Log("Intensity Button Clicked") self.__lastMode = self.__mode self.__drawIntensityButtons() ## Color Button has been clicked ------------------------------------------------------- def _idButtonClicked(self, ID): ## Currently only Color buttons are using the ID Button self.__Log("ColorID: %d" % ID) if self.__mode == PATTERN_EDIT_MODE: ## Show color select. self.__currentColorSelection = ID - 1 self.__drawColorButtons() elif self.__mode == INTENSITY_SELECT_MODE: # Get the intensity selected self.__intensitySelected(ID) elif self.__mode == PATTERN_PRESET_SELECT_MODE: self.__presetPatternSelectedForStart(ID) #self.__drawPatternButtons() else: self.__Log("Bad Mode") def _tagButtonClicked(self, buttonTag): self.__Log("Button Tag: %s, mode: %s" % (buttonTag, self.__mode)) if self.__mode == PATTERN_SELECT_MODE: self.__patternSelected(buttonTag) elif self.__mode == PATTERN_EDIT_MODE: # Must be the back or OK buttons if buttonTag == "Back": self.__patternEditControlPressed(buttonTag) elif buttonTag == "Save as Preset": self.__savePatternAsPreset() else: self.__colorSelected(buttonTag) elif self.__mode == PATTERN_PRESET_SELECT_MODE: if buttonTag == "Back": if self.__loadedPatternBeforePreset != None and self.__presetPatternForDeleting != None: self.__Log("Both are not none") if self.__loadedPatternBeforePreset.GetName( ) != self.__presetPatternForDeleting.GetName( ) and self.__loadedPatternBeforePreset.GetColorString( ) != self.__presetPatternForDeleting.GetColorString(): self.__Log( "Setting preset back to the one it was before") self.__loadedPattern = self.__loadedPatternBeforePreset self.__loadedPatternBeforePreset = None self.__presetPatternForDeleting = None self.__loadedPatternBeforePreset = None self.__drawPatternButtons() if self.__loadedPattern != None: self.__currentPatternLabel.setText( PATTERN_PREAMBLE + self.__loadedPattern.GetName() + ' ' + self.__loadedPattern.GetColorString()) elif buttonTag == "Delete": self.__presetPatternForDeleting = self.__loadedPattern if self.__loadedPatternBeforePreset != None and self.__presetPatternForDeleting != None: self.__Log("Both are not none") if self.__loadedPatternBeforePreset.GetName( ) == self.__presetPatternForDeleting.GetName( ) and self.__loadedPatternBeforePreset.GetColorString( ) == self.__presetPatternForDeleting.GetColorString(): self.__Log("Deleting the currently loaded pattern") self.__loadedPatternBeforePreset = None self.__loadedPattern = None self.__currentPatternLabel.setText( PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) else: self.__Log( "Setting the loaded pattern back to what it should be before delete occured" ) self.__loadedPattern = self.__loadedPatternBeforePreset self.__currentPatternLabel.setText( PATTERN_PREAMBLE + self.__loadedPattern.GetName() + ' ' + self.__loadedPattern.GetColorString()) elif self.__loadedPatternBeforePreset == None: self.__currentPatternLabel.setText(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) self.__loadedPattern = None else: self.__loadedPattern = self.__loadedPatternBeforePreset self.__currentPatternLabel.setText( PATTERN_PREAMBLE + self.__loadedPattern.GetName() + ' ' + self.__loadedPattern.GetColorString()) self.__deletePresetPattern() if len(self.__savedPresets) > 0: self.__drawPresetPatternsForSelection() else: self.__drawPatternButtons() else: self.__Log("Unknown button") else: self.__Log("Bad Mode") def __presetPatternSelectedForStart(self, ID): self.__Log("Preset pattern selected with ID %d" % ID) if ID >= 0 and ID < len(self.__savedPresets): self.__selectedPattern = self.__savedPresets[ID] self.__currentPatternLabel.setText( PATTERN_PREAMBLE + self.__selectedPattern.GetName() + ' ' + self.__selectedPattern.GetColorString()) self.__loadedPattern = self.__selectedPattern self.__presetDeleteButton.setEnabled(True) self.StartButton.setEnabled(True) return def __intensitySelected(self, ID): ## NOTE: INtensity does not change until the STOP->START is pressed. self.__Log("Got Intensity: %d" % ID) self.__currentIntensity = ID self.__intensityLabel.setText(INTENSITY_PREAMBLE + str(ID)) self.__mode = self.__lastMode self.__redrawMode() def __colorSelected(self, colorTag): self.__Log("Got Color Selected: %s, setting index %d" % (colorTag, self.__currentColorSelection)) presetColorList = list() if (self.__savedPresets != None): for aPreset in self.__savedPresets: self.__Log("Preset Colors:%s" % (",".join(aPreset.GetColorList()))) newList = list() for color in aPreset.GetColorList(): for presetColor in ColorsByIndex: if presetColor == color: newList += [presetColor] break presetColorList += [newList] self.__Log("Preset Colors:%s" % (",".join(newList))) #presetColorList += [aPreset.GetColorList()] self.__selectedPattern.SetColor(self.__currentColorSelection, colorTag) if self.__savedPresets != None: for ind, aPreset in enumerate(self.__savedPresets): self.__Log("Colors: %s" % (",".join(presetColorList[ind]))) aPreset.SetColorList(presetColorList[ind]) self.__Log("Preset Colors:%s" % (",".join(aPreset.GetColorList()))) ## Check to see if this is now valid if self.__selectedPattern.CanStart(): self.__loadedPattern = self.__selectedPattern self.StartButton.setEnabled(True) self.__drawPatternSettings(self.__selectedPattern) def __savePatternAsPreset(self): self.__Log("Save Pattern As Preset") if self.__selectedPattern.CanStart(): self.__Log("%d Presets already made" % len(self.__savedPresets)) for aPreset in self.__savedPresets: self.__Log("Preset Colors:%s" % (",".join(aPreset.GetColorList()))) if len(self.__savedPresets) < MAX_NUM_PRESETS: # Check to see if there is a duplicate of this already newPattern = Pattern() newPattern.SetName(self.__selectedPattern.GetName()) newPattern.SetDescription( self.__selectedPattern.GetDescription()) newPattern.SetLog(self.__log) newPattern.SetPwmSequenceDict( self.__selectedPattern.GetPwmSequenceDict()) newPattern.SetColorList(self.__selectedPattern.GetColorList()) newPattern.SetRequiredColors( self.__selectedPattern.GetRequiredColors()) self.__Log("Colors %s" % (",".join(newPattern.GetColorList()))) for pattern in self.__savedPresets: if pattern.GetName() == newPattern.GetName(): if pattern.GetColorList() == newPattern.GetColorList(): self.__drawPatternSettings(self.__selectedPattern, False, True, PRESET_EXISTS) return self.__savedPresets += [newPattern] self.__CACHED_PRESET = None self.__Log("Saved Pattern.") self.__presetManager.SavePresetPattern(newPattern) self.__drawPatternSettings(self.__selectedPattern, False, True, PRESET_SAVED) def __patternEditControlPressed(self, buttonTag): if buttonTag == "Back": self.__drawPatternButtons() if self.__loadedPattern != None: self.__currentPatternLabel.setText( PATTERN_PREAMBLE + self.__loadedPattern.GetName() + ' ' + self.__loadedPattern.GetColorString()) else: self.__Log("Unknown tag: %s" % buttonTag) def __patternSelected(self, buttonTag): self.__Log("Pattern \'%s\' pressed" % buttonTag) if buttonTag == PRESET_TAG: self.__Log("Preset Button Pressed.") self.__loadedPatternBeforePreset = self.__loadedPattern self.__drawPresetPatternsForSelection() return # Get the actual pattern from the list of patterns for it in range(0, len(self.__patterns)): self.__selectedPattern = self.__patterns[it] if self.__selectedPattern.GetName() == buttonTag: self.__Log("FOUND PATTERN") self.__selectedPattern.ClearColors() self.__drawPatternSettings(self.__selectedPattern) return self.__Log("Didn't find a pattern that matched tag!") def __handleStart(self): self.__Log("START") if self.__loadedPattern != None: if self.__running: if (self.EXECUTION_THREAD != None): self.EXECUTION_THREAD.join() time.sleep(.5) self.__running = True self.__currentStatusLabel.setText(STATUS_PREAMBLE + RUNNING) self.EXECUTION_THREAD = ExecutionThread(self.__loadedPattern, self.__currentIntensity, self.__log) self.EXECUTION_THREAD.start() time.sleep(.5) def __handleStop(self): self.__Log("STOP") if self.__running: self.__running = False #self.__selectedPattern.ClearColors() #self.__currentPatternLabel.setText(PATTERN_PREAMBLE + NO_PATTERN_SELECTED) self.__currentStatusLabel.setText(STATUS_PREAMBLE + STOPPED) # Stop Threading if (self.EXECUTION_THREAD != None): self.EXECUTION_THREAD.join() time.sleep(.5) self.__redrawMode() def __phoneHome(self): if RASPI: os.system("/home/pi/Desktop/Lightbox/util/phoneHome.sh &") def __exit(self): self.__handleStop() self.close() def __shutdown(self): response = QMessageBox.question(self, "Shutdown", "Proceed with shutdown?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if response == QMessageBox.Yes: self.__handleStop() if RASPI: os.system("sudo shutdown -h 0") self.close() ### DISABLED----------------------------------------------------- def __addPattern(self): self.__Log("Add Pattern") newPattern = Pattern() newDescription = "Pattern %d" % (len(self.__patterns)) self.__Log("New description %s" % newDescription) copyPattern = self.__patterns[0] newPattern = copyPattern.CopyPattern(newDescription) self.__patterns += [newPattern] self.__drawPatternButtons() ## Delete a preset pattern -------------------------------------- def __deletePresetPattern(self): self.__Log("Delete Preset Pattern") self.__savedPresets.remove(self.__presetPatternForDeleting) self.__presetManager.DeletePresetPattern( self.__presetPatternForDeleting) def __setFont(self, object, size): font = QFont(object.font()) font.setPointSize(size) object.setFont(font) def __startValid(self): self.__Log("In start Valid") if self.__mode == PATTERN_EDIT_MODE or self.__mode == PATTERN_PRESET_SELECT_MODE: if self.__selectedPattern != None: self.StartButton.setEnabled(self.__selectedPattern.CanStart()) else: self.StartButton.setEnabled(False) self.__Log( "In edit mode/preset selection (same state as edit, selectedPattern has to be valid." ) elif self.__loadedPattern != None: self.__Log("Looking at loaded pattern") if self.__loadedPattern.CanStart(): self.StartButton.setEnabled(self.__loadedPattern.CanStart()) else: self.StartButton.setEnabled(False) def __redrawMode(self): if self.__mode == PATTERN_EDIT_MODE: self.__drawPatternSettings(self.__selectedPattern) elif self.__mode == PATTERN_SELECT_MODE: self.__drawPatternButtons() elif self.__mode == PATTERN_PRESET_SELECT_MODE: self.__drawPresetPatternsForSelection() elif self.__mode == INTENSITY_SELECT_MODE: if (self.__modeBeforeIntensity != None): if self.__modeBeforeIntensity == PATTERN_EDIT_MODE: self.__drawPatternSettings(self.__selectedPattern) elif self.__mode == PATTERN_SELECT_MODE: self.__drawPatternButtons() elif self.__mode == PATTERN_PRESET_SELECT_MODE: self.__drawPresetPatternsForSelection() else: self.__drawPatternButtons() else: self.__drawPatternButtons() else: self.__Log("No mode to redraw") ## Draw the Premade pattern buttons ------------------------------------------------ def __drawPatternButtons(self): self.__mode = PATTERN_SELECT_MODE self.__startValid() self.__clearLayout(self.__selectedPatternLayout) self.__clearLayout(self.__defaultButtonLayout) self.__clearLayout(self.__intensitySelectLayout) self.__clearLayout(self.__presetButtonLayout) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensityLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() self.__buttons = list() # add label for this screen patternLabelLayout = QHBoxLayout() patternLabelLayout.addStretch(1) patternLabel = QLabel("Temporal Patterns") self.__setFont(patternLabel, PAGE_INFO_LABEL_SIZE) patternLabelLayout.addWidget(patternLabel) patternLabelLayout.addStretch(1) self.__defaultButtonLayout.addLayout(patternLabelLayout) self.__Log("Redrawing Buttons") numOfButtons = len(self.__patterns) # + 1 # One for preset numOfRows = numOfButtons / BUTTONS_PER_ROW lastRowStretch = False if numOfButtons % BUTTONS_PER_ROW != 0: numOfRows += 1 lastRowStretch = True self.__Log("Buttons: %d, Rows: %d" % (numOfButtons, numOfRows)) for i in range(0, numOfRows): #self.__Log("Row %d"%i) newRow = QHBoxLayout() buttonsLeft = numOfButtons - i * BUTTONS_PER_ROW buttonsInRow = BUTTONS_PER_ROW if buttonsLeft < BUTTONS_PER_ROW: buttonsInRow = buttonsLeft newRow.addStretch(1) for j in range(0, buttonsInRow): patternId = i * BUTTONS_PER_ROW + j #print "Pattern ID %d"%patternId pattern = self.__patterns[patternId] name = pattern.GetName() desc = pattern.GetDescription() #print "Name %s"%name newLabel = QLabel(desc) self.__setFont(newLabel, PATTERN_LABEL_FONT_SIZE) newButton = TagPushButton(self, name) newButton.setMinimumSize(MIN_BUTTON_WIDTH, MIN_BUTTON_HEIGHT) self.__setFont(newButton, PATTERN_BUTTON_FONT_SIZE) self.__buttons.append(newButton) newButtonLayout = QVBoxLayout() newButtonLayout.addWidget(newButton) labelLayout = QHBoxLayout() labelLayout.addStretch() labelLayout.addWidget(newLabel) labelLayout.addStretch() newButtonLayout.addLayout(labelLayout) newButtonLayout.addStretch(1) newRow.addLayout(newButtonLayout) # Iflast row and < full, add stretch to left and right side (left done above) if lastRowStretch and i == numOfRows - 1: ## Add the preset button here, we know it's there button = TagPushButton(self, PRESET_TAG) self.__setFont(button, PATTERN_BUTTON_FONT_SIZE) button.setMinimumSize(MIN_BUTTON_WIDTH, MIN_BUTTON_HEIGHT) presetLayout = QVBoxLayout() presetLayout.addWidget(button) presetLayout.addStretch(1) newRow.addLayout(presetLayout) newRow.addStretch(1) self.__defaultButtonLayout.addLayout(newRow) self.__mainLayout.addLayout(self.__defaultButtonLayout) ## Draw Settings Window ------------------------------------------------------- def __drawPatternSettings(self, pattern, withColors=False, withLogMessage=False, logMessage=""): self.__mode = PATTERN_EDIT_MODE if pattern.CanStart(): self.__currentPatternLabel.setText(PATTERN_PREAMBLE + pattern.GetName() + ' ' + pattern.GetColorString()) else: self.__currentPatternLabel.setText(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) self.__startValid() self.__Log("Draw pattern settings") self.__Log("Pattern \'%s\' pressed" % pattern.GetName()) self.__Log("Clearing pattern layout.") self.__clearLayout(self.__selectedPatternLayout) self.__clearLayout(self.__defaultButtonLayout) self.__clearLayout(self.__intensitySelectLayout) self.__clearLayout(self.__presetButtonLayout) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensityLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() # Pattern picture patternLayout = QHBoxLayout() patLabel = QLabel(pattern.GetName()) self.__setFont(patLabel, PAGE_INFO_LABEL_SIZE) image = QLabel("ICON HERE") patternLayout.addStretch(1) patternLayout.addWidget(patLabel) patternLayout.addStretch(1) self.__selectedPatternLayout.addLayout(patternLayout) # Color choosing buttons numOfColors = pattern.GetRequiredColors() self.__Log("Number of required colors is %d" % numOfColors) colorButtonLayout = QHBoxLayout() colorButtonLayout.addStretch(1) for x in range(1, numOfColors + 1, 1): buttonLayout = QVBoxLayout() # Make Button newButton = IDPushButton(self, "Color %d..." % x, x) self.__setFont(newButton, PATTERN_BUTTON_FONT_SIZE) newButton.setMaximumSize(100, 100) # Make Label newLabel = QLabel(self.__selectedPattern.GetColorByIndex(x - 1)) self.__setFont(newLabel, PATTERN_LABEL_FONT_SIZE) buttonLayout.addWidget(newButton) labelLayout = QHBoxLayout() labelLayout.addStretch(1) labelLayout.addWidget(newLabel) labelLayout.addStretch(1) # Add label to button layout, button layout to color button layout buttonLayout.addLayout(labelLayout) colorButtonLayout.addLayout(buttonLayout) colorButtonLayout.addStretch(1) self.__selectedPatternLayout.addLayout(colorButtonLayout) if withColors: self.__selectedPatternLayout.addLayout( self.__colorButtonChooserLayout) self.__selectedPatternLayout.addStretch(1) # Control buttons controlButtonLayout = QHBoxLayout() controlButtonLayout.addStretch(1) saveButton = TagPushButton(self, "Save as Preset") saveIcon = QIcon(SAVE_ICON_LOC) saveButton.setIcon(saveIcon) backButton = TagPushButton(self, "Back") backIcon = QIcon(BACK_ICON_LOC) backButton.setIcon(backIcon) saveButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) backButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) self.__setFont(saveButton, CONTROL_BUTTON_FONT_SIZE) self.__setFont(backButton, CONTROL_BUTTON_FONT_SIZE) ## If we just saved a preset, show the QLabel that we did. if (withLogMessage and logMessage != ""): logLabel = QLabel(logMessage) self.__setFont(logLabel, CONTROL_LABEL_FONT_SIZE) controlButtonLayout.addWidget(logLabel) ## Check to see if adding a preset is okay? if len(self.__savedPresets) >= MAX_NUM_PRESETS: saveButton.setEnabled(False) presetsFullLabel = QLabel("Presets Full!") self.__setFont(presetsFullLabel, CONTROL_LABEL_FONT_SIZE) controlButtonLayout.addWidget(presetsFullLabel) else: saveButton.setEnabled(self.__selectedPattern.CanStart()) controlButtonLayout.addWidget(saveButton) controlButtonLayout.addWidget(backButton) self.__selectedPatternLayout.addLayout(controlButtonLayout) self.__mainLayout.addLayout(self.__selectedPatternLayout) def __drawColorButtons(self): self.__colorButtonChooserLayout = QHBoxLayout() numOfColors = len(Colors) for i in range(0, numOfColors - 1): ## -1 excludes the Empty button = TagPushButton(self, Colors[i]) self.__setFont(button, PATTERN_BUTTON_FONT_SIZE) button.setIcon(self.ColorIcons[i]) self.__colorButtonChooserLayout.addWidget(button) self.__drawPatternSettings(self.__selectedPattern, True) def __drawIntensityButtons(self): self.__modeBeforeIntensity = self.__mode self.__mode = INTENSITY_SELECT_MODE self.__Log("Draw intensity buttons") self.__clearLayout(self.__selectedPatternLayout) self.__clearLayout(self.__defaultButtonLayout) self.__clearLayout(self.__intensitySelectLayout) self.__clearLayout(self.__presetButtonLayout) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensitySelectLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() self.__intensitySelectLayout.addStretch(1) labelLayout = QHBoxLayout() labelLayout.addStretch(1) intensityLabel = QLabel("Intensity Select (candela)") self.__setFont(intensityLabel, PAGE_INFO_LABEL_SIZE) labelLayout.addWidget(intensityLabel) labelLayout.addStretch(1) self.__intensitySelectLayout.addLayout(labelLayout) numOfButtons = len(Intensities) maxButtonsPerRow = 3 numOfRows = numOfButtons / maxButtonsPerRow if numOfButtons % maxButtonsPerRow != 0: numOfRows += 1 for i in range(0, numOfRows): rowLayout = QHBoxLayout() rowLayout.addStretch(1) buttonsLeft = numOfButtons - i * maxButtonsPerRow buttonsInRow = maxButtonsPerRow if buttonsLeft < maxButtonsPerRow: buttonsInRow = buttonsLeft for j in range(0, buttonsInRow): button = IDPushButton( self, str(Intensities[j + (i * maxButtonsPerRow)]), Intensities[j + (i * maxButtonsPerRow)]) self.__setFont(button, INTENSITY_BUTTON_FONT_SIZE) button.setMinimumSize(INTENSITY_BUTTON_MIN_WIDTH, INTENSITY_BUTTON_MIN_HEIGHT) rowLayout.addWidget(button) rowLayout.addStretch(1) self.__intensitySelectLayout.addLayout(rowLayout) self.__mainLayout.addLayout(self.__intensitySelectLayout) def __drawPresetPatternsForSelection(self): if len(self.__savedPresets) > 0: self.__mode = PATTERN_PRESET_SELECT_MODE self.__createPresetPatternLayout() controlLayout = QHBoxLayout() controlLayout.addStretch(1) self.__presetDeleteButton = TagPushButton(self, "Delete") deleteIcon = QIcon(DELETE_ICON_LOC) self.__presetDeleteButton.setIcon(deleteIcon) self.__setFont(self.__presetDeleteButton, CONTROL_BUTTON_FONT_SIZE) self.__presetDeleteButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) self.__presetDeleteButton.setEnabled(False) backButton = TagPushButton(self, "Back") self.__setFont(backButton, CONTROL_BUTTON_FONT_SIZE) backButton.setMinimumSize(CONTROL_BUTTON_WIDTH, CONTROL_BUTTON_HEIGHT) backIcon = QIcon(BACK_ICON_LOC) backButton.setIcon(backIcon) controlLayout.addWidget(self.__presetDeleteButton) controlLayout.addWidget(backButton) self.__presetButtonLayout.addStretch(1) self.__presetButtonLayout.addLayout(controlLayout) self.__mainLayout.addLayout(self.__presetButtonLayout) self.__selectedPattern = None self.__startValid() def __createPresetPatternLayout(self): self.__clearLayout(self.__selectedPatternLayout) self.__clearLayout(self.__defaultButtonLayout) self.__clearLayout(self.__intensitySelectLayout) self.__clearLayout(self.__presetButtonLayout) self.__currentPatternLabel.setText(PATTERN_PREAMBLE + EMPTY_PATTERN_SELECTED) self.__defaultButtonLayout = QVBoxLayout() self.__selectedPatternLayout = QVBoxLayout() self.__intensityLayout = QVBoxLayout() self.__presetButtonLayout = QVBoxLayout() presetLabelLayout = QHBoxLayout() presetLabelLayout.addStretch(1) presetPatternLabel = QLabel("Preset Patterns") self.__setFont(presetPatternLabel, PAGE_INFO_LABEL_SIZE) presetLabelLayout.addWidget(presetPatternLabel) presetLabelLayout.addStretch(1) self.__presetButtonLayout.addLayout(presetLabelLayout) if len(self.__savedPresets) <= 0: return numOfButtons = len(self.__savedPresets) numOfRows = numOfButtons / BUTTONS_PER_ROW lastRowStretch = False if numOfButtons % BUTTONS_PER_ROW != 0: numOfRows += 1 lastRowStretch = True self.__Log("Buttons: %d, Rows: %d" % (numOfButtons, numOfRows)) for i in range(0, numOfRows): self.__Log("Row %d" % i) newRow = QHBoxLayout() buttonsLeft = numOfButtons - i * BUTTONS_PER_ROW buttonsInRow = BUTTONS_PER_ROW if buttonsLeft < BUTTONS_PER_ROW: buttonsInRow = buttonsLeft newRow.addStretch(1) for j in range(0, buttonsInRow): patternId = i * BUTTONS_PER_ROW + j #print "Pattern ID %d"%patternId pattern = self.__savedPresets[patternId] name = pattern.GetName() desc = ",".join(pattern.GetColorList()) #print "Name %s"%name newLabel = QLabel(desc) self.__setFont(newLabel, PATTERN_LABEL_FONT_SIZE) newButton = IDPushButton(self, name, patternId) newButton.setMinimumSize(MIN_BUTTON_WIDTH, MIN_BUTTON_HEIGHT) self.__setFont(newButton, PATTERN_BUTTON_FONT_SIZE) self.__buttons.append(newButton) newButtonLayout = QVBoxLayout() newButtonLayout.addWidget(newButton) labelLayout = QHBoxLayout() labelLayout.addStretch(1) labelLayout.addWidget(newLabel) labelLayout.addStretch(1) newButtonLayout.addLayout(labelLayout) newRow.addLayout(newButtonLayout) # Iflast row and < full, add stretch to left and right side (left done above) if lastRowStretch and i == numOfRows - 1: newRow.addStretch(1) self.__presetButtonLayout.addLayout(newRow)
class PlotWindow(QDialog): """ Class for some plots. """ def __init__(self, parent=None, name="", **kwargs): """ Initialization. """ super().__init__(parent) self.setParent(parent) print("Initialize this plot window...") self.name = name self.kwargs = kwargs self.initInnerParameters() self.initGui() @footprint def initInnerParameters(self): """ Initialize the inner parameters. """ self.is_closed = False self._timer = QtCore.QTimer() self._is_emulate = False self.data = None self._init_window_width = 600 # [pixel] self._init_window_height = 600 # [pixel] self._subplot_size = 100 # [pixel] self._font_size_groupbox_title = 11 # [pixel] @footprint def initGui(self): """ Initialize the GUI. """ self.resize(self._init_window_width, self._init_window_height) grid = QGridLayout(self) grid.setSpacing(10) ### Functions. group_func = QGroupBox(self) font = group_func.font() font.setPointSize(self._font_size_groupbox_title) group_func.setFont(font) group_func.resize(400, 100) grid_func = QGridLayout(group_func) grid_func.setSpacing(10) # Some buttons. self._is_bp = self.kwargs.get("bp", True) if self._is_bp: self.bp = QPushButton(group_func) self.bp.setText("Start plotting") self.bp.clicked.connect(self.pushButton) # Some options. label_logscale = QLabel(group_func) label_logscale.setText("Log") self.checkbox_logscale = QCheckBox(group_func) # Construct. if self._is_bp: grid_func.addWidget(self.bp, 0, 0, 1, 1) grid_func.addWidget(label_logscale, 0, 1) grid_func.addWidget(self.checkbox_logscale, 0, 2) ### Coordinate and Value of the mouse pointer. widget_coor_value = QWidget(self) widget_coor_value.resize(self._init_window_width, 30) grid_coor_value = QGridLayout(widget_coor_value) grid_coor_value.setSpacing(10) label_coor_value = QLabel(self) label_coor_value.setText("Coor, Value:") label_coor_value.setAlignment(Qt.AlignRight) # label_coor_value.setFixedWidth(120) font = label_coor_value.font() font.setPointSize(self._font_size_groupbox_title) font.setBold(True) label_coor_value.setFont(font) self.label_coor_value = QLabel(self) # self.label_coor_value.setFixedSize(200, 30) self.label_coor_value.setText("") font = self.label_coor_value.font() font.setPointSize(self._font_size_groupbox_title) font.setBold(True) self.label_coor_value.setFont(font) # Construct. grid_coor_value.addWidget(label_coor_value, 0, 0) grid_coor_value.addWidget(self.label_coor_value, 0, 1, 1, 3) ### Plotting area. self.initPlotArea() ### Construct the layout. grid.addWidget(group_func, 0, 0) grid.addWidget(self.glw, 1, 0) grid.addWidget(widget_coor_value, 1, 0) @footprint def initPlotArea(self): """ Initialize the plot area. """ # Construct the graphic layout. self.glw = pg.GraphicsLayoutWidget() self.glw.resize(self._init_window_width, self._init_window_height) # Plot area. self.plotArea = self.glw.addPlot() # # Plot area for the image. # p1 = self.glw.addPlot() # p1.setAspectLocked(True) # self.iw = pg.ImageItem() # p1.addItem(self.iw) def mouseMoved(pos): try: coor = self.plotArea.mapFromScene(pos) x, y = int(coor.x()), int(coor.y()) if self.iw.image is not None: img = self.iw.image if 0 <= x <= img.shape[1] and 0 <= y <= img.shape[0]: self.label_coor_value.setText( "({0}, {1}, {2:.2e})".format(x, y, img[y, x])) except Exception as ex: print(ex) self.plotArea.scene().sigMouseMoved.connect(mouseMoved) @footprint @pyqtSlot() def pushButton(self): """ Button function. """ try: if not self._timer.isActive(): self._timer.setInterval(1000) self._timer.timeout.connect(self.updateImage) self._timer.start() self.bp.setText("Stop plotting") else: self._timer.stop() self.bp.setText("Start plotting") except Exception as ex: print(ex) # @footprint @pyqtSlot() def updateImage(self): """ Update the image and the other plots. """ try: if self.data is not None: if self._is_emulate: self.data = np.random.normal(100, 10, (100, 100)) self.iw.setImage(self.data) # self.hist.vb.setLimits(yMin=self.data.min(), yMax=self.data.max()) if self.checkbox_logscale.isChecked: # if self.data.min() < 0: # self.hist.vb.setLimits(yMin=0.1, yMax=self.data.max()) self.hist.plot.setLogMode(False, True) if self._is_px: self.px.plot(self.data.mean(axis=1), np.arange(self.data.shape[0]), clear=True) if self._is_py: self.py.plot(np.arange(self.data.shape[1]), self.data.mean(axis=0), clear=True) if self._is_ph: hist, xbins = np.histogram(self.data.flatten()) dxbins = xbins[1] - xbins[0] self.ph.plot(xbins + dxbins / 2.0, hist, clear=True, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150)) except Exception as ex: print(ex) @footprint def closeEvent(self, event): self.is_closed = True if self._timer.isActive(): print("Stop the active timer.") self._timer.stop() self.data = None
class DataViewerBase(QMainWindow): """ Base GUI class for viewing data / images. This class was made in the purpose of viewing VMI images. """ # _name = DataViewerBase().__class__.__name__ def __init__(self, filepath=""): """ Initialization. """ super().__init__() self.initInnerParameters(filepath) self.initGui() self.initGetDataProcess() self.initUpdateImageProcess() self.initCheckWindowProcess() @footprint def initInnerParameters(self, filepath): """ Initialize the inner parameters. """ self._mutex = QMutex() self._windows = [] self.initData() self._isUpdatingImage = False self._font_size_button = 16 # [pixel] self._font_size_groupbox_title = 12 # [pixel] self._font_size_label = 11 # [pixel] self._font_bold_label = True self._init_window_width = 1600 # [pixel] self._init_window_height = 700 # [pixel] self._init_button_color = "#EBF5FB" self.main_bgcolor = "#FDF2E9" self._get_data_interval = 1 # [sec] self._get_data_worker_sleep_interval = self._get_data_interval - 0.1 # [sec] self._update_image_interval = 2 # [sec] self._get_update_delay = 1 # [sec] self._check_window_interval = 1 # [sec] self._currentDir = os.path.dirname(__file__) self._online = False self._closing_dialog = True if os.path.exists( os.path.join(os.path.dirname(__file__), "config.json")): self.loadConfig() if not os.path.exists( os.path.join(os.path.dirname(__file__), "config_getdata.json")): raise FileNotFoundError("config_getdata.json") self.loadConfigGetData() @footprint @pyqtSlot() def initData(self): """ Initialize inner data. """ self.dataset = { "sig_wl": None, "sig_wol": None, "bg_wl": None, "bg_wol": None } self.nbr_of_sig = 0 self.nbr_of_bg = 0 self.sig = None self.bg = None self.currentRun = -1 self.startTag = -1 self.endTag = -1 @footprint def loadConfig(self): """ Load a config file. """ with open(os.path.join(os.path.dirname(__file__), "config.json"), 'r') as ff: config = json.load(ff) if config.get("currentDir") is not None: if isinstance(config.get("currentDir"), str): if os.path.exists(config.get("currentDir")): self._currentDir = config["currentDir"] if config.get("online") is not None: if isinstance(config.get("online"), bool): self._online = config["online"] if config.get("closing_dialog") is not None: if isinstance(config.get("closing_dialog"), bool): self._closing_dialog = config["closing_dialog"] if config.get("emulate") is not None: if isinstance(config.get("emulate"), bool): self._emulate = config["emulate"] if config.get("font_size_button") is not None: if isinstance(config.get("font_size_button"), int): self._font_size_button = config["font_size_button"] if config.get("font_size_groupbox_title") is not None: if isinstance(config.get("font_size_groupbox_title"), int): self._font_size_groupbox_title = config[ "font_size_groupbox_title"] if config.get("font_size_label") is not None: if isinstance(config.get("font_size_label"), int): self._font_size_label = config["font_size_label"] if config.get("font_bold_label") is not None: if isinstance(config.get("font_bold_label"), bool): self._font_bold_label = config["font_bold_label"] self._config = config def loadConfigGetData(self): """ Load a config file of getDatawithOLPY. """ with open( os.path.join(os.path.dirname(__file__), "config_getdata.json"), 'r') as ff: config_get_data = json.load(ff) self._get_data_interval = config_get_data["interval"] # [sec] self._get_data_worker_sleep_interval = self._get_data_interval - 0.1 # [sec] self._get_data_ports = config_get_data["port"] self._get_info_port = config_get_data["port_info"] self._config_get_data = config_get_data @footprint def initGui(self): """ Initialize the GUI. """ self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.initMainWidget() self.setMenuBar() self.setWindowTitle("VMI Viewer") self.resize(self._init_window_width, self._init_window_height) ### RunInfo. group_runinfo = QGroupBox(self) group_runinfo.setTitle("RunInfo") font = group_runinfo.font() font.setPointSize(self._font_size_groupbox_title) group_runinfo.setFont(font) group_runinfo.resize(400, 100) grid_runinfo = QGridLayout(group_runinfo) # Run No. label_run = QLabel(self) label_run.setText("Run No. : ") label_run.setAlignment(Qt.AlignRight) font = label_run.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_run.setFont(font) self.label_run_number = QLabel(self) self.label_run_number.setText("Unknown") pal = QPalette() pal.setColor(QPalette.Foreground, QColor("#0B5345")) self.label_run_number.setPalette(pal) font = self.label_run_number.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_run_number.setFont(font) # Tag No. label_tag = QLabel(self) label_tag.setText("Tag No. : ") label_tag.setAlignment(Qt.AlignRight) font = label_tag.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_tag.setFont(font) self.label_tag_start = QLabel(self) self.label_tag_start.setText("None") font = self.label_tag_start.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_tag_start.setFont(font) label_tag_hyphen = QLabel(self) label_tag_hyphen.setText(" - ") label_tag_hyphen.setFixedWidth(30) font = label_tag_hyphen.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_tag_hyphen.setFont(font) self.label_tag_end = QLabel(self) self.label_tag_end.setText("None") font = self.label_tag_end.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_tag_end.setFont(font) # Sig / BG. label_sig = QLabel(self) label_sig.setText("# of Sig : ") label_sig.setAlignment(Qt.AlignRight) font = label_sig.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_sig.setFont(font) self.label_nbr_of_sig = QLabel(self) self.label_nbr_of_sig.setText("None") font = self.label_nbr_of_sig.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_nbr_of_sig.setFont(font) label_bg = QLabel(self) label_bg.setText("# of BG : ") label_bg.setAlignment(Qt.AlignRight) font = label_bg.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_bg.setFont(font) self.label_nbr_of_bg = QLabel(self) self.label_nbr_of_bg.setText("None") font = self.label_nbr_of_bg.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_nbr_of_bg.setFont(font) # Construct the layout. grid_runinfo.addWidget(label_run, 0, 0) grid_runinfo.addWidget(self.label_run_number, 0, 1, 1, 3) grid_runinfo.addWidget(label_tag, 1, 0) grid_runinfo.addWidget(self.label_tag_start, 1, 1) grid_runinfo.addWidget(label_tag_hyphen, 1, 2) grid_runinfo.addWidget(self.label_tag_end, 1, 3) grid_runinfo.addWidget(label_sig, 2, 0) grid_runinfo.addWidget(self.label_nbr_of_sig, 2, 1) grid_runinfo.addWidget(label_bg, 2, 2) grid_runinfo.addWidget(self.label_nbr_of_bg, 2, 3) ### Settings. # group_settings = QGroupBox(self) # group_settings.setTitle("Settings") # font = group_settings.font() # font.setPointSize(self._font_size_groupbox_title) # group_settings.setFont(font) # group_settings.resize(400, 100) # grid_settings = QGridLayout(group_settings) # # Update interval. # label_upd_rate = QLabel(self) # label_upd_rate.setText("Upd. image interval: ") # font = label_upd_rate.font() # font.setPointSize(self._font_size_label) # font.setBold(self._font_bold_label) # label_upd_rate.setFont(font) # self.spinbox_upd_img_interval = QDoubleSpinBox(self) # self.spinbox_upd_img_interval.setValue(self._get_data_interval) # self.spinbox_upd_img_interval.setFixedWidth(100) # self.spinbox_upd_img_interval.setAlignment(Qt.AlignRight) # font = self.spinbox_upd_img_interval.font() # font.setBold(True) # font.setPointSize(self._font_size_label) # self.spinbox_upd_img_interval.setFont(font) # label_upd_rate_unit = QLabel(self) # label_upd_rate_unit.setText("sec") # font = label_upd_rate_unit.font() # font.setPointSize(self._font_size_label) # font.setBold(self._font_bold_label) # label_upd_rate_unit.setFont(font) # Construct the layout. # grid_settings.addWidget(label_upd_rate, 0, 0, 1, 3) # grid_settings.addWidget(self.spinbox_upd_img_interval, 0, 3) # grid_settings.addWidget(label_upd_rate_unit, 0, 4) ### Function buttons. group_func = QGroupBox(self) group_func.setTitle("Function") font = group_func.font() font.setPointSize(self._font_size_groupbox_title) group_func.setFont(font) group_func.resize(400, 100) grid_func = QGridLayout(group_func) grid_func.setSpacing(10) # Start/Stop main process button. self.brun = QPushButton(group_func) self.brun.setText("Start") font = self.brun.font() font.setPointSize(self._font_size_button) self.brun.setFont(font) self.brun.resize(400, 50) self.brun.setStyleSheet("background-color:{};".format( self._init_button_color)) self.brun.clicked.connect(self.runMainProcess) # Clear data button. bclear = QPushButton(group_func) bclear.setText("Clear") font = bclear.font() font.setPointSize(self._font_size_button) bclear.setFont(font) bclear.resize(400, 50) bclear.setStyleSheet("background-color:{};".format( self._init_button_color)) bclear.clicked.connect(self.clearData) # Save images button. bsave = QPushButton(group_func) bsave.setText("Save") font = bsave.font() font.setPointSize(self._font_size_button) bsave.setFont(font) bsave.resize(400, 50) bsave.setStyleSheet("background-color:{};".format( self._init_button_color)) bsave.clicked.connect(self.saveData) # New window button. bwindow = QPushButton(group_func) bwindow.setText("Window") font = bwindow.font() font.setPointSize(self._font_size_button) bwindow.setFont(font) bwindow.resize(400, 50) bwindow.setStyleSheet("background-color:{};".format( self._init_button_color)) bwindow.clicked.connect(self.showWindow) # Construct the layout of RunInfo groupbox. grid_func.addWidget(self.brun, 0, 0) grid_func.addWidget(bclear, 0, 1) grid_func.addWidget(bsave, 1, 0) grid_func.addWidget(bwindow, 1, 1) ### Plotting area. grp1 = QGroupBox(self) # grp1.setTitle("SIG WL") grp1.setTitle("SIG") font = grp1.font() font.setPointSize(self._font_size_groupbox_title) grp1.setFont(font) gp1 = QGridLayout(grp1) gp1.setSpacing(10) grp2 = QGroupBox(self) # grp2.setTitle("SIG WOL") grp2.setTitle("BG") font = grp2.font() font.setPointSize(self._font_size_groupbox_title) grp2.setFont(font) gp2 = QGridLayout(grp2) gp2.setSpacing(10) grp3 = QGroupBox(self) # grp3.setTitle("BG WL") grp3.setTitle("SIg - BG") font = grp3.font() font.setPointSize(self._font_size_groupbox_title) grp3.setFont(font) gp3 = QGridLayout(grp3) gp3.setSpacing(10) # grp4 = QGroupBox(self) # grp4.setTitle("BG WOL") # font = grp4.font() # font.setPointSize(self._font_size_groupbox_title) # grp4.setFont(font) # gp4 = QGridLayout(grp4) # gp4.setSpacing(10) kwargs = dict(px=False, py=False, ph=False, bp=False) self.pw1 = PlotWindow(self, **kwargs) self.pw2 = PlotWindow(self, **kwargs) self.pw3 = PlotWindow(self, **kwargs) # self.pw4 = PlotWindow(self, **kwargs) gp1.addWidget(self.pw1, 0, 0) gp2.addWidget(self.pw2, 0, 0) gp3.addWidget(self.pw3, 0, 0) # gp4.addWidget(self.pw4, 0, 0) ### Construct the layout. self.grid.addWidget(group_runinfo, 0, 0) # self.grid.addWidget(group_settings, 0, 1) self.grid.addWidget(group_func, 0, 1) self.grid.addWidget(grp1, 1, 0, 2, 1) self.grid.addWidget(grp2, 1, 1, 2, 1) self.grid.addWidget(grp3, 1, 2, 2, 1) # self.grid.addWidget(grp4, 1, 3, 2, 1) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) @footprint def initMainWidget(self): """ Initialize the main widget and the grid. """ self.main_widget = QWidget(self) self.setStyleSheet("background-color:{};".format(self.main_bgcolor)) self.grid = QGridLayout(self.main_widget) self.grid.setSpacing(10) self.setWindowIcon( QIcon(os.path.join(os.path.dirname(__file__), "python.png"))) @footprint def setMenuBar(self): """ Set the contents of the menu bar """ ## File file_menu = QMenu('&File', self) # Open # file_menu.addAction('&Open', self.openFile, # QtCore.Qt.CTRL + QtCore.Qt.Key_O) # Config file_menu.addAction('&Config', self.setConfig, QtCore.Qt.CTRL + QtCore.Qt.Key_C) # Quit file_menu.addAction('&Quit', self.quitApp, QtCore.Qt.CTRL + QtCore.Qt.Key_Q) self.menuBar().addMenu(file_menu) ## Help # help_menu = QMenu('&Help', self) # help_menu.addAction('Help', self.showHelp) # help_menu.addAction('About...', self.showAbout) self.menuBar().addSeparator() # self.menuBar().addMenu(help_menu) ######################## Menu bar ######################## @footprint def openFile(self): """ Show a file dialog and select a file """ pass @footprint def setConfig(self): """ Set configuration of this application. """ pass @footprint def quitApp(self): """ Quit this application. """ self.close() @footprint def showHelp(self): """ Show a pop-up dialog showing how to use this application. """ pass @footprint def showAbout(self): """ Show a pop-up dialog describing this application. """ pass ######################## Widgets' functions ######################## @footprint @pyqtSlot() def showWindow(self): window = PlotWindow(self, "win{0:02d}".format(len(self._windows) + 1)) window.show() window.raise_() window.activateWindow() self._windows.append(window) @footprint @pyqtSlot() def runMainProcess(self): if not self._timer_getData.isActive(): self.initData() for listener in self._worker_getData.listeners.values(): listener.Connect() self._worker_getData.listener_info.Connect() # self._update_image_interval = self.spinbox_upd_img_interval.value() # self.spinbox_upd_img_interval.setEnabled(False) self._timer_getData.start() self.brun.setText("Stop") if not self._timer_updImage.isActive(): time.sleep(self._get_update_delay) self._timer_updImage.start() else: self.brun.setEnabled(False) self.stopTimer = True @footprint @pyqtSlot() def saveData(self): now_save = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") now = datetime.datetime.now().strftime("%Y%m%d%H%M%S") saveDataDir = os.path.join(os.path.dirname(__file__), "data", "Run{}".format(str(self.currentRun))) # Data. if not os.path.exists(saveDataDir): os.makedirs(saveDataDir) for _types in self._get_data_ports.keys(): np.save(os.path.join(saveDataDir, "data_{0}_{1}.npy".format(now, _types)), \ self.dataset[_types]) # Image. # saveScn = os.path.join(saveDataDir, "{}_screenshot.png".format(now)) # QPixmap.grabWindow(self.winId()).save(saveScn, 'png') # Status. status = { "save_datetime": now_save, "Run": self.label_run_number.text(), "StartTag": self.label_tag_start.text(), "CurrentTag": self.label_tag_end.text() } with open(os.path.join(saveDataDir, "{}_status.json".format(now)), "w") as ff: json.dump(status, ff) @footprint @pyqtSlot() def clearData(self): self.saveData() self.initData() ######################## GetDataProcess ######################## @footprint def initGetDataProcess(self): self._timer_getData = QTimer() self._timer_getData.setInterval(int(self._get_data_interval * 1000)) self.stopTimer = False self._thread_getData = QThread() self._worker_getData = GetDataWorker3(port=self._get_data_ports, port_info=self._get_info_port) self._worker_getData.sleepInterval = self._get_data_worker_sleep_interval # Start. self._timer_getData.timeout.connect(self.startGettingDataThread) self._thread_getData.started.connect(self._worker_getData.process) self._worker_getData.do_something.connect(self.updateData) # Finish. self._worker_getData.finished.connect(self._thread_getData.quit) self._thread_getData.finished.connect(self.checkIsTimerStopped) # Move. self._worker_getData.moveToThread(self._thread_getData) @footprint @pyqtSlot() def startGettingDataThread(self): if not self._thread_getData.isRunning(): print("start thread by timer.") self._thread_getData.start() else: print("Thread is running.") @footprint @pyqtSlot(object) def updateData(self, obj): if self._isUpdatingImage is False: # In case. if obj is not None: for key in self.dataset.keys(): if self.dataset.get(key) is None and obj.get( key) is not None: self.dataset[key] = obj.get(key).copy() elif obj.get(key) is not None: self.dataset[key] += obj.get(key).copy() currentRun = obj.get("currentRun") self.label_run_number.setText(str(currentRun)) if self.nbr_of_sig == 0: self.label_tag_start.setText(str(obj.get("startTag"))) self.label_tag_end.setText(str(obj.get("endTag"))) self.nbr_of_sig += obj.get("nbr_sig_wl") + obj.get( "nbr_sig_wol") self.nbr_of_bg += obj.get("nbr_bg_wl") + obj.get("nbr_bg_wol") self.label_nbr_of_sig.setText(str(self.nbr_of_sig)) self.label_nbr_of_bg.setText(str(self.nbr_of_bg)) if self.currentRun != -1 and currentRun != self.currentRun: self.saveData() self.initData() self.currentRun = currentRun @footprint @pyqtSlot() def checkIsTimerStopped(self): if self.stopTimer: self._timer_getData.stop() self._timer_updImage.stop() print("timer stopped.") for listener in self._worker_getData.listeners.values(): listener.Close() self._worker_getData.listener_info.Close() self.stopTimer = False self.brun.setEnabled(True) self.brun.setText("Start") # self.spinbox_upd_img_interval.setEnabled(True) ######################## updateImageProcess ######################## @footprint def initUpdateImageProcess(self): self._timer_updImage = QTimer() self._timer_updImage.setInterval( int(self._update_image_interval * 1000)) self._timer_updImage.timeout.connect(self.updateImage) @footprint def updateImage(self): self._isUpdatingImage = True try: with QMutexLocker(self._mutex): sig_wl = self.dataset.get("sig_wl", None) sig_wol = self.dataset.get("sig_wol", None) bg_wl = self.dataset.get("bg_wl", None) bg_wol = self.dataset.get("bg_wol", None) if self.sig is None or self.bg is None: self.sig = sig_wl + sig_wol self.bg = bg_wl + bg_wol else: self.sig += sig_wl + sig_wol self.bg += bg_wl + bg_wol # print(self.sig.dtype) # buff1 = self.sig / float(self.nbr_of_sig) self.pw1.data = self.sig / float(self.nbr_of_sig) # buff1 = self.bg / float(self.nbr_of_bg) self.pw2.data = self.bg / float(self.nbr_of_bg) self.pw3.data = self.pw1.data - self.pw2.data # self.pw4.data = bg_wol # if sig_wl is not None and sig_wol is not None: # self.pw3.data = sig_wl - sig_wol for window in self._windows: if not window.is_closed: window.data = sig_wl except Exception as ex: print(ex) self._isUpdatingImage = False if self.sig is not None and self.bg is not None: self.pw1.updateImage() self.pw2.updateImage() self.pw3.updateImage() # self.pw4.updateImage() ######################## CheckWindowProcess ######################## @footprint def initCheckWindowProcess(self): """ Initialize checkWindow process. """ self._timer_checkWindow = QTimer() self._timer_checkWindow.setInterval( int(self._check_window_interval * 1000)) self._timer_checkWindow.timeout.connect(self.checkWindow) self._timer_checkWindow.start() # @footprint @pyqtSlot() def checkWindow(self): """ Check whether windows are active. """ # print(len(self._windows)) N = len(self._windows) * 1 for ii in range(N): if self._windows[N - ii - 1].is_closed: del self._windows[N - ii - 1] # @footprint # @pyqtSlot() # def finishWorker(self): # pass ######################## Closing processes ######################## @footprint def closeEvent(self, event): if self._thread_getData.isRunning(): string = "Some threads are still running.\n" string += "Please wait for their finishing." confirmObject = QMessageBox.warning(self, "Closing is ignored.", string, QMessageBox.Ok) event.ignore() return if self._closing_dialog: confirmObject = QMessageBox.question( self, "Closing...", "Are you sure to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if confirmObject == QMessageBox.Yes: self.makeConfig() with open( os.path.join(os.path.dirname(__file__), "config.json"), "w") as ff: json.dump(self.config, ff) self.stopAllTimers() self.saveData() event.accept() else: event.ignore() else: self.makeConfig() with open(os.path.join(os.path.dirname(__file__), "config.json"), "w") as ff: json.dump(self.config, ff, indent=4) self.saveData() self.stopAllTimers() @footprint def stopAllTimers(self): if self._timer_getData.isActive(): self._timer_getData.stop() if self._timer_updImage.isActive(): self._timer_updImage.stop() if self._timer_checkWindow.isActive(): self._timer_checkWindow.stop() @footprint def makeConfig(self): """ Make a config dict object to save the latest configration in. """ self.config = OrderedDict([ ("online", self._online), ("closing_dialog", self._closing_dialog), ("currentDir", self._currentDir), ("emulate", self._emulate), ("font_size_button", self._font_size_button), ("font_size_label", self._font_size_label), ("font_size_groupbox_title", self._font_size_groupbox_title) ])
def initGui(self): """ Initialize the GUI. """ self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.initMainWidget() self.setMenuBar() self.setWindowTitle("VMI Viewer") self.resize(self._init_window_width, self._init_window_height) ### RunInfo. group_runinfo = QGroupBox(self) group_runinfo.setTitle("RunInfo") font = group_runinfo.font() font.setPointSize(self._font_size_groupbox_title) group_runinfo.setFont(font) group_runinfo.resize(400, 100) grid_runinfo = QGridLayout(group_runinfo) # Run No. label_run = QLabel(self) label_run.setText("Run No. : ") label_run.setAlignment(Qt.AlignRight) font = label_run.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_run.setFont(font) self.label_run_number = QLabel(self) self.label_run_number.setText("Unknown") pal = QPalette() pal.setColor(QPalette.Foreground, QColor("#0B5345")) self.label_run_number.setPalette(pal) font = self.label_run_number.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_run_number.setFont(font) # Tag No. label_tag = QLabel(self) label_tag.setText("Tag No. : ") label_tag.setAlignment(Qt.AlignRight) font = label_tag.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_tag.setFont(font) self.label_tag_start = QLabel(self) self.label_tag_start.setText("None") font = self.label_tag_start.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_tag_start.setFont(font) label_tag_hyphen = QLabel(self) label_tag_hyphen.setText(" - ") label_tag_hyphen.setFixedWidth(30) font = label_tag_hyphen.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_tag_hyphen.setFont(font) self.label_tag_end = QLabel(self) self.label_tag_end.setText("None") font = self.label_tag_end.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_tag_end.setFont(font) # Sig / BG. label_sig = QLabel(self) label_sig.setText("# of Sig : ") label_sig.setAlignment(Qt.AlignRight) font = label_sig.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_sig.setFont(font) self.label_nbr_of_sig = QLabel(self) self.label_nbr_of_sig.setText("None") font = self.label_nbr_of_sig.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_nbr_of_sig.setFont(font) label_bg = QLabel(self) label_bg.setText("# of BG : ") label_bg.setAlignment(Qt.AlignRight) font = label_bg.font() font.setPointSize(self._font_size_label) font.setBold(self._font_bold_label) label_bg.setFont(font) self.label_nbr_of_bg = QLabel(self) self.label_nbr_of_bg.setText("None") font = self.label_nbr_of_bg.font() font.setBold(True) font.setPointSize(self._font_size_label) self.label_nbr_of_bg.setFont(font) # Construct the layout. grid_runinfo.addWidget(label_run, 0, 0) grid_runinfo.addWidget(self.label_run_number, 0, 1, 1, 3) grid_runinfo.addWidget(label_tag, 1, 0) grid_runinfo.addWidget(self.label_tag_start, 1, 1) grid_runinfo.addWidget(label_tag_hyphen, 1, 2) grid_runinfo.addWidget(self.label_tag_end, 1, 3) grid_runinfo.addWidget(label_sig, 2, 0) grid_runinfo.addWidget(self.label_nbr_of_sig, 2, 1) grid_runinfo.addWidget(label_bg, 2, 2) grid_runinfo.addWidget(self.label_nbr_of_bg, 2, 3) ### Settings. # group_settings = QGroupBox(self) # group_settings.setTitle("Settings") # font = group_settings.font() # font.setPointSize(self._font_size_groupbox_title) # group_settings.setFont(font) # group_settings.resize(400, 100) # grid_settings = QGridLayout(group_settings) # # Update interval. # label_upd_rate = QLabel(self) # label_upd_rate.setText("Upd. image interval: ") # font = label_upd_rate.font() # font.setPointSize(self._font_size_label) # font.setBold(self._font_bold_label) # label_upd_rate.setFont(font) # self.spinbox_upd_img_interval = QDoubleSpinBox(self) # self.spinbox_upd_img_interval.setValue(self._get_data_interval) # self.spinbox_upd_img_interval.setFixedWidth(100) # self.spinbox_upd_img_interval.setAlignment(Qt.AlignRight) # font = self.spinbox_upd_img_interval.font() # font.setBold(True) # font.setPointSize(self._font_size_label) # self.spinbox_upd_img_interval.setFont(font) # label_upd_rate_unit = QLabel(self) # label_upd_rate_unit.setText("sec") # font = label_upd_rate_unit.font() # font.setPointSize(self._font_size_label) # font.setBold(self._font_bold_label) # label_upd_rate_unit.setFont(font) # Construct the layout. # grid_settings.addWidget(label_upd_rate, 0, 0, 1, 3) # grid_settings.addWidget(self.spinbox_upd_img_interval, 0, 3) # grid_settings.addWidget(label_upd_rate_unit, 0, 4) ### Function buttons. group_func = QGroupBox(self) group_func.setTitle("Function") font = group_func.font() font.setPointSize(self._font_size_groupbox_title) group_func.setFont(font) group_func.resize(400, 100) grid_func = QGridLayout(group_func) grid_func.setSpacing(10) # Start/Stop main process button. self.brun = QPushButton(group_func) self.brun.setText("Start") font = self.brun.font() font.setPointSize(self._font_size_button) self.brun.setFont(font) self.brun.resize(400, 50) self.brun.setStyleSheet("background-color:{};".format( self._init_button_color)) self.brun.clicked.connect(self.runMainProcess) # Clear data button. bclear = QPushButton(group_func) bclear.setText("Clear") font = bclear.font() font.setPointSize(self._font_size_button) bclear.setFont(font) bclear.resize(400, 50) bclear.setStyleSheet("background-color:{};".format( self._init_button_color)) bclear.clicked.connect(self.clearData) # Save images button. bsave = QPushButton(group_func) bsave.setText("Save") font = bsave.font() font.setPointSize(self._font_size_button) bsave.setFont(font) bsave.resize(400, 50) bsave.setStyleSheet("background-color:{};".format( self._init_button_color)) bsave.clicked.connect(self.saveData) # New window button. bwindow = QPushButton(group_func) bwindow.setText("Window") font = bwindow.font() font.setPointSize(self._font_size_button) bwindow.setFont(font) bwindow.resize(400, 50) bwindow.setStyleSheet("background-color:{};".format( self._init_button_color)) bwindow.clicked.connect(self.showWindow) # Construct the layout of RunInfo groupbox. grid_func.addWidget(self.brun, 0, 0) grid_func.addWidget(bclear, 0, 1) grid_func.addWidget(bsave, 1, 0) grid_func.addWidget(bwindow, 1, 1) ### Plotting area. grp1 = QGroupBox(self) # grp1.setTitle("SIG WL") grp1.setTitle("SIG") font = grp1.font() font.setPointSize(self._font_size_groupbox_title) grp1.setFont(font) gp1 = QGridLayout(grp1) gp1.setSpacing(10) grp2 = QGroupBox(self) # grp2.setTitle("SIG WOL") grp2.setTitle("BG") font = grp2.font() font.setPointSize(self._font_size_groupbox_title) grp2.setFont(font) gp2 = QGridLayout(grp2) gp2.setSpacing(10) grp3 = QGroupBox(self) # grp3.setTitle("BG WL") grp3.setTitle("SIg - BG") font = grp3.font() font.setPointSize(self._font_size_groupbox_title) grp3.setFont(font) gp3 = QGridLayout(grp3) gp3.setSpacing(10) # grp4 = QGroupBox(self) # grp4.setTitle("BG WOL") # font = grp4.font() # font.setPointSize(self._font_size_groupbox_title) # grp4.setFont(font) # gp4 = QGridLayout(grp4) # gp4.setSpacing(10) kwargs = dict(px=False, py=False, ph=False, bp=False) self.pw1 = PlotWindow(self, **kwargs) self.pw2 = PlotWindow(self, **kwargs) self.pw3 = PlotWindow(self, **kwargs) # self.pw4 = PlotWindow(self, **kwargs) gp1.addWidget(self.pw1, 0, 0) gp2.addWidget(self.pw2, 0, 0) gp3.addWidget(self.pw3, 0, 0) # gp4.addWidget(self.pw4, 0, 0) ### Construct the layout. self.grid.addWidget(group_runinfo, 0, 0) # self.grid.addWidget(group_settings, 0, 1) self.grid.addWidget(group_func, 0, 1) self.grid.addWidget(grp1, 1, 0, 2, 1) self.grid.addWidget(grp2, 1, 1, 2, 1) self.grid.addWidget(grp3, 1, 2, 2, 1) # self.grid.addWidget(grp4, 1, 3, 2, 1) self.main_widget.setFocus() self.setCentralWidget(self.main_widget)
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 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 __init__(self, parent=None): QWidget.__init__(self, parent) self.setFixedSize(500, 400) self.setStyleSheet('background-color: #ffffdd;') topLine = QFrame() topLine.setFrameShape(QFrame.HLine) topLine.setLineWidth(2) botLine = QFrame() botLine.setFrameShape(QFrame.HLine) botLine.setLineWidth(2) title = QLabel('CCB') title.setAlignment(Qt.AlignCenter) font = title.font() font.setPointSize(72) font.setWeight(QFont.Bold) title.setFont(font) subTitle = QLabel('Coriolis & Chams Builder for the Dummies') subTitle.setAlignment(Qt.AlignCenter) subTitle.setFont(QFont('Courier', 10, QFont.Bold)) authors = QLabel('Coriolis CAD System 1.0 . . . . . . . . ccb 1.0\n' 'Copyright (c) 2008-2016 . . . . . . . . . . UPMC\n' 'Authors . . . . . . . . . . . . . Damien Dupuis\n' ' . . . . . . . . . . . . Jean-Paul Chaput\n' 'E-Mail . . . . . . . . [email protected]') authors.setAlignment(Qt.AlignCenter) authors.setFont(QFont('Courier', 10, QFont.Bold)) vLayout = QVBoxLayout() vLayout.addStretch(10) vLayout.addWidget(topLine) vLayout.addWidget(title) vLayout.addStretch(1) vLayout.addWidget(subTitle) vLayout.addWidget(authors) vLayout.addStretch(1) vLayout.addWidget(botLine) vLayout.addStretch(10) frame = QFrame() frame.setFrameShape(QFrame.Box) frame.setFrameShadow(QFrame.Sunken) frame.setLayout(vLayout) frame.setLineWidth(1) vLayout = QVBoxLayout() vLayout.addWidget(frame) self.setLayout(vLayout) self._exitAction = QAction('&Exit', self) self._exitAction.setStatusTip('Exit CCB (settings are saved)') self._exitAction.setShortcut(QKeySequence('CTRL+Q')) self._exitAction.triggered.connect(QApplication.closeAllWindows) self.addAction(self._exitAction) self._closeAction = QAction('&Close', self) self._closeAction.setStatusTip('Close the About Window') self._closeAction.setShortcut(QKeySequence('CTRL+A')) self._closeAction.triggered.connect(self.close) self.addAction(self._closeAction) return
class CImprovedButton(QToolButton): def __init__(self, parent=None): QToolButton.__init__(self, parent) #TESTO ALTERNATIVO #Spesso se il pulsante ha icona troppo grossa e quando per ragioni di spazio o altro non si può spostare #o ridimensionare il pulsante stesso, la label ha posizioni assurde e schifose. Aggiungerne una "+ controllabile" #è l'unico modo.. self.__fixed_label = QLabel("alternative label", self) self.__fixed_label.move(0, self.geometry().height() - 35) self.__fixed_label.resize(self.geometry().width(), self.__fixed_label.geometry().height()) self.__fixed_label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) self.__font = QtGui.QFont("Arial", 10) self.__fixed_label.setFont(self.__font) self.__fixed_label.show() #INDICATORE STILE iOS self.__indicator = QLabel("0", self) self.__indicator.setStyleSheet("border-image: url(':/images/backgrounds/indicator.png'); padding-right:1px; color: white;") self.__indicator.geometry().setWidth(25) self.__indicator.geometry().setHeight(20) self.__indicator.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) self.__indicator.setVisible(False) self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0)) #default top-right corner #Quando il pulsante viene ridimensionato (designer o meno) devo anche sistemare la label di conseguenza self.resizeEvent = self.__onResize self.__indicator.resizeEvent = self.__on_indicator_Resize self.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) self.clicked.connect(self.stopAllAnimations) #BLINK self.__blink_timer = QTimer(parent) self.__blink_timer.timeout.connect(self.__on_blink_timer) self.__blink_timer_interval = 1000 #FADING self.__opacity_effect = QGraphicsOpacityEffect() self.__fading_timer = QTimer(parent) self.__fading_timer.timeout.connect(self.__on_fading_timer) self.__FADE_TYPE = Enum("IN", "OUT") self.__fade_time = 20 self.__opacity = 1.0 self.__opacity_fading_coefficient = 0.02 self.__selected_fade_type = self.__FADE_TYPE.IN # ANIMAZIONI GROW self.__animationGrow = QPropertyAnimation(self, "iconSize", self) self.__animationGrow.setDuration(1000) self.__animationGrow.setEasingCurve(QEasingCurve.Linear) self.__animationGrow.finished.connect(self.__on_growed) self.__animationShrink = QPropertyAnimation(self, "iconSize", self) self.__animationShrink.setDuration(1000) self.__animationShrink.setEasingCurve(QEasingCurve.Linear) self.__animationShrink.finished.connect(self.__on_shrinked) self.__defaultIconDimension = 60 self.__iconGrowsBy = 40 self.__growing = False # ANIMAZIONI BOUNCE self.__animationUp = QPropertyAnimation(self, "pos", self) self.__animationUp.setDuration(200) self.__animationUp.setEasingCurve(QEasingCurve.Linear) self.__animationUp.finished.connect(self.__on_top_reached) self.__animationBounce = QPropertyAnimation(self, "pos", self) self.__animationBounce.setDuration(1000) self.__animationBounce.setEasingCurve(QEasingCurve.OutBounce) self.__animationBounce.finished.connect(self.__on_bounce_finished) self.__bouncing = False self.__startPos = QPoint(self.pos().x(), self.pos().y()) #PIXMAP & MASCHERA self.__pmap = QPixmap(self.size()) self.__pmap_fname = "" self.__show_mask_preview = False def setDefaultIconSize(self, value): """ Sets default icon size when growing stops. @param value: size (both width and height) @type value: int """ self.__defaultIconDimension = value def getDefaultIconSize(self): return self.__defaultIconDimension defaultIconSize = QtCore.pyqtProperty("int", getDefaultIconSize, setDefaultIconSize) def setFixetTextVisibility(self, bool): """ Sets if fixed text is visible or not. @param bool: visible or not @type bool: bool """ self.__fixed_label.setVisible(bool) def getFixetTextVisibility(self): return self.__fixed_label.isVisible() fixetTextVisibility = QtCore.pyqtProperty("bool", fget=getFixetTextVisibility, fset=setFixetTextVisibility) def setFixedText(self, txt): """ Sets text on the button. @param txt: text @type txt: string """ self.__fixed_label.setText(txt) def getFixedText(self): return self.__fixed_label.text() fixedText = QtCore.pyqtProperty("QString", getFixedText, setFixedText) def setFixedTextPos(self, qpoint): """ Sets text position in the button. @param qpoint: Position RELATIVE. 0,0 is top left corner of the button. @type qpoint: QPoint """ self.__fixed_label.move(qpoint) def getFixedTextPos(self): return self.__fixed_label.pos() fixedTextPos = QtCore.pyqtProperty("QPoint", getFixedTextPos, setFixedTextPos) def setFixedTextFont(self, font): """ Sets text font. @param font: Font for fixed text. @type font: QFont """ self.__font = font self.__fixed_label.setFont(self.__font) def getFixedTextFont(self): return self.__font fixedTextFont = QtCore.pyqtProperty("QFont", getFixedTextFont, setFixedTextFont) #FUNZIONI INDICATORE def setIndicatorVisibility(self, bool): """ Sets if indicator is visible or not. @param bool: visible or not @type bool: bool """ self.__indicator.setVisible(bool) def getIndicatorVisibility(self): return self.__indicator.isVisible() indicatorVisibility = QtCore.pyqtProperty("bool", fget=getIndicatorVisibility, fset=setIndicatorVisibility) def setIndicatorPos(self, qpoint): """ Sets indicator position in the button. @param qpoint: Position RELATIVE. 0,0 is top left corner of the button. @type qpoint: QPoint """ self.__indicator.move(qpoint) def getIndicatorPos(self): return self.__indicator.pos() indicatorPos = QtCore.pyqtProperty("QPoint", getIndicatorPos, setIndicatorPos) def setIndicatorSize(self, size): """ Sets indicator size. @param size: Size @type size: QSize """ self.__indicator.resize(size) def getIndicatorSize(self): return self.__indicator.size() indicatorSize = QtCore.pyqtProperty("QSize", getIndicatorSize, setIndicatorSize) def setIndicatorFont(self, font): """ Sets indicator text font. @param font: Font for indicator text. @type font: QFont """ self.__indicator.setFont(font) def getIndicatorFont(self): return self.__indicator.font() indicatorFont = QtCore.pyqtProperty("QFont", getIndicatorFont, setIndicatorFont) ## FUNZIONI PER BLINK def __on_blink_timer(self): self.setVisible(not (self.isVisible())) def setBlinking(self, blink): """ Sets if the button have to blink or not. @param blink: blinking or not @type blink: bool """ if blink: self.__blink_timer.setInterval(self.__blink_timer_interval) self.__blink_timer.start() else: self.__blink_timer.stop() self.setVisible(True) def setBlinkInterval(self, value): """ Sets blink interval. @param blink: blink interval (msec) @type blink: int """ self.__blink_timer_interval = value def getBlinkInterval(self): return self.__blink_timer_interval blinkInterval = QtCore.pyqtProperty("int", getBlinkInterval, setBlinkInterval) ##FUNZIONI PER FADING def fadeIn(self): """ Button fades in from completely invisible to completely visible. """ self.__opacity = 0.0 self.__selected_fade_type = self.__FADE_TYPE.IN self.__fading_timer.start(self.__fade_time) def fadeOut(self): """ Button fades out from completely visible to completely invisible. """ self.__selected_fade_type = self.__FADE_TYPE.OUT self.__fading_timer.start(self.__fade_time) def setFadeTime(self, value): """ Sets fading time. Everytime interval is reached, alpha is increased (or decreased) by __opacity_fading_coefficient. @param value: fade time (msec) @type value: int """ self.__fade_time = value def getFadeTime(self): return self.__fade_time fadeInterval = QtCore.pyqtProperty("int", getFadeTime, setFadeTime) def setFadeCoefficient(self, value): """ Sets fading coefficient. Alpha is increased (or decreased) by this value. @param value: coefficient (min 0.0 - max 1.0) @type value: float """ self.__opacity_fading_coefficient = value def getFadeCoefficient(self): return self.__opacity_fading_coefficient fadeCoefficient = QtCore.pyqtProperty("double", getFadeCoefficient, setFadeCoefficient) def __on_fading_timer(self): if self.__selected_fade_type == self.__FADE_TYPE.OUT: if self.__opacity > 0: self.__opacity -= self.__opacity_fading_coefficient self.__opacity_effect.setOpacity(self.__opacity) self.setGraphicsEffect(self.__opacity_effect) else: self.__fading_timer.stop() if self.__selected_fade_type == self.__FADE_TYPE.IN: if self.__opacity <= 1.0: self.__opacity += self.__opacity_fading_coefficient self.__opacity_effect.setOpacity(self.__opacity) self.setGraphicsEffect(self.__opacity_effect) else: self.__fading_timer.stop() # FUNZIONI PER GROW\SHRINK def __on_growed(self): self.__animationShrink.setStartValue(QSize(self.iconSize().width(), self.iconSize().height())) self.__animationShrink.setEndValue( QSize(self.iconSize().width() - self.__iconGrowsBy, self.iconSize().height() - self.__iconGrowsBy)) self.__animationShrink.start() def __on_shrinked(self): self.__animationGrow.setStartValue(QSize(self.iconSize().width(), self.iconSize().height())) self.__animationGrow.setEndValue( QSize(self.iconSize().width() + self.__iconGrowsBy, self.iconSize().height() + self.__iconGrowsBy)) self.__animationGrow.start() def startGrow(self): """ Button ICON starts to grow and shrink to standard value when maximum size (configured) is reached """ if self.__growing: return self.__animationGrow.setStartValue(QSize(self.iconSize().width(), self.iconSize().height())) self.__animationGrow.setEndValue( QSize(self.iconSize().width() + self.__iconGrowsBy, self.iconSize().height() + self.__iconGrowsBy)) self.__animationGrow.start() self.__growing = True def stopGrow(self): if self.__animationGrow.startValue().toSize() != QSize(0, 0) and self.__animationShrink.startValue().toSize() != QPoint( 0, 0): self.__animationGrow.stop() self.__animationShrink.stop() self.setIconSize(QSize(self.__defaultIconDimension, self.__defaultIconDimension)) self.__growing = False #FUNZIONI PER BOUNCE def startBounce(self): """ Button starts to bounce requiring attention. """ if self.__bouncing: return self.__startPos = QPoint(self.pos().x(), self.pos().y()) self.__animationUp.setStartValue(QPoint(self.__startPos.x(), self.__startPos.y())) self.__animationUp.setEndValue(QPoint(self.__startPos.x(), self.__startPos.y() - self.geometry().height())) self.__animationUp.start() self.__bouncing = True def stopBounce(self): if self.__animationUp.startValue().toPoint() != QPoint(0,0) and self.__animationBounce.startValue().toPoint() != QPoint(0,0): self.__animationBounce.stop() self.__animationUp.stop() self.setGeometry(self.__startPos.x(), self.__startPos.y(), self.geometry().width(), self.geometry().height()) self.__bouncing = False def __on_top_reached(self): self.__animationBounce.setStartValue(QPoint(self.pos().x(), self.pos().y())) self.__animationBounce.setEndValue(QPoint(self.__startPos.x(), self.__startPos.y())) self.__animationBounce.start() def __on_bounce_finished(self): self.__animationUp.start() def stopAllAnimations(self): self.stopBounce() self.stopGrow() #FUNZIONI PER PIXMAP & MASCHERA def setPixmapFile(self, image_file): self.__pmap = image_file self.__pmap.scaled(self.size()) #NB: Il pixmap deve essere BIANCO e NERO. Con heuristicMask il primo pixel in alto a sinistra (0,0) viene #usato per decidere il colore trasparente, tutto il resto è visibile. def getPixmapFile(self): return self.__pmap pixmapFile = QtCore.pyqtProperty("QPixmap", getPixmapFile, setPixmapFile) def applyMask(self, bool): self.__show_mask_preview = bool if bool: self.setMask(QBitmap(self.__pmap.createHeuristicMask().scaled(self.size()))) else: self.setMask(QBitmap()) def getMask(self): return self.__show_mask_preview appliedMask = QtCore.pyqtProperty("bool", fget=getMask, fset=applyMask) def __onResize(self, event): self.__fixed_label.move(0, self.geometry().height() - 35) self.__fixed_label.resize(self.geometry().width(), self.__fixed_label.geometry().height()) self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0)) self.__pmap.scaled(self.size()) if self.__show_mask_preview: self.setMask(QBitmap(self.__pmap.createHeuristicMask().scaled(self.size()))) def __on_indicator_Resize(self, event): self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0))
class TempoAdjuster(QWidget): tempo = 140.0 factor = 75.0 format = '%0.3fbpm' slide_factor = 100.0 slide_interval = 25 slide_step = .15 def __init__(self, parent=None): QWidget.__init__(self, parent) Layout = QVBoxLayout(self) Layout.setMargin(0) Layout.setSpacing(5) self._block_emit = False self.actualLabel = QLabel(self) self.actualLabel.setFixedHeight(25) font = self.actualLabel.font() font.setPointSize(20) self.actualLabel.setFont(font) self.actualLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) Layout.addWidget(self.actualLabel) self.slideLabel = QLabel(self) self.slideLabel.setFixedHeight(25) font = self.slideLabel.font() font.setPointSize(20) self.slideLabel.setFont(font) self.slideLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) Layout.addWidget(self.slideLabel) self.adjuster = Adjuster(self) base = QColor(Adjuster.diff_brush) base.setAlpha(100) self.adjuster.palette().setColor(QPalette.Window, base) Layout.addWidget(self.adjuster) QObject.connect(self.adjuster, SIGNAL('moved_x(int)'), self.adjust) QObject.connect(self.adjuster, SIGNAL('moved_y(int)'), self.set_slide_tempo) QObject.connect(self.adjuster, SIGNAL('released'), self.start_slide) self._slide_tempo = self.tempo self._slide_timer = QTimer(self) QObject.connect(self._slide_timer, SIGNAL('timeout()'), self.do_slide) self.adjust(0.0) def set_slide_tempo(self, delta): delta *= -1 self._slide_tempo += delta / self.slide_factor self.slideLabel.setText(self.format % self._slide_tempo) self.emit(SIGNAL('tempo(float)'), self._slide_tempo) def start_slide(self): if self._slide_tempo != self.tempo: if self._slide_timer.isActive(): self._slide_timer.stop() self.do_slide() self._slide_timer.start(self.slide_interval) self.emit(SIGNAL('tempo(float)'), self._slide_tempo) def do_slide(self): if self._slide_tempo > self.tempo: self._slide_tempo -= self.slide_step if self._slide_tempo < self.tempo: self._slide_tempo = self.tempo elif self._slide_tempo < self.tempo: self._slide_tempo += self.slide_step if self._slide_tempo > self.tempo: self._slide_tempo = self.tempo self.slideLabel.setText(self.format % self._slide_tempo) self.emit(SIGNAL('tempo(float)'), self._slide_tempo) if self._slide_tempo == self.tempo: self._slide_timer.stop() def set_tempo(self, tempo, emit=True): self.tempo = tempo self._block_emit = True self.adjust(0.0) self._block_emit = False def adjust(self, delta): self.tempo += delta / self.factor self._slide_tempo = self.tempo self.actualLabel.setText(self.format % self.tempo) self.slideLabel.setText(self.format % self._slide_tempo) if self._block_emit is False: self.emit(SIGNAL('tempo(float)'), self.tempo)
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 PlotScalesWidget(QWidget): plotScaleChanged = pyqtSignal() def __init__(self, type_key, title, select_min_time_value=False): QWidget.__init__(self) self.__type_key = type_key self.__type = None self.__double_spinner = self.createDoubleSpinner(minimum=-999999999.0, maximum=999999999.0) self.__integer_spinner = self.createIntegerSpinner(minimum=0, maximum=999999999) self.__time_map = ReportStepsModel().getList() self.__time_index_map = {} for index in range(len(self.__time_map)): time = self.__time_map[index] self.__time_index_map[time] = index self.__time_spinner = self.createTimeSpinner(select_minimum_value=select_min_time_value) layout = QVBoxLayout() self.setLayout(layout) self.__label = QLabel(title) self.__label.setAlignment(Qt.AlignHCenter) self.__stack = QStackedWidget() self.__stack.setSizePolicy(QSizePolicy(QSizePolicy.Preferred)) self.__stack.addWidget(self.__integer_spinner) self.__stack.addWidget(self.__double_spinner) self.__stack.addWidget(self.__time_spinner) layout.addWidget(self.__stack) layout.addWidget(self.__label) self.setLayout(layout) def createDoubleSpinner(self, minimum, maximum): spinner = QDoubleSpinBox() spinner.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) spinner.setMinimumWidth(105) spinner.setRange(minimum, maximum) spinner.setKeyboardTracking(False) spinner.setDecimals(8) spinner.editingFinished.connect(self.plotScaleChanged) spinner.valueChanged.connect(self.plotScaleChanged) return spinner def createIntegerSpinner(self, minimum, maximum): spinner = QSpinBox() spinner.setMinimumWidth(75) spinner.setRange(minimum, maximum) spinner.setKeyboardTracking(False) spinner.editingFinished.connect(self.plotScaleChanged) spinner.valueChanged.connect(self.plotScaleChanged) return spinner def createTimeSpinner(self, select_minimum_value): def converter(item): return "%s" % (str(item.date())) spinner = ListSpinBox(self.__time_map) spinner.setMinimumWidth(75) if select_minimum_value: spinner.setValue(0) spinner.valueChanged[int].connect(self.plotScaleChanged) spinner.editingFinished.connect(self.plotScaleChanged) spinner.setStringConverter(converter) return spinner def getValue(self): if self.__type is int: return self.__integer_spinner.value() elif self.__type is float: return self.__double_spinner.value() elif self.__type is CTime: index = self.__time_spinner.value() return self.__time_map[index] else: raise TypeError("Unsupported spinner type: %s" % self.__type) def setValue(self, value): if value is not None: if self.__type is int: self.__integer_spinner.setValue(int(value)) elif self.__type is float: self.__double_spinner.setValue(value) elif self.__type is CTime: index = self.__time_index_map[value] self.__time_spinner.setValue(index) else: raise TypeError("Unsupported spinner type: %s" % self.__type) def setFontSize(self, size): font = self.__double_spinner.font() font.setPointSize(size) self.__double_spinner.setFont(font) font = self.__integer_spinner.font() font.setPointSize(size) self.__integer_spinner.setFont(font) font = self.__time_spinner.font() font.setPointSize(size) self.__time_spinner.setFont(font) font = self.__label.font() font.setPointSize(size) self.__label.setFont(font) def setType(self, spinner_type): self.__type = spinner_type if spinner_type is int: self.__stack.setCurrentWidget(self.__integer_spinner) elif spinner_type is float: self.__stack.setCurrentWidget(self.__double_spinner) elif spinner_type is CTime: self.__stack.setCurrentWidget(self.__time_spinner) else: raise TypeError("Unsupported spinner type: %s" % spinner_type) def getType(self): return self.__type
def __init__(self, parent, enable_replace=False): QWidget.__init__(self, parent) self.enable_replace = enable_replace self.editor = None glayout = QGridLayout() glayout.setContentsMargins(0, 0, 0, 0) self.setLayout(glayout) self.close_button = create_toolbutton( self, triggered=self.hide, icon=get_std_icon("DialogCloseButton")) glayout.addWidget(self.close_button, 0, 0) # Find layout self.search_text = PatternComboBox(self, tip=self.tr("Search string"), adjust_to_minimum=False) self.connect(self.search_text, SIGNAL("editTextChanged(QString)"), self.text_has_changed) self.previous_button = create_toolbutton( self, text=self.tr("Previous"), triggered=self.find_previous, icon=get_std_icon("ArrowBack")) self.next_button = create_toolbutton(self, text=self.tr("Next"), triggered=self.find_next, icon=get_std_icon("ArrowForward")) self.connect(self.next_button, SIGNAL('clicked()'), self.update_search_combo) self.connect(self.previous_button, SIGNAL('clicked()'), self.update_search_combo) self.case_check = QCheckBox(self.tr("Case Sensitive")) self.connect(self.case_check, SIGNAL("stateChanged(int)"), self.find) self.words_check = QCheckBox(self.tr("Whole words")) self.connect(self.words_check, SIGNAL("stateChanged(int)"), self.find) hlayout = QHBoxLayout() self.widgets = [ self.close_button, self.search_text, self.previous_button, self.next_button, self.case_check, self.words_check ] for widget in self.widgets[1:]: hlayout.addWidget(widget) glayout.addLayout(hlayout, 0, 1) # Replace layout replace_with1 = QLabel(self.tr("Replace")) replace_with2 = QLabel() font = replace_with2.font() font.setBold(True) replace_with2.setFont(font) replace_with3 = QLabel(self.tr("with:")) self.replace_text = PatternComboBox(self, adjust_to_minimum=False, tip=self.tr("Replace string")) self.replace_button = create_toolbutton( self, text=self.tr("Replace/find"), triggered=self.replace_find, icon=get_std_icon("DialogApplyButton")) self.connect(self.replace_button, SIGNAL('clicked()'), self.update_replace_combo) self.connect(self.replace_button, SIGNAL('clicked()'), self.update_search_combo) self.all_check = QCheckBox(self.tr("Replace all")) self.replace_layout = QHBoxLayout() widgets = [ replace_with1, replace_with2, replace_with3, self.replace_text, self.replace_button, self.all_check ] for widget in widgets: self.replace_layout.addWidget(widget) self.connect(self.search_text, SIGNAL("editTextChanged(QString)"), replace_with2, SLOT("setText(QString)")) glayout.addLayout(self.replace_layout, 1, 1) self.widgets.extend(widgets) self.replace_widgets = widgets self.hide_replace() self.search_text.setTabOrder(self.search_text, self.replace_text) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
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