def rowValidator(self): if self.numberValidator() is not None: return self.numberValidator() minimum = self.minimumRow if self.sender.text() == "" else int( self.sender.text()) validator = QIntValidator(minimum, self.maximumRow) result = (validator.validate(self.widget.text(), 0)) message = "Недопустимый диапазон строк!" if self.buttonSwitcher(result[0], message) != QValidator.Acceptable: self.result["row"] = True return result[0]
def isValid(self): valid, _text, _npos = QIntValidator.validate( self.int_validator, self.le1.text(), self.le1.cursorPosition()) if valid == QValidator.Acceptable: print("Valid " + self.le1.text()) elif valid == QValidator.Intermediate: print("Close, but not valid") elif valid == QValidator.Invalid: print("This is clearly not valid")
def colValidator(self): if self.letterValidator() is not None: return self.letterValidator() minimum = self.letterIndexToIntValue(self.minimumCol) \ if self.sender.text() == "" \ else self.letterIndexToIntValue(self.sender.text()) validator = QIntValidator(minimum, self.letterIndexToIntValue(self.maximumCol)) result = validator.validate( str(self.letterIndexToIntValue(self.widget.text())), 0) message = "Недопустимый диапазон столбцов!" if self.buttonSwitcher(result[0], message) != QValidator.Acceptable: self.result["col"] = True return result[0]
class PVLineEdit(QLineEdit): pvChanged = pyqtSignal(str) def __init__(self, pvname=None, parent=None): QLineEdit.__init__(self, parent) self.returnPressed.connect(self.onReturn) self.pv = None self.cb_index = None if pvname is not None: self.setPV(pvname) def setPV(self, pvname, type=float, prec=5): if self.pv is not None and self.cb_index is not None: self.pv.remove_callback(self.cb_index) self.pvChanged.disconnect(self.updatePV) self.prec = prec self.type = type self.pv = epics.PV(BYTES2STR(pvname)) self.cb_index = self.pv.add_callback(self.onPVChange) self.pvChanged.connect(self.updatePV) if self.type == float: self.validator = QDoubleValidator() self.setValidator(self.validator) elif self.type == int: self.validator = QIntValidator() self.setValidator(self.validator) #self.updatePV(self.pv.char_value) def onPVChange(self, pvname=None, char_value=None, **kws): self.pvChanged.emit(char_value) def updatePV(self, char_value): if self.type == float: text = float(char_value) self.setText(("{:." + str(self.prec) + "f}").format(text)) else: self.setText(char_value) def onReturn(self): if (self.type == float or self.type == int): if self.validator.validate(self.text(), 0)[0] == self.validator.Acceptable: self.pv.put(BYTES2STR(self.text())) else: QMessageBox.warning( self, 'Value Error', 'Please input floating point numbers only', QMessageBox.Ok) else: self.pv.put(BYTES2STR(self.text()))
class Energy_Widget(QWidget): """ """ energyChanging = pyqtSignal(float) energyChanged = pyqtSignal(int) def __init__(self, parent=None): """ """ QWidget.__init__(self, parent) loadUi('UI_Forms/Energy_Widget.ui', self) self.tabWidget.setTabText(0, 'Xtal Plot') self.tabWidget.setTabText(1, 'Mirror Plot') self.loadPVs() self.init_validation() self.xtalMinChanged() self.xtalMaxChanged() self.mirrorMinChanged() self.mirrorMaxChanged() self.xtalStepsChanged() self.mirrorStepsChanged() self.stoppedTracking = False self.init_signals() self.undulatorStartPV = epics.PV(BYTES2STR("ID15:Start.VAL")) self.undulatorStopPV = epics.PV(BYTES2STR("ID15:Start.VAL")) self.scaler_15IDC_PV = epics.PV(BYTES2STR("15IDC:scaler1.CNT")) self.scaler_15IDD_PV = epics.PV(BYTES2STR("15IDD:vsc:c0.CNT")) self.countTime_15IDC_PV = epics.PV(BYTES2STR("15IDC:scaler1.TP")) self.countTime_15IDD_PV = epics.PV(BYTES2STR("15IDD:vsc:c0.TP")) self.xiaShutter_PV = epics.PV(BYTES2STR("15IDD:2openXIAShutter")) self.countTime_15IDC_PV.put(1) self.countTime_15IDD_PV.put(1) self.getUndulatorOffset() self.undulatorChanging = False if self.feedbackComboBox.pv.value == 1: # self.feedback_enabled=True # self.feedback_disable=False QMessageBox.warning( self, 'Feedback Warning', 'Please switch off the feedback before start energy tracking', QMessageBox.Ok) # else: # self.feedback_enabled=False # self.feedback_disabled=True def getUndulatorOffset(self): self.undulatorOffset = self.undulatorEnergyLineEdit.pv.value - self.energyLineEdit.pv.value self.undulatorOffsetLineEdit.setText('%.4f' % self.undulatorOffset) def init_validation(self): self.dbleValidator = QDoubleValidator() self.intValidator = QIntValidator() self.xtalMinLineEdit.setValidator(self.dbleValidator) self.xtalMaxLineEdit.setValidator(self.dbleValidator) self.mirrorMinLineEdit.setValidator(self.dbleValidator) self.mirrorMaxLineEdit.setValidator(self.dbleValidator) self.xtalStepsLineEdit.setValidator(self.intValidator) self.mirrorStepsLineEdit.setValidator(self.intValidator) self.undulatorOffsetLineEdit.setValidator(self.dbleValidator) def init_signals(self): self.undulatorStartPushButton.clicked.connect(self.startUndulator) self.undulatorStopPushButton.clicked.connect(self.stopUndulator) self.undulatorOffsetLineEdit.returnPressed.connect(self.offsetChanged) self.getUndulatorOffsetPushButton.clicked.connect( self.getUndulatorOffset) self.startTrackingPushButton.clicked.connect(self.track_undulator) self.stopTrackingPushButton.clicked.connect(self.untrack_undulator) self.xtalScanPushButton.clicked.connect(self.scan_xtal) self.mirrorScanPushButton.clicked.connect(self.scan_mirror) self.xtalMinLineEdit.returnPressed.connect(self.xtalMinChanged) self.xtalMaxLineEdit.returnPressed.connect(self.xtalMaxChanged) self.mirrorMinLineEdit.returnPressed.connect(self.mirrorMinChanged) self.mirrorMaxLineEdit.returnPressed.connect(self.mirrorMaxChanged) self.xtalStepsLineEdit.returnPressed.connect(self.xtalStepsChanged) self.mirrorStepsLineEdit.returnPressed.connect(self.mirrorStepsChanged) def loadPVs(self): # pass self.feedbackComboBox.setPV("15IDA:pid_mono_1.FBON") self.shutterComboBox.setPV("15IDD:2openXIAShutter") self.monBCountsLabel.setPV("15IDC:scaler1.S2", type=int) self.monPCountsLabel.setPV("15IDC:scaler1.S3", type=int) self.monDCountsLabel.setPV("15IDD:vsc:c0.S8", type=int) self.pdCountsLabel.setPV("15IDD:vsc:c0.S4", type=int) self.energyRDBKLabel.setPV("15IDA:BraggERdbkAO", prec=4) self.lambdaRDBKLabel.setPV("15IDA:BraggLambdaRdbkAO", prec=5) self.braggRDBKLabel.setPV("15IDA:BraggThetaRdbkAO", prec=5) self.energyLineEdit.setPV("15IDA:BraggEAO.VAL", prec=4) self.lambdaLineEdit.setPV("15IDA:BraggLambdaAO.VAL", prec=5) self.braggLineEdit.setPV("15IDA:BraggThetaAO.VAL", prec=5) self.monoModeComboBox.setPV("15IDA:KohzuModeBO.VAL") self.monoStatusLabel.setPV("15IDA:KohzuMoving", type=str) self.undulatorHarmonicLineEdit.setPV("ID15:HarmonicValue", type=int) self.undulatorGapLineEdit.setPV("ID15:GapSet.VAL", prec=3) self.undulatorGapLabel.setPV("ID15:Gap.VAL", prec=3, type=float) self.undulatorEnergyLineEdit.setPV("ID15:EnergySet.VAL", prec=4) self.undulatorEnergyLabel.setPV("ID15:Energy.VAL", prec=4, type=float) self.undulatorStatusLabel.setPV("ID15:Busy.VAL", type=str) self.mirrorDACLineEdit.setPV("15IDA:DAC1_2.VAL", prec=4) self.xtalDACLineEdit.setPV("15IDA:DAC1_4.VAL", prec=4) def startUndulator(self): self.undulatorStartPV.put(1) def stopUndulator(self): self.undulatorStopPV.put(1) def offsetChanged(self): if self.dbleValidator.validate(self.undulatorOffsetLineEdit.text(), 0)[0] == self.dbleValidator.Acceptable: self.undulatorOffset = float(self.undulatorOffsetLineEdit.text()) else: QMessageBox.warning(self, 'Value Error', "Please enter floating point numbers only", QMessageBox.Ok) def xtalMinChanged(self): if self.dbleValidator.validate(self.xtalMinLineEdit.text(), 0)[0] == self.dbleValidator.Acceptable: self.xtalMin = float(self.xtalMinLineEdit.text()) else: QMessageBox.warning(self, 'Value Error', "Please enter floating point numbers only", QMessageBox.Ok) def xtalMaxChanged(self): if self.dbleValidator.validate(self.xtalMaxLineEdit.text(), 0)[0] == self.dbleValidator.Acceptable: self.xtalMax = float(self.xtalMaxLineEdit.text()) else: QMessageBox.warning(self, 'Value Error', "Please enter floating point numbers only", QMessageBox.Ok) def mirrorMinChanged(self): if self.dbleValidator.validate(self.mirrorMinLineEdit.text(), 0)[0] == self.dbleValidator.Acceptable: self.mirrorMin = float(self.mirrorMinLineEdit.text()) else: QMessageBox.warning(self, 'Value Error', "Please enter floating point numbers only", QMessageBox.Ok) def mirrorMaxChanged(self): if self.dbleValidator.validate(self.mirrorMaxLineEdit.text(), 0)[0] == self.dbleValidator.Acceptable: self.mirrorMax = float(self.mirrorMaxLineEdit.text()) else: QMessageBox.warning(self, 'Value Error', "Please enter floating point numbers only", QMessageBox.Ok) def xtalStepsChanged(self): if self.intValidator.validate(self.xtalStepsLineEdit.text(), 0)[0] == self.intValidator.Acceptable: self.xtalSteps = int(self.xtalStepsLineEdit.text()) else: QMessageBox.warning(self, 'Value Error', "Please enter integer value only") def mirrorStepsChanged(self): if self.intValidator.validate(self.mirrorStepsLineEdit.text(), 0)[0] == self.intValidator.Acceptable: self.mirrorSteps = int(self.xtalStepsLineEdit.text()) else: QMessageBox.warning(self, 'Value Error', "Please enter integer value only") def track_undulator(self): self.stoppedTracking = False self.enable_widgets(enable=False) try: self.braggLineEdit.pvChanged.disconnect(self.changeUndulatorEnergy) except: pass self.braggLineEdit.pvChanged.connect(self.changeUndulatorEnergy) def untrack_undulator(self): self.enable_widgets(enable=True) self.stoppedTracking = True try: self.braggLineEdit.pvChanged.disconnect(self.changeUndulatorEnergy) except: pass def changeUndulatorEnergy(self): # self.feedback_OFF() # print("Feedback Disabled") print('Changing Undulator') self.undulatorChanging = True self.undulatorEnergyLineEdit.pv.put(self.energyLineEdit.pv.value + self.undulatorOffset) self.startUndulator() while epics.caget(BYTES2STR("15IDA:KohzuMoving")) == 1: QTest.qWait(10) print('Undulator Changed') self.wait_for_stablization(detector='MonB') #print("Undulator change stablized") if self.trackXtalCheckBox.isChecked(): print("Scanning 2nd Xtal...") self.scan_xtal() if self.trackMirrorCheckBox.isChecked(): print("Scanning 2nd Mirror...") self.scan_mirror() self.undulatorChanging = False # self.feeback_ON() # print("Feedback Enabled") def scan_xtal(self): # if self.feedback_enabled: # print("Feedback Disabled") # self.feedback_OFF() self.stoppedTracking = False self.scan(dac='xtal') # print("Feedback Enabled") # self.feeback_ON() def scan_mirror(self): self.stoppedTracking = False self.scan(dac='mirror') def scan(self, dac='xtal', save=True): self.countTime_15IDC_PV.put(1) self.countTime_15IDD_PV.put(1) if dac == 'xtal': xold = self.xtalDACLineEdit.pv.value xmin = xold + self.xtalMin xmax = xold + self.xtalMax steps = self.xtalSteps yaxis = self.xtalDetectorComboBox.currentText() self.xtalPlotTab.setXLabel(dac) self.xtalPlotTab.setYLabel(yaxis) else: xold = self.mirrorDACLineEdit.pv.value xmin = xold + self.mirrorMin xmax = xold + self.mirrorMax steps = self.mirrorSteps yaxis = self.mirrorDetectorComboBox.currentText() self.mirrorPlotTab.setXLabel(dac) self.mirrorPlotTab.setYLabel(yaxis) data = {} data[dac] = np.linspace(xmin, xmax, steps) data['MonB'] = np.array([]) data['MonP'] = np.array([]) data['MonD'] = np.array([]) # data['Readback'] = np.array([]) data['PD'] = np.array([]) self.auto_count_off() if dac == 'xtal': self.xtalDACLineEdit.pv.put(data[dac][0], wait=True) else: self.mirrorDACLineEdit.pv.put(data[dac][0], wait=True) #print('val=%.4f I m waiting' % val) #t=time.time() QTest.qWait(1000) #print(time.time()-t) for i, val in enumerate(data[dac][1:]): if not self.stoppedTracking: self.trigger_scalers() data['MonB'] = np.append(data['MonB'], self.monBCountsLabel.pv.value) data['MonP'] = np.append(data['MonP'], self.monPCountsLabel.pv.value) data['MonD'] = np.append(data['MonD'], self.monDCountsLabel.pv.value) data['PD'] = np.append(data['PD'], self.pdCountsLabel.pv.value) # data['Readback'] = np.append(data['Readback'], float(epics.caget(BYTES2STR("15IDA:pid_mono_1.CVAL")))) if dac == 'xtal': self.tabWidget.setCurrentIndex(0) self.xtalPlotTab.add_data(data[dac][:i + 1], data[yaxis], name=dac + '-' + yaxis) else: self.tabWidget.setCurrentIndex(1) self.mirrorPlotTab.add_data(data[dac][:i + 1], data[yaxis], name=dac + '-' + yaxis) if dac == 'xtal': self.xtalDACLineEdit.pv.put(val, wait=True) else: self.mirrorDACLineEdit.pv.put(val, wait=True) QTest.qWait(100) else: break if not self.stoppedTracking: maxval = data[dac][data[yaxis].argmax()] # self.readbackvalue=data['Readback'][data[yaxis].argmax()] if dac == 'xtal': # offset of -0.06 is added because we find the # peak position obtained from scan is -0.06 from the real peak position print('Moving to Maximum %.4f' % (maxval - 0.06)) self.xtalDACLineEdit.pv.put( maxval - 0.06) #Moving DAC to the maximum xtalintensity value else: print('Moving to Maximum %.4f' % maxval) self.mirrorDACLineEdit.pv.put( maxval) # Moving DAC to the maximum mirror intensity value else: print('Moving to old value') if dac == 'xtal': self.xtalDACLineEdit.pv.put( xold) #Moving DAC to the known old value else: self.mirrorDACLineEdit.pv.put( xold) # Moving DAC to the known old value self.auto_count_on() def wait_for_stablization(self, detector='MonB'): self.auto_count_off() self.countTime_15IDC_PV.put(1) self.countTime_15IDD_PV.put(1) if detector == 'MonB': self.trigger_scalers() for i in range(10): QTest.qWait(1000) counts = 0 monbCounts = self.monBCountsLabel.pv.value while np.abs(counts - monbCounts) > np.sqrt( monbCounts) and not self.stoppedTracking: QTest.qWait(100) print(np.abs(counts - monbCounts), np.sqrt(monbCounts)) counts = copy.copy(monbCounts) self.trigger_scalers() monbCounts = self.monBCountsLabel.pv.value elif detector == 'MonP': self.trigger_scalers() counts = 0 monpCounts = self.monPCountsLabel.pv.value while np.abs(counts - monpCounts) > np.sqrt( monpCounts) and not self.stoppedTracking: QTest.qWait(1000) counts = copy.copy(monpCounts) self.trigger_scalers() monpCounts = self.monPCountsLabel.pv.value elif detector == 'MonD': self.trigger_scalers() counts = 0 mondCounts = self.monDCountsLabel.pv.value while np.abs(counts - mondCounts) > np.sqrt( mondCounts) and not self.stoppedTracking: QTest.qWait(1000) counts = copy.copy(mondCounts) self.trigger_scalers() mondCounts = self.monDCountsLabel.pv.value elif detector == 'PD': self.trigger_scalers() counts = 0 pdCounts = self.pdCountsLabel.pv.value while np.abs(counts - pdCounts) > np.sqrt(pdCounts): QTest.qWait(1000) counts = copy.copy(pdCounts) self.trigger_scalers() pdCounts = self.pdCountsLabel.pv.value self.auto_count_on() # def feeback_ON(self): # epics.caput(BYTES2STR("15IDA:pid_mono_1.INP"),"15IDA:pid_mono_1_incalc.D", wait=True) # sfb=float(epics.caget(BYTES2STR("15IDA:pid_mono_1_incalc.INPC"))) # sf=96.0*sfb/self.readbackvalue # print(self.readbackvalue,sfb) # epics.caput(BYTES2STR("15IDA:pid_mono_1_incalc.INPC"), '%.3f'%sf, wait=True) # epics.caput(BYTES2STR("15IDA:pid_mono_1.FBON"), 1, wait=True) # self.feedback_enabled=True # self.feedback_disabled=False # # def feedback_OFF(self): # epics.caput(BYTES2STR("15IDA:pid_mono_1.FBON"), 0) # self.feedback_disabled=True # self.feedback_enabled=False def auto_count_on(self): epics.caput(BYTES2STR("15IDC:scaler1.CONT"), 1) # setting autocount on for 15IDC scaler epics.caput(BYTES2STR("15IDD:vsc:c0.CONT"), 1) # setting autocount on for 15IDD scaler def auto_count_off(self): epics.caput(BYTES2STR("15IDC:scaler1.CONT"), 0) # setting autocount off for 15IDC scaler epics.caput(BYTES2STR("15IDD:vsc:c0.CONT"), 0) # setting autocount off for 15IDD scaler def trigger_scalers(self): self.xiaShutter_PV.put(0) QTest.qWait(100) self.trigger_15IDC_scaler() self.trigger_15IDD_scaler() QTest.qWait(10) while self.scaler_15IDD_PV.value == 1 or self.scaler_15IDC_PV.value == 1: QTest.qWait(10) self.xiaShutter_PV.put(1) def trigger_15IDC_scaler(self): self.scaler_15IDC_PV.put( 1, wait=False) # Start counting for 1 sec with 15IDC counter def trigger_15IDD_scaler(self): self.scaler_15IDD_PV.put( 1, wait=False) # Start counting for 1 sec with 15IDD counter def enable_widgets(self, enable=True): self.feedbackComboBox.setEnabled(enable) self.energyLineEdit.setEnabled(enable) self.lambdaLineEdit.setEnabled(enable) self.braggLineEdit.setEnabled(enable) self.undulatorEnergyLineEdit.setEnabled(enable) self.undulatorGapLineEdit.setEnabled(enable) self.undulatorHarmonicLineEdit.setEnabled(enable) self.undulatorStartPushButton.setEnabled(enable) self.undulatorStopPushButton.setEnabled(enable) self.xtalDACLineEdit.setEnabled(enable) self.xtalMinLineEdit.setEnabled(enable) self.xtalMaxLineEdit.setEnabled(enable) self.xtalStepsLineEdit.setEnabled(enable) self.xtalScanPushButton.setEnabled(enable) self.mirrorDACLineEdit.setEnabled(enable) self.mirrorMinLineEdit.setEnabled(enable) self.mirrorMaxLineEdit.setEnabled(enable) self.mirrorStepsLineEdit.setEnabled(enable) self.mirrorScanPushButton.setEnabled(enable) self.startTrackingPushButton.setEnabled(enable) self.stopTrackingPushButton.setEnabled(not enable)
class ScaniGUI(QMainWindow): def __init__(self, parent=None): self.dev = None self.model = None self.connected = False super(ScaniGUI, self).__init__(parent) self.widget = QWidget() self.setCentralWidget(self.widget) vb = QVBoxLayout() hb1 = QHBoxLayout() self.scanigr = QGroupBox("Rede") self.confgr = QGroupBox("Config") hb1.addWidget(self.scanigr) vb1 = QVBoxLayout() hb2 = QHBoxLayout() hb2.addWidget(QLabel("IP")) self.ip_ed = QLineEdit("191.30.80.131") hb2.addWidget(self.ip_ed) vb1.addLayout(hb2) self.connbut = QPushButton("Conectar") self.connbut.clicked.connect(self.connect) vb1.addWidget(self.connbut) self.scanigr.setLayout(vb1) hb1.addWidget(self.confgr) vb.addLayout(hb1) self.zerobut = QPushButton("Hard Zero") self.zerobut.clicked.connect(self.hard_zero) self.zerobut.setEnabled(False) vb.addWidget(self.zerobut) self.listsbut = QPushButton("LIST S") self.listsbut.clicked.connect(self.listS) self.listsbut.setEnabled(False) vb.addWidget(self.listsbut) self.okbut = QPushButton("Ok") vb.addWidget(self.okbut) #self.szerobut.QPushButton("Soft Zero") #self.szerobut.setEnabled(False) gr1 = QGridLayout() vb2 = QVBoxLayout() gr1.addWidget(QLabel("FPS"), 0, 0) gr1.addWidget(QLabel("PERIOD"), 1, 0) gr1.addWidget(QLabel("AVG"), 2, 0) self.fps_ed = QLineEdit("1") self.fps_val = QIntValidator(1, 2147483647) self.fps_ed.setValidator(self.fps_val) self.fps_ed.textChanged.connect(self.check_state) self.fps_ed.textChanged.emit(self.fps_ed.text()) self.period_ed = QLineEdit("500") self.period_val = QIntValidator(150, 62500) self.period_ed.setValidator(self.period_val) self.period_ed.textChanged.connect(self.check_state) self.period_ed.textChanged.emit(self.period_ed.text()) self.avg_ed = QLineEdit("1") self.avg_val = QIntValidator(1, 240) self.avg_ed.setValidator(self.avg_val) self.avg_ed.textChanged.connect(self.check_state) self.avg_ed.textChanged.emit(self.avg_ed.text()) self.freqlab = QLabel("") self.ttotlab = QLabel("") gr1.addWidget(self.fps_ed, 0, 1) gr1.addWidget(self.period_ed, 1, 1) gr1.addWidget(self.avg_ed, 2, 1) gr1.addWidget(QLabel("Freq (Hz)"), 3, 0) gr1.addWidget(self.freqlab, 3, 1) gr1.addWidget(QLabel("Tempo (s)"), 4, 0) gr1.addWidget(self.ttotlab, 4, 1) self.confgr.setEnabled(False) vb2.addLayout(gr1) self.confbut = QPushButton("Configurar") self.confbut.clicked.connect(self.config) vb2.addWidget(self.confbut) self.confgr.setLayout(vb2) self.widget.setLayout(vb) def ipaddr(self): return self.ip_ed.text().strip() def connect(self): if self.connected: self.connbut.setText("Conectar") self.confgr.setEnabled(False) self.zerobut.setEnabled(False) self.listsbut.setEnabled(False) self.dev.close() self.dev = None self.connected = False else: ip = self.ipaddr() if scani.check_server(ip, 23, 2): try: self.dev = scani.Scanivalve(ip) except: QMessageBox.warning(self, "Erro", "Não foi possível conectar com o Scanivalve") return try: self.model = self.dev.get_model() lists = self.dev.list_any_map("S") except: QMessageBox.warning(self, "Problemas com Scanivalve", "Problemas na configuração do Scanivalve") return fps = lists['FPS'] avg = lists['AVG'] period = lists['PERIOD'] self.fps_ed.setText(fps) self.period_ed.setText(period) self.avg_ed.setText(avg) self.freqlab.setText(str(1/self.dev.dt)) self.ttotlab.setText(str(self.dev.dt*int(fps))) if self.model=='3017': self.period_val.setBottom(500) self.avg_val.setTop(32767) else: self.period_val.setBottom(150) self.avg_val.setTop(240) self.connbut.setText("DESconectar") self.confgr.setEnabled(True) self.listsbut.setEnabled(True) self.zerobut.setEnabled(True) self.connected = True return else: QMessageBox.warning(self, "Sem conexão", "Não foi possível conectar com o scanivalve") return def check_state(self, *args, **kwargs): sender = self.sender() validator = sender.validator() state = validator.validate(sender.text(), 0)[0] if state == QValidator.Acceptable: color = '#c4df9b' # green #elif state == QtGui.QValidator.Intermediate: # color = '#fff79a' # yellow else: color = '#f6989d' # red sender.setStyleSheet('QLineEdit { background-color: %s }' % color) def config(self): avg = self.avg_ed.text() state = self.avg_val.validate(avg, 0)[0] if state != QValidator.Acceptable: QMessageBox.warning(self, "Valor ilegal", "AVG está fora dos valores permitidos") return period = self.period_ed.text() state = self.period_val.validate(period, 0)[0] if state != QValidator.Acceptable: QMessageBox.warning(self, "Valor ilegal", "PERIOD está fora dos valores permitidos") return fps = self.fps_ed.text() state = self.fps_val.validate(fps, 0)[0] if state != QValidator.Acceptable: QMessageBox.warning(self, "Valor ilegal", "FPS está fora dos valores permitidos") return self.dev.config(FPS=int(fps), AVG=int(avg), PERIOD=int(period)) self.freqlab.setText("{:05.3f}".format(1/self.dev.dt)) self.ttotlab.setText("{:05.3f}".format(self.dev.dt * int(fps))) return None def hard_zero(self): if self.dev is not None: self.dev.hard_zero() self.setEnabled(False) QtTest.QTest.qWait(15000) self.setEnabled(True) return None def listS(self): if self.dev is not None: lists = self.dev.list_any("S") s = '\n'.join([' '.join(l) for l in lists]) QMessageBox.information(self, "LIST S", s) return None def scanivalve(self): return self.dev
class MoonController(QObject): """ Класс MoonController представляет реализацию контроллера. Согласовывает работу представления с моделью. """ SETTING_WAY = 'Last opened moon app' changedWindowTitle = pyqtSignal(str) def __init__(self, in_model): """ Конструктор принимает ссылку на модель. Конструктор создаёт и отображает представление. """ super().__init__() self._mModel = in_model self._mView = MoonView(self, self._mModel) self._mMoonPhase = MoonPhase(self._mModel) # устанавливаем валидатор для значения Y self.validator = QIntValidator(-10, 10, self) # создаем экземпляр класса формата даты self.c_date = QDate() # имя файла self.file_name_for_save = '' self.opened_file_title = '' # создаем QSettings для сохранения пути в реестре self.settings = QSettings() self.file_name_from_qsettings = self.settings.value( self.SETTING_WAY, '', str) # запускаем визуальное представление self._mView.show() def onItemChanged(self, item): """ Метод реагирует на сигнал Изменяет данные модели """ if item.column() == 0: # если данные забиты в столбце с датой self.changeModelDate(item) elif item.column() == 1: # если столбец для mood self.changeModelMood(item) self._mModel.cleanerRow() # подчищаем лишние ячейки пустые self._mView.updateGraph() # запускаем отрисовку графика def changeModelDate(self, item): """ Меняет модель Date определенным образом """ new_data = item.data(Qt.DisplayRole) # вытаскиваем из item данные if new_data == '' and (self._mModel.getLengthDate() == 1 or self._mModel.getLengthDate() == 0): self._mModel.addEmptyDate( ) # в случае пустой первой ячейки записываем значение None return self.c_date = self.c_date.fromString( new_data, "dd.MM.yyyy") # данные из формата дата переводим в QDate if self.c_date.isValid() is False and item.row( ) == 0: # если дата не подходящего вида оставляем ячейку пустой item.setText(None) return if self._mModel.getLengthDate() > item.row( ): # если данные поменялись в середине стобца, а не в конце if item.row( ) == 0: # если ошибка в первой строке, то ее можно исправить self._mModel.changedDates(self.c_date) else: item.setText(self._mModel.getDateString(item.row())) else: self._mModel.addDate(self.c_date) # если добавляются новые данные self._mModel.addMood(None) def changeModelMood(self, item): """ Меняет модель Mood определенным образом """ new_data = item.data(Qt.DisplayRole) # вытаскиваем из item данные if self.validate(item.data(Qt.DisplayRole) ) is True: # если данные проходят валидацию или None self._mModel.addMood( int(new_data), item.row()) # то записываем в модель новые значения if self.checkNextRow( item ) is True: # метод проверяет последняя строка заполнена ли, если заполнена self._mModel.addNextDate( ) # вызваем метод добавления строк с новыми датами else: self._mModel.addMood(None, item.row( )) # если данные не проходят валидацию, ячейку оставляем пустой item.setText(None) def validate(self, item): """ Метод проверяет корректность написания данных Mood """ p = 0 result = self.validator.validate(item, p) return result[0] == 2 def checkNextRow(self, item): """ Метод проверяет есть строки после измененной ячейки """ if (item.row() + 1) == self._mModel.getRowCount(): return True else: return False def cleanAll(self): """ Метод очищает все данные """ self._mModel.setNullModel() self._mMoonPhase.setNullQuarterPhase() self._mView.ui.tableWidget.clearContents() self._mView.ui.tableWidget.setRowCount(1) self._mView.ui.MplWidget.setMaxScroll(0) def save_file_name(self, name): """ Метод сохраняет путь до файла в реестре """ self.settings.setValue(self.SETTING_WAY, name) def get_file_name_title(self, name): """ Метод достает из строки пути до файла название самого файла для отображения в назании программы """ name = name.split('/') if name[-1].endswith('mmf'): name[-1] = ' (' + name[-1][:-4] + ')' return name[-1] else: return def openNewFile(self): """ Метод вызывается при открытии нового файла """ self.file_name_for_save = '' self.opened_file_title = '' self.changedWindowTitle.emit(self.opened_file_title) self.cleanAll() self._mView.ui.MplWidget.setStep(6.0) self._mView.resetFigure() self._mView.ui.MplWidget.canvas.draw() def saveAsData(self): """ Метод вызывается при сохранении данных """ name = QtWidgets.QFileDialog.getSaveFileName( None, 'Save File', '', 'Mood Moon Files (*.mmf)') self.file_name_for_save = name[0] self.opened_file_title = self.get_file_name_title( self.file_name_for_save) self.changedWindowTitle.emit(self.opened_file_title) if name[0] == '': return with open(name[0], 'w') as file: for i in range(0, self._mModel.getLengthDate()): data = self._mModel.getDateString(i) + '\t' + str( self._mModel.getMood(i)) + '\n' file.write(data) self.save_file_name(self.file_name_for_save) def saveData(self): """ Метод вызывается при сохранении данных """ if self.file_name_for_save == '': self.saveAsData() return name = self.file_name_for_save with open(name, 'w') as file: for i in range(0, self._mModel.getLengthDate()): data = self._mModel.getDateString(i) + '\t' + str( self._mModel.getMood(i)) + '\n' file.write(data) def openFileWithName(self, file_name): """ Метод открывает переданный файл """ if file_name == '': return self.opened_file_title = self.get_file_name_title(file_name) self.changedWindowTitle.emit(self.opened_file_title) with open(file_name, 'r') as file: data = file.read() data = data.split('\n') data = data[:-1] self.cleanAll() self.writeDataToModel(data) self._mView.ui.MplWidget.setStep(6.0) def openFile(self): """ Метод вызывается при открытии файла с сохраненными данными """ name = QtWidgets.QFileDialog.getOpenFileName( None, "Open Mood and Moon File", "", "Mood Moon Files (*.mmf)") self.file_name_for_save = name[0] self.openFileWithName(self.file_name_for_save) self.save_file_name(self.file_name_for_save) def openLastFile(self): """ Метод запускает открытие последнего закрытого файла """ self.openFileWithName(self.file_name_from_qsettings) def copyDataSelectedRows(self): """ Метод вызывается при копировании данных Переводит все в строку для буфера обмена """ selectedRows = self._mView.ui.tableWidget.selectedIndexes() self.dataForClipboard = '' for i in range(0, len(selectedRows)): self.dataForClipboard += selectedRows[i].data(Qt.DisplayRole) if i % 2 == 0: self.dataForClipboard += '\t' else: self.dataForClipboard += '\n' self._mView.clipboard.setText(self.dataForClipboard) def pasteDataSelectedRows(self): """ Метод вызывается при вставки данных в таблицу Вставляет если таблица пустая, если данные там уже есть ничего не делает """ selectedItem = self._mView.ui.tableWidget.selectedIndexes() line = self._mView.clipboard.text() data = line.split('\n') # убираем перенос if data[-1] == '': data = data[:-1] if selectedItem[0].data( Qt.DisplayRole) is None: # проверка пустая ли строка self.writeDataToModel(data) else: pass def writeDataToModel(self, data): """ Метод переводит данные в необходимы тип и записывает в модель Запускает заполнение таблицы и отрисовку графика """ for d in range(0, len(data)): data[d] = data[d].split('\t') # разделяем дату и число Mood for d in data: self.c_date = self.c_date.fromString( d[0], "dd.MM.yyyy") # дату перефодим в тип QDate if self.c_date.isValid() is False: pass else: self._mModel.addDate(self.c_date) # сохраняем в модель даты if d[1] != 'None': # число сохраняем модель Y if self.validate(d[1]) is True: d[1] = int(d[1]) self._mModel.addMood(d[1]) else: pass else: self._mModel.addMood(None) if self._mModel.getDate() != [] or self._mModel.getMood( ) != []: # провека не полностью ли таблица пустая self._mModel.setRowCount( self._mModel.getLengthDate()) # сохраянем в модель число строк if self._mModel.getMood( -1 ) is not None: # проверка наличия последней пустой строки self._mModel.addNextDate() self._mView.ui.MplWidget.setMaxScroll(self._mModel.getRowCount()) self._mView.dataFilling() # запускаем заполнение таблицы self._mView.updateGraph() # запускаем отрисовку графика else: self._mModel.setRowCount(1) self._mView.resetFigure() self._mView.ui.MplWidget.canvas.draw()