class MyView(QWidget): def __init__(self, windowTitle, posX, posY, sizeX, sizeY): self.app = QApplication(sys.argv) super().__init__() print("MyView::__init__(windowTitle, posX, posY, sizeX, sizeY)") self.setGeometry(posX, posY, sizeX, sizeY) self.setWindowTitle(windowTitle) #setting up the Vertical Layout self.control_layout = QVBoxLayout() self.setLayout(self.control_layout) #setting up the button widget self.button = QPushButton() self.button.setFixedSize(40, 40) self.button.setText("+") self.button.clicked.connect(self.buttonClicked) #setting up the Counter widget self.timer = QLCDNumber() self.timer.setNumDigits(4) self.timer.setStyleSheet("QLCDNumber {color: pink;}") self.timer.setFixedWidth(400) #self.timer.display(self.getVal()) self.control_layout.addWidget(self.timer) self.control_layout.addWidget(self.button) self.show() def getVal(self,val): self.timer.display(val) def keyPressEvent(self, e): if e.key(): print("Key +1") return "a" def buttonClicked(self): print("Button +1") return True def run(self): sys.exit(self.app.exec_())
class TimeSettingWidget(QWidget): def __init__(self, parent=None): super(TimeSettingWidget, self).__init__(parent) self.initUI() def initUI(self): self.lcd = QLCDNumber(self) self.lcd.setNumDigits(2) self.lcd.setMinimumHeight(80) self.lcd.setStyleSheet("QLCDNumber{ color: black;}") self.sld = QSlider(Qt.Horizontal, self) self.sld.setMinimum(1) self.sld.setMaximum(90) self.vbox = QVBoxLayout() self.vbox.addWidget(self.lcd) self.vbox.addWidget(self.sld) self.setLayout(self.vbox) self.sld.valueChanged.connect(self.lcd.display) def setTime(self, t): self.sld.setValue(t) def setDisplayTime(self, t): self.lcd.display(t) def setActiveStyle(self): self.lcd.setStyleSheet("QLCDNumber{ color: green;}") def setInactiveStyle(self): self.lcd.setStyleSheet("QLCDNumber{ color: black;}") def setSliderEnable(self, bool): self.sld.setEnabled(bool) def freshDisplayTime(self): self.lcd.display(self.sld.value()) def getTime(self): return self.sld.value()
class ClassMain(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.dong_ho = QLCDNumber(self) self.dong_ho.setNumDigits(8) self.dong_ho.setGeometry(10, 10, 280, 80) dem_gio = QTimer(self) dem_gio.timeout.connect(self.hien_gio) dem_gio.start(1000) self.setWindowTitle('Vsmart CARPARKING SYSTEM V.1.01') self.setWindowIcon(QIcon('clock.png')) self.resize(300, 100) #setFixedSize(300,100) self.show() def hien_gio(self): self.dong_ho.display(strftime("%H" + ":" + "%M" + ":" + "%S"))
class Trigan_Result_Window(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): global COUNT_TRUES_EQUATIONS, begin global COUNT_TRIES_EQUATIONS self.f_r = open("info", mode='r') self.frm = QFrame(self) self.frm.setStyleSheet("QWidget { background-color: %s }" % self.f_r.read(7)) self.frm.setGeometry(0, 0, 2000, 1000) self.setGeometry(500, 300, 400, 200) self.setWindowTitle('Результаты работы') self.lcdNumber = QLCDNumber(self) self.lcdNumber.setGeometry(QtCore.QRect(0, 0, 80, 35)) self.lcdNumber.move(300, 10) self.lcdNumber.setNumDigits(5) self.str1 = "{:0>2d}:{:0>2d}".format(begin // 60, begin % 60) self.lcdNumber.display(self.str1) self.result_label = QLabel(self) self.result_label.setText( f"Ваш результат: {COUNT_TRUES_EQUATIONS} из {COUNT_TRIES_EQUATIONS}" ) self.result_label.setFont( QtGui.QFont("Currently only TrueType fonts", 14)) self.result_label.resize(300, 50) self.result_label.move(70, 70) self.f_r.seek(14) self.result_label.setStyleSheet("QLabel {color: %s;}" % self.f_r.read(7)) COUNT_TRIES_EQUATIONS = 0 COUNT_TRUES_EQUATIONS = 0 begin = 0 self.back_btn = QPushButton('← Меню', self) self.back_btn.resize(90, 30) self.back_btn.move(10, 160) self.f_r.seek(7) self.back_btn.setStyleSheet( "QPushButton { background-color: %s; border: %s; color: %s}" % (self.f_r.read(7), None, self.f_r.read(7))) self.qu_btn = QPushButton('↺ Заново', self) self.qu_btn.resize(90, 30) self.qu_btn.move(110, 160) self.f_r.seek(7) self.qu_btn.setStyleSheet( "QPushButton { background-color: %s; border: %s; color: %s}" % (self.f_r.read(7), None, self.f_r.read(7))) self.f_r.close() self.back_btn.clicked.connect(self.back) self.qu_btn.clicked.connect(self.ques) def back(self): self.back_form = MainMenu() self.back_form.show() self.close() def ques(self): self.ques_form = Trigan_Window() self.ques_form.show() self.close()
class Trigan_Window(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): global TIMER, COUNT_ARRAY global TIME_COUNT, array TIMER = 1 self.f_r = open("info", mode='r') self.frm = QFrame(self) self.frm.setStyleSheet("QWidget { background-color: %s }" % self.f_r.read(7)) self.frm.setGeometry(0, 0, 2000, 1000) self.setGeometry(400, 200, 500, 450) self.setWindowTitle('Формулы приведения') con = sqlite3.connect("name_users.db") cur = con.cursor() self.answer_name_label = QLabel(self) self.answer_name_label.setText("Введите ваш ответ: ") self.answer_name_label.resize(250, 50) self.answer_name_label.move(0, 380) self.f_r.seek(14) self.answer_name_label.setStyleSheet("QLabel {color: %s;}" % self.f_r.read(7)) self.rec_btn = QPushButton('Следующий', self) self.rec_btn.resize(480, 170) self.rec_btn.move(10, 200) self.f_r.seek(7) self.rec_btn.setStyleSheet( "QPushButton { background-color: %s; border: %s; color: %s}" % (self.f_r.read(7), None, self.f_r.read(7))) self.f_r.close() font = QtGui.QFont() font.setPointSize(17) self.rec_btn.setFont(font) self.rec_btn.clicked.connect(self.recursion) result = cur.execute("""SELECT * FROM Trigonometry WHERE Way like '%'""" ) if COUNT_ARRAY == 0: array = list(result) random.shuffle(array) self.true_answers = [] self.player_answers = [] self.way = array[COUNT_ARRAY] self.true_answers.append(self.way[1]) self.pixmap = QPixmap(self.way[0]) self.image = QLabel(self) self.image.move(85, 10) self.image.resize(330, 160) self.image.setPixmap(self.pixmap) self.answer_input = QLineEdit(self) self.answer_input.resize(150, 30) self.answer_input.move(160, 390) self.player_answers.append(self.answer_input.text()) self.lcdNumber = QLCDNumber(self) self.lcdNumber.setGeometry(QtCore.QRect(0, 0, 80, 35)) self.lcdNumber.move(400, 390) self.lcdNumber.setNumDigits(5) self.str1 = "{:0>2d}:{:0>2d}".format(begin // 60, begin % 60) self.lcdNumber.display(self.str1) self.timer = QTimer(self) self.timer.timeout.connect(self.showTime) self.timer.start(1000) con.commit() con.close() def recursion(self): global COUNT_TRIES_EQUATIONS, begin global COUNT_TRUES_EQUATIONS, COUNT_ARRAY self.timer.stop() if str(self.answer_input.text()) == str(self.true_answers[-1]): COUNT_TRUES_EQUATIONS += 1 COUNT_TRIES_EQUATIONS += 1 COUNT_ARRAY += 1 if COUNT_TRIES_EQUATIONS < 32: self.rec_form = Trigan_Window() self.rec_form.show() self.close() else: COUNT_ARRAY = 0 self.res_form = Trigan_Result_Window() self.res_form.show() self.close() def showTime(self): global begin begin = begin + 1 self.str1 = "{:0>2d}:{:0>2d}:{:0>2d}".format(begin // 3600, (begin % 3600) // 60, begin % 60) self.lcdNumber.display(self.str1)
class EnglishWordRelay(QWidget): def __init__(self, parent=None): super().__init__(parent) self.word = Word('words.txt') mainLayout = QGridLayout() # timer 관련 위젯 생성 lcdlbl = QLabel("Timer") lcdlbl.setAlignment(Qt.AlignRight) mainLayout.addWidget(lcdlbl, 0, 0) self.timeLcd = QLCDNumber() mainLayout.addWidget(self.timeLcd, 0, 1) self.timeLcd.setNumDigits(2) self.timeLcd.display('10') # score 관련 위젯 생성 scorelbl = QLabel("Score") mainLayout.addWidget(scorelbl, 0, 2) scorelbl.setAlignment(Qt.AlignRight) self.scoreLcd = QLineEdit() self.scoreLcd.setReadOnly(True) self.scoreLcd.setAlignment(Qt.AlignRight) font = self.scoreLcd.font() font.setPointSize(font.pointSize() + 15) self.scoreLcd.setFont(font) self.scoreLcd.setFixedWidth(100) mainLayout.addWidget(self.scoreLcd, 0, 3) # 단어 message 위젯 설정 self.message = QLineEdit() self.message.setReadOnly(True) self.message.setAlignment(Qt.AlignCenter) font = self.message.font() font.setPointSize(font.pointSize() + 8) self.message.setFont(font) self.message.setMaxLength(52) mainLayout.addWidget(self.message, 1, 0, 1, 4) # Input 위젯 설정 self.Input = QLineEdit() font = self.Input.font() font.setPointSize(font.pointSize() + 8) self.Input.setFont(font) self.Input.setMaxLength(20) # 게임에서 send 버튼의 클릭 기능을 엔터키로도 할 수 있게 기능 추가 self.Input.returnPressed.connect(self.sendClicked) mainLayout.addWidget(self.Input, 2, 0, 1, 3) # sendButton 위젯 설정 self.sendButton = QToolButton() self.sendButton.setText('Send') self.sendButton.clicked.connect(self.sendClicked) mainLayout.addWidget(self.sendButton, 2, 3) # newGameButton 위젯 설 newGameButton = QToolButton() newGameButton.setText('New Game') newGameButton.clicked.connect(self.startGame) mainLayout.addWidget(newGameButton, 3, 0) self.setLayout(mainLayout) self.setWindowTitle('English Word Relay Game') self.setFixedSize(400, 300) self.move(750, 300) # 게임 시작 self.startGame() def startGame(self): # 게임을 시작할 때마다 Timer, Score 클래스를 호출하여 제한 시간 10초, 점수 0점으로 초기화 self.timer = Timer(self.timeLcd, self.message, self.scoreLcd, self.sendButton, self.Input) self.scoreValue = Score() self.message.clear() self.Input.clear() self.message.setText(self.word.startRandFromDB()) self.scoreLcd.setText(str(self.scoreValue.score)) self.sendButton.setDisabled(False) self.Input.setReadOnly(False) def sendClicked(self): answer = self.Input.text() self.Input.clear() # 입력된 단어의 유효성 검사 if self.word.testWord(answer): # 사용자의 입력의 마지막 글자로 시작하는 다음 단어 출력 firstChar = answer.strip()[-1] self.message.setText(self.word.relayRandomFromDB(firstChar)) # 점수 추가 & 점수 출력 self.scoreValue.increaseScore(answer) self.scoreLcd.setText(str(self.scoreValue.score)) # 시간 초기화 if self.timer.gameTime > 0: self.timer.gameTime = 10
class Run_gui(QMainWindow): def __init__(self): super().__init__() self.cwd = os.getcwd() self.load_() # Enable antialiasing for prettier plots self.initUI() def initUI(self): ################### MENU BARS START ################## MyBar = QMenuBar(self) fileMenu = MyBar.addMenu("File") self.fileSave = fileMenu.addAction("Save thinfilm config") self.fileSave.triggered.connect(self.save_) self.fileSave.setShortcut('Ctrl+S') self.fileLoadAs = fileMenu.addAction("Load config section") self.fileLoadAs.triggered.connect(self.load_config_dialog) fileClose = fileMenu.addAction("Close") fileClose.triggered.connect(self.close) # triggers closeEvent() fileClose.setShortcut('Ctrl+X') self.loadMenu = MyBar.addMenu("Load data") loadSubOlis = self.loadMenu.addAction("OLIS sub") loadSubFilmOlis = self.loadMenu.addAction("OLIS sub + thin film") loadSubFTIR = self.loadMenu.addAction("FTIR sub") loadSubFilmFTIR = self.loadMenu.addAction("FTIR sub + thin film") loadSubOlis.triggered.connect(self.loadSubOlisDialog) loadSubFilmOlis.triggered.connect(self.loadSubFilmOlisDialog) loadSubFTIR.triggered.connect(self.loadSubFTIRDialog) loadSubFilmFTIR.triggered.connect(self.loadSubFilmFTIRDialog) self.emailMenu = MyBar.addMenu("E-mail") self.emailSettings = self.emailMenu.addAction("E-mail settings") self.emailSettings.triggered.connect(self.email_set_dialog) self.emailData = self.emailMenu.addAction("E-mail data") self.emailData.triggered.connect(self.email_data_dialog) helpMenu = MyBar.addMenu("Help") helpParam = helpMenu.addAction("Instructions") helpParam.triggered.connect(self.helpParamDialog) contact = helpMenu.addAction("Contact") contact.triggered.connect(self.contactDialog) ################### MENU BARS END ################## # status info which button has been pressed Start_lbl = QLabel("PLOTS and analysis steps", self) Start_lbl.setStyleSheet("color: blue") self.Step0_Button = QPushButton("Raw data", self) self.Step0_Button.setToolTip("STEP 0. Plot raw data for OLIS and FTIR") self.button_style(self.Step0_Button, 'black') self.Step1_Button = QPushButton("Tmin and Tmax", self) self.Step1_Button.setToolTip( "STEP 1. Find all the minima and maxima positions using Gaussian filter" ) self.button_style(self.Step1_Button, 'black') self.Step2_Button = QPushButton("Std.Dev. in d", self) self.Step2_Button.setToolTip( "STEP 2. Minimize standard deviation in the film thickness d") self.button_style(self.Step2_Button, 'black') self.Step3_Button = QPushButton("Index n", self) self.Step3_Button.setToolTip( "STEP 3. Plot refractive indicies n1 and n2") self.button_style(self.Step3_Button, 'black') self.Step4_Button = QPushButton("Absorption alpha", self) self.Step4_Button.setToolTip( "STEP 4. Plot abosorption alpha based on n2") self.button_style(self.Step4_Button, 'black') self.Step5_Button = QPushButton("Wavenumber k", self) self.Step5_Button.setToolTip("STEP 5. Plot wavenumber k based on n2") self.button_style(self.Step5_Button, 'black') #################################################### # status info which button has been pressed self.NewFiles = QLabel('No files created yet!', self) self.NewFiles.setStyleSheet("color: blue") newfont = QFont("Times", 10, QFont.Normal) self.NewFiles.setFont(newfont) ''' self.NewFiles = numpy.zeros(5,dtype=object) for i in range(4): self.NewFiles[i] = QLabel(''.join([str(i+1),': ']), self) self.NewFiles[i].setStyleSheet("color: magenta") ''' #################################################### loads_lbl = QLabel("RAW data files", self) loads_lbl.setStyleSheet("color: blue") configFile_lbl = QLabel("Current thinfilm", self) self.config_file_lbl = QLabel("", self) self.config_file_lbl.setStyleSheet("color: green") loadSubOlis_lbl = QLabel("OLIS sub", self) self.loadSubOlisFile_lbl = QLabel("", self) self.loadSubOlisFile_lbl.setStyleSheet("color: magenta") loadSubFilmOlis_lbl = QLabel("OLIS sub + thin film", self) self.loadSubFilmOlisFile_lbl = QLabel("", self) self.loadSubFilmOlisFile_lbl.setStyleSheet("color: magenta") loadSubFTIR_lbl = QLabel("FTIR sub", self) self.loadSubFTIRFile_lbl = QLabel("", self) self.loadSubFTIRFile_lbl.setStyleSheet("color: magenta") loadSubFilmFTIR_lbl = QLabel("FTIR sub + thin film", self) self.loadSubFilmFTIRFile_lbl = QLabel("", self) self.loadSubFilmFTIRFile_lbl.setStyleSheet("color: magenta") self.cb_sub_olis = QCheckBox('', self) self.cb_sub_olis.toggle() self.cb_subfilm_olis = QCheckBox('', self) self.cb_subfilm_olis.toggle() self.cb_sub_ftir = QCheckBox('', self) self.cb_sub_ftir.toggle() self.cb_subfilm_ftir = QCheckBox('', self) self.cb_subfilm_ftir.toggle() plot_X_lbl = QLabel("Plot X axis in", self) self.combo2 = QComboBox(self) self.mylist2 = ["eV", "nm"] self.combo2.addItems(self.mylist2) self.combo2.setFixedWidth(70) #################################################### lbl1 = QLabel("GAUSSIAN filter settings", self) lbl1.setStyleSheet("color: blue") interpol_lbl = QLabel("Interpolation method", self) self.combo4 = QComboBox(self) self.mylist4 = ["spline", "linear"] self.combo4.setToolTip( "Interpolation method for local minima Tmin and local maxima Tmax can only be linear or spline." ) self.combo4.addItems(self.mylist4) self.combo4.setFixedWidth(70) factors_lbl = QLabel("Gaussian factors", self) self.factorsEdit = QLineEdit("", self) self.factorsEdit.setToolTip( "HIGH gaussian factor = broadband noise filtering.\nLOW gaussian factor = narrowband noise filtering.\nHigh gauissian factors (>2) will result in relatively large deviation from the raw data.\nGauissian factors of zero or near zero (<0.5) will closely follow trend of the raw data." ) self.factorsEdit.setFixedWidth(200) borders_lbl = QLabel("Gaussian borders [eV]", self) self.bordersEdit = QLineEdit("", self) self.bordersEdit.setToolTip( "Gaussian borders should be typed in ascending order and the number of\nborders is always one more compared with the number of Gaussian factors." ) self.bordersEdit.setFixedWidth(200) ############################################## lbl2 = QLabel("ABSORPTION alpha and n1 and n2", self) lbl2.setStyleSheet("color: blue") poly_lbl = QLabel("Polyfit order", self) self.combo1 = QComboBox(self) self.mylist1 = ["1", "2", "3", "4", "5"] self.combo1.addItems(self.mylist1) self.combo1.setFixedWidth(70) polybord_lbl = QLabel("Polyfit range(s) [eV]", self) self.poly_bordersEdit = QLineEdit("", self) self.poly_bordersEdit.setFixedWidth(140) self.cb_polybord = QCheckBox('', self) self.cb_polybord.toggle() ignore_data_lbl = QLabel("No. of ignored points", self) self.ignore_data_ptsEdit = QLineEdit("", self) self.ignore_data_ptsEdit.setFixedWidth(140) corr_slit_lbl = QLabel("Correction slit width [nm]", self) self.corr_slitEdit = QLineEdit("", self) self.corr_slitEdit.setToolTip( "Finite spectrometer bandwidth (slit width) in the transmission spectrum." ) self.corr_slitEdit.setFixedWidth(140) ############################################## lbl4 = QLabel("STORAGE location (folder/file)", self) lbl4.setStyleSheet("color: blue") self.filenameEdit = QLineEdit("", self) #self.filenameEdit.setFixedWidth(180) self.cb_save_figs = QCheckBox('Save figs', self) self.cb_save_figs.toggle() ############################################## self.lcd = QLCDNumber(self) self.lcd.setStyleSheet("color: red") self.lcd.setFixedHeight(60) self.lcd.setSegmentStyle(QLCDNumber.Flat) self.lcd.setToolTip("Timetrace for saving files") self.lcd.setNumDigits(11) ############################################## self.initUI_() ############################################## # Add all widgets g1_0 = QGridLayout() g1_0.addWidget(MyBar, 0, 0) g1_1 = QGridLayout() g1_1.addWidget(loads_lbl, 0, 0) g1_1.addWidget(configFile_lbl, 1, 0) g1_1.addWidget(self.config_file_lbl, 1, 1) g1_1.addWidget(loadSubOlis_lbl, 2, 0) g1_1.addWidget(self.loadSubOlisFile_lbl, 2, 1) g1_1.addWidget(self.cb_sub_olis, 2, 2) g1_1.addWidget(loadSubFilmOlis_lbl, 3, 0) g1_1.addWidget(self.loadSubFilmOlisFile_lbl, 3, 1) g1_1.addWidget(self.cb_subfilm_olis, 3, 2) g1_1.addWidget(loadSubFTIR_lbl, 4, 0) g1_1.addWidget(self.loadSubFTIRFile_lbl, 4, 1) g1_1.addWidget(self.cb_sub_ftir, 4, 2) g1_1.addWidget(loadSubFilmFTIR_lbl, 5, 0) g1_1.addWidget(self.loadSubFilmFTIRFile_lbl, 5, 1) g1_1.addWidget(self.cb_subfilm_ftir, 5, 2) g1_1.addWidget(plot_X_lbl, 6, 0) g1_1.addWidget(self.combo2, 6, 1) g1_2 = QGridLayout() g1_2.addWidget(lbl1, 0, 0) g1_3 = QGridLayout() g1_3.addWidget(interpol_lbl, 0, 0) g1_3.addWidget(self.combo4, 0, 1) g1_3.addWidget(factors_lbl, 1, 0) g1_3.addWidget(self.factorsEdit, 1, 1) g1_3.addWidget(borders_lbl, 2, 0) g1_3.addWidget(self.bordersEdit, 2, 1) g1_4 = QGridLayout() g1_4.addWidget(lbl2, 0, 0) g1_5 = QGridLayout() g1_5.addWidget(poly_lbl, 0, 0) g1_5.addWidget(self.combo1, 0, 1) g1_5.addWidget(polybord_lbl, 1, 0) g1_5.addWidget(self.poly_bordersEdit, 1, 1) g1_5.addWidget(self.cb_polybord, 1, 2) g1_5.addWidget(ignore_data_lbl, 2, 0) g1_5.addWidget(self.ignore_data_ptsEdit, 2, 1) g1_5.addWidget(corr_slit_lbl, 3, 0) g1_5.addWidget(self.corr_slitEdit, 3, 1) g4_0 = QGridLayout() g4_0.addWidget(lbl4, 0, 0) g4_0.addWidget(self.cb_save_figs, 0, 1) g4_1 = QGridLayout() g4_1.addWidget(self.filenameEdit, 0, 0) v1 = QVBoxLayout() v1.addLayout(g1_0) v1.addLayout(g1_1) v1.addLayout(g1_2) v1.addLayout(g1_3) v1.addLayout(g1_4) v1.addLayout(g1_5) v1.addLayout(g4_0) v1.addLayout(g4_1) ################################################### g1_6 = QGridLayout() g1_6.addWidget(Start_lbl, 0, 0) g1_7 = QGridLayout() g1_7.addWidget(self.Step0_Button, 0, 0) g1_7.addWidget(self.Step1_Button, 1, 0) g1_7.addWidget(self.Step2_Button, 2, 0) g1_7.addWidget(self.Step3_Button, 3, 0) g1_7.addWidget(self.Step4_Button, 4, 0) g1_7.addWidget(self.Step5_Button, 5, 0) g1_8 = QGridLayout() g1_8.addWidget(self.NewFiles, 0, 0) g1_8.addWidget(self.lcd, 1, 0) v0 = QVBoxLayout() v0.addLayout(g1_6) v0.addLayout(g1_7) v0.addLayout(g1_8) # SET ALL VERTICAL COLUMNS TOGETHER hbox = QHBoxLayout() hbox.addLayout(v1) hbox.addLayout(v0) ############################################################################### # reacts to choises picked in the menu self.combo1.activated[str].connect(self.onActivated1) self.combo2.activated[str].connect(self.onActivated2) self.combo4.activated[str].connect(self.onActivated4) # reacts to choises picked in the menu self.Step0_Button.clicked.connect(self.set_run) self.Step1_Button.clicked.connect(self.set_run) self.Step2_Button.clicked.connect(self.set_run) self.Step3_Button.clicked.connect(self.set_run) self.Step4_Button.clicked.connect(self.set_run) self.Step5_Button.clicked.connect(self.set_run) # reacts to choises picked in the checkbox self.cb_sub_olis.stateChanged.connect(self.sub_olis_check) self.cb_subfilm_olis.stateChanged.connect(self.subfilm_olis_check) self.cb_sub_ftir.stateChanged.connect(self.sub_ftir_check) self.cb_subfilm_ftir.stateChanged.connect(self.subfilm_ftir_check) self.cb_save_figs.stateChanged.connect(self.save_figs_check) self.cb_polybord.stateChanged.connect(self.polybord_check) self.threadpool = QThreadPool() print("Multithreading in TEST_gui_v1 with maximum %d threads" % self.threadpool.maxThreadCount()) self.isRunning = False self.move(0, 0) #self.setGeometry(50, 50, 800, 500) hbox.setSizeConstraint(hbox.SetFixedSize) self.setWindowTitle("Swanepoel method for thin film analysis") w = QWidget() w.setLayout(hbox) self.setCentralWidget(w) self.show() def bool_(self, txt): if txt == "True": return True elif txt == "False": return False def initUI_(self): self.config_file_lbl.setText(self.last_used_scan) self.loadSubOlisFile_lbl.setText(self.loadSubOlis_str) self.loadSubFilmOlisFile_lbl.setText(self.loadSubFilmOlis_str) self.loadSubFTIRFile_lbl.setText(self.loadSubFTIR_str) self.loadSubFilmFTIRFile_lbl.setText(self.loadSubFilmFTIR_str) ############################################## self.sub_olis_check(self.loadSubOlis_check) self.cb_sub_olis.setChecked(self.loadSubOlis_check) self.subfilm_olis_check(self.loadSubFilmOlis_check) self.cb_subfilm_olis.setChecked(self.loadSubFilmOlis_check) self.sub_ftir_check(self.loadSubFTIR_check) self.cb_sub_ftir.setChecked(self.loadSubFTIR_check) self.subfilm_ftir_check(self.loadSubFilmFTIR_check) self.cb_subfilm_ftir.setChecked(self.loadSubFilmFTIR_check) self.save_figs_check(self.save_figs) self.cb_save_figs.setChecked(self.save_figs) self.filenameEdit.setText(self.filename_str) ############################################## if len(self.fit_poly_ranges) == 0: self.fit_poly_ranges_check = False self.polybord_check(self.fit_poly_ranges_check) self.cb_polybord.setChecked(self.fit_poly_ranges_check) else: self.polybord_check(self.fit_poly_ranges_check) self.cb_polybord.setChecked(self.fit_poly_ranges_check) ############################################## self.factorsEdit.setText(self.gaussian_factors) self.bordersEdit.setText(self.gaussian_borders) ############################################## self.combo1.setCurrentIndex(self.mylist1.index(self.fit_poly_order)) self.combo2.setCurrentIndex(self.mylist2.index(self.plot_X)) self.combo4.setCurrentIndex(self.mylist4.index(self.fit_linear_spline)) ############################################## self.poly_bordersEdit.setText(self.fit_poly_ranges) self.ignore_data_ptsEdit.setText(self.ignore_data_pts) self.corr_slitEdit.setText(self.corr_slit) ############################################## self.NewFiles.setToolTip(''.join([ "Display newly created and saved files in ", os.sep, self.filename_str, os.sep ])) self.lcd.display(self.timetrace) def button_style(self, button, color): button.setStyleSheet(''.join([ 'QPushButton {background-color: lightblue; font-size: 18pt; color: ', color, '}' ])) button.setFixedWidth(260) button.setFixedHeight(65) def loadSubOlisDialog(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog files, _ = QFileDialog.getOpenFileNames( self, "Open files", ''.join(['data', os.sep]), "All Files (*);;Dat Files (*.dat);;Text Files (*.txt)", options=options) for afile in files: head, tail = os.path.split(str(afile)) self.loadSubOlis_str = tail self.loadSubOlisFile_lbl.setText(tail) self.cb_sub_olis.setEnabled(True) self.loadSubOlis_check = True self.cb_sub_olis(self.loadSubOlis_check) def loadSubFilmOlisDialog(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog files, _ = QFileDialog.getOpenFileNames( self, "Open files", ''.join(['data', os.sep]), "All Files (*);;Dat Files (*.dat);;Text Files (*.txt)", options=options) for afile in files: head, tail = os.path.split(str(afile)) self.loadSubFilmOlis_str = tail self.loadSubFilmOlisFile_lbl.setText(tail) self.cb_subfilm_olis.setEnabled(True) self.loadSubFilmOlis_check = True self.cb_subfilm_olis(self.loadSubFilmOlis_check) def loadSubFTIRDialog(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog files, _ = QFileDialog.getOpenFileNames( self, "Open files", ''.join(['data', os.sep]), "All Files (*);;Dat Files (*.dat);;Text Files (*.txt)", options=options) for afile in files: head, tail = os.path.split(str(afile)) self.loadSubFTIR_str = tail self.loadSubFTIRFile_lbl.setText(tail) self.cb_sub_ftir.setEnabled(True) self.loadSubFTIR_check = True self.cb_sub_ftir(self.loadSubFTIR_check) def loadSubFilmFTIRDialog(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog files, _ = QFileDialog.getOpenFileNames( self, "Open files", ''.join(['data', os.sep]), "All Files (*);;Dat Files (*.dat);;Text Files (*.txt)", options=options) for afile in files: head, tail = os.path.split(str(afile)) self.loadSubFilmFTIR_str = tail self.loadSubFilmFTIRFile_lbl.setText(tail) self.cb_subfilm_ftir.setEnabled(True) self.loadSubFilmFTIR_check = True self.cb_subfilm_ftir.setChecked(self.loadSubFilmFTIR_check) def load_config_dialog(self): self.Load_config_dialog = Load_config_dialog.Load_config_dialog( self, self.config, self.load_, self.initUI_, self.cwd) self.Load_config_dialog.exec() def email_data_dialog(self): self.Send_email_dialog = Send_email_dialog.Send_email_dialog( self, self.cwd) self.Send_email_dialog.exec() def email_set_dialog(self): self.Email_dialog = Email_settings_dialog.Email_dialog( self, self.lcd, self.cwd) self.Email_dialog.exec() def helpParamDialog(self): helpfile = '' with open('config_Swanepoel_forklaringer.py', 'r') as f: for line in f: helpfile = helpfile + line msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText( "Apply the Swanepoel method using the following analysis steps:") msg.setInformativeText(helpfile) msg.setWindowTitle("Help") #msg.setDetailedText(helpfile) msg.setStandardButtons(QMessageBox.Ok) #msg.setGeometry(1000, 0, 1000+250, 350) msg.exec_() def contactDialog(self): QMessageBox.information( self, "Contact information", "Suggestions, comments or bugs can be reported to [email protected]" ) def onActivated1(self, text): self.fit_poly_order = int(text) def onActivated2(self, text): self.plot_X = str(text) def onActivated4(self, text): self.fit_linear_spline = str(text) def save_figs_check(self, state): if state in [Qt.Checked, True]: self.save_figs = True else: self.save_figs = False def sub_olis_check(self, state): if state in [Qt.Checked, True]: self.loadSubOlis_check = True self.loadSubOlisFile_lbl.setStyleSheet("color: magenta") self.cb_sub_olis.setText('incl') else: self.loadSubOlis_check = False self.loadSubOlisFile_lbl.setStyleSheet("color: grey") self.cb_sub_olis.setText('exc') def subfilm_olis_check(self, state): if state in [Qt.Checked, True]: self.loadSubFilmOlis_check = True self.loadSubFilmOlisFile_lbl.setStyleSheet("color: magenta") self.cb_subfilm_olis.setText('incl') else: self.loadSubFilmOlis_check = False self.loadSubFilmOlisFile_lbl.setStyleSheet("color: grey") self.cb_subfilm_olis.setText('exc') def sub_ftir_check(self, state): if state in [Qt.Checked, True]: self.loadSubFTIR_check = True self.loadSubFTIRFile_lbl.setStyleSheet("color: magenta") self.cb_sub_ftir.setText('incl') else: self.loadSubFTIR_check = False self.loadSubFTIRFile_lbl.setStyleSheet("color: grey") self.cb_sub_ftir.setText('exc') def subfilm_ftir_check(self, state): if state in [Qt.Checked, True]: self.loadSubFilmFTIR_check = True self.loadSubFilmFTIRFile_lbl.setStyleSheet("color: magenta") self.cb_subfilm_ftir.setText('incl') else: self.loadSubFilmFTIR_check = False self.loadSubFilmFTIRFile_lbl.setStyleSheet("color: grey") self.cb_subfilm_ftir.setText('exc') def polybord_check(self, state): if state in [Qt.Checked, True]: self.fit_poly_ranges_check = True self.poly_bordersEdit.setEnabled(True) self.cb_polybord.setText('incl') else: self.fit_poly_ranges_check = False self.poly_bordersEdit.setEnabled(False) self.cb_polybord.setText('exc') ############################################################ # Check input if a number, ie. digits or fractions such as 3.141 # Source: http://www.pythoncentral.io/how-to-check-if-a-string-is-a-number-in-python-including-unicode/ def is_int(self, s): try: int(s) return True except ValueError: return False def is_number(self, s): try: float(s) return True except ValueError: pass try: import unicodedata unicodedata.numeric(s) return True except (TypeError, ValueError): pass return False def create_file(self, mystr): head, ext = os.path.splitext(mystr) totalpath = ''.join([self.cwd, os.sep, head, '_', self.timetrace]) my_dir = os.path.dirname(totalpath) if not os.path.isdir(my_dir): QMessageBox.warning( self, "Message", "".join(["Folder(s) named ", my_dir, " will be created!"])) try: os.makedirs(my_dir, exist_ok=True) except Exception as e: QMessageBox.critical( self, "Message", "".join(["Folder named ", head, " not valid!\n\n", str(e)])) return "" return totalpath def set_run(self): # Save all the currently changed varaibles self.save_() # Register the sender of the command (a button or similar) sender = self.sender() ## gaussian_borders and gaussian_factors warnings and errors gaus_bord = str(self.bordersEdit.text()).split(',') for tal in gaus_bord: if not self.is_number(tal): QMessageBox.critical(self, 'Message', "Gaussian borders must be real numbers!") return elif float(tal) < 0.0: QMessageBox.critical( self, 'Message', "Gaussian borders must be positive or zero!") return if len(gaus_bord) < 2: QMessageBox.critical( self, 'Message', "You must enter at least 2 gaussian borders!") return if not numpy.array_equal([numpy.float(i) for i in gaus_bord], numpy.sort( [numpy.float(i) for i in gaus_bord])): QMessageBox.critical( self, 'Message', "The gaussian borders must be entered in the ascending order!") return gaus_fact = str(self.factorsEdit.text()).split(',') for tal in gaus_fact: if not self.is_number(tal): QMessageBox.critical(self, 'Message', "Gaussian factors must be real numbers!") return elif float(tal) < 0.0: QMessageBox.critical( self, 'Message', "Gaussian factors must be positive or zero!") return if len(gaus_fact) < 1: QMessageBox.critical(self, 'Message', "You must enter at least 1 gaussian factor!") return if len(gaus_bord) != len(gaus_fact) + 1: QMessageBox.critical( self, 'Message', "The number of gaussian factors is exactly one less than the number of gaussian borders!" ) return ## ignored data points warnings and errors ign_pts = str(self.ignore_data_ptsEdit.text()) if not self.is_int(ign_pts): QMessageBox.critical( self, 'Message', "The number of ignored points is an integer!") return elif int(ign_pts) < 0: QMessageBox.critical( self, 'Message', "The number of ignored points is a positive integer!") return ## correction slit width warnings and errors corr_pts = str(self.corr_slitEdit.text()) if not self.is_number(corr_pts): QMessageBox.critical( self, 'Message', "The correction slit width is a real number!") return elif float(corr_pts) < 0: QMessageBox.critical( self, 'Message', "The correction slit width is a positive number!") return ## fit_poly_ranges warnings and errors if self.fit_poly_ranges_check == True: polyfit_bord = str(self.poly_bordersEdit.text()).split(',') for tal in polyfit_bord: if not self.is_number(tal): QMessageBox.critical( self, 'Message', "The polyfit range enteries must be real numbers!") return elif float(tal) < 0.0: QMessageBox.critical( self, 'Message', "The polyfit range enteries must be positive or zero!") return if len(polyfit_bord) < 2 or len(polyfit_bord) % 2 != 0: QMessageBox.critical( self, 'Message', "The polyfit range list accepts minimum 2 or even number of enteries!" ) return if not numpy.array_equal( [numpy.float(i) for i in polyfit_bord], numpy.sort([numpy.float(i) for i in polyfit_bord])): QMessageBox.critical( self, 'Message', "The polyfit range list must be entered in ascending order!" ) return # When all user defined enteries are approved save the data self.create_file(str(self.filenameEdit.text())) if sender.text() != 'Raw data': ## raw data files warnings and errors if not self.loadSubOlis_check and not self.loadSubFilmOlis_check: pass elif self.loadSubOlis_check and self.loadSubFilmOlis_check: pass else: QMessageBox.critical( self, 'Message', "Select both OLIS data files subfilmRAW and subRAW!") return if not self.loadSubFTIR_check and not self.loadSubFilmFTIR_check: pass elif self.loadSubFTIR_check and self.loadSubFilmFTIR_check: pass else: QMessageBox.critical( self, 'Message', "Select both FTIR data files subfilmRAW and subRAW!") return if not self.loadSubOlis_check and not self.loadSubFilmOlis_check and not self.loadSubFTIR_check and not self.loadSubFilmFTIR_check: QMessageBox.critical(self, 'Message', "No data files selected!") return if sender.text() == 'Raw data': if not self.loadSubOlis_check and not self.loadSubFilmOlis_check and not self.loadSubFTIR_check and not self.loadSubFilmFTIR_check: QMessageBox.critical(self, 'Message', "No raw data files selected!") return self.button_style(self.Step0_Button, 'red') self.button_style(self.Step1_Button, 'grey') self.button_style(self.Step2_Button, 'grey') self.button_style(self.Step3_Button, 'grey') self.button_style(self.Step4_Button, 'grey') self.button_style(self.Step5_Button, 'grey') elif sender.text() == 'Tmin and Tmax': self.button_style(self.Step1_Button, 'red') self.button_style(self.Step0_Button, 'grey') self.button_style(self.Step2_Button, 'grey') self.button_style(self.Step3_Button, 'grey') self.button_style(self.Step4_Button, 'grey') self.button_style(self.Step5_Button, 'grey') elif sender.text() == 'Std.Dev. in d': self.button_style(self.Step2_Button, 'red') self.button_style(self.Step0_Button, 'grey') self.button_style(self.Step1_Button, 'grey') self.button_style(self.Step3_Button, 'grey') self.button_style(self.Step4_Button, 'grey') self.button_style(self.Step5_Button, 'grey') elif sender.text() == 'Index n': self.button_style(self.Step3_Button, 'red') self.button_style(self.Step0_Button, 'grey') self.button_style(self.Step1_Button, 'grey') self.button_style(self.Step2_Button, 'grey') self.button_style(self.Step4_Button, 'grey') self.button_style(self.Step5_Button, 'grey') elif sender.text() == 'Absorption alpha': self.button_style(self.Step4_Button, 'red') self.button_style(self.Step0_Button, 'grey') self.button_style(self.Step1_Button, 'grey') self.button_style(self.Step2_Button, 'grey') self.button_style(self.Step3_Button, 'grey') self.button_style(self.Step5_Button, 'grey') elif sender.text() == 'Wavenumber k': self.button_style(self.Step5_Button, 'red') self.button_style(self.Step0_Button, 'grey') self.button_style(self.Step1_Button, 'grey') self.button_style(self.Step2_Button, 'grey') self.button_style(self.Step3_Button, 'grey') self.button_style(self.Step4_Button, 'grey') else: return worker = Worker(sender.text(), self.cwd) worker.signals.pass_plots.connect(self.pass_plots) worker.signals.critical.connect(self.critical) worker.signals.finished.connect(self.finished) # Execute self.threadpool.start(worker) self.isRunning = True def pass_plots(self, obj): self.my_plots, sender = obj my_str = 'Data files:\n' try: self.datafiles = self.my_plots.make_plots() for i, ii in zip(self.datafiles, range(len(self.datafiles))): head, tail = os.path.split(i) my_str += ''.join([str(ii + 1), ': ', tail, '\n']) self.NewFiles.setText(my_str) self.my_plots.show_plots() except Exception as inst: QMessageBox.critical(self, 'Message', str(inst)) def load_(self): # Initial read of the config file self.config = configparser.ConfigParser() try: self.config.read(''.join([self.cwd, os.sep, "config.ini"])) self.last_used_scan = self.config.get('LastScan', 'last_used_scan') self.loadSubOlis_str = self.config.get( self.last_used_scan, "loadsubolis").strip().split(':')[0] self.loadSubOlis_check = self.bool_( self.config.get(self.last_used_scan, 'loadsubolis').strip().split(':')[1]) self.loadSubFilmOlis_str = self.config.get( self.last_used_scan, 'loadsubfilmolis').strip().split(':')[0] self.loadSubFilmOlis_check = self.bool_( self.config.get(self.last_used_scan, 'loadsubfilmolis').strip().split(':')[1]) self.loadSubFTIR_str = self.config.get( self.last_used_scan, 'loadsubftir').strip().split(':')[0] self.loadSubFTIR_check = self.bool_( self.config.get(self.last_used_scan, 'loadsubftir').strip().split(':')[1]) self.loadSubFilmFTIR_str = self.config.get( self.last_used_scan, 'loadsubfilmftir').strip().split(':')[0] self.loadSubFilmFTIR_check = self.bool_( self.config.get(self.last_used_scan, 'loadsubfilmftir').strip().split(':')[1]) self.fit_linear_spline = self.config.get(self.last_used_scan, 'fit_linear_spline') self.gaussian_factors = self.config.get(self.last_used_scan, 'gaussian_factors') self.gaussian_borders = self.config.get(self.last_used_scan, 'gaussian_borders') self.ignore_data_pts = self.config.get(self.last_used_scan, 'ignore_data_pts') self.corr_slit = self.config.get(self.last_used_scan, 'corr_slit') self.fit_poly_order = self.config.get(self.last_used_scan, 'fit_poly_order') self.fit_poly_ranges = self.config.get( self.last_used_scan, 'fit_poly_ranges').strip().split(':')[0] self.fit_poly_ranges_check = self.bool_( self.config.get(self.last_used_scan, 'fit_poly_ranges').strip().split(':')[1]) self.filename_str = self.config.get(self.last_used_scan, 'filename') self.timetrace = self.config.get(self.last_used_scan, 'timetrace') self.save_figs = self.bool_( self.config.get(self.last_used_scan, 'save_figs')) self.plot_X = self.config.get(self.last_used_scan, 'plot_x') self.emailset_str = self.config.get(self.last_used_scan, 'emailset').strip().split(',') self.emailrec_str = self.config.get(self.last_used_scan, 'emailrec').strip().split(',') except configparser.NoOptionError as nov: QMessageBox.critical( self, 'Message', ''.join([ "Main FAULT while reading the config.ini file\n", str(nov) ])) raise def save_(self): self.timetrace = time.strftime("%y%m%d-%H%M") self.lcd.display(self.timetrace) self.config.read(''.join([self.cwd, os.sep, "config.ini"])) self.config.set('LastScan', "last_used_scan", self.last_used_scan) self.config.set( self.last_used_scan, "loadSubOlis", ':'.join([self.loadSubOlis_str, str(self.loadSubOlis_check)])) self.config.set( self.last_used_scan, "loadSubFilmOlis", ':'.join( [self.loadSubFilmOlis_str, str(self.loadSubFilmOlis_check)])) self.config.set( self.last_used_scan, "loadSubFTIR", ':'.join([self.loadSubFTIR_str, str(self.loadSubFTIR_check)])) self.config.set( self.last_used_scan, "loadSubFilmFTIR", ':'.join( [self.loadSubFilmFTIR_str, str(self.loadSubFilmFTIR_check)])) self.config.set(self.last_used_scan, "fit_linear_spline", self.fit_linear_spline) self.config.set(self.last_used_scan, "gaussian_factors", str(self.factorsEdit.text())) self.config.set(self.last_used_scan, "gaussian_borders", str(self.bordersEdit.text())) self.config.set(self.last_used_scan, "ignore_data_pts", str(self.ignore_data_ptsEdit.text())) self.config.set(self.last_used_scan, "corr_slit", str(self.corr_slitEdit.text())) self.config.set(self.last_used_scan, "fit_poly_order", str(self.fit_poly_order)) self.config.set( self.last_used_scan, "fit_poly_ranges", ':'.join([ str(self.poly_bordersEdit.text()), str(self.fit_poly_ranges_check) ])) self.config.set(self.last_used_scan, "filename", str(self.filenameEdit.text())) self.config.set(self.last_used_scan, "timetrace", self.timetrace) self.config.set(self.last_used_scan, "save_figs", str(self.save_figs)) self.config.set(self.last_used_scan, "plot_x", self.plot_X) with open(''.join([self.cwd, os.sep, "config.ini"]), "w") as configfile: self.config.write(configfile) def finished(self): self.my_plots.close_plots() self.load_() if self.emailset_str[1] == "yes": self.send_notif() if self.emailset_str[2] == "yes": self.send_data() self.button_style(self.Step0_Button, 'black') self.button_style(self.Step1_Button, 'black') self.button_style(self.Step2_Button, 'black') self.button_style(self.Step3_Button, 'black') self.button_style(self.Step4_Button, 'black') self.button_style(self.Step5_Button, 'black') self.isRunning = False def allButtons_torf(self, trueorfalse, *argv): if argv[0] == 'allfalse': self.cb_sub_olis.setEnabled(False) self.cb_subfilm_olis.setEnabled(False) self.cb_sub_ftir.setEnabled(False) self.cb_subfilm_ftir.setEnabled(False) self.poly_bordersEdit.setEnabled(False) self.fileSave.setEnabled(trueorfalse) self.loadMenu.setEnabled(trueorfalse) self.emailMenu.setEnabled(trueorfalse) self.cb_save_figs.setEnabled(trueorfalse) self.cb_polybord.setEnabled(trueorfalse) self.Step0_Button.setEnabled(trueorfalse) self.Step1_Button.setEnabled(trueorfalse) self.Step2_Button.setEnabled(trueorfalse) self.Step3_Button.setEnabled(trueorfalse) self.Step4_Button.setEnabled(trueorfalse) self.Step5_Button.setEnabled(trueorfalse) self.combo1.setEnabled(trueorfalse) self.combo2.setEnabled(trueorfalse) self.combo4.setEnabled(trueorfalse) self.factorsEdit.setEnabled(trueorfalse) self.bordersEdit.setEnabled(trueorfalse) self.ignore_data_ptsEdit.setEnabled(trueorfalse) self.corr_slitEdit.setEnabled(trueorfalse) self.filenameEdit.setEnabled(trueorfalse) def warning(self, mystr): QMessageBox.warning(self, "Message", mystr) def send_notif(self): contents = [ "The scan is done. Please visit the experiment site and make sure that all light sources are switched off." ] subject = "The scan is done" obj = type( "obj", (object, ), { "subject": subject, "contents": contents, "settings": self.emailset_str, "receivers": self.emailrec_str }) worker = Send_Email_Worker(obj) worker.signals.critical.connect(self.critical) worker.signals.warning.connect(self.warning) worker.signals.finished.connect(self.finished1) # Execute self.md = Indicator_dialog.Indicator_dialog( self, "...sending notification...", "indicators/ajax-loader-ball.gif") self.threadpool.start(worker) self.isRunning = True def send_data(self): contents = [ "The scan is done and the logged data is attached to this email. Please visit the experiment site and make sure that all light sources are switched off." ] contents.extend(self.datafiles) subject = "The scan data from the latest scan!" obj = type( "obj", (object, ), { "subject": subject, "contents": contents, "settings": self.emailset_str, "receivers": self.emailrec_str }) worker = Send_Email_Worker(obj) worker.signals.critical.connect(self.critical) worker.signals.warning.connect(self.warning) worker.signals.finished.connect(self.finished1) # Execute self.md = Indicator_dialog.Indicator_dialog( self, "...sending files...", "indicators/ajax-loader-ball.gif") self.threadpool.start(worker) self.isRunning = True def finished1(self): self.isRunning = False self.md.close_() def critical(self, mystr): QMessageBox.critical(self, 'Message', mystr) def closeEvent(self, event): reply = QMessageBox.question(self, 'Message', "Quit now?", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: if self.isRunning: QMessageBox.warning( self, 'Message', "Analysis in progress. Wait the analysis to finish and then quit!" ) event.ignore() else: event.accept() elif reply == QMessageBox.No: event.ignore()
class TabMatch(QWidget): def __init__(self): super(TabMatch, self).__init__() layout = QVBoxLayout() self.setLayout(layout) self.LCD = QLCDNumber() self.LCD.setNumDigits(4) self.LCD.display("0:00") layout.addWidget(self.LCD) #sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) #sizePolicy.setHorizontalStretch(0) #sizePolicy.setVerticalStretch(0) #self.LCD.setSizePolicy(sizePolicy) hbox = QHBoxLayout() self.cmbTeam1 = QComboBox() self.empty = QLabel() self.versus = QLabel() self.cmbTeam2 = QComboBox() img = QPixmap('./gui/res/vs.png') self.versus.setPixmap(img) img = QPixmap('./gui/res/null.png') self.empty.setPixmap(img) #hbox.addWidget(self.cmbTeam1) #hbox.addWidget(self.versus) #hbox.addWidget(self.cmbTeam2) #layout.addLayout(hbox) aux = QHBoxLayout() aux.addStretch(0) aux.addWidget(self.versus) aux.addStretch(0) sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) self.versus.setSizePolicy(sizePolicy) layout.addWidget(self.cmbTeam1) layout.addLayout(aux) layout.addWidget(self.cmbTeam2) hbox = QHBoxLayout() self.btnPlay = QPushButton() icon = QIcon('./gui/res/play_icon.png') self.btnPlay.setIcon(icon) self.btnStop = QPushButton() icon = QIcon('./gui/res/stop_icon.png') self.btnStop.setIcon(icon) hbox.addWidget(self.btnPlay) hbox.addWidget(self.btnStop) layout.addLayout(hbox) self.show()
class MainWindow(QWidget): def __init__(self): super().__init__() self.backlogMgr = BacklogMgr() self.initUI() def initUI(self): self.setWindowTitle("TurboClock") self.resize(400, 300) self.setWindowIcon(QIcon('Images//clock.png')) self.icon = QSystemTrayIcon(self) self.icon.setIcon(QIcon('Images//clock.png')) self.icon.setVisible(True) self.lcdNumber = QLCDNumber() self.lcdNumber.setNumDigits(8) self.btnStartPause = QPushButton('', self) self.btnStartPause.setIcon(QIcon('Images//play_icon.png')) self.btnStartPause.clicked.connect(self.manageStartPauseClickedEvent) self.btnDutyDetails = QPushButton('Duty details...') self.btnDutyDetails.clicked.connect(self.manageDutyDetailsClickedEvent) self.btnAddTfsTask = QPushButton('', self) self.btnAddTfsTask.setIcon(QIcon('Images//plus_icon.png')) self.btnAddTfsTask.clicked.connect(self.manageEditTasksOptions) self.progressBar = QProgressBar() self.progressBar.setValue(0) self.dutyTimeCompLbl = QLabel() self.currTaskItemRow = 0 self.taskTFSCb = QComboBox(self) self.initTFSTaskCombobox() mainLayout = QVBoxLayout(self) layoutTimer = QVBoxLayout() layoutTimer.addWidget(self.lcdNumber) fieldsInputLayout = QHBoxLayout() layoutInputCodes = QVBoxLayout() layoutInputCodes.addWidget(self.taskTFSCb) layoutAddBtn = QVBoxLayout() layoutAddBtn.addWidget(self.btnAddTfsTask) fieldsInputLayout.addLayout(layoutInputCodes) fieldsInputLayout.addLayout(layoutAddBtn) layoutDutyStat = QHBoxLayout() layoutDutyStat.addWidget(self.dutyTimeCompLbl) layoutProgressBar = QHBoxLayout() layoutProgressBar.addWidget(self.progressBar) mainLayout.addLayout(layoutTimer) mainLayout.addLayout(fieldsInputLayout) mainLayout.addWidget(self.btnStartPause) mainLayout.addWidget(self.btnDutyDetails) mainLayout.addWidget(self.progressBar) mainLayout.addLayout(layoutDutyStat) self.timer = QTimer(self) self.deltaTimer = 0 self.currTimeLCD = QTime(0, 0, 0) self.currTimeDuty = QTime(0, 0, 0) self.timer.timeout.connect(self.incrementTimer) self.updateTimeLCD() self.updateDutyTimeDisp() self.updateProgressBarDisplay() self.startTime = 0 self.stopTime = 0 self.editTasksGUI = EditTasksOptionsGUI(self, self.backlogMgr) def initTFSTaskCombobox(self): self.updateTaskCombobox() self.taskTFSCb.currentIndexChanged.connect(self.manageCbTFSIndexChange) def updateProgressBarDisplay(self): estimatedTime = self.backlogMgr.backlogData.currTask.estimatedTime if estimatedTime == 0: return ratioFromTimer = (self.deltaTimer / estimatedTime) * 100 totalCompletionRatio = self.backlogMgr.getCompletionRatio( self.backlogMgr.backlogData.currTaskIndex) + ratioFromTimer if totalCompletionRatio <= 100: self.progressBar.setValue(totalCompletionRatio) else: self.progressBar.setValue(100) def updateTaskCombobox(self): currTaskIndex = self.currTaskItemRow self.taskTFSCb.clear() taskList = self.backlogMgr.getTasksFromGUI() for currTask in taskList: taskDesc = currTask.title + ' (' + currTask.prjCode + ')' self.taskTFSCb.addItem(taskDesc) self.taskTFSCb.setCurrentIndex(currTaskIndex) self.backlogMgr.setCurrentTaskFromGUI(currTaskIndex) def manageCbTFSIndexChange(self): self.currTaskItemRow = self.taskTFSCb.currentIndex() if self.currTaskItemRow >= 0: self.backlogMgr.manageTaskChangeFromGUI(self.currTaskItemRow) self.updateTimeLCD() self.deltaTimer = 0 self.updateProgressBarDisplay() def updateTimeLCD(self): currTaskTime_split = self.backlogMgr.getCompletedTimeCurrTaskFromGUI( ).split(':') h = int(currTaskTime_split[0]) m = int(currTaskTime_split[1]) s = int(currTaskTime_split[2]) self.currTimeLCD = QTime(h, m, s) self.lcdNumber.display(self.currTimeLCD.toString('hh:mm:ss')) def updateDutyTimeDisp(self): currTaskTime_split = self.backlogMgr.getCurrDutyTimeCompletedFromGUI( ).split(':') h = int(currTaskTime_split[0]) m = int(currTaskTime_split[1]) s = int(currTaskTime_split[2]) self.currTimeDuty = QTime(h, m, s) self.dutyTimeCompLbl.setText('Daily time completed: ' + self.currTimeDuty.toString('hh:mm:ss')) def incrementTimer(self): self.currTimeLCD = self.currTimeLCD.addSecs(1) self.lcdNumber.display(self.currTimeLCD.toString('hh:mm:ss')) self.currTimeDuty = self.currTimeDuty.addSecs(1) self.dutyTimeCompLbl.setText('Daily time completed: ' + self.currTimeDuty.toString('hh:mm:ss')) self.deltaTimer += 1 self.updateProgressBarDisplay() def manageStartPauseClickedEvent(self): self.backlogMgr.manageClickButtonFromGUI() self.deltaTimer = 0 if self.timer.isActive(): self.timer.stop() self.btnStartPause.setIcon(QIcon('Images//play_icon.png')) else: self.timer.start(1000) self.btnStartPause.setIcon(QIcon('Images//pause_icon.png')) def manageDutyDetailsClickedEvent(self): ex = DutyDetailsWindow(self, self.backlogMgr.backlogData) ex.show() def manageEditTasksOptions(self): self.editTasksGUI.exec_() self.updateTaskCombobox() def closeEvent(self, event): event.accept()
class MainWindow(QMainWindow): """ Mainwindow class operates the pyqt5 window and all of its widgets. It also hosts most of the basic methods connected to the widgets. There are start and stop methods, and a waiter thread that keeps an eye on the finite measurement. Settings typed by the user get stored in a dictionary class and get updated before each measurement call. Mainwindow launches all of the subprocesses connecting to the daqmx cards. Communication between threads and mainwindow is established via pyqtSignals, between mainwindow and subprocesses via multiprocessing queue. The main control variable for measurements is a multiprocessing event variable. """ def __init__(self): super(MainWindow, self).__init__() """ Init hosts all the variables and UI related functionality. The following classes can not be initializes in here, because they inherit from multiprocessing.Process: libs.Counter, libs.Laser and libs.dataProcesser. Arguments have to be passed by inheritance, later there's no possibility, due to their separation from the main loop. libs.Animation also gets instanciated later, due to the window launching functionality in its init method. """ self._dict = libs.UIsettings.UIsettings() self._files = libs.SaveFiles.SaveFiles() self._changeRA = libs.ChangeReadArray.ChangeReadArray() self._timetrace = libs.Timetraces.Timetrace() self._r = libs.Refresh.Refresh() self._readArraySize = int(1e3) # Queues, Semaphores and Events all derived from the multiprocessing library self._dataQ1 = mpQueue() self._dataQ2 = mpQueue() self._animDataQ1 = mpQueue() self._animDataQ2 = mpQueue() self._running = mpEvent() self._semaphore = Semaphore(3) # pyqtSignals self.signal = Communicate() self.signal.stopMeasurement.connect(self.stopBtn) self.signal.measurementProgress.connect(lambda x: self.setProgressBar(x)) self.signal.warning.connect(self.warnPopUp) self.signal.displayRates.connect(lambda x: self.displayRatesOnLCD(x)) self.signal.convertDone.connect(lambda: self.statusBar.showMessage('Conversion done!')) self.signal.alreadyConverted.connect(lambda: self.statusBar.showMessage('Already converted!')) self.signal.noData.connect(lambda: self.statusBar.showMessage('No data files in this directory!')) # ################## # # Window and widgets # # ################## # self.setGeometry(500, 300, 500, 200) # x, y, width, height self.setWindowTitle('ALEX') # ## Statusbar self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.statusBar.showMessage("idle") # ## file menue # load app, loads laser settings from file self.loadApp = QAction('Load settings', self) self.loadApp.setShortcut('Ctrl+l') self.loadApp.triggered.connect(self.loadDict) # save app, saves measurement settings to file self.saveApp = QAction('Save settings', self) self.saveApp.setShortcut('Ctrl+s') self.saveApp.triggered.connect(lambda: self._files.saveSetsDict(self._dict._a, self.getDirectory(), 'Measurement_settings')) # convert data to photon-hdf5 self.convertData = QAction('Convert raw data to photon-hdf5', self) self.convertData.setShortcut('Ctrl+c') self.convertData.triggered.connect(lambda: self._files.convertToPhotonHDF5(self.getDirectory(), self.signal)) # change ReadArray size self.setArraySize = QAction('Read arrays size', self) self.setArraySize.setShortcut('Ctrl+a') self.setArraySize.triggered.connect(self.changeArraySize) # close the app self.closeApp = QAction('Close', self) self.closeApp.setShortcut('Ctrl+q') self.closeApp.triggered.connect(self.closeApplication) self.menueLayout() # ## GroupBox Directory: # Group contains: # - Location display QLineEdit # - Browse directories QPushButton filesGroup = QGroupBox('Directory') hbox12 = QHBoxLayout() filesGroup.setLayout(hbox12) self._location = QLineEdit() self._location.setToolTip("Please select a directory. If you do not, the data will not be saved!") self._location.setMaxLength(100) self._location.setReadOnly(True) hbox12.addWidget(self._location) hbox12.setSpacing(10) self._browseButton = QPushButton('Browse', self) self._browseButton.clicked.connect(self.getFileLocation) hbox12.addWidget(self._browseButton) # ## label for different widgets self.label1 = QLabel("Laserpower green") self.label2 = QLabel("Laserpower red") self.label3 = QLabel("Ratio of illumination\ngreen/red") self.label4 = QLabel("ALEX\nfrequency [Hz]") self.label5 = QLabel("Measurement\nduration [s]") self.label6 = QLabel("Measurement mode") self.label7 = QLabel("Counts in green channel") self.label8 = QLabel("Counts in red channel") self.label9 = QLabel("% Green") self.label10 = QLabel("% Red") # ## GroupBox Laser: # Group contains: # - Laser power red slider # - Laser power red spinbox # - Laser power green slider # - Laser power green spinbox # - Laser period percentage slider # - Laser period percentage red spinbox # - Laser period percentage green spinbox laserGroup = QGroupBox("Laser settings") hbox1 = QHBoxLayout() hbox1.setSpacing(30) hbox2 = QHBoxLayout() hbox2.setSpacing(30) hbox9 = QHBoxLayout() hbox11 = QHBoxLayout() hbox11.setSpacing(30) hbox10 = QHBoxLayout() hbox10.setSpacing(30) vbox1 = QVBoxLayout() vbox1.addWidget(self.label2) vbox1.addLayout(hbox1) vbox1.addStretch(1) vbox1.addWidget(self.label1) vbox1.addLayout(hbox2) vbox1.addStretch(1) vbox1.addWidget(self.label3) vbox1.addLayout(hbox9) vbox1.addStretch(1) vbox1.addLayout(hbox11) vbox1.addStretch(1) vbox1.addLayout(hbox10) vbox1.addStretch(1) laserGroup.setLayout(vbox1) hbox11.addWidget(self.label9) hbox11.addWidget(self.label10) # Laserpower slider red self.sld_red = QSlider(Qt.Horizontal, self) self.sld_red.setFocusPolicy(Qt.NoFocus) self.sld_red.setGeometry(80, 20, 50, 10) self.sld_red.setMinimum(0) self.sld_red.setMaximum(100) self.sld_red.setValue(50) self.sld_red.setTickPosition(QSlider.TicksBelow) self.sld_red.setTickInterval(20) self.sld_red.valueChanged.connect(lambda: self.refreshUI(0, 'sld_red', self.sld_red.value())) hbox1.addWidget(self.sld_red) # Laserpower QSpinBox red self.sb_red = QSpinBox(self) self.sb_red.setMinimum(0) self.sb_red.setMaximum(100) self.sb_red.setValue(50) self.sb_red.valueChanged.connect(lambda: self.refreshUI(1, 'sb_red', self.sb_red.value())) hbox1.addWidget(self.sb_red) # Laserpower slider green self.sld_green = QSlider(Qt.Horizontal, self) self.sld_green.setFocusPolicy(Qt.NoFocus) self.sld_green.setGeometry(160, 40, 100, 30) self.sld_green.setMinimum(0) self.sld_green.setMaximum(100) self.sld_green.setValue(50) self.sld_green.setTickPosition(QSlider.TicksBelow) self.sld_green.setTickInterval(20) self.sld_green.valueChanged.connect(lambda: self.refreshUI(0, 'sld_green', self.sld_green.value())) hbox2.addWidget(self.sld_green) # Laserpower QSpinBox green self.sb_green = QSpinBox(self) self.sb_green.setMinimum(0) self.sb_green.setMaximum(100) self.sb_green.setValue(50) self.sb_green.valueChanged.connect(lambda: self.refreshUI(1, 'sb_green', self.sb_green.value())) hbox2.addWidget(self.sb_green) # Illumination percentage slider self.sld_percentage = QSlider(Qt.Horizontal, self) self.sld_percentage.setFocusPolicy(Qt.NoFocus) self.sld_percentage.setGeometry(160, 40, 100, 30) self.sld_percentage.setMinimum(0) self.sld_percentage.setMaximum(100) self.sld_percentage.setTickPosition(QSlider.TicksBelow) self.sld_percentage.setTickInterval(10) self.sld_percentage.setValue(50) self.sld_percentage.valueChanged.connect(lambda: self.refreshUI(0, 'sld_percentage', self.sld_percentage.value())) hbox9.addWidget(self.sld_percentage) # Illumination percentage QSpinBox green self.sb_percentG = QSpinBox(self) self.sb_percentG.setMinimum(0) self.sb_percentG.setMaximum(100) self.sb_percentG.setValue(50) self.sb_percentG.valueChanged.connect(lambda: self.refreshUI(1, 'sb_percentG', self.sb_percentG.value())) hbox10.addWidget(self.sb_percentG) # Illumination QSpinBox red self.sb_percentR = QSpinBox(self) self.sb_percentR.setMinimum(0) self.sb_percentR.setMaximum(100) self.sb_percentR.setValue(50) self.sb_percentR.valueChanged.connect(lambda: self.refreshUI(1, 'sb_percentR', self.sb_percentR.value())) hbox10.addWidget(self.sb_percentR) # ## APD GroupBox # Group contains: # - Laser alternation frequency spinbox # - Measurement mode continuous radiobutton # - Measurement mode finite radiobutton # - Measurement duration spinbox apdGroup = QGroupBox("Measurement") hbox3 = QHBoxLayout() hbox3.setSpacing(30) hbox4 = QHBoxLayout() hbox4.setSpacing(30) hbox5 = QHBoxLayout() hbox5.setSpacing(30) vbox2 = QVBoxLayout() vbox2.addLayout(hbox3) vbox2.addStretch(1) vbox2.addLayout(hbox4) vbox2.addStretch(1) vbox2.addWidget(self.label6) vbox2.addLayout(hbox5) apdGroup.setLayout(vbox2) hbox3.addWidget(self.label4) hbox3.addWidget(self.label5) # Sample frequence QSpinBox self.sb_sampFreq = QSpinBox(self) self.sb_sampFreq.setMinimum(100) self.sb_sampFreq.setMaximum(100000) self.sb_sampFreq.setValue(10000) self.sb_sampFreq.valueChanged.connect(lambda: self.refreshUI(1, 'sb_sampFreq', self.sb_sampFreq.value())) hbox4.addWidget(self.sb_sampFreq) # Radiobutton Continuous Measurement self.rb_cont = QRadioButton("Continuous") self.rb_cont.setChecked(True) self.rb_cont.toggled.connect(lambda: self.refreshUI(2, self.rb_cont, self.rb_finite)) hbox5.addWidget(self.rb_cont) # Radiobutton Finite Measurement self.rb_finite = QRadioButton("Finite") self.rb_finite.toggled.connect(lambda: self.refreshUI(2, self.rb_finite, self.rb_cont)) hbox5.addWidget(self.rb_finite) # Measurement duration QSpinBox self.duration = QSpinBox(self) self.duration.setMinimum(0) self.duration.setMaximum(600) self.duration.setValue(300.0) self.duration.valueChanged.connect(lambda: self.refreshUI(1, 'duration', self.duration.value())) hbox4.addWidget(self.duration) # ## Button GroupBox: # Group contains: # - Start button # - Stop button # - ProgressBar buttonGroup = QGroupBox("Control") hbox6 = QHBoxLayout() hbox11 = QHBoxLayout() vbox3 = QVBoxLayout() vbox3.addLayout(hbox6) vbox3.addStretch(1) vbox3.addLayout(hbox11) vbox3.addStretch(1) buttonGroup.setLayout(vbox3) # Start button self.startButton = QPushButton("Start", self) self.startButton.clicked.connect(self.startBtn) hbox6.addWidget(self.startButton) # Stop button self.stopButton = QPushButton("Stop", self) self.stopButton.clicked.connect(self.stopBtn) hbox6.addWidget(self.stopButton) # Progress Bar self.progress = QProgressBar(self) self.progress.setAlignment(Qt.AlignHCenter) self.progress.setRange(0, 100) hbox11.addWidget(self.progress) # ## LCD display group: # Group contains widgets: # - LCD display green # - LCD display red lcdGroup = QGroupBox("Count rates") hbox7 = QHBoxLayout() hbox8 = QHBoxLayout() vbox4 = QVBoxLayout() vbox4.addLayout(hbox7) vbox4.addLayout(hbox8) lcdGroup.setLayout(vbox4) hbox7.addWidget(self.label7) hbox7.addWidget(self.label8) # Green channel count rate self.green_lcd = QLCDNumber(self) self.green_lcd.setNumDigits(12) hbox8.addWidget(self.green_lcd) # Red channel count rate self.red_lcd = QLCDNumber(self) self.red_lcd.setNumDigits(12) hbox8.addWidget(self.red_lcd) # ## General Layout settings: self.centralBox = QGroupBox("Settings") self.setCentralWidget(self.centralBox) # self.centralWidget.setStyleSheet("QMainWindow {background: 'yellow';}"); # Arrange groups in grid: grid = QGridLayout() grid.addWidget(filesGroup, 0, 0, 1, 3) grid.addWidget(laserGroup, 1, 0, 2, 2) grid.addWidget(apdGroup, 1, 2, 1, 1) grid.addWidget(buttonGroup, 2, 2, 1, 1) grid.addWidget(lcdGroup, 3, 0, 1, 3) self.centralBox.setLayout(grid) def menueLayout(self): """ Here the file menue gets evoked. The actions are widgets, which get connected to the GetFileName method. It directs then to different functionality in a separate class. """ menubar = self.menuBar() fileMenue = menubar.addMenu('&File') fileMenue.addAction(self.loadApp) fileMenue.addAction(self.saveApp) fileMenue.addAction(self.convertData) fileMenue.addAction(self.setArraySize) fileMenue.addAction(self.closeApp) def getFilename(self): """ Select a file with qdialog. The return value of qdialog 'getOpenFileName' is list containing the filter information and the absolute path. @return: path """ start = 'C:/Users/Karoline2' path = QFileDialog.getOpenFileName(None, 'Select file', start) return path[0] def getDirectory(self): """ Select a directory with qdialog. """ start = 'C:/Users/Karoline2' path = QFileDialog.getExistingDirectory(None, 'Select directory', start, QFileDialog.ShowDirsOnly) return path def getFileLocation(self): path = self.getDirectory() self._location.setText(path) def loadDict(self): """ Load a settings dict from a '*.p' file. """ path = self.getFilename() new_dict = self._files.loadSetsDict(path) if new_dict is not None: self._dict._a.update(new_dict) self.refreshUI(3, self._dict._a, 0) self.statusBar.showMessage('Settings updated!') else: self.statusBar.showMessage('No valid settings dictionary in that file!') def closeApplication(self): """Close the app and animation window via file menue.""" choice = QMessageBox.question(self, 'Quit!', 'Really quit session?', QMessageBox.Yes | QMessageBox.No) if choice == QMessageBox.Yes: try: self._anim.__del__() except: pass sys.exit(0) else: pass def closeEvent(self, event): """Close also the animation window when the red 'X' button is pressed.""" try: self._anim.__del__() except: pass sys.exit(0) def refreshUI(self, changeType, changeKey, value): """ This is the first connection to the widgets. Here the widgets identify by changeType (their type) and changeKey (individual key), and pass a value. The values can only be applied if the event variable self._running is set to False. Changes are processed in refresher.refreshUI method, which returns a whole new dictionary. @param changeType: str @param changeKey: str @param value: int or float """ if self._running.is_set(): self.statusBar.showMessage("Please don't change parameters during measurement. Stop and restart with new settings.") else: self._dict._a = self._r.refreshUI(changeType, changeKey, value) self.refreshAll() def refreshRadioButton(self): """The radio buttons need a setChecked update, hence the extra method.""" state = self._dict._a["Radio"] if state == 0: self.rb_cont.setChecked(True) else: self.rb_finite.setChecked(True) def refreshAll(self): """All the widgets get updated with new values.""" self.sld_red.setValue(self._dict._a["lpower red"]) self.sld_green.setValue(self._dict._a["lpower green"]) self.sb_red.setValue(self._dict._a["lpower red"]) self.sb_green.setValue(self._dict._a["lpower green"]) self.sb_sampFreq.setValue(self._dict._a["laser frequency"]) self.duration.setValue(self._dict._a["Duration"]) self.refreshRadioButton() self.sld_percentage.setValue(self._dict._a["laser percentageG"]) self.sb_percentG.setValue(self._dict._a["laser percentageG"]) self.sb_percentR.setValue(self._dict._a["laser percentageR"]) def startBtn(self): """ Set the flag of '_running' to True and close all active (additional) windows. Then start the processes. If users click on start while the measurement is already running, a message 'Already running' is displayed. """ if not self._running.is_set(): self._running.set() # try to close animation and timetrace window # if timetrace does not close reliably, it could # cause problems try: plt.close('all') except: pass self.startProcesses() else: self.statusBar.showMessage("Already running!") def finalLocation(self): """ Calls the hdf mask, from which the sample name gets retrieved. Combined with actual date and time, it creates a new folder in the 'location' directory. Measurements settings and hdf info get saved into that new folder as .p and .txt files. If the hdfmask window is not exited by 'save', the measurement will be canceled. @return: str """ if self._dict._a["Radio"] == 0: new_folder = 'Cont' self.statusBar.showMessage("You are measuring in 'continuous' mode. The data will not get saved!") elif self._dict._a["Radio"] == 1: if self._location.text(): new_folder = self._files.saveRawData(self._location.text(), self._dict._a) if not new_folder: return 0 else: self.statusBar.showMessage('Please select a file directory!') new_folder = 0 return new_folder def startProcesses(self): """Get folder and start all processes and threads.""" self._new_folder = self.finalLocation() if self._new_folder: pass else: self.statusBar.showMessage('Please select a file location with the "Browse" button or save specs.') self._running.clear() return # Initialize processes and waiter thread self._duration = self._dict._a["Duration"] self._counter2 = libs.Counter.Counter(self._running, self._dataQ2, self._readArraySize, self._semaphore, 2) self._counter1 = libs.Counter.Counter(self._running, self._dataQ1, self._readArraySize, self._semaphore, 1) self._laser = libs.Laser.Laser(self._running, self._dict._a, self._semaphore) self._anim = libs.Animation.Animation(self._animDataQ1, self._animDataQ2, self.signal) self._dataProcesser1 = libs.DataProcesser.DataProcesser(self._dataQ1, self._animDataQ1, self._readArraySize, 1, self._new_folder) self._dataProcesser2 = libs.DataProcesser.DataProcesser(self._dataQ2, self._animDataQ2, self._readArraySize, 2, self._new_folder) self.statusBar.showMessage("Started!") self._anim.run() self._u = Thread(target=self.waiter, args=(), name='iterator', daemon=True) # Starting all processes and threads self._counter2.start() self._counter1.start() self._laser.start() self._u.start() self._dataProcesser1.start() self._dataProcesser2.start() self._anim.animate() # this command is vicious, it seems everything following # it gets delayed or not executed at all. Best always called last. def waiter(self): """ Illumination and APDs acquire the semaphore after initialization of tasks, the waiter waits for the semaphore to have its internal counter down to zero (when als tasks are ready). Only then the waiter proceeds and does actually nothing (mode = 0 --> continuous mode) or starts the progressBar and timing (mode 1 --> finite mode). In case of finite mode, the waiter stops the measurement after the duration elapses. In continuous mode, the measuremt must be stopped by the user In case of finite mode, the waiter stops the measurement after the duration elapses. In continuous mode, the measuremt must be stopped by the user. """ while self._semaphore.get_value() > 0: pass if self._dict._a["Radio"] == 0: self.progress.setRange(0, 0) else: # duration = self._dict._a["Duration"] duration_iter = np.arange(self._duration) self.progress.setRange(0, self._duration) for sec in duration_iter: time.sleep(1) self.signal.measurementProgress.emit(sec) if not self._running.is_set(): break else: self.signal.stopMeasurement.emit() @pyqtSlot(int) def setProgressBar(self, i): """ Setting the progressbar, it gets called solely by a pyqtSignal from the waiter thread. @param i: int """ self.progress.setValue(i) @pyqtSlot(list) def displayRatesOnLCD(self, x): """ Setting the lcd numbers with the count rates, it gets called solely by a pyqtSignal from the animation class. """ self.red_lcd.display(x[1]) self.green_lcd.display(x[0]) @pyqtSlot() def warnPopUp(self): """ Called from Animation if the count rate of one of the APDs is higher than 15MHz (15Mc/s). It pops up a message window, informing the user. Currently no stop mechanism is included, so the user has to stop the measurement mechanically. """ msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("APD count should not exceed 15 MHz!\nStop the measurement, check APDs and sample.") msg.setWindowTitle("APD Warning") msg.exec() def changeArraySize(self): answer = self._changeRA.showDialog() if answer is None: pass else: self._readArraySize = answer msg = 'The read array size is now {}'.format(self._readArraySize) self.statusBar.showMessage(msg) print(answer, self._readArraySize) @pyqtSlot() def stopBtn(self): """ Try to stop animation and join all the processes/threads. Extensive checking can be shortened. """ if self._running.is_set(): self._running.clear() self._anim.anim._stop() self.progress.setRange(0, 1) while not self._semaphore.get_value() == 3: pass # joining self.statusBar.showMessage("Stopped! Please wait while data is being processed.") self._laser.join(timeout=3.0) self._u.join(timeout=3.0) self._counter1.join(timeout=5.0) self._counter2.join(timeout=5.0) self._dataProcesser2.join(timeout=5.0) self._dataProcesser1.join(timeout=5.0) # extensive checking for joining check = 0 if self._dataProcesser1.is_alive(): print("DataProcesser 1 did not join.") del self._dataProcesser1 check += 1 if self._dataProcesser2.is_alive(): print("DataProcesser 2 did not join.") del self._dataProcesser2 check += 1 if self._counter1.is_alive(): print("Counter 1 did not join.") del self._counter1 check += 1 if self._counter2.is_alive(): print("Counter 2 did not join.") del self._counter2 check += 1 if self._u.is_alive(): print("Waiter thread did not join.") del self._u check += 1 if self._laser.is_alive(): print("Laser did not join.") del self._laser check += 1 if not check: print("All workers have joined.") # Print the timetrace of the data, is also saved as *.png into the data folder if not self._new_folder == 'Cont': self._timetrace.doThings(self._new_folder) self._files.convertToPhotonHDF5(self._new_folder, self.signal) # Unfortunately there is no other way than deleting the queues # If not done so, the rest data will be shown in the next measurement # instead of the new data. del self._animDataQ1, self._animDataQ2 self._animDataQ1 = mpQueue() self._animDataQ2 = mpQueue() self.statusBar.showMessage("Stopped and idle!") else: self.statusBar.showMessage("Already stopped or not running at all.")
class Window(QWidget): def __init__(self, **kwargs): super().__init__(**kwargs) self.ui() self.current_date() self.filling_in_data() def ui(self): """" Прописываем все необходимые видщеты. """ self.setWindowTitle('Курс валюты ЦБ') self.setGeometry(320, 320, 200, 100) # Создаем два дисплея для отображения курса валют. self.hbox_3 = QHBoxLayout() self.hbox_4 = QHBoxLayout() self.label_usd = QLabel('USD') self.label_usd.setPixmap(QPixmap('usd.png')) self.label_eur = QLabel('EUR') self.label_eur.setPixmap(QPixmap('eur.png')) self.lcd = QLCDNumber() self.lcd_2 = QLCDNumber() self.hbox_3.addWidget(self.label_usd) self.hbox_3.addWidget(self.lcd) self.hbox_4.addWidget(self.label_eur) self.hbox_4.addWidget(self.lcd_2) self.hbox_2 = QHBoxLayout() self.label = QLabel('День :') self.label.setFont(QFont('ubuntu', 15)) self.label_2 = QLabel('Месяц :') self.label_2.setFont(QFont('ubuntu', 15)) self.label_3 = QLabel('Год :') self.label_3.setFont(QFont('ubuntu', 15)) # Упаковка в горизонтальный контейнер. self.hbox_2.addWidget(self.label) self.hbox_2.addWidget(self.label_2) self.hbox_2.addWidget(self.label_3) # Создаем горизонтальный контенер для установки даты. self.hbox = QHBoxLayout() # 3 Параметра для установки даты для запроса. self.date_h = QComboBox() self.date_h.setFont(QFont('ubuntu', 12)) self.month_h = QComboBox() self.month_h.setFont(QFont('ubuntu', 12)) self.year_h = QComboBox() self.year_h.setFont(QFont('ubuntu', 12)) self.btn_cal = QPushButton() self.btn_cal.setIcon(QIcon('cal.png')) self.dialog = Calendar(self) self.btn_cal.clicked.connect(self.dialog.exec) # Упаковываем ComboBox в горизонтальный контенер. self.hbox.addWidget(self.date_h) self.hbox.addWidget(self.month_h) self.hbox.addWidget(self.year_h) self.hbox.addWidget(self.btn_cal) # Создание кнопки. self.btn = QPushButton('Получить курс валюты') self.btn.clicked.connect(self.currency_parsing) # Создаем вертикальный контейнер. self.vbox = QVBoxLayout() # Упаковка вертикального контейнера. self.vbox.addLayout(self.hbox_3) self.vbox.addLayout(self.hbox_4) self.vbox.addLayout(self.hbox_2) self.vbox.addLayout(self.hbox) self.vbox.addWidget(self.btn) # Отображение контенеров. self.setLayout(self.vbox) self.show() def current_date(self): """" Получаем текущию дату и по умолчанию в параметрах устанавливаем её. """ dt = datetime.now() self.date_h.addItem(str(dt.day)) self.month_h.addItem(str(dt.month)) self.year_h.addItem(str(dt.year)) def filling_in_data(self): # Заполняем данными параметры через циклы. for i in range(1, 32): self.date_h.addItem(str(i)) for i in range(1, 13): self.month_h.addItem(str(i)) for i in range(2020, 1989, -1): self.year_h.addItem(str(i)) def currency_parsing(self): """ парсим курсы валют по API ЦБ РФ. Получаем дату для получения курса валют. Если число или месяц от 1-9 тогда мы добавляем значения '0' для правильного запроса формата 'dd/mm/yyyy' """ d = self.date_h.currentText() if len(d) == 1: d = '0' + d m = self.month_h.currentText() if len(m) == 1: m = '0' + m y = self.year_h.currentText() # Делаем проверку даты,если выбраная дата больше текущей тогда выводим ошибку. current_date = datetime.now().strftime('%d%m%Y') date_comboBox = datetime(int(y), int(m), int(d)).strftime('%d%m%Y') if date_comboBox > current_date: QMessageBox.about( self, 'Сообщение', 'Невозможно получить курс валюты\n' 'т.к.выбранная дата больше текущего дня.') else: # Делаем запрос на сайт,передаем ему параметр. url = 'http://www.cbr.ru/scripts/XML_daily.asp?' params = {'date_req': '{0}/{1}/{2}'.format(d, m, y)} try: try: request = requests.get(url, params) soup = bs(request.content, 'xml') find_usd = soup.find(ID='R01235').Value.string self.lcd.setDisabled(False) self.lcd.setNumDigits(7) self.lcd.display(find_usd[:6]) except AttributeError: self.lcd.display('0') self.lcd.setDisabled(True) self.gfgfg() try: find_eur = soup.find(ID='R01239').Value.string self.lcd_2.setDisabled(False) self.lcd_2.setNumDigits(7) self.lcd_2.display(find_eur[:6]) except AttributeError: self.lcd_2.display('0') self.lcd_2.setDisabled(True) self.gfgfg() except AttributeError: self.lcd.display('0') self.lcd_2.display('0') def gfgfg(self): QMessageBox.about( self, 'Соощение', 'На данную дату мы не смогли получить курс валют\n' 'At this date we were unable to get the exchange rate')
class GamePlayerWidget(QGroupBox): def __init__(self, nick, colour=None, parent=None): super(GamePlayerWidget, self).__init__(parent) self.player = nick self.pcolour = colour self.initUI() def initUI(self): # self.setMinimumWidth(300) self.mainLayout = QHBoxLayout(self) # self.mainLayout.addStretch() self.scoreLCD = QLCDNumber(self) self.scoreLCD.setSegmentStyle(QLCDNumber.Flat) self.mainLayout.addWidget(self.scoreLCD) self.scoreLCD.setNumDigits(3) self.scoreLCD.setFixedSize(100, 60) self.scoreLCD.display(0) css = "QLCDNumber {{ color:rgb({},{},{});}}" self.scoreLCD.setStyleSheet(css.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue())) self.nameLabel = QLabel(self) self.nameLabel.setText(self.player) sh = ("QLabel {{ font-size: 32px; font-weight: " "bold; color:rgb({},{},{});}}") self.nameLabel.setStyleSheet(sh.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue())) self.mainLayout.addWidget(self.nameLabel) self.dealerPixmap = QtGui.QPixmap('icons/cards.png') self.nonDealerPixmap = QtGui.QPixmap() self.winnerPixmap = QtGui.QPixmap('icons/winner.png') self.iconlabel = IconLabel(self) self.iconlabel.setFixedSize(50, 50) self.iconlabel.setScaledContents(True) self.mainLayout.insertWidget(0, self.iconlabel) # self.mainLayout.addStretch() self.unsetDealer() def updateDisplay(self, points): if points >= 1000: self.scoreLCD.setNumDigits(4) self.scoreLCD.display(points) def setDealer(self): self.iconlabel.setPixmap(self.dealerPixmap) def unsetDealer(self): self.iconlabel.setPixmap(self.nonDealerPixmap) def setWinner(self): self.iconlabel.setPixmap(self.winnerPixmap) def setColour(self, colour): self.pcolour = colour css = "QLCDNumber {{ color:rgb({},{},{});}}" self.scoreLCD.setStyleSheet(css.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue())) sh = ("QLabel {{ font-size: 32px; font-weight: bold; " "color:rgb({},{},{});}}") self.nameLabel.setStyleSheet(sh.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue()))
class Run_CM110(QMainWindow): def __init__(self): super().__init__() self.cwd = os.getcwd() self.load_() # Enable antialiasing for prettier plots pg.setConfigOptions(antialias=True) self.initUI() def initUI(self): ################### MENU BARS START ################## MyBar = QMenuBar(self) fileMenu = MyBar.addMenu("File") fileSavePlt = fileMenu.addAction("Save plots") fileSavePlt.triggered.connect(self.save_plots) fileSavePlt.setShortcut('Ctrl+P') fileSaveSet = fileMenu.addAction("Save settings") fileSaveSet.triggered.connect(self.save_) # triggers closeEvent() fileSaveSet.setShortcut('Ctrl+S') fileClose = fileMenu.addAction("Close") fileClose.triggered.connect(self.close) # triggers closeEvent() fileClose.setShortcut('Ctrl+X') instMenu = MyBar.addMenu("Instruments") self.conMode = instMenu.addAction("Load instruments") self.conMode.triggered.connect(self.instrumentsDialog) ################### MENU BARS END ################## ##################################################### lbl1 = QLabel("MONOCHROMATOR CM110 settings:", self) lbl1.setStyleSheet("color: blue") intervals_lbl = QLabel("Number of intervals", self) self.combo4 = QComboBox(self) mylist4=["1","2"] self.combo4.addItems(mylist4) self.combo4.setCurrentIndex(mylist4.index(str(self.numofintervals))) start_lbl = QLabel("Start[nm]",self) stop_lbl = QLabel("Stop[nm]",self) step_lbl = QLabel("Step[nm]",self) dwelltime = QLabel("Dwell[s]",self) self.startEdit = [QLineEdit("",self) for tal in range(2)] self.stopEdit = [QLineEdit("",self) for tal in range(2)] self.stepEdit = [QLineEdit("",self) for tal in range(2)] self.dwelltimeEdit = [QLineEdit("",self) for tal in range(2)] # disable those fields that will be ignored anyway for tal in range(2): if tal<self.numofintervals: self.startEdit[tal].setText(str(self.start_[tal])) self.stopEdit[tal].setText(str(self.stop[tal])) self.stepEdit[tal].setText(str(self.step[tal])) self.dwelltimeEdit[tal].setText(str(self.dwell_time[tal])) else: self.startEdit[tal].setEnabled(False) self.stopEdit[tal].setEnabled(False) self.stepEdit[tal].setEnabled(False) self.dwelltimeEdit[tal].setEnabled(False) lbl3 = QLabel("NEWPORT stepper SMC100:", self) lbl3.setStyleSheet("color: blue") startst_lbl = QLabel("Start",self) stopst_lbl = QLabel("Stop",self) stepst_lbl = QLabel("Step",self) lcdst_lbl = QLabel("Current pos",self) self.startst_Edit = QLineEdit(str(self.startst),self) self.stopst_Edit = QLineEdit(str(self.stopst),self) self.stepst_Edit = QLineEdit(str(self.stepst),self) self.lcdst = QLCDNumber(self) self.lcdst.setStyleSheet("color: blue") #self.lcdst.setFixedHeight(40) self.lcdst.setSegmentStyle(QLCDNumber.Flat) self.lcdst.setNumDigits(5) self.lcdst.display("-----") lbl2 = QLabel("ARDUINO Mega2560 settings:", self) lbl2.setStyleSheet("color: blue") dwelltime_lbl = QLabel("Dwell time [ms]",self) self.dwelltimeEdit_ard = QLineEdit(str(self.dwell_time_ard),self) avgpts_lbl = QLabel("Averaging points", self) self.combo1 = QComboBox(self) mylist=["1","5","10","50","100","200"] self.combo1.addItems(mylist) self.combo1.setCurrentIndex(mylist.index(str(self.avg_pts))) lbl4 = QLabel("STORAGE filename and location settings:", self) lbl4.setStyleSheet("color: blue") filename = QLabel("folder/file",self) self.filenameEdit = QLineEdit(self.filename_str,self) lbl6 = QLabel("PLOT options:", self) lbl6.setStyleSheet("color: blue") mylist2=["200","400","800","1600","3200","6400"] schroll_lbl = QLabel("Schroll time after",self) self.combo2 = QComboBox(self) self.combo2.addItems(mylist2) self.combo2.setCurrentIndex(mylist2.index(str(self.schroll_time))) schroll2_lbl = QLabel("Schroll wavelength after",self) self.combo3 = QComboBox(self) self.combo3.addItems(mylist2) self.combo3.setCurrentIndex(mylist2.index(str(self.schroll_wl))) ############################################## lbl5 = QLabel("RECORD data and save images:", self) lbl5.setStyleSheet("color: blue") #save_str = QLabel("Store settings", self) #self.saveButton = QPushButton("Save",self) #self.saveButton.setEnabled(True) run_str = QLabel("Record lock-in data", self) self.runButton = QPushButton("Load instruments",self) #saveplots_str = QLabel("Save plots as png", self) #self.saveplotsButton = QPushButton("Save plots",self) #self.saveplotsButton.setEnabled(True) ''' elapsedtime_str = QLabel('Show voltage vs. time', self) self.elapsedtimeButton = QPushButton("Plot 2",self) self.elapsedtimeButton.setEnabled(False) ''' cancel_str = QLabel("Stop current run", self) self.stopButton = QPushButton("STOP",self) self.stopButton.setEnabled(False) ############################################## # status info which button has been pressed #self.status_str = QLabel("Edit settings and press SAVE!", self) #self.status_str.setStyleSheet("color: green") ############################################## # status info which button has been pressed self.elapsedtime_str = QLabel("TIME trace for storing plots and data:", self) self.elapsedtime_str.setStyleSheet("color: blue") ############################################## self.lcd = QLCDNumber(self) self.lcd.setStyleSheet("color: red") self.lcd.setFixedHeight(60) self.lcd.setSegmentStyle(QLCDNumber.Flat) self.lcd.setNumDigits(11) self.lcd.display(self.timestr) ############################################## # Add all widgets g1_0 = QGridLayout() g1_0.addWidget(MyBar,0,0) g1_0.addWidget(lbl1,1,0) g1_1 = QGridLayout() #g1_1.addWidget(cm110port,0,0) #g1_1.addWidget(self.cm110portEdit,0,1) g1_3 = QGridLayout() g1_3.addWidget(intervals_lbl,0,0) g1_3.addWidget(self.combo4,0,1) g1_2 = QGridLayout() g1_2.addWidget(start_lbl,0,0) g1_2.addWidget(stop_lbl,0,1) g1_2.addWidget(step_lbl,0,2) g1_2.addWidget(dwelltime,0,3) for tal in range(2): g1_2.addWidget(self.startEdit[tal],1+tal,0) g1_2.addWidget(self.stopEdit[tal],1+tal,1) g1_2.addWidget(self.stepEdit[tal],1+tal,2) g1_2.addWidget(self.dwelltimeEdit[tal],1+tal,3) v1 = QVBoxLayout() v1.addLayout(g1_0) v1.addLayout(g1_1) v1.addLayout(g1_3) v1.addLayout(g1_2) g9_0 = QGridLayout() g9_0.addWidget(lbl3,0,0) g9_1 = QGridLayout() g9_1.addWidget(startst_lbl,0,0) g9_1.addWidget(stopst_lbl,0,1) g9_1.addWidget(stepst_lbl,0,2) g9_1.addWidget(lcdst_lbl,0,3) g9_1.addWidget(self.startst_Edit,1,0) g9_1.addWidget(self.stopst_Edit,1,1) g9_1.addWidget(self.stepst_Edit,1,2) g9_1.addWidget(self.lcdst,1,3) v9 = QVBoxLayout() v9.addLayout(g9_0) v9.addLayout(g9_1) g2_0 = QGridLayout() g2_0.addWidget(lbl2,0,0) g2_1 = QGridLayout() #g2_1.addWidget(ardport,0,0) g2_1.addWidget(dwelltime_lbl,0,0) g2_1.addWidget(avgpts_lbl,1,0) #g2_1.addWidget(self.ardportEdit,0,1) g2_1.addWidget(self.dwelltimeEdit_ard,0,1) g2_1.addWidget(self.combo1,1,1) v2 = QVBoxLayout() v2.addLayout(g2_0) v2.addLayout(g2_1) g4_0 = QGridLayout() g4_0.addWidget(lbl4,0,0) g4_1 = QGridLayout() g4_1.addWidget(filename,0,0) g4_1.addWidget(self.filenameEdit,0,1) v4 = QVBoxLayout() v4.addLayout(g4_0) v4.addLayout(g4_1) g7_0 = QGridLayout() g7_0.addWidget(lbl6,0,0) g7_1 = QGridLayout() g7_1.addWidget(schroll2_lbl,0,0) g7_1.addWidget(self.combo3,0,1) g7_1.addWidget(schroll_lbl,1,0) g7_1.addWidget(self.combo2,1,1) v7 = QVBoxLayout() v7.addLayout(g7_0) v7.addLayout(g7_1) g5_0 = QGridLayout() g5_0.addWidget(lbl5,0,0) g5_1 = QGridLayout() #g5_1.addWidget(save_str,0,0) g5_1.addWidget(run_str,0,0) #g5_1.addWidget(saveplots_str,2,0) g5_1.addWidget(cancel_str,1,0) #g5_1.addWidget(self.saveButton,0,1) g5_1.addWidget(self.runButton,0,1) #g5_1.addWidget(self.saveplotsButton,2,1) g5_1.addWidget(self.stopButton,1,1) v5 = QVBoxLayout() v5.addLayout(g5_0) v5.addLayout(g5_1) g6_0 = QGridLayout() g6_0.addWidget(self.elapsedtime_str,0,0) g6_0.addWidget(self.lcd,1,0) v6 = QVBoxLayout() v6.addLayout(g6_0) # add all groups from v1 to v6 in one vertical group v7 v8 = QVBoxLayout() v8.addLayout(v1) v8.addLayout(v9) v8.addLayout(v2) v8.addLayout(v4) v8.addLayout(v7) v8.addLayout(v5) v8.addLayout(v6) # set graph and toolbar to a new vertical group vcan vcan = QVBoxLayout() self.pw1 = pg.PlotWidget(name="Plot1") ## giving the plots names allows us to link their axes together vcan.addWidget(self.pw1) self.pw2 = pg.PlotWidget(name="Plot2") vcan.addWidget(self.pw2) # SET ALL VERTICAL COLUMNS TOGETHER hbox = QHBoxLayout() hbox.addLayout(v8,1) hbox.addLayout(vcan,3.75) ############################################## # PLOT 1 settings # create plot and add it to the figure canvas self.p0 = self.pw1.plotItem self.curve1=[self.p0.plot()] # create plot and add it to the figure self.p0vb = pg.ViewBox() self.curve5=pg.PlotCurveItem(pen=None) self.p0vb.addItem(self.curve5) # connect respective axes to the plot self.p0.showAxis('right') self.p0.getAxis('right').setLabel("10-bit Arduino output") self.p0.scene().addItem(self.p0vb) self.p0.getAxis('right').linkToView(self.p0vb) self.p0vb.setXLink(self.p0) # Use automatic downsampling and clipping to reduce the drawing load self.pw1.setDownsampling(mode='peak') self.pw1.setClipToView(True) # PLOT 2 settings # create plot and add it to the figure canvas self.p1 = self.pw2.plotItem self.curve2=self.p1.plot(pen='r') self.curve3=self.p1.plot() # create plot and add it to the figure self.p2 = pg.ViewBox() self.curve4=pg.PlotCurveItem(pen='y') self.curve6=pg.PlotCurveItem(pen='m') self.p2.addItem(self.curve4) self.p2.addItem(self.curve6) # connect respective axes to the plot self.p1.showAxis('right') self.p1.getAxis('right').setLabel("Wavelength", units='m', color='yellow') self.p1.scene().addItem(self.p2) self.p1.getAxis('right').linkToView(self.p2) self.p2.setXLink(self.p1) # Use automatic downsampling and clipping to reduce the drawing load self.pw2.setDownsampling(mode='peak') self.pw2.setClipToView(True) # Initialize and set titles and axis names for both plots self.clear_vars_graphs() ############################################################################### self.inst_list = {} self.colors = itertools.cycle(["r", "b", "g", "y", "m", "c", "w"]) self.threadpool = QThreadPool() print("Multithreading in Run_COMPexPRO with maximum %d threads" % self.threadpool.maxThreadCount()) # reacts to choises picked in the menu self.combo1.activated[str].connect(self.onActivated1) self.combo2.activated[str].connect(self.onActivated2) self.combo3.activated[str].connect(self.onActivated3) self.combo4.activated[str].connect(self.onActivated4) # save all paramter data in the config file #self.saveButton.clicked.connect(self.save_) #self.saveButton.clicked.connect(self.set_elapsedtime_text) # run the main script self.runButton.clicked.connect(self.set_run) # cancel the script run self.stopButton.clicked.connect(self.set_stop) self.allFields(False) ############################################## self.timer = QTimer(self) self.timer.timeout.connect(self.set_disconnect) self.timer.setSingleShot(True) ############################################## self.setGeometry(100, 100, 1100, 650) self.setWindowTitle("Monochromator CM110 Control And Data Acqusition") w = QWidget() w.setLayout(hbox) self.setCentralWidget(w) self.show() def instrumentsDialog(self): self.Inst = Instruments_dialog.Instruments_dialog(self,self.inst_list,self.cwd,self.lcdst) self.Inst.exec() if self.inst_list.get("CM110") or self.inst_list.get("Ard") or self.inst_list.get("SR530") or self.inst_list.get("SMC100"): self.allFields(True) self.runButton.setText("Scan") self.timer.start(1000*60*self.minutes) else: self.allFields(False) self.runButton.setText("Load instrument!") def allFields(self,trueorfalse): for tal in range(2): if tal<self.numofintervals: self.startEdit[tal].setEnabled(trueorfalse) self.stopEdit[tal].setEnabled(trueorfalse) self.stepEdit[tal].setEnabled(trueorfalse) self.dwelltimeEdit[tal].setEnabled(trueorfalse) self.startst_Edit.setEnabled(trueorfalse) self.stopst_Edit.setEnabled(trueorfalse) self.stepst_Edit.setEnabled(trueorfalse) self.dwelltimeEdit_ard.setEnabled(trueorfalse) self.combo1.setEnabled(trueorfalse) self.combo2.setEnabled(trueorfalse) self.combo3.setEnabled(trueorfalse) self.combo4.setEnabled(trueorfalse) self.filenameEdit.setEnabled(trueorfalse) self.runButton.setEnabled(trueorfalse) def onActivated1(self, text): self.avg_pts = str(text) def onActivated2(self, text): self.schroll_time=int(text) def onActivated3(self, text): self.schroll_wl=int(text) def onActivated4(self, text): self.numofintervals = int(text) for tal in range(2): if tal<self.numofintervals: self.startEdit[tal].setEnabled(True) self.stopEdit[tal].setEnabled(True) self.stepEdit[tal].setEnabled(True) self.dwelltimeEdit[tal].setEnabled(True) else: self.startEdit[tal].setEnabled(False) self.stopEdit[tal].setEnabled(False) self.stepEdit[tal].setEnabled(False) self.dwelltimeEdit[tal].setEnabled(False) # Check input if a number, ie. digits or fractions such as 3.141 # Source: http://www.pythoncentral.io/how-to-check-if-a-string-is-a-number-in-python-including-unicode/ def is_number(self,s): try: float(s) return True except ValueError: pass try: import unicodedata unicodedata.numeric(s) return True except (TypeError, ValueError): pass return False def create_file(self, mystr): head, ext = os.path.splitext(mystr) #print("head: ",head) #print("ext: ",ext) #print("filename: ",self.filenameEdit.text()) totalpath = ''.join([self.cwd,os.sep,head,'_',self.timestr,ext]) my_dir = os.path.dirname(totalpath) if not os.path.isdir(my_dir): QMessageBox.warning(self, "Message","".join(["Folder(s) named ",my_dir," will be created!"])) try: os.makedirs(my_dir, exist_ok=True) except Exception as e: QMessageBox.critical(self, "Message","".join(["Folder named ",head," not valid!\n\n",str(e)])) return "" return totalpath def set_run(self): # MINIMUM REQUIREMENTS for proper run if not self.inst_list.get("CM110") and not self.inst_list.get("SR530") and not self.inst_list.get("Ard") and not self.inst_list.get("SMC100"): QMessageBox.critical(self, 'Message',"No instruments connected. At least 1 instrument is required.") return ######################################################## if self.inst_list.get("SMC100"): val = self.inst_list.get("SMC100").return_ts(1) if val[-2:] not in ["32","33","34","35"]: # RESET the stepper if active self.Reset_dialog = Reset_dialog.Reset_dialog(self, self.inst_list) self.Reset_dialog.exec() # Checkif the stepper is ready val = self.inst_list.get("SMC100").return_ts(1) if val[-2:] not in ["32","33","34","35"]: return ######################################################## try: for i in range(self.numofintervals): arr = numpy.arange(int(self.startEdit[i].text()),int(self.stopEdit[i].text()),int(self.stepEdit[i].text())) if len(arr)==0: QMessageBox.warning(self, 'Message',''.join(["Empty array returned. Check wavelength start and stop values!"])) return except Exception as e: QMessageBox.warning(self, 'Message',''.join(["All wavelength scan parameters should be integers!\n\n",str(e)])) return try: arr = numpy.arange(float(self.startst_Edit.text()),float(self.stopst_Edit.text()),float(self.stepst_Edit.text())) if len(arr)==0: QMessageBox.warning(self, 'Message',''.join(["Empty array returned. Check Newport start and stop values!"])) return except Exception as e: QMessageBox.warning(self, 'Message',''.join(["All stepper position parameters should be real numbers!\n\n",str(e)])) return for i in range(self.numofintervals): if not self.is_number(self.dwelltimeEdit[i].text()): QMessageBox.warning(self, 'Message',"Dwell time scan parameter is not a real number!") return # For SAVING data if "\\" in self.filenameEdit.text(): self.filenameEdit.setText(self.filenameEdit.text().replace("\\",os.sep)) if "/" in self.filenameEdit.text(): self.filenameEdit.setText(self.filenameEdit.text().replace("/",os.sep)) if not self.filenameEdit.text(): self.filenameEdit.setText(''.join(["data",os.sep,"data"])) if not os.sep in self.filenameEdit.text(): self.filenameEdit.setText(''.join(["data", os.sep, self.filenameEdit.text()])) # Initial read of the config file start_sc = [int(self.startEdit[i].text()) for i in range(self.numofintervals)] stop_sc = [int(self.stopEdit[i].text()) for i in range(self.numofintervals)] step_sc = [int(self.stepEdit[i].text()) for i in range(self.numofintervals)] start_st = float(self.startst_Edit.text()) stop_st = float(self.stopst_Edit.text()) step_st = float(self.stepst_Edit.text()) dwelltime = [float(self.dwelltimeEdit[ii].text()) for ii in range(self.numofintervals)] dwell_ard = float(self.dwelltimeEdit_ard.text()) file_txt = self.create_file(''.join([self.filenameEdit.text(),".txt"])) file_hdf5 = self.create_file(''.join([self.filenameEdit.text(),".hdf5"])) for start,stop,step,dwell in zip(start_sc,stop_sc,step_sc,dwelltime): if start<0 or start>9000: QMessageBox.warning(self, 'Message',"Minimum start wavelength is 0 nm and maximum 9000 nm!") return if stop<0 or stop>9000: QMessageBox.warning(self, 'Message',"Minimum stop wavelength is 0 nm and maximum 9000 nm!") return if step<0 or step>127: QMessageBox.warning(self, 'Message',"Minimum step is 0 units and maximum 127 units!") return if dwell<3*dwell_ard/1000 or dwell>100: QMessageBox.warning(self, 'Message',"Monochromator dwell time is minimum 3 times Arduino dwell time and maximum 100 s!") return if dwell_ard<10 or dwell_ard>dwell*1000: QMessageBox.warning(self, 'Message',"Arduino dwell time is minimum 10 ms and maximum CM110 dwell time!") return self.clear_vars_graphs() self.allFields(False) self.conMode.setEnabled(False) self.runButton.setEnabled(False) self.stopButton.setEnabled(True) self.stopButton.setText("STOP") self.runButton.setText("Scanning...") self.timer.stop() self.get_thread=Run_CM110_Thread(start_sc,stop_sc,step_sc,dwelltime,dwell_ard,self.avg_pts,file_txt,file_hdf5,self.timestr,self.analogref,self.inst_list,start_st,stop_st,step_st) self.get_thread.signals.make_update1.connect(self.make_update1) self.get_thread.signals.make_update2.connect(self.make_update2) self.get_thread.signals.make_update3.connect(self.make_update3) self.get_thread.signals.make_update4.connect(self.make_update4) self.get_thread.signals.finished.connect(self.finished) # Execute self.threadpool.start(self.get_thread) def make_update1(self,set_position,real_positions,endpoint_data,endpoints_times,raw_data): self.set_wl.extend([ 1e-9*set_position ]) self.real_wl.extend([ 1e-9*real_positions ]) self.all_volts.extend([ endpoint_data ]) self.all_times.extend([ endpoints_times ]) self.all_raw.extend([ raw_data ]) if len(self.set_wl)>self.schroll_wl: self.plot_volts[:-1] = self.plot_volts[1:] # shift data in the array one sample left self.plot_volts[-1] = endpoint_data self.plot_wl[:-1] = self.plot_wl[1:] # shift data in the array one sample left self.plot_wl[-1] = 1e-9*set_position self.plot_set_wl[:-1] = self.plot_set_wl[1:] # shift data in the array one sample left self.plot_set_wl[-1] = 1e-9*set_position self.plot_real_wl[:-1] = self.plot_real_wl[1:] # shift data in the array one sample left self.plot_real_wl[-1] = 1e-9*real_positions self.plot_raw[:-1] = self.plot_raw[1:] # shift data in the array one sample left self.plot_raw[-1] = raw_data else: self.plot_volts.extend([ float(endpoint_data) ]) self.plot_wl.extend([ 1e-9*set_position ]) self.plot_set_wl.extend([ 1e-9*set_position ]) self.plot_real_wl.extend([ 1e-9*real_positions ]) self.plot_raw.extend([ int(raw_data) ]) self.curve1[-1].setData(self.plot_wl, self.plot_volts) self.curve5.setData(self.plot_set_wl, self.plot_raw) ## Handle view resizing def updateViews(): ## view has resized; update auxiliary views to match self.p0vb.setGeometry(self.p0.vb.sceneBoundingRect()) ## need to re-update linked axes since this was called ## incorrectly while views had different shapes. ## (probably this should be handled in ViewBox.resizeEvent) self.p0vb.linkedViewChanged(self.p0.vb, self.p0vb.XAxis) updateViews() self.p0.vb.sigResized.connect(updateViews) ########################################################### # Update curve3 in different plot if len(self.set_wl_tr)>=self.schroll_time: local_times=self.all_times[-self.counter:] local_volts=self.all_volts[-self.counter:] self.curve3.setData(local_times, local_volts) else: self.curve3.setData(self.all_times, self.all_volts) def make_update2(self,set_position,real_positions,all_data,timelist): self.set_wl_tr.extend([ 1e-9*set_position ]) self.real_wl_tr.extend([ 1e-9*real_positions ]) #self.all_volts_tr.extend([ float(all_data) ]) #self.all_time_tr.extend([ float(timelist) ]) if len(self.set_wl_tr)==self.schroll_time: self.counter=len(self.set_wl) if len(self.set_wl_tr)>self.schroll_time: self.plot_time_tr[:-1] = self.plot_time_tr[1:] # shift data in the array one sample left self.plot_time_tr[-1] = timelist self.plot_volts_tr[:-1] = self.plot_volts_tr[1:] # shift data in the array one sample left self.plot_volts_tr[-1] = all_data self.plot_set_wl_tr[:-1] = self.plot_set_wl_tr[1:] # shift data in the array one sample left self.plot_set_wl_tr[-1] = 1e-9*set_position self.plot_real_wl_tr[:-1] = self.plot_real_wl_tr[1:] # shift data in the array one sample left self.plot_real_wl_tr[-1] = 1e-9*real_positions else: self.plot_set_wl_tr.extend([ 1e-9*set_position ]) self.plot_real_wl_tr.extend([ 1e-9*real_positions ]) self.plot_volts_tr.extend([ all_data ]) self.plot_time_tr.extend([ timelist ]) ## Handle view resizing def updateViews(): ## view has resized; update auxiliary views to match self.p2.setGeometry(self.p1.vb.sceneBoundingRect()) #p3.setGeometry(p1.vb.sceneBoundingRect()) ## need to re-update linked axes since this was called ## incorrectly while views had different shapes. ## (probably this should be handled in ViewBox.resizeEvent) self.p2.linkedViewChanged(self.p1.vb, self.p2.XAxis) #p3.linkedViewChanged(p1.vb, p3.XAxis) updateViews() self.p1.vb.sigResized.connect(updateViews) self.curve2.setData(self.plot_time_tr, self.plot_volts_tr) self.curve4.setData(self.plot_time_tr, self.plot_set_wl_tr) self.curve6.setData(self.plot_time_tr, self.plot_real_wl_tr) def make_update3(self): self.plot_wl = [] self.plot_volts = [] mycol=next(self.colors) self.curve1.extend( [self.p0.plot(pen=pg.mkPen(mycol,width=1), symbolPen=mycol, symbolBrush=mycol, symbolSize=3)] ) def make_update4(self,val): self.lcdst.display(str(val)[:5]) def set_disconnect(self): ########################################## if self.inst_list.get("CM110"): if self.inst_list.get("CM110").is_open(): self.inst_list.get("CM110").close() self.inst_list.pop("CM110", None) ########################################## if self.inst_list.get("Ard"): if self.inst_list.get("Ard").is_open(): self.inst_list.get("Ard").close() self.inst_list.pop("Ard", None) ########################################## if self.inst_list.get("SR530"): if self.inst_list.get("SR530").is_open(): self.inst_list.get("SR530").close() self.inst_list.pop("SR530", None) ########################################## if self.inst_list.get("SMC100"): if self.inst_list.get("SMC100").is_open(): self.inst_list.get("SMC100").close() self.inst_list.pop("SMC100", None) ########################################## print("All com ports DISCONNECTED") self.allFields(False) self.conMode.setEnabled(True) self.runButton.setText("Load instrument!") self.runButton.setEnabled(False) def set_stop(self): self.stopButton.setEnabled(False) self.stopButton.setText("Stopped") if hasattr(self, "get_thread"): self.get_thread.abort() self.stop_pressed = True def clear_vars_graphs(self): # PLOT 1 initial canvas settings self.set_wl=[] self.real_wl=[] self.all_volts=[] self.all_times=[] self.all_raw=[] self.plot_set_wl=[] self.plot_real_wl=[] self.plot_raw=[] self.plot_volts=[] self.plot_wl=[] for c in self.curve1: c.setData([],[]) self.curve5.setData(self.plot_set_wl, self.plot_raw) self.curve3.setData([], []) self.pw1.enableAutoRange() # Labels and titels are placed here since they change dynamically self.pw1.setTitle(''.join(["CM110 scan as function of wavelength"])) self.pw1.setLabel('left', "Voltage", units='V') self.pw1.setLabel('bottom', "Wavelength", units='m') # PLOT 2 initial canvas settings self.set_wl_tr=[] self.real_wl_tr=[] self.plot_set_wl_tr=[] self.plot_real_wl_tr=[] self.plot_volts_tr=[] self.plot_time_tr=[] self.curve2.setData(self.plot_time_tr, self.plot_volts_tr) self.curve4.setData(self.plot_time_tr, self.plot_set_wl_tr) self.curve6.setData(self.plot_time_tr, self.plot_real_wl_tr) self.pw2.enableAutoRange() # Labels and titels are placed here since they change dynamically self.p1.setTitle(''.join(["CM110 scan as function of time"])) self.p1.setLabel('left', "Voltage", units='V', color='red') self.p1.setLabel('bottom', "Elapsed time", units='s') self.stop_pressed = False def load_(self): # Initial read of the config file self.config = configparser.ConfigParser() try: self.config.read(''.join([self.cwd,os.sep,"config.ini"])) self.last_used_scan = self.config.get("LastScan","last_used_scan") self.numofintervals = int(self.config.get(self.last_used_scan,"numofintervals")) self.start_ = [int(i) for i in self.config.get(self.last_used_scan,"start").strip().split(',')] self.stop = [int(i) for i in self.config.get(self.last_used_scan,"stop").strip().split(',')] self.step = [int(i) for i in self.config.get(self.last_used_scan,"step").strip().split(',')] self.startst = float(self.config.get(self.last_used_scan,"startst")) self.stopst = float(self.config.get(self.last_used_scan,"stopst")) self.stepst = float(self.config.get(self.last_used_scan,"stepst")) self.dwell_time = [int(i) for i in self.config.get(self.last_used_scan,"wait_time").strip().split(',')] self.dwell_time_ard = int(self.config.get(self.last_used_scan,"wait_time_ard")) self.avg_pts = int(self.config.get(self.last_used_scan,"avg_pts")) self.schroll_time = int(self.config.get(self.last_used_scan,"schroll_time")) self.schroll_wl = int(self.config.get(self.last_used_scan,"schroll_wl")) self.filename_str = self.config.get(self.last_used_scan,"filename") self.timestr = self.config.get(self.last_used_scan,"timestr") self.analogref = float(self.config.get(self.last_used_scan,"analogref")) self.minutes = float(self.config.get(self.last_used_scan,"timer")) except configparser.NoOptionError as nov: QMessageBox.critical(self, "Message","".join(["Main FAULT while reading the config.ini file\n",str(nov)])) raise def save_(self): self.timestr=time.strftime("%y%m%d-%H%M") self.lcd.display(self.timestr) self.config.set("LastScan","last_used_scan", self.last_used_scan ) self.config.set(self.last_used_scan,"numofintervals",str(self.numofintervals) ) self.config.set(self.last_used_scan,"start",','.join([str(self.startEdit[ii].text()) for ii in range(self.numofintervals)]) ) self.config.set(self.last_used_scan,"stop",','.join([str(self.stopEdit[ii].text()) for ii in range(self.numofintervals)]) ) self.config.set(self.last_used_scan,"step",','.join([str(self.stepEdit[ii].text()) for ii in range(self.numofintervals)]) ) self.config.set(self.last_used_scan,"wait_time",','.join([str(self.dwelltimeEdit[ii].text()) for ii in range(self.numofintervals)]) ) self.config.set(self.last_used_scan,"startst", str(self.startst_Edit.text()) ) self.config.set(self.last_used_scan,"stopst", str(self.stopst_Edit.text()) ) self.config.set(self.last_used_scan,"stepst", str(self.stepst_Edit.text()) ) self.config.set(self.last_used_scan,"wait_time_ard", str(self.dwelltimeEdit_ard.text()) ) self.config.set(self.last_used_scan,"avg_pts", str(self.avg_pts) ) self.config.set(self.last_used_scan,"schroll_time", str(self.schroll_time) ) self.config.set(self.last_used_scan,"schroll_wl", str(self.schroll_wl) ) self.config.set(self.last_used_scan,"filename", self.filenameEdit.text() ) self.config.set(self.last_used_scan,"timestr", str(self.timestr) ) self.config.set(self.last_used_scan,"analogref", str(self.analogref) ) with open(''.join([self.cwd,os.sep,"config.ini"]), "w") as configfile: self.config.write(configfile) def finished(self): if not self.stop_pressed: self.stopButton.setEnabled(False) if hasattr(self, "get_thread"): self.get_thread.abort() self.stop_pressed = True self.allFields(True) self.conMode.setEnabled(True) if self.inst_list.get("CM110") or self.inst_list.get("SR530") or self.inst_list.get("Ard") or self.inst_list.get("SMC100"): self.allFields(True) self.runButton.setText("Scan") else: self.allFields(False) self.runButton.setText("Load instrument!") self.timer.start(1000*60*self.minutes) def closeEvent(self, event): reply = QMessageBox.question(self, 'Message', "Quit now? Any changes that are not saved will stay unsaved!", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: if self.inst_list.get("CM110"): if not hasattr(self, "get_thread"): if self.inst_list.get("CM110").is_open(): self.inst_list.get("CM110").close() else: if not self.stop_pressed: QMessageBox.warning(self, "Message", "Scan in progress. Stop the scan then quit!") event.ignore() return else: if self.inst_list.get("CM110").is_open(): self.inst_list.get("CM110").close() if self.inst_list.get("SR530"): if not hasattr(self, "get_thread"): if self.inst_list.get("SR530").is_open(): self.inst_list.get("SR530").close() else: if not self.stop_pressed: QMessageBox.warning(self, "Message", "Scan in progress. Stop the scan then quit!") event.ignore() return else: if self.inst_list.get("SR530").is_open(): self.inst_list.get("SR530").close() if self.inst_list.get("SMC100"): if not hasattr(self, "get_thread"): if self.inst_list.get("SMC100").is_open(): self.inst_list.get("SMC100").close() else: if not self.stop_pressed: QMessageBox.warning(self, "Message", "Scan in progress. Stop the scan then quit!") event.ignore() return else: if self.inst_list.get("SMC100").is_open(): self.inst_list.get("SMC100").close() if self.inst_list.get("Ard"): if not hasattr(self, "get_thread"): if self.inst_list.get("Ard").is_open(): self.inst_list.get("Ard").close() else: if not self.stop_pressed: QMessageBox.warning(self, "Message", "Scan in progress. Stop the scan then quit!") event.ignore() return else: if self.inst_list.get("Ard").is_open(): self.inst_list.get("Ard").close() if hasattr(self, "timer"): if self.timer.isActive(): self.timer.stop() event.accept() else: event.ignore() ########################################## def save_plots(self): # For SAVING data if "\\" in self.filenameEdit.text(): self.filenameEdit.setText(self.filenameEdit.text().replace("\\",os.sep)) if "/" in self.filenameEdit.text(): self.filenameEdit.setText(self.filenameEdit.text().replace("/",os.sep)) if not self.filenameEdit.text(): self.filenameEdit.setText(''.join(["data",os.sep,"data"])) if not os.sep in self.filenameEdit.text(): self.filenameEdit.setText(''.join(["data", os.sep, self.filenameEdit.text()])) save_plot1 = self.create_file(''.join([self.filenameEdit.text(),".png"])) save_plot2 = self.create_file(''.join([self.filenameEdit.text(),"_elapsedtime",".png"])) # create an exporter instance, as an argument give it # the item you wish to export exporter = pg.exporters.ImageExporter(self.pw1.plotItem) exporter.params.param('width').setValue(1920, blockSignal=exporter.widthChanged) exporter.params.param('height').setValue(1080, blockSignal=exporter.heightChanged) # set export parameters if needed #exporter.parameters()['width'] = 100 # (note this also affects height parameter) # save to file exporter.export(save_plot1) exporter = pg.exporters.ImageExporter(self.pw2.plotItem) exporter.params.param('width').setValue(1920, blockSignal=exporter.widthChanged) exporter.params.param('height').setValue(1080, blockSignal=exporter.heightChanged) # set export parameters if needed #exporter.parameters()['width'] = 100 # (note this also affects height parameter) # save to file exporter.export(save_plot2)
class Phase10PlayerWidget(GamePlayerWidget): roundWinnerSet = QtCore.pyqtSignal(str) def __init__(self, nick, engine, bgroup=None, parent=None): self.engine = engine self.current_phase = min( self.engine.getRemainingPhasesFromPlayer(nick)) self.phases_in_order = self.engine.getPhasesInOrderFlag() self.bgroup = bgroup super(Phase10PlayerWidget, self).__init__( nick, PlayerColours[self.engine.getListPlayers().index(nick)], parent) def initUI(self): css = ("QGroupBox {{ font-size: 28px;" "font-weight: bold; color:rgb({},{},{});}}") self.setStyleSheet(css.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue())) self.setTitle(self.player) super(Phase10PlayerWidget, self).initUI() trashWidget = QWidget() trashWidget.setLayout(self.mainLayout) self.mainLayout = QVBoxLayout(self) self.mainLayout.addStretch() self.upperLayout = QHBoxLayout() self.mainLayout.addLayout(self.upperLayout) self.upperLayout.addStretch() self.phaseNameLabel = QLabel(self) self.phaseNameLabel.setStyleSheet( "font-weight: bold; font-size: 24px;") self.updatePhaseName() self.upperLayout.addWidget(self.phaseNameLabel) self.upperLayout.addStretch() self.lowerLayout = QHBoxLayout() self.mainLayout.addLayout(self.lowerLayout) self.mainLayout.addStretch() self.phaseLabelsLayout = QGridLayout() self.phaseLabelsLayout.setSpacing(5) self.checkboxLayout = QVBoxLayout() self.scoreLCD = QLCDNumber(self) self.scoreLCD.setSegmentStyle(QLCDNumber.Flat) self.mainLayout.addWidget(self.scoreLCD) self.scoreLCD.setNumDigits(3) self.scoreLCD.setMinimumWidth(100) css = "QLCDNumber {{ color:rgb({},{},{});}}" self.scoreLCD.setStyleSheet(css.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue())) # Left part - score self.lowerLayout.addWidget(self.iconlabel) self.lowerLayout.addWidget(self.scoreLCD) self.lowerLayout.addLayout(self.phaseLabelsLayout) self.lowerLayout.addLayout(self.checkboxLayout) self.iconlabel.setMinimumSize(60, 60) # self.scoreLCD.setMinimumWidth(100) # self.scoreLCD.setMaximumWidth(200) # self.scoreLCD.setMinimumHeight(60) # self.scoreLCD.setMaximumHeight(80) self.scoreLCD.display(self.engine.getScoreFromPlayer(self.player)) # Middle part - Phase list self.phaseLabels = list() for phase in range(1, 11): label = Phase10Label(phase, self) if phase == self.current_phase: label.setCurrent() elif self.engine.hasPhaseCompleted(self.player, phase): label.setPassed() self.phaseLabels.append(label) self.phaseLabelsLayout.addWidget( label, (phase-1)/5, (phase-1) % 5, 1, 1) # Middle part - Inputs self.roundWinnerRadioButton = QRadioButton() self.bgroup.addButton(self.roundWinnerRadioButton) self.checkboxLayout.addWidget(self.roundWinnerRadioButton) self.roundPhaseClearedCheckbox = QCheckBox(self) self.checkboxLayout.addWidget(self.roundPhaseClearedCheckbox) self.roundScore = Phase10ScoreSpinBox(self) self.roundScore.setMaximumWidth(90) self.roundScore.valueChanged.connect(self.updateRoundPhaseCleared) self.lowerLayout.addWidget(self.roundScore) self.roundWinnerRadioButton.toggled.connect( self.roundScore.setDisabled) self.roundWinnerRadioButton.toggled.connect( self.roundPhaseClearedCheckbox.setDisabled) self.roundWinnerRadioButton.toggled.connect( self.roundPhaseClearedCheckbox.setChecked) self.roundWinnerRadioButton.toggled.connect(self.roundWinnerSetAction) self.retranslateUI() def retranslateUI(self): self.roundWinnerRadioButton.setText( i18n("Phase10PlayerWidget", "Winner")) self.roundPhaseClearedCheckbox.setText( i18n("Phase10PlayerWidget", "Completed")) self.updatePhaseName() def updateDisplay(self, points, completed_phases, remaining_phases): if len(remaining_phases) == 0: self.current_phase = 0 else: self.current_phase = min(remaining_phases) self.roundWinnerRadioButton.setDown(True) if points >= 1000: self.scoreLCD.setNumDigits(4) self.scoreLCD.display(points) self.roundScore.setValue(5) self.roundScore.clear() self.roundPhaseClearedCheckbox.setChecked(False) for phase, label in enumerate(self.phaseLabels, start=1): if phase == self.current_phase and not self.engine.getWinner(): if not label.isCurrent(): label.setCurrent() elif phase in completed_phases: if not label.isPassed(): label.setPassed() else: if not label.isRemaining(): label.setRemaining() self.updatePhaseName() def getScore(self): if self.isRoundWinner(): return 0 try: return int(self.roundScore.value()) except Exception: return -1 def switchPhasesInOrder(self, in_order): self.phases_in_order = in_order if not self.phases_in_order: return self.phaseLabels[self.current_phase-1].setRemaining() for label in self.phaseLabels: if label.isRemaining(): label.setCurrent() self.current_phase = label.getNumber() break def updatePhaseSelected(self, phaselabel): if phaselabel.isRemaining(): self.current_phase = phaselabel.getNumber() for label in self.phaseLabels: if label.isCurrent(): label.setRemaining() phaselabel.setCurrent() self.updatePhaseName() def updatePhaseName(self): phasenames = getPhaseNames(self.engine.getPhases()) self.phaseNameLabel.setText(phasenames[self.current_phase-1]) def updateRoundPhaseCleared(self, value): try: score = int(self.roundScore.text()) except Exception: self.roundPhaseClearedCheckbox.setChecked(False) return if score < 0: if not self.roundWinnerRadioButton.isChecked(): self.roundPhaseClearedCheckbox.setChecked(False) return if (score % 5 != 0): return if (score >= 50): self.roundWinnerRadioButton.setChecked(False) self.roundPhaseClearedCheckbox.setChecked(False) elif (score == 0): self.roundWinnerRadioButton.setChecked(True) self.roundPhaseClearedCheckbox.setChecked(True) else: self.roundWinnerRadioButton.setChecked(False) self.roundPhaseClearedCheckbox.setChecked(True) def mousePressEvent(self, event): child = self.childAt(event.pos()) if child is None: self.roundScore.setFocus() elif type(child) == Phase10Label and not self.phases_in_order: self.updatePhaseSelected(child) return QGroupBox.mousePressEvent(self, event) # def isRoundWinner(self): return self.roundWinnerRadioButton.isChecked() def getRoundPhase(self): return self.current_phase def isRoundCleared(self): return self.roundPhaseClearedCheckbox.isChecked() def roundWinnerSetAction(self, isset): if isset: self.roundWinnerSet.emit(self.player) def reset(self): pass def finish(self): self.roundWinnerRadioButton.toggled.disconnect( self.roundScore.setDisabled) self.roundWinnerRadioButton.toggled.disconnect( self.roundPhaseClearedCheckbox.setDisabled) self.roundWinnerRadioButton.toggled.disconnect( self.roundPhaseClearedCheckbox.setChecked) self.roundWinnerRadioButton.toggled.disconnect( self.roundWinnerSetAction) self.roundWinnerRadioButton.setDisabled(True) self.roundPhaseClearedCheckbox.setDisabled(True) self.roundScore.setDisabled(True) def setColour(self, colour): self.pcolour = colour css = ("QGroupBox {{ font-size: 28px; font-weight: bold;" "color:rgb({},{},{});}}") self.setStyleSheet(css.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue()))
class GUV_TEST_dialog(QDialog): def __init__(self, parent): super().__init__(parent) # Initial read of the config file self.config = configparser.ConfigParser() try: self.config.read('config.ini') self.last_used_scan = self.config.get('LastScan', 'last_used_scan') #self.log_guv=self.bool_(self.config.get(self.last_used_scan,'log_guv')) self.schroll_pts = int( self.config.get(self.last_used_scan, 'schroll')) self.log_guv_str = self.config.get(self.last_used_scan, 'log_guv').strip().split(',')[0] self.log_guv_check = self.bool_( self.config.get(self.last_used_scan, 'log_guv').strip().split(',')[1]) self.guvip = self.config.get("Instruments", 'guvport').strip().split(',')[0] self.guvport = self.config.get("Instruments", 'guvport').strip().split(',')[1] self.guvtype_str = self.config.get("Instruments", 'guvtype') except configparser.NoOptionError as e: QMessageBox.critical( self, 'Message', ''.join( ["Main FAULT while reading the config.ini file\n", str(e)])) raise self.setupUi() def bool_(self, txt): if txt == "True": return True elif txt == "False": return False def setupUi(self): ipport = QLabel("TCP/IP port", self) self.ipportEdit = QLineEdit(self.guvip, self) tcpport = QLabel("TCP port", self) self.tcpportEdit = QLineEdit(self.guvport, self) guvtype_lbl = QLabel("GUV type", self) self.guvtype_cb = QComboBox(self) mylist = ["GUV-541", "GUV-2511", "GUV-3511"] self.guvtype_cb.addItems(mylist) self.guvtype_cb.setCurrentIndex(mylist.index(self.guvtype_str)) ############################################## self.runstopButton = QPushButton("START", self) self.clearButton = QPushButton("Clear", self) ############################################## schroll_lbl = QLabel("Schroll elapsed time ", self) self.combo0 = QComboBox(self) mylist0 = ["100", "200", "400", "600", "800", "1000", "1500", "2000"] self.combo0.addItems(mylist0) self.combo0.setCurrentIndex(mylist0.index(str(self.schroll_pts))) ############################################## self.cb_logdata = QCheckBox('Log data to file', self) self.cb_logdata.toggle() self.cb_logdata.setChecked(self.log_guv_check) #self.cb_logdata.setLayoutDirection(Qt.RightToLeft) self.file_edit = QLineEdit(self.log_guv_str, self) self.file_edit.setStyleSheet("color: blue") if self.cb_logdata.isChecked(): self.file_edit.setEnabled(True) else: self.file_edit.setEnabled(False) self.lcd = QLCDNumber(self) self.lcd.setStyleSheet("color: red") self.lcd.setFixedWidth(170) self.lcd.setFixedHeight(35) self.lcd.setSegmentStyle(QLCDNumber.Flat) self.lcd.setNumDigits(11) self.time_str = time.strftime("%y%m%d-%H%M") self.lcd.display(self.time_str) ############################################## g0_1 = QGridLayout() g0_1.addWidget(ipport, 0, 0) g0_1.addWidget(self.ipportEdit, 0, 1) g0_1.addWidget(tcpport, 0, 2) g0_1.addWidget(self.tcpportEdit, 0, 3) g0_1.addWidget(guvtype_lbl, 0, 4) g0_1.addWidget(self.guvtype_cb, 0, 5) g0_2 = QGridLayout() g0_2.addWidget(schroll_lbl, 0, 0) g0_2.addWidget(self.combo0, 0, 1) g0_2.addWidget(self.runstopButton, 0, 2) g0_2.addWidget(self.clearButton, 0, 3) g0_2.addWidget(self.cb_logdata, 1, 0) g0_2.addWidget(self.lcd, 1, 1) g0_4 = QVBoxLayout() g0_4.addLayout(g0_1) g0_4.addLayout(g0_2) g0_4.addWidget(self.file_edit) ############################################## # set graph and toolbar to a new vertical group vcan self.pw1 = pg.PlotWidget() self.pw1.setFixedWidth(600) ############################################## # create table self.tableWidget = self.createTable() ############################################## # SET ALL VERTICAL COLUMNS TOGETHER vbox = QVBoxLayout() vbox.addLayout(g0_4) vbox.addWidget(self.pw1) hbox = QVBoxLayout() hbox.addLayout(vbox) hbox.addWidget(self.tableWidget) self.threadpool = QThreadPool() print("Multithreading in the GUV dialog with maximum %d threads" % self.threadpool.maxThreadCount()) self.isRunning = False self.setLayout(hbox) self.setWindowTitle("Test GUV") # PLOT 2 settings # create plot and add it to the figure canvas self.p1 = self.pw1.plotItem self.curves = [] colors = itertools.cycle(["r", "b", "g", "y", "m", "c", "w"]) for i in range(20): mycol = next(colors) self.curves.append( self.p1.plot(pen=pg.mkPen(color=mycol), symbol='s', symbolPen=mycol, symbolBrush=mycol, symbolSize=4)) # create plot and add it to the figure self.p0_1 = pg.ViewBox() self.curve2 = pg.PlotCurveItem(pen='r') self.p0_1.addItem(self.curve2) # connect respective axes to the plot #self.p1.showAxis('left') self.p1.getAxis('left').setLabel("Power density", units="", color='yellow') self.p1.showAxis('right') self.p1.getAxis('right').setLabel("Arb unit", units="", color='red') self.p1.scene().addItem(self.p0_1) self.p1.getAxis('right').linkToView(self.p0_1) self.p0_1.setXLink(self.p1) self.p1.getAxis('bottom').setLabel("Time passed", units="s", color='yellow') # Use automatic downsampling and clipping to reduce the drawing load self.pw1.setDownsampling(mode='peak') self.pw1.setClipToView(True) # Initialize and set titles and axis names for both plots self.clear_vars_graphs() self.combo0.activated[str].connect(self.onActivated0) self.guvtype_cb.activated[str].connect(self.onActivated1) self.cb_logdata.toggled.connect(self.logdata) # run or cancel the main script self.runstopButton.clicked.connect(self.runstop) self.clearButton.clicked.connect(self.set_clear) self.clearButton.setEnabled(False) def logdata(self): if self.cb_logdata.isChecked(): self.time_str = time.strftime("%y%m%d-%H%M") head, tail = os.path.split(str(self.file_edit.text())) self.log_guv_str = ''.join( [head, '/log_', self.guvtype_str, '_', self.time_str]) self.lcd.display(self.time_str) self.file_edit.setText(self.log_guv_str) self.file_edit.setEnabled(True) else: self.file_edit.setEnabled(False) def onActivated0(self, text): old_st = self.schroll_pts self.schroll_pts = int(str(text)) if old_st > self.schroll_pts: self.set_clear() def onActivated1(self, text): old_guvtype = self.guvtype_str self.guvtype_str = str(text) if old_guvtype != self.guvtype_str: head, tail = os.path.split(str(self.file_edit.text())) self.log_guv_str = ''.join( [head, '/log_', self.guvtype_str, '_', self.time_str]) self.file_edit.setText(self.log_guv_str) self.set_clear() ''' self.config.set(self.last_used_scan, 'guvtype', self.guvtype_str) with open('config.ini', 'w') as configfile: self.config.write(configfile) ''' def createTable(self): tableWidget = QTableWidget() #tableWidget.setFixedWidth(175) # set row count #tableWidget.setRowCount(20) # set column count tableWidget.setColumnCount(2) # hide grid tableWidget.setShowGrid(False) # hide vertical header vh = tableWidget.verticalHeader() vh.setVisible(False) # set the font font = QFont("Courier New", 9) tableWidget.setFont(font) tableWidget.setStyleSheet("color: blue") # place content into individual table fields #tableWidget.setItem(0,0, QTableWidgetItem("abe")) tableWidget.setHorizontalHeaderLabels( ["Time[s]", "Channel power density"]) #tableWidget.setVerticalHeaderLabels(["aa","bb","cc","dd"]) # set horizontal header properties hh = tableWidget.horizontalHeader() hh.setStretchLastSection(True) # set column width to fit contents tableWidget.resizeColumnsToContents() # enable sorting #tableWidget.setSortingEnabled(True) return tableWidget def set_cancel(self): self.worker.abort() self.clearButton.setEnabled(True) self.runstopButton.setText("START") def set_clear(self): self.clear_vars_graphs() self.clearButton.setEnabled(False) self.clearButton.setText("Cleared") def runstop(self): sender = self.sender() if sender.text() == "START": self.set_run() elif sender.text() == "STOP": self.set_cancel() def set_run(self): if self.cb_logdata.isChecked(): # Check if folder exists and if not create it head, tail = os.path.split(str(self.file_edit.text())) if head: if head[0] == '/': QMessageBox.critical( self, 'Message', 'Path name should not start with a forward slash (/)') return else: QMessageBox.critical(self, 'Message', 'No path to folder(s) provided!') return try: os.makedirs(os.path.dirname(str(self.file_edit.text())), exist_ok=True) except Exception as e: QMessageBox.critical( self, 'Message', ''.join(["Folder named ", head, " not valid!\n", str(e)])) return self.log_guv_str = str(self.file_edit.text()) self.config.set(self.last_used_scan, 'log_guv', ','.join([self.log_guv_str, str(True)])) else: self.config.set(self.last_used_scan, 'log_guv', ','.join([self.log_guv_str, str(False)])) with open('config.ini', 'w') as configfile: self.config.write(configfile) try: self.GUV = GUV.GUV([ str(self.ipportEdit.text()), str(self.tcpportEdit.text()), self.guvtype_str ], False, self.config) except Exception as e: reply = QMessageBox.critical( self, ''.join([self.guvtype_str, ' TEST MODE']), ''.join([ self.guvtype_str, " could not return valid echo signal. Check the port name and check the connection.\n", str(e), "\n\nShould the program proceeds into the TEST MODE?" ]), QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.GUV = GUV.GUV([ str(self.ipportEdit.text()), str(self.tcpportEdit.text()), self.guvtype_str ], True, self.config) else: return #self.set_clear() self.runstopButton.setEnabled(True) self.runstopButton.setText("STOP") self.clearButton.setEnabled(False) self.combo0.setEnabled(False) self.ipportEdit.setEnabled(False) self.tcpportEdit.setEnabled(False) self.guvtype_cb.setEnabled(False) self.cb_logdata.setEnabled(False) self.file_edit.setEnabled(False) self.isRunning = True setrun_obj = type('setscan_obj', (object, ), {'guv': self.GUV}) self.worker = GUV_Worker(setrun_obj) self.worker.signals.update0.connect(self.update0) self.worker.signals.finished.connect(self.finished) # Execute self.threadpool.start(self.worker) def update0(self, times, volts): self.tal += 1 times = [i + self.stoptime for i in times] # set row height self.tableWidget.setRowCount(self.tal + 1) self.tableWidget.setRowHeight(self.tal, 12) # add row elements self.tableWidget.setItem(self.tal, 0, QTableWidgetItem(format(times[0], '.2e'))) self.tableWidget.setItem( self.tal, 1, QTableWidgetItem(', '.join( [format(float(i), '.2e') for i in volts]))) if self.tal > self.schroll_pts: self.times[:-1] = self.times[ 1:] # shift data in the array one sample left self.times[-1] = times self.plot_volts_tr[:-1] = self.plot_volts_tr[ 1:] # shift data in the array one sample left self.plot_volts_tr[-1] = volts else: self.times.append(times) self.plot_volts_tr.append(volts) ## Handle view resizing def updateViews(): ## view has resized; update auxiliary views to match self.p0_1.setGeometry(self.p1.vb.sceneBoundingRect()) #p3.setGeometry(p1.vb.sceneBoundingRect()) ## need to re-update linked axes since this was called ## incorrectly while views had different shapes. ## (probably this should be handled in ViewBox.resizeEvent) self.p0_1.linkedViewChanged(self.p1.vb, self.p0_1.XAxis) #p3.linkedViewChanged(p1.vb, p3.XAxis) updateViews() self.p1.vb.sigResized.connect(updateViews) times_ = list(map(list, zip(*self.times))) plot_volts_tr_ = list(map(list, zip(*self.plot_volts_tr))) for i in range(len(times_)): self.curves[i].setData(times_[i], plot_volts_tr_[i]) #self.curve2.setData(self.times, self.plot_volts_tr) def finished(self): self.stoptime = self.times[-1][-1] self.isRunning = False self.ipportEdit.setEnabled(True) self.tcpportEdit.setEnabled(True) self.guvtype_cb.setEnabled(True) self.cb_logdata.setEnabled(True) if self.cb_logdata.isChecked(): self.file_edit.setEnabled(True) else: self.file_edit.setEnabled(False) self.combo0.setEnabled(True) self.clearButton.setEnabled(True) self.clearButton.setText("Clear") def clear_vars_graphs(self): # PLOT 2 initial canvas settings self.stoptime = 0 self.tal = -1 self.times = [] self.plot_volts_tr = [] for i in range(20): self.curves[i].clear() self.curve2.clear() self.tableWidget.clearContents() def closeEvent(self, event): reply = QMessageBox.question(self, 'Message', "Quit now? Changes will not be saved!", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: if hasattr(self, 'GUV'): if self.isRunning: QMessageBox.warning( self, 'Message', "Run in progress. Cancel the scan then quit!") event.ignore() return event.accept() else: event.ignore()
class MainWindow(QWidget): def __init__(self): super().__init__() self.backlog = Backlog() self.backlog.load( "C:\\Users\\Patrick\\Documents\\Python\\Giro\\turboClock\\Data\\tasksData.dat" ) self.currTask = Task() self.currPiece = Piece() self.currDuty = Duty() self.currTaskItemRow = 0 self.isTimerRunning = False self.editTasksGUI = EditBacklogGUI(self, self.backlog) self.initUI() def initUI(self): self.setWindowTitle("TurboClock") self.resize(400, 300) self.setWindowIcon(QIcon('Images//clock.png')) self.icon = QSystemTrayIcon(self) self.icon.setIcon(QIcon('Images//clock.png')) self.icon.setVisible(True) self.lcdNumber = QLCDNumber() self.lcdNumber.setNumDigits(8) self.btnStartPause = QPushButton('', self) self.btnStartPause.setIcon(QIcon('Images//play_icon.png')) self.btnStartPause.clicked.connect(self.manageStartPauseClickButton) self.btnDutyDetails = QPushButton('Duty details...') self.btnDutyDetails.clicked.connect(self.manageDutyDetailsClickedEvent) self.btnAddTfsTask = QPushButton('', self) self.btnAddTfsTask.setIcon(QIcon('Images//plus_icon.png')) self.btnAddTfsTask.clicked.connect(self.manageEditTasksOptions) self.progressBar = QProgressBar() self.progressBar.setValue(0) self.dutyTimeCompLbl = QLabel() self.taskCb = QComboBox(self) self.initTaskCombobox() mainLayout = QVBoxLayout(self) layoutTimer = QVBoxLayout() layoutTimer.addWidget(self.lcdNumber) fieldsInputLayout = QHBoxLayout() layoutInputCodes = QVBoxLayout() layoutInputCodes.addWidget(self.taskCb) layoutAddBtn = QVBoxLayout() layoutAddBtn.addWidget(self.btnAddTfsTask) fieldsInputLayout.addLayout(layoutInputCodes) fieldsInputLayout.addLayout(layoutAddBtn) layoutDutyStat = QHBoxLayout() layoutDutyStat.addWidget(self.dutyTimeCompLbl) layoutProgressBar = QHBoxLayout() layoutProgressBar.addWidget(self.progressBar) mainLayout.addLayout(layoutTimer) mainLayout.addLayout(fieldsInputLayout) mainLayout.addWidget(self.btnStartPause) mainLayout.addWidget(self.btnDutyDetails) mainLayout.addWidget(self.progressBar) mainLayout.addLayout(layoutDutyStat) self.timer = QTimer(self) self.deltaTimer = 0 self.currTimeLCD = QTime(0, 0, 0) self.currTimeDuty = QTime(0, 0, 0) self.timer.timeout.connect(self.incrementTimer) self.updateTimeLCD() self.updateDutyTimeDisp() self.updateProgressBarDisplay() def initTaskCombobox(self): self.updateTaskCombobox() self.taskCb.currentIndexChanged.connect(self.manageCbIndexChange) def updateProgressBarDisplay(self): estimatedTime = self.currTask.estimatedTime if estimatedTime == 0: return ratioFromTimer = (self.deltaTimer / estimatedTime) totalCompletionPerc = int( (self.currTask.completionRatio + ratioFromTimer) * 100) if totalCompletionPerc <= 100: self.progressBar.setValue(totalCompletionPerc) else: self.progressBar.setValue(100) def updateTaskCombobox(self): currTaskIndex = 0 self.taskCb.clear() tasks = self.backlog.tasks for currTask in tasks: taskDesc = currTask.title + ' - ' + currTask.prjCode self.taskCb.addItem(taskDesc) self.taskCb.setCurrentIndex(currTaskIndex) self.manageSelectedTaskChange(self.taskCb.currentText()) def manageCbIndexChange(self): self.currTaskItemRow = self.taskCb.currentIndex() if self.currTaskItemRow >= 0 and self.currTaskItemRow <= self.taskCb.count( ): currTextCb = self.taskCb.currentText() self.manageSelectedTaskChange(currTextCb) self.updateTimeLCD() self.deltaTimer = 0 self.updateProgressBarDisplay() def updateTimeLCD(self): currTaskTimeStr = str( datetime.timedelta(seconds=self.currTask.completedTime)) currTaskTime_split = str(currTaskTimeStr).split(':') h = int(currTaskTime_split[0]) m = int(currTaskTime_split[1]) s = int(currTaskTime_split[2]) self.currTimeLCD = QTime(h, m, s) self.lcdNumber.display(self.currTimeLCD.toString('hh:mm:ss')) def updateDutyTimeDisp(self): currDutyTimeStr = str( datetime.timedelta(seconds=self.currDuty.totalTimeCompleted)) currDutyTime_split = currDutyTimeStr.split(':') h = int(currDutyTime_split[0]) m = int(currDutyTime_split[1]) s = int(currDutyTime_split[2]) self.currTimeDuty = QTime(h, m, s) self.dutyTimeCompLbl.setText('Daily time completed: ' + self.currTimeDuty.toString('hh:mm:ss')) def incrementTimer(self): self.currTimeLCD = self.currTimeLCD.addSecs(1) self.lcdNumber.display(self.currTimeLCD.toString('hh:mm:ss')) self.currTimeDuty = self.currTimeDuty.addSecs(1) self.dutyTimeCompLbl.setText('Daily time completed: ' + self.currTimeDuty.toString('hh:mm:ss')) self.deltaTimer += 1 self.updateProgressBarDisplay() def manageSelectedTaskChange(self, iCbbText): splitCurrTextCb = iCbbText.split(' - ') title = splitCurrTextCb[0] prjCode = splitCurrTextCb[1] indexBacklogCurrTask = self.backlog.getIndexFromTask( Task(prjCode, title)) if indexBacklogCurrTask != None: if self.isTimerRunning: self.endPiece() self.startPiece() self.currTask = self.backlog.tasks[indexBacklogCurrTask] else: return def startPiece(self): self.currPiece = Piece(self.currTask, datetime.datetime.now()) self.isTimerRunning = True def endPiece(self): self.currPiece.setEndDateTime(datetime.datetime.now()) self.currDuty.addPiece(self.currPiece) self.currTask.addCompletedTime(self.currPiece.task.completedTime) self.isTimerRunning = False def manageStartPauseClickButton(self): if self.currTask: self.deltaTimer = 0 if self.isTimerRunning: self.timer.stop() self.endPiece() self.btnStartPause.setIcon(QIcon('Images//play_icon.png')) else: self.timer.start(1000) self.startPiece() self.btnStartPause.setIcon(QIcon('Images//pause_icon.png')) def manageDutyDetailsClickedEvent(self): pass def manageEditTasksOptions(self): self.editTasksGUI.exec_()