Exemple #1
0
    def initUI(self):
        grid = QGridLayout()
        self.setLayout(grid)

        display = QLCDNumber(self)
        display.setFixedHeight(80)
        display.display(0)
        grid.addWidget(display, 0, 0, 1, 5)

        names = [
            'MC', 'MR', 'MS', 'M+', 'M-', '\u20D6', 'CE', 'C', '\u00B1',
            '\u221A', '7', '8', '9', '/', '%', '4', '5', '6', '*', '1/x', '1',
            '2', '3', '-', '=', '0', '', ',', '+', ''
        ]

        positions = [(i, j) for i in range(1, 7) for j in range(5)]
        for position, name in zip(positions, names):

            if name == '':
                continue

            button = QPushButton(name)
            if name == '0':
                grid.addWidget(button, 6, 0, 1, 2)
            elif name == '=':
                button.setFixedHeight(80)
                grid.addWidget(button, 5, 4, 2, 1)
            else:
                grid.addWidget(button, *position)
Exemple #2
0
 def __build_lcd_number_widget(self):
     """Build a LCD Number widget."""
     lcdnumber = QLCDNumber(self)
     lcdnumber.setSegmentStyle(QLCDNumber.Filled)
     lcdnumber.setFixedHeight(40)
     lcdnumber.setFrameStyle(QFrame.NoFrame)
     return lcdnumber
Exemple #3
0
    def fillVbox(self, vbox):
        lcd = QLCDNumber()
        # lcd.setFixedSize(150, 70)
        lcd.setFixedHeight(150)
        layout = QGridLayout()
        vbox.addLayout(layout)

        label = [
            'MC', 'MR', 'MS', 'M+', 'M-', '<-', 'CE', 'C', '+/-', 'sqrt', 7, 8,
            9, '/', '%', 4, 5, 6, '*', '1/x', 1, 2, 3, '-', 'x', 'x', 'x', '.',
            '+', 'x'
        ]
        for w in range(0, len(label)):
            layout.addWidget(QPushButton(str(label[w])), int(1 + w / 5),
                             int(w % 5))
        layout.addWidget(lcd, 0, 0, 1, 5)
        layout.addWidget(QPushButton(str("0")), 1 + 5, 0, 1, 2)
        layout.addWidget(QPushButton(str("\n\n=\n")), 1 + 4, 4, 2, 1)
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        
        self.lcd = QLCDNumber()
        self.lcd.setFixedWidth(100)
        self.lcd.setFixedHeight(100)
        
        mySlyder = QSlider(Qt.Horizontal,self)
        mySlyder.setMaximun(254)
        mySlyder.setMinimun(0)
		mySlyder.setGeometry(30,40,200,30)
        mySlyder.valueChanged.connect(self.changedValue)
        
        self.setGeometry(50,50,320,200)
        self.setWindowTitle("Curso RPI4")
        
        layout = QVBoxLayout()
        layout.addWidget(self.lcd)
        layout.addWidget(mySlider)
        self.setLayout(layout)
class parameterWidget(QWidget):
    def __init__(self,minimum,maximum):
        super(parameterWidget,self).__init__()
        self.container = QVBoxLayout()
        self.container.addStretch(1)
        self.slider = QSlider(Qt.Horizontal, self)
        self.slider.setMinimum(minimum)
        self.slider.setMaximum(maximum)
        self.slider.setTickInterval(1)
        self.slider.setSingleStep(1)
        self.container.addWidget(self.slider)
        self.lcd = QLCDNumber()
        self.lcd.setFixedHeight(100)
        self.lcd.setFixedWidth(100)
        self.lcd.resize(50, 100)
        self.container.addWidget(self.lcd)
        self.lcd.setDigitCount(8)
        self.slider.valueChanged.connect(self.update_lcd)
        self.container.addStretch(1)
        self.setLayout(self.container)

    @pyqtSlot(int)
    def update_lcd(self,value):
        self.lcd.display(str(value))
Exemple #6
0
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()
Exemple #7
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupTrayicon()
        self.setupVariables()
        self.setupUi()
        self.setupConnections()
        self.show()

    def setupVariables(self):
        settings = QSettings()
        self.workEndTime = QTime(
            int(settings.value(workHoursKey, 0)),
            int(settings.value(workMinutesKey, 25)),
            int(settings.value(workSecondsKey, 0)),
        )
        self.restEndTime = QTime(
            int(settings.value(restHoursKey, 0)),
            int(settings.value(restMinutesKey, 5)),
            int(settings.value(restSecondsKey, 0)),
        )
        self.timeFormat = "hh:mm:ss"
        self.time = QTime(0, 0, 0, 0)
        self.workTime = QTime(0, 0, 0, 0)
        self.restTime = QTime(0, 0, 0, 0)
        self.totalTime = QTime(0, 0, 0, 0)
        self.currentMode = Mode.work
        self.maxRepetitions = -1
        self.currentRepetitions = 0

    def setupConnections(self):
        """ Create button connections """
        self.startButton.clicked.connect(self.startTimer)
        self.startButton.clicked.connect(
            lambda: self.startButton.setDisabled(True))
        self.startButton.clicked.connect(
            lambda: self.pauseButton.setDisabled(False))
        self.startButton.clicked.connect(
            lambda: self.resetButton.setDisabled(False))
        self.pauseButton.clicked.connect(self.pauseTimer)
        self.pauseButton.clicked.connect(
            lambda: self.startButton.setDisabled(False))
        self.pauseButton.clicked.connect(
            lambda: self.pauseButton.setDisabled(True))
        self.pauseButton.clicked.connect(
            lambda: self.resetButton.setDisabled(False))
        self.pauseButton.clicked.connect(
            lambda: self.startButton.setText("continue"))
        self.resetButton.clicked.connect(self.resetTimer)
        self.resetButton.clicked.connect(
            lambda: self.startButton.setDisabled(False))
        self.resetButton.clicked.connect(
            lambda: self.pauseButton.setDisabled(True))
        self.resetButton.clicked.connect(
            lambda: self.resetButton.setDisabled(True))
        self.resetButton.clicked.connect(
            lambda: self.startButton.setText("start"))
        self.acceptTaskButton.pressed.connect(self.insertTask)
        self.deleteTaskButton.pressed.connect(self.deleteTask)
        """ Create spinbox  connections """
        self.workHoursSpinBox.valueChanged.connect(self.updateWorkEndTime)
        self.workMinutesSpinBox.valueChanged.connect(self.updateWorkEndTime)
        self.workSecondsSpinBox.valueChanged.connect(self.updateWorkEndTime)
        self.restHoursSpinBox.valueChanged.connect(self.updateRestEndTime)
        self.restMinutesSpinBox.valueChanged.connect(self.updateRestEndTime)
        self.restSecondsSpinBox.valueChanged.connect(self.updateRestEndTime)
        self.repetitionsSpinBox.valueChanged.connect(self.updateMaxRepetitions)
        """ Create combobox connections """
        self.modeComboBox.currentTextChanged.connect(self.updateCurrentMode)
        """ Create tablewidget connections """
        self.tasksTableWidget.cellDoubleClicked.connect(
            self.markTaskAsFinished)

    def setupUi(self):
        self.size_policy = sizePolicy = QSizePolicy(QSizePolicy.Expanding,
                                                    QSizePolicy.Expanding)
        """ Create tabwidget """
        self.tabWidget = QTabWidget()
        """ Create tab widgets """
        timerWidget = self.setupTimerTab()
        tasksWidget = self.setupTasksTab()
        statisticsWidget = self.setupStatisticsTab()
        """ add tab widgets to tabwidget"""
        self.timerTab = self.tabWidget.addTab(timerWidget, makeIcon("timer"),
                                              "Timer")
        self.tasksTab = self.tabWidget.addTab(tasksWidget, makeIcon("tasks"),
                                              "Tasks")
        self.statisticsTab = self.tabWidget.addTab(statisticsWidget,
                                                   makeIcon("statistics"),
                                                   "Statistics")
        """ Set mainwindows central widget """
        self.setCentralWidget(self.tabWidget)

    def setupTimerTab(self):
        settings = QSettings()
        self.timerContainer = QWidget(self)
        self.timerContainerLayout = QVBoxLayout(self.timerContainer)
        self.timerContainer.setLayout(self.timerContainerLayout)
        """ Create work groupbox"""
        self.workGroupBox = QGroupBox("Work")
        self.workGroupBoxLayout = QHBoxLayout(self.workGroupBox)
        self.workGroupBox.setLayout(self.workGroupBoxLayout)
        self.workHoursSpinBox = QSpinBox(
            minimum=0,
            maximum=24,
            value=int(settings.value(workHoursKey, 0)),
            suffix="h",
            sizePolicy=self.size_policy,
        )
        self.workMinutesSpinBox = QSpinBox(
            minimum=0,
            maximum=60,
            value=int(settings.value(workMinutesKey, 25)),
            suffix="m",
            sizePolicy=self.size_policy,
        )
        self.workSecondsSpinBox = QSpinBox(
            minimum=0,
            maximum=60,
            value=int(settings.value(workSecondsKey, 0)),
            suffix="s",
            sizePolicy=self.size_policy,
        )
        """ Create rest groupbox"""
        self.restGroupBox = QGroupBox("Rest")
        self.restGroupBoxLayout = QHBoxLayout(self.restGroupBox)
        self.restGroupBox.setLayout(self.restGroupBoxLayout)
        self.restHoursSpinBox = QSpinBox(
            minimum=0,
            maximum=24,
            value=int(settings.value(restHoursKey, 0)),
            suffix="h",
            sizePolicy=self.size_policy,
        )
        self.restMinutesSpinBox = QSpinBox(
            minimum=0,
            maximum=60,
            value=int(settings.value(restMinutesKey, 5)),
            suffix="m",
            sizePolicy=self.size_policy,
        )
        self.restSecondsSpinBox = QSpinBox(
            minimum=0,
            maximum=60,
            value=int(settings.value(restSecondsKey, 0)),
            suffix="s",
            sizePolicy=self.size_policy,
        )
        self.restGroupBoxLayout.addWidget(self.restHoursSpinBox)
        self.restGroupBoxLayout.addWidget(self.restMinutesSpinBox)
        self.restGroupBoxLayout.addWidget(self.restSecondsSpinBox)
        """ Create other groupbox"""
        self.otherGroupBox = QGroupBox("Other")
        self.otherGroupBoxLayout = QHBoxLayout(self.otherGroupBox)
        self.otherGroupBox.setLayout(self.otherGroupBoxLayout)
        self.repetitionsLabel = QLabel("Repetitions")
        self.repetitionsSpinBox = QSpinBox(
            minimum=0,
            maximum=10000,
            value=0,
            sizePolicy=self.size_policy,
            specialValueText="∞",
        )
        self.modeLabel = QLabel("Mode")
        self.modeComboBox = QComboBox(sizePolicy=self.size_policy)
        self.modeComboBox.addItems(["work", "rest"])
        self.otherGroupBoxLayout.addWidget(self.repetitionsLabel)
        self.otherGroupBoxLayout.addWidget(self.repetitionsSpinBox)
        self.otherGroupBoxLayout.addWidget(self.modeLabel)
        self.otherGroupBoxLayout.addWidget(self.modeComboBox)
        """ Create timer groupbox"""
        self.lcdDisplayGroupBox = QGroupBox("Time")
        self.lcdDisplayGroupBoxLayout = QHBoxLayout(self.lcdDisplayGroupBox)
        self.lcdDisplayGroupBox.setLayout(self.lcdDisplayGroupBoxLayout)
        self.timeDisplay = QLCDNumber(8, sizePolicy=self.size_policy)
        self.timeDisplay.setFixedHeight(100)
        self.timeDisplay.display("00:00:00")
        self.lcdDisplayGroupBoxLayout.addWidget(self.timeDisplay)
        """ Create pause, start and reset buttons"""
        self.buttonContainer = QWidget()
        self.buttonContainerLayout = QHBoxLayout(self.buttonContainer)
        self.buttonContainer.setLayout(self.buttonContainerLayout)
        self.startButton = self.makeButton("start", disabled=False)
        self.resetButton = self.makeButton("reset")
        self.pauseButton = self.makeButton("pause")
        """ Add widgets to container """
        self.workGroupBoxLayout.addWidget(self.workHoursSpinBox)
        self.workGroupBoxLayout.addWidget(self.workMinutesSpinBox)
        self.workGroupBoxLayout.addWidget(self.workSecondsSpinBox)
        self.timerContainerLayout.addWidget(self.workGroupBox)
        self.timerContainerLayout.addWidget(self.restGroupBox)
        self.timerContainerLayout.addWidget(self.otherGroupBox)
        self.timerContainerLayout.addWidget(self.lcdDisplayGroupBox)
        self.buttonContainerLayout.addWidget(self.pauseButton)
        self.buttonContainerLayout.addWidget(self.startButton)
        self.buttonContainerLayout.addWidget(self.resetButton)
        self.timerContainerLayout.addWidget(self.buttonContainer)
        return self.timerContainer

    def setupTasksTab(self):
        settings = QSettings()
        """ Create vertical tasks container """
        self.tasksWidget = QWidget(self.tabWidget)
        self.tasksWidgetLayout = QVBoxLayout(self.tasksWidget)
        self.tasksWidget.setLayout(self.tasksWidgetLayout)
        """ Create horizontal input container """
        self.inputContainer = QWidget()
        self.inputContainer.setFixedHeight(50)
        self.inputContainerLayout = QHBoxLayout(self.inputContainer)
        self.inputContainerLayout.setContentsMargins(0, 0, 0, 0)
        self.inputContainer.setLayout(self.inputContainerLayout)
        """ Create text edit """
        self.taskTextEdit = QTextEdit(
            placeholderText="Describe your task briefly.",
            undoRedoEnabled=True)
        """ Create vertical buttons container """
        self.inputButtonContainer = QWidget()
        self.inputButtonContainerLayout = QVBoxLayout(
            self.inputButtonContainer)
        self.inputButtonContainerLayout.setContentsMargins(0, 0, 0, 0)
        self.inputButtonContainer.setLayout(self.inputButtonContainerLayout)
        """ Create buttons """
        self.acceptTaskButton = QToolButton(icon=makeIcon("check"))
        self.deleteTaskButton = QToolButton(icon=makeIcon("trash"))
        """ Create tasks tablewidget """
        self.tasksTableWidget = QTableWidget(0, 1)
        self.tasksTableWidget.setHorizontalHeaderLabels(["Tasks"])
        self.tasksTableWidget.horizontalHeader().setStretchLastSection(True)
        self.tasksTableWidget.verticalHeader().setVisible(False)
        self.tasksTableWidget.setWordWrap(True)
        self.tasksTableWidget.setTextElideMode(Qt.ElideNone)
        self.tasksTableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tasksTableWidget.setSelectionMode(
            QAbstractItemView.SingleSelection)
        self.insertTasks(*settings.value(tasksKey, []))
        """ Add widgets to container widgets """
        self.inputButtonContainerLayout.addWidget(self.acceptTaskButton)
        self.inputButtonContainerLayout.addWidget(self.deleteTaskButton)
        self.inputContainerLayout.addWidget(self.taskTextEdit)
        self.inputContainerLayout.addWidget(self.inputButtonContainer)
        self.tasksWidgetLayout.addWidget(self.inputContainer)
        self.tasksWidgetLayout.addWidget(self.tasksTableWidget)
        return self.tasksWidget

    def setupStatisticsTab(self):
        """ Create statistics container """
        self.statisticsContainer = QWidget()
        self.statisticsContainerLayout = QVBoxLayout(self.statisticsContainer)
        self.statisticsContainer.setLayout(self.statisticsContainerLayout)
        """ Create work time groupbox """
        self.statisticsWorkTimeGroupBox = QGroupBox("Work Time")
        self.statisticsWorkTimeGroupBoxLayout = QHBoxLayout()
        self.statisticsWorkTimeGroupBox.setLayout(
            self.statisticsWorkTimeGroupBoxLayout)
        self.statisticsWorkTimeDisplay = QLCDNumber(8)
        self.statisticsWorkTimeDisplay.display("00:00:00")
        self.statisticsWorkTimeGroupBoxLayout.addWidget(
            self.statisticsWorkTimeDisplay)
        """ Create rest time groupbox """
        self.statisticsRestTimeGroupBox = QGroupBox("Rest Time")
        self.statisticsRestTimeGroupBoxLayout = QHBoxLayout()
        self.statisticsRestTimeGroupBox.setLayout(
            self.statisticsRestTimeGroupBoxLayout)
        self.statisticsRestTimeDisplay = QLCDNumber(8)
        self.statisticsRestTimeDisplay.display("00:00:00")
        self.statisticsRestTimeGroupBoxLayout.addWidget(
            self.statisticsRestTimeDisplay)
        """ Create total time groupbox """
        self.statisticsTotalTimeGroupBox = QGroupBox("Total Time")
        self.statisticsTotalTimeGroupBoxLayout = QHBoxLayout()
        self.statisticsTotalTimeGroupBox.setLayout(
            self.statisticsTotalTimeGroupBoxLayout)
        self.statisticsTotalTimeDisplay = QLCDNumber(8)
        self.statisticsTotalTimeDisplay.display("00:00:00")
        self.statisticsTotalTimeGroupBoxLayout.addWidget(
            self.statisticsTotalTimeDisplay)
        """ Add widgets to container """
        self.statisticsContainerLayout.addWidget(
            self.statisticsTotalTimeGroupBox)
        self.statisticsContainerLayout.addWidget(
            self.statisticsWorkTimeGroupBox)
        self.statisticsContainerLayout.addWidget(
            self.statisticsRestTimeGroupBox)
        return self.statisticsContainer

    def setupTrayicon(self):
        self.trayIcon = QSystemTrayIcon(makeIcon("tomato"))
        self.trayIcon.setContextMenu(QMenu())
        self.quitAction = self.trayIcon.contextMenu().addAction(
            makeIcon("exit"), "Quit", self.exit)
        self.quitAction.triggered.connect(self.exit)
        self.trayIcon.activated.connect(self.onActivate)
        self.trayIcon.show()

    def leaveEvent(self, event):
        super(MainWindow, self).leaveEvent(event)
        self.tasksTableWidget.clearSelection()

    def closeEvent(self, event):
        super(MainWindow, self).closeEvent(event)
        settings = QSettings()
        settings.setValue(workHoursKey, self.workHoursSpinBox.value())
        settings.setValue(
            workMinutesKey,
            self.workMinutesSpinBox.value(),
        )
        settings.setValue(
            workSecondsKey,
            self.workSecondsSpinBox.value(),
        )
        settings.setValue(restHoursKey, self.restHoursSpinBox.value())
        settings.setValue(
            restMinutesKey,
            self.restMinutesSpinBox.value(),
        )
        settings.setValue(
            restSecondsKey,
            self.restSecondsSpinBox.value(),
        )

        tasks = []
        for i in range(self.tasksTableWidget.rowCount()):
            item = self.tasksTableWidget.item(i, 0)
            if not item.font().strikeOut():
                tasks.append(item.text())
        settings.setValue(tasksKey, tasks)

    def startTimer(self):
        try:
            if not self.timer.isActive():
                self.createTimer()
        except:
            self.createTimer()

    def createTimer(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.updateTime)
        self.timer.timeout.connect(self.maybeChangeMode)
        self.timer.setInterval(1000)
        self.timer.setSingleShot(False)
        self.timer.start()

    def pauseTimer(self):
        try:
            self.timer.stop()
            self.timer.disconnect()
        except:
            pass

    def resetTimer(self):
        try:
            self.pauseTimer()
            self.time = QTime(0, 0, 0, 0)
            self.displayTime()
        except:
            pass

    def maybeStartTimer(self):
        if self.currentRepetitions != self.maxRepetitions:
            self.startTimer()
            started = True
        else:
            self.currentRepetitions = 0
            started = False
        return started

    def updateWorkEndTime(self):
        self.workEndTime = QTime(
            self.workHoursSpinBox.value(),
            self.workMinutesSpinBox.value(),
            self.workSecondsSpinBox.value(),
        )

    def updateRestEndTime(self):
        self.restEndTime = QTime(
            self.restHoursSpinBox.value(),
            self.restMinutesSpinBox.value(),
            self.restSecondsSpinBox.value(),
        )

    def updateCurrentMode(self, mode: str):
        self.currentMode = Mode.work if mode == "work" else Mode.rest

    def updateTime(self):
        self.time = self.time.addSecs(1)
        self.totalTime = self.totalTime.addSecs(1)
        if self.modeComboBox.currentText() == "work":
            self.workTime = self.workTime.addSecs(1)
        else:
            self.restTime = self.restTime.addSecs(1)
        self.displayTime()

    def updateMaxRepetitions(self, value):
        if value == 0:
            self.currentRepetitions = 0
            self.maxRepetitions = -1
        else:
            self.maxRepetitions = 2 * value

    def maybeChangeMode(self):
        if self.currentMode is Mode.work and self.time >= self.workEndTime:
            self.resetTimer()
            self.modeComboBox.setCurrentIndex(1)
            self.incrementCurrentRepetitions()
            started = self.maybeStartTimer()
            self.showWindowMessage(
                Status.workFinished if started else Status.repetitionsReached)
        elif self.currentMode is Mode.rest and self.time >= self.restEndTime:
            self.resetTimer()
            self.modeComboBox.setCurrentIndex(0)
            self.incrementCurrentRepetitions()
            started = self.maybeStartTimer()
            self.showWindowMessage(
                Status.restFinished if started else Status.repetitionsReached)

    def incrementCurrentRepetitions(self):
        if self.maxRepetitions > 0:
            self.currentRepetitions += 1

    def insertTask(self):
        task = self.taskTextEdit.toPlainText()
        self.insertTasks(task)

    def insertTasks(self, *tasks):
        for task in tasks:
            if task:
                rowCount = self.tasksTableWidget.rowCount()
                self.tasksTableWidget.setRowCount(rowCount + 1)
                self.tasksTableWidget.setItem(rowCount, 0,
                                              QTableWidgetItem(task))
                self.tasksTableWidget.resizeRowsToContents()
                self.taskTextEdit.clear()

    def deleteTask(self):
        selectedIndexes = self.tasksTableWidget.selectedIndexes()
        if selectedIndexes:
            self.tasksTableWidget.removeRow(selectedIndexes[0].row())

    def markTaskAsFinished(self, row, col):
        item = self.tasksTableWidget.item(row, col)
        font = self.tasksTableWidget.item(row, col).font()
        font.setStrikeOut(False if item.font().strikeOut() else True)
        item.setFont(font)

    def displayTime(self):
        self.timeDisplay.display(self.time.toString(self.timeFormat))
        self.statisticsRestTimeDisplay.display(
            self.restTime.toString(self.timeFormat))
        self.statisticsWorkTimeDisplay.display(
            self.workTime.toString(self.timeFormat))
        self.statisticsTotalTimeDisplay.display(
            self.totalTime.toString(self.timeFormat))

    def showWindowMessage(self, status):
        if status is Status.workFinished:
            self.trayIcon.showMessage("Break", choice(work_finished_phrases),
                                      makeIcon("tomato"))
        elif status is Status.restFinished:
            self.trayIcon.showMessage("Work", choice(rest_finished_phrases),
                                      makeIcon("tomato"))
        else:
            self.trayIcon.showMessage("Finished",
                                      choice(pomodoro_finished_phrases),
                                      makeIcon("tomato"))
            self.resetButton.click()

    def makeButton(self, text, iconName=None, disabled=True):
        button = QPushButton(text, sizePolicy=self.size_policy)
        if iconName:
            button.setIcon(makeIcon(iconName))
        button.setDisabled(disabled)
        return button

    def exit(self):
        self.close()
        app = QApplication.instance()
        if app:
            app.quit()

    def onActivate(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            self.show()
Exemple #8
0
class ToolBar(QToolBar):
    def __init__(self, appctxt, params, parent):
        super(ToolBar, self).__init__(parent)
        self.appctxt = appctxt
        self.params = params
        self.setIconSize(QSize(30, 30))

        self.playPause = QAction("Play/Pause (Space)", self)
        self.playPause.setShortcut(Qt.Key_Space)
        self.playPause.setShortcutContext(Qt.ApplicationShortcut)
        self.playPause.setIcon(
            QtGui.QIcon(self.appctxt.get_resource("Images/svg/play.svg")))

        self.reset = QAction("Reset Memory (Ctrl+R)", self)
        self.reset.setShortcut("Ctrl+R")
        self.reset.setShortcutContext(Qt.ApplicationShortcut)
        self.reset.setIcon(
            QIcon(self.appctxt.get_resource("Images/svg/reset.svg")))

        self.condition = QAction("Condition (Ctrl+C)", self)
        self.condition.setShortcut("Ctrl+C")
        self.condition.setShortcutContext(Qt.ApplicationShortcut)
        self.condition.setIcon(
            QIcon(self.appctxt.get_resource("Images/svg/upload.svg")))

        self.preferences = QAction("Preferences (Ctrl+P)", self)
        self.preferences.setShortcut("Ctrl+P")
        self.preferences.setShortcutContext(Qt.ApplicationShortcut)
        self.preferences.setIcon(
            QIcon(self.appctxt.get_resource("Images/svg/settingsBlueBig.svg")))

        self.save = QAction("Save (Ctrl+S)", self)
        self.save.setShortcut("Ctrl+S")
        self.save.setShortcutContext(Qt.ApplicationShortcut)
        self.save.setIcon(
            QIcon(self.appctxt.get_resource("Images/svg/save.svg")))

        self.lcd = QLCDNumber(self)
        self.lcd.display(1)
        self.lcd.setDigitCount(1)
        self.lcd.setFixedHeight(35)
        self.lcd.setFixedWidth(35)
        #sld.valueChanged.connect(self.lineEdit.setText())
        # # get the palette
        # palette = self.lcd.palette()
        # # foreground color
        # palette.setColor(palette.WindowText, QtGui.QColor(85, 85, 255))
        # # background color
        # palette.setColor(palette.Background, QtGui.QColor(0, 170, 255))
        # # "light" border
        # palette.setColor(palette.Light, QtGui.QColor(255, 0, 0))
        # # "dark" border
        # palette.setColor(palette.Dark, QtGui.QColor(0, 255, 0))

        # # set the palette
        # self.lcd.setPalette(palette)

        self.bpmBox = QSpinBox(self)
        self.bpmBox.setSuffix(" BPM")
        #self.bpmBox.setMinimumSize(30,30)
        self.bpmBox.setFixedHeight(35)
        self.bpmBox.setRange(20, 150)
        self.bpmBox.setSingleStep(5)
        self.bpmBox.setValue(self.params['metronome']["BPM"])

        # self.enforce = QAction("Enforce",self)
        # self.enforce.setShortcut("Ctrl+E")
        # self.enforce.setShortcutContext(Qt.ApplicationShortcut)

        # self.clear = QAction("Clear",self)
        # #self.clear.setShortcut("Ctrl+E")
        # self.clear.setShortcutContext(Qt.ApplicationShortcut)

        #self.enforce.setIcon(QIcon(self.appctxt.get_resource("Images/reset.svg")))
        #self.toolbarAction.setStatusTip("STARTPAUSE")
        #self.toolbarAction.setWhatsThis("srgsr")
        self.addAction(self.playPause)
        self.addAction(self.reset)
        self.addAction(self.condition)
        self.addAction(self.preferences)
        self.addAction(self.save)
        self.addWidget(self.bpmBox)
        self.addWidget(self.lcd)
        self.keyIndicator = QLabel("          ", objectName='keyIndicator')
Exemple #9
0
class WheelBox(QWidget):
    valueChanged = pyqtSignal('double', name="valueChanged")

    def __init__(self, title, min, max, stepSize, parent):
        super().__init__(parent)

        self.__d_number = QLCDNumber(self)
        self.__d_number.setSegmentStyle(QLCDNumber.Filled)
        self.__d_number.setAutoFillBackground(True)
        self.__d_number.setFixedHeight(self.__d_number.sizeHint().height() * 2)
        self.__d_number.setFocusPolicy(Qt.WheelFocus)

        pal = QPalette(Qt.black)
        pal.setColor(QPalette.WindowText, Qt.green)
        self.__d_number.setPalette(pal)

        self.__d_wheel = Wheel(self)
        self.__d_wheel.setOrientation(Qt.Vertical)
        self.__d_wheel.setInverted(True)
        self.__d_wheel.setRange(min, max)
        self.__d_wheel.setSingleStep(stepSize)
        self.__d_wheel.setPageStepCount(5)
        self.__d_wheel.setFixedHeight(self.__d_number.height())

        self.__d_number.setFocusProxy(self.__d_wheel)

        font = QFont("Helvetica", 10)
        font.setBold(True)

        self.__d_label = QLabel(title, self)
        self.__d_label.setFont(font)

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(2)
        hLayout.addWidget(self.__d_number, 10)
        hLayout.addWidget(self.__d_wheel)

        vLayout = QVBoxLayout(self)
        vLayout.addLayout(hLayout, 10)
        vLayout.addWidget(self.__d_label, 0, Qt.AlignTop | Qt.AlignHCenter)

        self.__d_wheel.valueChanged.connect(self.display)

        self.__d_wheel.valueChanged.connect(self.valueChanged)

    def display(self, value):
        self.__d_number.display(value)

    def theme(self):
        return self.__d_wheel.palette().color(QPalette.Window)

    def setTheme(self, color):
        self.__d_wheel.setPalette(QPalette(color))

    def setValue(self, value):
        self.__d_wheel.setValue(value)
        self.__d_number.display(value)

    def value(self):
        return self.__d_wheel.value()

    theme = pyqtProperty(QColor, theme, setTheme)
Exemple #10
0
class Timer(QDialog):
    timeout = pyqtSignal()
    def __init__(self, parent=None):
        super().__init__(parent)

        self.time=0
        self.timeInterval = 1000 #默认秒

        self.timerUp = QTimer()
        self.timerUp.setInterval(self.timeInterval)
        self.timerUp.timeout.connect(self.updateUptime)

        self.timerDown = QTimer()
        self.timerDown.setInterval(self.timeInterval)
        self.timerDown.timeout.connect(self.updateDowntime)

        self.initUi()

        self.buttonStart.clicked.connect(self.timerUp.start)
        self.buttonStop.clicked.connect(self.timerUp.stop)
        self.buttonReset.clicked.connect(self.reset)
        self.buttonCountDown.clicked.connect(self.timerDown.start)
        self.buttonStopAlarm.clicked.connect(self.timerDown.stop)
        self.timeSpinBox.valueChanged.connect(self.settimer)


    def initUi(self):
        mainLayout = QVBoxLayout()
        self.setLayout(mainLayout)

        self.groupBox = QGroupBox("unit")
        self.radioButton1 = QRadioButton("s")
        self.radioButton1.toggled.connect(self.setUnit)
        self.radioButton2 = QRadioButton("0.1s")
        self.radioButton2.toggled.connect(self.setUnit)
        self.radioButton3 = QRadioButton("0.01s")
        self.radioButton3.toggled.connect(self.setUnit)
        self.radioButton4 = QRadioButton("1ms")
        self.radioButton4.toggled.connect(self.setUnit)
        self.radioButton1.setChecked(True)
        self.unitLayout = QHBoxLayout()
        self.unitLayout.addWidget(self.radioButton1)
        self.unitLayout.addWidget(self.radioButton2)
        self.unitLayout.addWidget(self.radioButton3)
        self.unitLayout.addWidget(self.radioButton4)
        self.groupBox.setLayout(self.unitLayout)
        mainLayout.addWidget(self.groupBox)

        self.buttonStart = QPushButton(self.tr("start"))
        mainLayout.addWidget(self.buttonStart)


        self.buttonStop = QPushButton(self.tr("stop"))
        mainLayout.addWidget(self.buttonStop)

        self.timeViewer = QLCDNumber()
        self.timeViewer.setFixedHeight(45)
        mainLayout.addWidget(self.timeViewer)

        self.timeForHuman = QLabel()
        mainLayout.addWidget(self.timeForHuman)


        self.buttonReset = QPushButton(self.tr("reset"))
        mainLayout.addWidget(self.buttonReset)

        self.timeSpinBox = QSpinBox()
        self.timeSpinBox.setRange(0,10000)
        mainLayout.addWidget(self.timeSpinBox)
        self.buttonCountDown = QPushButton(self.tr("countdown"))
        mainLayout.addWidget(self.buttonCountDown)
        self.buttonStopAlarm = QPushButton(self.tr("stopalarm"))
        mainLayout.addWidget(self.buttonStopAlarm)



    def setUnit(self):
        if self.radioButton1.isChecked():
            self.timeInterval = 1000
        elif self.radioButton2.isChecked():
            self.timeInterval = 100
        elif self.radioButton3.isChecked():
            self.timeInterval = 10
        elif self.radioButton1.isChecked():
            self.timeInterval = 1
        self.timerUp.setInterval(self.timeInterval)
        self.timerDown.setInterval(self.timeInterval)


    def updateUptime(self):
        self.time += 1
        self.settimer(self.time)
        print(self.time)

    def updateDowntime(self):
        self.time =self.time-1
        self.settimer(self.time)
        print(self.time)
        if self.time <=0:
            self.timeout.emit()


    def settimer(self,int):
        self.time=int
        self.timeViewer.display(self.time)

        if self.timeInterval ==1000:
            self.timeForHuman.setText(time.strftime('%H hour %M minute %S second',time.gmtime(self.time)))
        elif self.timeInterval ==100:
            self.timeForHuman.setText(time.strftime('%H hour %M minute %S second',time.gmtime(self.time/10)))
        elif self.timeInterval ==10:
            self.timeForHuman.setText(time.strftime('%H hour %M minute %S second',time.gmtime(self.time/100)))
        elif self.timeInterval ==1:
            self.timeForHuman.setText(time.strftime('%H hour %M minute %S second',time.gmtime(self.time/1000)))


    def reset(self):
        self.time=0
        self.settimer(self.time)
Exemple #11
0
class GameGUI(QMainWindow):
    BEFORE_START = 0
    RUNNING = 1
    PAUSED = 2
    OVER = 3

    sgn_game_over = pyqtSignal()
    sgn_update_score = pyqtSignal(int)

    def __init__(self, speed=1000):
        super().__init__()
        self.speed = speed

        # flag
        self.game_status = self.BEFORE_START    # 0:未开始 1:正在运行 2:暂停 3:游戏结束

        # signal
        self.sgn_game_over.connect(self.game_over)
        self.sgn_update_score.connect(self.update_score)

        # gui
        self.board = None
        self.next_panel = None
        self.score_ui = None
        self.timer = None
        self.init_gui()
        self.start()

    def init_gui(self, width_block=10, height_block=22, grid_size=20):
        center_widget = QWidget()

        h_layout = QHBoxLayout()
        self.board = Board(None, grid_size, width_block, height_block)
        self.next_panel = NextBlockPanel(None, grid_size, self.board.core.next_shape)

        self.score_ui = QLCDNumber(self)
        self.score_ui.setDigitCount(6)
        self.score_ui.setSegmentStyle(QLCDNumber.Flat)
        self.score_ui.setFixedHeight(50)
        self.score_ui.display(0)

        right_widget = QWidget()
        right_layout = QVBoxLayout()
        right_layout.addWidget(self.next_panel, 0, Qt.AlignCenter | Qt.AlignTop)
        right_layout.addWidget(QLabel("<h3>Score</h3>"), 0, Qt.AlignLeft | Qt.AlignTop)
        right_layout.addWidget(self.score_ui, 1, Qt.AlignCenter | Qt.AlignTop)
        right_layout.setSpacing(0)
        right_widget.setLayout(right_layout)

        h_layout.addWidget(self.board)
        h_layout.addWidget(right_widget)
        h_layout.setSpacing(0)

        self.timer = QBasicTimer()
        self.setFocusPolicy(Qt.StrongFocus)

        self.setWindowTitle('Tetris')
        center_widget.setFixedSize(self.board.width() + self.next_panel.width() + 30, self.board.height()+15)
        self.setFixedSize(center_widget.width(), center_widget.height())
        center_widget.setLayout(h_layout)

        self.setCentralWidget(center_widget)

        print(self.dockOptions())

        self.show()

    def start(self):
        self.board.core.remove_lines()
        self.board.core.generate_next_shape()
        self.next_panel.set_shape(self.board.core.next_shape)
        self.game_status = self.RUNNING
        self.timer.start(self.speed, self)
        self.update()

    def update_window(self):
        self.board.update()
        self.next_panel.update()
        # self.score_ui.update()
        self.update()

    def next_block(self):
        if self.board.core.merge_board():
            self.board.core.remove_lines()
            self.sgn_update_score.emit(self.board.core.score)
            self.board.core.generate_next_shape()
            self.next_panel.set_shape(self.board.core.next_shape)
            return True
        else:
            self.sgn_game_over.emit()
            return False

    def game_over(self):
        print('close')
        self.close()

    def update_score(self, score):
        self.score_ui.display(score)

    def timerEvent(self, event):
        if event.timerId() == self.timer.timerId():
            if self.board.core.move_down():
                pass
            else:
                self.next_block()
            self.update_window()
        else:
            super().timerEvent(event)

    def keyPressEvent(self, event):
        if self.game_status == self.RUNNING:
            key = event.key()
            if key in {Qt.Key_Left, Qt.Key_A}:
                self.board.core.move_left()
                self.update_window()
                return
            elif key in {Qt.Key_Right, Qt.Key_D}:
                self.board.core.move_right()
                self.update_window()
                return
            elif key in {Qt.Key_Up, Qt.Key_W}:
                self.board.core.rotate_right()
                self.update_window()
                return
            elif key in {Qt.Key_Down, Qt.Key_S}:
                if not self.board.core.move_down():
                    self.next_block()
                self.update_window()
        super().keyPressEvent(event)
        return
Exemple #12
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        settings = QSettings()
        self.setup_trayicon()
        self.setup_ui()
        self.update_work_end_time()
        self.update_rest_end_time()
        self.setup_connections()
        self.timeFormat = "hh:mm:ss"
        self.time = QTime(0, 0, 0, 0)
        self.workTime = QTime(0, 0, 0, 0)
        self.restTime = QTime(0, 0, 0, 0)
        self.totalTime = QTime(0, 0, 0, 0)
        self.currentMode = Mode.work
        self.maxRepetitions = -1
        self.currentRepetitions = 0
        self.show()

    def leaveEvent(self, event):
        super(MainWindow, self).leaveEvent(event)
        self.tasksTableWidget.clearSelection()

    def closeEvent(self, event):
        super(MainWindow, self).closeEvent(event)
        settings = QSettings()
        settings.setValue("timer/work/hours", self.workHoursSpinBox.value())
        settings.setValue("timer/work/minutes",
                          self.workMinutesSpinBox.value())
        settings.setValue("timer/work/seconds",
                          self.workSecondsSpinBox.value())
        settings.setValue("timer/rest/hours", self.restHoursSpinBox.value())
        settings.setValue("timer/rest/minutes",
                          self.restMinutesSpinBox.value())
        settings.setValue("timer/rest/seconds",
                          self.restSecondsSpinBox.value())

        tasks = []
        for i in range(self.tasksTableWidget.rowCount()):
            item = self.tasksTableWidget.item(i, 0)
            if not item.font().strikeOut():
                tasks.append(item.text())
        settings.setValue("tasks/tasks", tasks)

    def start_timer(self):
        try:
            if not self.timer.isActive():
                self.create_timer()
        except:
            self.create_timer()

    def create_timer(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_time)
        self.timer.timeout.connect(self.maybe_change_mode)
        self.timer.setInterval(1000)
        self.timer.setSingleShot(False)
        self.timer.start()

    def pause_timer(self):
        try:
            self.timer.stop()
            self.timer.disconnect()
        except:
            pass

    def reset_timer(self):
        try:
            self.pause_timer()
            self.time = QTime(0, 0, 0, 0)
            self.display_time()
        except:
            pass

    def maybe_start_timer(self):
        if self.currentRepetitions != self.maxRepetitions:
            self.start_timer()
            started = True
        else:
            self.currentRepetitions = 0
            started = False
        return started

    def update_work_end_time(self):
        self.workEndTime = QTime(self.workHoursSpinBox.value(),
                                 self.workMinutesSpinBox.value(),
                                 self.workSecondsSpinBox.value())

    def update_rest_end_time(self):
        self.restEndTime = QTime(self.restHoursSpinBox.value(),
                                 self.restMinutesSpinBox.value(),
                                 self.restSecondsSpinBox.value())

    def update_current_mode(self, mode: str):
        self.currentMode = Mode.work if mode == "work" else Mode.rest

    def update_time(self):
        self.time = self.time.addSecs(1)
        self.totalTime = self.totalTime.addSecs(1)
        if self.modeComboBox.currentText() == "work":
            self.workTime = self.workTime.addSecs(1)
        else:
            self.restTime = self.restTime.addSecs(1)
        self.display_time()

    def update_max_repetitions(self, value):
        if value == 0:
            self.currentRepetitions = 0
            self.maxRepetitions = -1
        else:
            self.maxRepetitions = 2 * value

    def maybe_change_mode(self):
        if self.currentMode is Mode.work and self.time >= self.workEndTime:
            self.reset_timer()
            self.modeComboBox.setCurrentIndex(1)
            self.increment_current_repetitions()
            started = self.maybe_start_timer()
            self.show_window_message(
                Status.workFinished if started else Status.repetitionsReached)
        elif self.currentMode is Mode.rest and self.time >= self.restEndTime:
            self.reset_timer()
            self.modeComboBox.setCurrentIndex(0)
            self.increment_current_repetitions()
            started = self.maybe_start_timer()
            self.show_window_message(
                Status.restFinished if started else Status.repetitionsReached)

    def increment_current_repetitions(self):
        if self.maxRepetitions > 0:
            self.currentRepetitions += 1

    def insert_task(self):
        task = self.taskTextEdit.toPlainText()
        self.insert_tasks(task)

    def insert_tasks(self, *tasks):
        for task in tasks:
            if task:
                rowCount = self.tasksTableWidget.rowCount()
                self.tasksTableWidget.setRowCount(rowCount + 1)
                self.tasksTableWidget.setItem(rowCount, 0,
                                              QTableWidgetItem(task))
                self.tasksTableWidget.resizeRowsToContents()
                self.taskTextEdit.clear()

    def delete_task(self):
        selectedIndexes = self.tasksTableWidget.selectedIndexes()
        if selectedIndexes:
            self.tasksTableWidget.removeRow(selectedIndexes[0].row())

    def mark_task_as_finished(self, row, col):
        item = self.tasksTableWidget.item(row, col)
        font = self.tasksTableWidget.item(row, col).font()
        font.setStrikeOut(False if item.font().strikeOut() else True)
        item.setFont(font)

    def display_time(self):
        self.timeDisplay.display(self.time.toString(self.timeFormat))
        self.statisticsRestTimeDisplay.display(
            self.restTime.toString(self.timeFormat))
        self.statisticsWorkTimeDisplay.display(
            self.workTime.toString(self.timeFormat))
        self.statisticsTotalTimeDisplay.display(
            self.totalTime.toString(self.timeFormat))

    def show_window_message(self, status):
        if status is Status.workFinished:
            self.trayIcon.showMessage("Break", choice(work_finished_phrases),
                                      QIcon("icons/tomato.png"))
        elif status is Status.restFinished:
            self.trayIcon.showMessage("Work", choice(rest_finished_phrases),
                                      QIcon("icons/tomato.png"))
        else:
            self.trayIcon.showMessage("Finished",
                                      choice(pomodoro_finished_phrases),
                                      QIcon("icons/tomato.png"))
            self.resetButton.click()

    def setup_connections(self):
        self.playButton.clicked.connect(self.start_timer)
        self.playButton.clicked.connect(
            lambda: self.playButton.setDisabled(True))
        self.playButton.clicked.connect(
            lambda: self.pauseButton.setDisabled(False))
        self.playButton.clicked.connect(
            lambda: self.resetButton.setDisabled(False))

        self.pauseButton.clicked.connect(self.pause_timer)
        self.pauseButton.clicked.connect(
            lambda: self.playButton.setDisabled(False))
        self.pauseButton.clicked.connect(
            lambda: self.pauseButton.setDisabled(True))
        self.pauseButton.clicked.connect(
            lambda: self.resetButton.setDisabled(False))

        self.resetButton.clicked.connect(self.reset_timer)
        self.resetButton.clicked.connect(
            lambda: self.playButton.setDisabled(False))
        self.resetButton.clicked.connect(
            lambda: self.pauseButton.setDisabled(True))
        self.resetButton.clicked.connect(
            lambda: self.resetButton.setDisabled(True))

        self.workHoursSpinBox.valueChanged.connect(self.update_work_end_time)
        self.workMinutesSpinBox.valueChanged.connect(self.update_work_end_time)
        self.workSecondsSpinBox.valueChanged.connect(self.update_work_end_time)

        self.restHoursSpinBox.valueChanged.connect(self.update_rest_end_time)
        self.restMinutesSpinBox.valueChanged.connect(self.update_rest_end_time)
        self.restSecondsSpinBox.valueChanged.connect(self.update_rest_end_time)

        self.modeComboBox.currentTextChanged.connect(self.update_current_mode)
        self.repetitionsSpinBox.valueChanged.connect(
            self.update_max_repetitions)

        self.acceptTaskButton.pressed.connect(self.insert_task)
        self.deleteTaskButton.pressed.connect(self.delete_task)

        self.tasksTableWidget.cellDoubleClicked.connect(
            self.mark_task_as_finished)

    def setup_ui(self):
        settings = QSettings()

        self.size_policy = sizePolicy = QSizePolicy(QSizePolicy.Expanding,
                                                    QSizePolicy.Expanding)
        #TABWIDGET
        self.tabWidget = QTabWidget()

        self.pomodoroWidget = QWidget(self)

        self.pomodoroWidgetLayout = QVBoxLayout(self.pomodoroWidget)
        self.pomodoroWidget.setLayout(self.pomodoroWidgetLayout)
        # work
        self.workGroupBox = QGroupBox("Work")
        self.workGroupBoxLayout = QHBoxLayout(self.workGroupBox)
        self.workGroupBox.setLayout(self.workGroupBoxLayout)
        self.workHoursSpinBox = QSpinBox(minimum=0,
                                         maximum=24,
                                         value=settings.value(
                                             "timer/work/hours", 0),
                                         suffix="h",
                                         sizePolicy=self.size_policy)
        self.workMinutesSpinBox = QSpinBox(minimum=0,
                                           maximum=60,
                                           value=settings.value(
                                               "timer/work/minutes", 25),
                                           suffix="m",
                                           sizePolicy=self.size_policy)
        self.workSecondsSpinBox = QSpinBox(minimum=0,
                                           maximum=60,
                                           value=settings.value(
                                               "timer/work/seconds", 0),
                                           suffix="s",
                                           sizePolicy=self.size_policy)
        self.workGroupBoxLayout.addWidget(self.workHoursSpinBox)
        self.workGroupBoxLayout.addWidget(self.workMinutesSpinBox)
        self.workGroupBoxLayout.addWidget(self.workSecondsSpinBox)
        # rest
        self.restGroupBox = QGroupBox("Rest")
        self.restGroupBoxLayout = QHBoxLayout(self.restGroupBox)
        self.restGroupBox.setLayout(self.restGroupBoxLayout)
        self.restHoursSpinBox = QSpinBox(minimum=0,
                                         maximum=24,
                                         value=settings.value(
                                             "timer/rest/hours", 0),
                                         suffix="h",
                                         sizePolicy=self.size_policy)
        self.restMinutesSpinBox = QSpinBox(minimum=0,
                                           maximum=60,
                                           value=settings.value(
                                               "timer/rest/minutes", 5),
                                           suffix="m",
                                           sizePolicy=self.size_policy)
        self.restSecondsSpinBox = QSpinBox(minimum=0,
                                           maximum=60,
                                           value=settings.value(
                                               "timer/rest/seconds", 0),
                                           suffix="s",
                                           sizePolicy=self.size_policy)
        self.restGroupBoxLayout.addWidget(self.restHoursSpinBox)
        self.restGroupBoxLayout.addWidget(self.restMinutesSpinBox)
        self.restGroupBoxLayout.addWidget(self.restSecondsSpinBox)
        #OTHER
        self.otherGroupBox = QGroupBox("Other")
        self.otherGroupBoxLayout = QHBoxLayout(self.otherGroupBox)
        self.otherGroupBox.setLayout(self.otherGroupBoxLayout)
        self.repetitionsLabel = QLabel("Repetitions",
                                       sizePolicy=self.size_policy)
        self.repetitionsSpinBox = QSpinBox(minimum=0,
                                           maximum=10000,
                                           value=0,
                                           sizePolicy=self.size_policy,
                                           specialValueText="∞")
        self.modeLabel = QLabel("Mode", sizePolicy=self.size_policy)
        self.modeComboBox = QComboBox()
        self.modeComboBox.addItems(["work", "rest"])
        self.otherGroupBoxLayout.addWidget(self.repetitionsLabel)
        self.otherGroupBoxLayout.addWidget(self.repetitionsSpinBox)
        self.otherGroupBoxLayout.addWidget(self.modeLabel)
        self.otherGroupBoxLayout.addWidget(self.modeComboBox)
        #LCDDISPLAY
        self.lcdDisplayGroupBox = QGroupBox("Time")
        self.lcdDisplayGroupBoxLayout = QHBoxLayout(self.lcdDisplayGroupBox)
        self.lcdDisplayGroupBox.setLayout(self.lcdDisplayGroupBoxLayout)
        self.timeDisplay = QLCDNumber(8, sizePolicy=self.size_policy)
        self.timeDisplay.setFixedHeight(100)
        self.timeDisplay.display("00:00:00")
        self.lcdDisplayGroupBoxLayout.addWidget(self.timeDisplay)

        #BUTTONS
        self.buttonWidget = QWidget()
        self.buttonWidgetLayout = QHBoxLayout(self.buttonWidget)
        self.buttonWidget.setLayout(self.buttonWidgetLayout)
        self.playButton = self.make_button("start", disabled=False)
        self.resetButton = self.make_button("reset")
        self.pauseButton = self.make_button("pause")
        self.buttonWidgetLayout.addWidget(self.pauseButton)
        self.buttonWidgetLayout.addWidget(self.playButton)
        self.buttonWidgetLayout.addWidget(self.resetButton)

        #CENTRALWIDGET
        self.pomodoroWidgetLayout.addWidget(self.workGroupBox)
        self.pomodoroWidgetLayout.addWidget(self.restGroupBox)
        self.pomodoroWidgetLayout.addWidget(self.otherGroupBox)
        self.pomodoroWidgetLayout.addWidget(self.lcdDisplayGroupBox)
        self.pomodoroWidgetLayout.addWidget(self.buttonWidget)
        #CREATE TASKS TAB
        self.tasksWidget = QWidget(self.tabWidget)
        self.tasksWidgetLayout = QVBoxLayout(self.tasksWidget)
        self.tasksWidget.setLayout(self.tasksWidgetLayout)
        self.inputWidget = QWidget()
        self.inputWidget.setFixedHeight(50)
        self.inputWidgetLayout = QHBoxLayout(self.inputWidget)
        self.inputWidgetLayout.setContentsMargins(0, 0, 0, 0)
        self.inputWidget.setLayout(self.inputWidgetLayout)
        self.taskTextEdit = QTextEdit(
            placeholderText="Describe your task briefly.",
            undoRedoEnabled=True)
        self.inputButtonContainer = QWidget()
        self.inputButtonContainerLayout = QVBoxLayout(
            self.inputButtonContainer)
        self.inputButtonContainerLayout.setContentsMargins(0, 0, 0, 0)
        self.inputButtonContainer.setLayout(self.inputButtonContainerLayout)
        self.acceptTaskButton = QToolButton(icon=QIcon("icons/check.png"))
        self.deleteTaskButton = QToolButton(icon=QIcon("icons/trash.png"))
        self.inputButtonContainerLayout.addWidget(self.acceptTaskButton)
        self.inputButtonContainerLayout.addWidget(self.deleteTaskButton)

        self.inputWidgetLayout.addWidget(self.taskTextEdit)
        self.inputWidgetLayout.addWidget(self.inputButtonContainer)
        self.tasksTableWidget = QTableWidget(0, 1)
        self.tasksTableWidget.setHorizontalHeaderLabels(["Tasks"])
        self.tasksTableWidget.horizontalHeader().setStretchLastSection(True)
        self.tasksTableWidget.verticalHeader().setVisible(False)
        self.tasksTableWidget.setWordWrap(True)
        self.tasksTableWidget.setTextElideMode(Qt.ElideNone)
        self.tasksTableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tasksTableWidget.setSelectionMode(
            QAbstractItemView.SingleSelection)
        self.insert_tasks(*settings.value("tasks/tasks", []))

        self.tasksWidgetLayout.addWidget(self.inputWidget)
        self.tasksWidgetLayout.addWidget(self.tasksTableWidget)
        #CREATE STATISTICS TAB
        self.statisticsWidget = QWidget()
        self.statisticsWidgetLayout = QVBoxLayout(self.statisticsWidget)
        self.statisticsWidget.setLayout(self.statisticsWidgetLayout)

        self.statisticsWorkTimeGroupBox = QGroupBox("Work Time")
        self.statisticsWorkTimeGroupBoxLayout = QHBoxLayout()
        self.statisticsWorkTimeGroupBox.setLayout(
            self.statisticsWorkTimeGroupBoxLayout)
        self.statisticsWorkTimeDisplay = QLCDNumber(8)
        self.statisticsWorkTimeDisplay.display("00:00:00")
        self.statisticsWorkTimeGroupBoxLayout.addWidget(
            self.statisticsWorkTimeDisplay)

        self.statisticsRestTimeGroupBox = QGroupBox("Rest Time")
        self.statisticsRestTimeGroupBoxLayout = QHBoxLayout()
        self.statisticsRestTimeGroupBox.setLayout(
            self.statisticsRestTimeGroupBoxLayout)
        self.statisticsRestTimeDisplay = QLCDNumber(8)
        self.statisticsRestTimeDisplay.display("00:00:00")
        self.statisticsRestTimeGroupBoxLayout.addWidget(
            self.statisticsRestTimeDisplay)

        self.statisticsTotalTimeGroupBox = QGroupBox("Total Time")
        self.statisticsTotalTimeGroupBoxLayout = QHBoxLayout()
        self.statisticsTotalTimeGroupBox.setLayout(
            self.statisticsTotalTimeGroupBoxLayout)
        self.statisticsTotalTimeDisplay = QLCDNumber(8)
        self.statisticsTotalTimeDisplay.display("00:00:00")
        self.statisticsTotalTimeGroupBoxLayout.addWidget(
            self.statisticsTotalTimeDisplay)

        self.statisticsWidgetLayout.addWidget(self.statisticsTotalTimeGroupBox)
        self.statisticsWidgetLayout.addWidget(self.statisticsWorkTimeGroupBox)
        self.statisticsWidgetLayout.addWidget(self.statisticsRestTimeGroupBox)

        #ADD TABS
        self.timerTab = self.tabWidget.addTab(self.pomodoroWidget,
                                              QIcon("icons/timer.png"),
                                              "Timer")
        self.tasksTab = self.tabWidget.addTab(self.tasksWidget,
                                              QIcon("icons/tasks.png"),
                                              "Tasks")
        self.statisticsTab = self.tabWidget.addTab(
            self.statisticsWidget, QIcon("icons/statistics.png"), "Statistics")

        self.setCentralWidget(self.tabWidget)

    def make_button(self, text, iconPath=None, disabled=True):
        button = QPushButton(text, sizePolicy=self.size_policy)
        if iconPath:
            button.setIcon(QIcon(iconPath))
        button.setDisabled(disabled)
        return button

    def setup_trayicon(self):
        self.trayIcon = QSystemTrayIcon(QIcon("icons/tomato.png"))
        self.trayIcon.setContextMenu(QMenu())
        self.quitAction = self.trayIcon.contextMenu().addAction(
            QIcon("icons/exit.png"), "Quit", self.exit)
        self.quitAction.triggered.connect(self.exit)
        self.trayIcon.activated.connect(self.onActivate)
        self.trayIcon.show()

    def exit(self):
        self.close()
        app = QApplication.instance()
        if app:
            app.quit()

    def onActivate(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            self.show()
class view(QWidget):
    def __init__(self):
        super().__init__()

        self.data_storage = datastorage.DataStorage()
        self.parser = parser.Parser(self.data_storage)
        self.thread = QThread()

        self.parser.dataChanged.connect(self.append_data)
        self.parser.moveToThread(self.thread)

        self.thread.started.connect(self.parser.parse)
        self.thread.start()

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.plot_data)
        self.timer.start(100)

        self.lastUpdate = pg.ptime.time()
        self.avgFps = 0.0
        self.cutoff = 0

        self.scroll_status = True
        self.plotting_status = True

        """Optimization settings"""
        self.end_dots = True
        self.graph_update_count = 0
        self.graph_update_interval = 3  # Increase this value to speed up graphing
        self.optimize_fps = True
        self.goal_fps = 30  # Max 60
        self.bounds = 10

        """Latest Telemetry Info"""
        self.lat = 0
        self.long = 0
        self.time = 0
        self.alt = 0
        self.vel = 0
        self.sat = 0
        self.accel = 0
        self.temp = 0
        self.gyro_x = 0

        self.antenna_angle = [0, 0]
        self.antenna_precision = 7
        self.antenna_font_size = 32

        self.initUI()

    def initUI(self):
        pg.setConfigOptions(antialias=False)  ## expensive ass setting for fps but yolo
        """Declare layouts"""
        hbox_Window = QHBoxLayout(self)
        vbox_LogoAndGraphs = QVBoxLayout()

        vbox_Logo = QVBoxLayout()
        hbox_Banner = QHBoxLayout()
        hbox_Graphs = QHBoxLayout()
        vbox_inner_Graphs = QVBoxLayout() # vbox for non-position graphs
        vbox_Indicators = QVBoxLayout()
        hbox_position = QHBoxLayout()
        vbox_Buttons = QVBoxLayout()

        """Declare widgets"""
        self.fps_label = QLabel()
        self.antenna_angle_label = QLabel()
        self.antenna_angle_label.setFont(QFont("Times", self.antenna_font_size, QFont.Bold))

        self.altitude_graph = pg.PlotWidget(title='Altitude', left='Height', bottom='Time')
        self.rssi_graph = pg.PlotWidget(title='RSSI', left='RSSI', bottom='Time')
        self.velocity_graph = pg.PlotWidget(title='Velocity', left='Velocity', bottom='Time')
        self.acceleration_graph = pg.PlotWidget(title='Acceleration', left='Acceleration', bottom='Time')
        self.position_graph = pg.PlotWidget(title='Position', left='Y Coordinate', bottom='X Coordinate')

        # self.altitude_graph.setClipToView(True) # OPTIMIZATION OPTIONS
        # self.altitude_graph.setDownsampling(mode='peak')
        # self.temperature_graph.setClipToView(True)
        # self.temperature_graph.setDownsampling(mode='peak')
        # self.velocity_graph.setClipToView(True)
        # self.velocity_graph.setDownsampling(mode='peak')
        # self.acceleration_graph.setClipToView(True)
        # self.acceleration_graph.setDownsampling(mode='peak')
        # self.position_graph.setClipToView(True)
        # self.position_graph.setDownsampling(mode='peak')
        # self.altitude_graph.setRange(xRange=[0, 10])
        # self.altitude_graph.setLimits(xMax=100)

        self.text_box = QLineEdit(self)
        self.text_box.setFixedWidth(250)

        self.button = QPushButton('Update Cutoff', self)
        self.button.clicked.connect(self.on_click)
        self.button.setFixedWidth(250)

        self.button_reset = QPushButton('RESET DATA', self)
        self.button_reset.clicked.connect(self.on_click_reset)
        self.button_reset.setFixedWidth(250)
        self.button_reset.setStyleSheet("background-color: red")

        self.scroll_checkbox = QCheckBox("Toggle Scrolling", self)
        self.scroll_checkbox.setChecked(self.scroll_status)
        self.scroll_checkbox.stateChanged.connect(self.on_click_scrolling)

        self.plot_checkbox = QCheckBox("Toggle Plotting", self)
        self.plot_checkbox.setChecked(self.plotting_status)
        self.plot_checkbox.stateChanged.connect(self.on_click_plotting)

        self.altitude_LCD = QLCDNumber(self)
        self.rssi_LCD = QLCDNumber(self)
        self.velocity_LCD = QLCDNumber(self)
        self.acceleration_LCD = QLCDNumber(self)
        self.positionX_LCD = QLCDNumber(self)
        self.positionY_LCD = QLCDNumber(self)

        self.altitude_LCD.setFixedHeight(LCD_HEIGHT)
        self.rssi_LCD.setFixedHeight(LCD_HEIGHT)
        self.velocity_LCD.setFixedHeight(LCD_HEIGHT)
        self.acceleration_LCD.setFixedHeight(LCD_HEIGHT)
        self.positionX_LCD.setFixedHeight(LCD_HEIGHT)
        self.positionY_LCD.setFixedHeight(LCD_HEIGHT)

        self.altitude_LCD.setDigitCount(9)
        self.rssi_LCD.setDigitCount(4)
        self.velocity_LCD.setDigitCount(9)
        self.acceleration_LCD.setDigitCount(9)
        self.positionX_LCD.setDigitCount(10)
        self.positionY_LCD.setDigitCount(10)

        altitude_label = QLabel("Current Altitude")
        rssi_label = QLabel("RSSI")
        velocity_label = QLabel("Current Velocity")
        acceleration_label = QLabel("Current Acceleration")
        position_label = QLabel("Current Position")

        MRT_Logo = QPixmap('./../media/MRT-logo.png')
        smaller_MRT_Logo = MRT_Logo.scaledToHeight(100)
        logo_Lbl = QLabel(self)
        logo_Lbl.setPixmap(smaller_MRT_Logo)

        MRT_label = QLabel("McGill Rocket Team Ground Station")
        MRT_label.setFont(QFont("Times", 30, QFont.Bold))

        """Layout Management"""
        vbox_Logo.addWidget(self.fps_label)
        vbox_Logo.addLayout(hbox_Banner)
        hbox_Banner.addWidget(logo_Lbl)
        hbox_Banner.addWidget(MRT_label)
        hbox_Banner.addStretch(1)

        vbox_inner_Graphs.addWidget(self.altitude_graph)
        vbox_inner_Graphs.addWidget(self.rssi_graph)
        vbox_inner_Graphs.addWidget(self.velocity_graph)
        vbox_inner_Graphs.addWidget(self.acceleration_graph)
        hbox_Graphs.addLayout(vbox_inner_Graphs)
        hbox_Graphs.addWidget(self.position_graph)

        vbox_Indicators.addWidget(altitude_label)
        vbox_Indicators.addWidget(self.altitude_LCD)
        vbox_Indicators.addWidget(rssi_label)
        vbox_Indicators.addWidget(self.rssi_LCD)
        vbox_Indicators.addWidget(velocity_label)
        vbox_Indicators.addWidget(self.velocity_LCD)
        vbox_Indicators.addWidget(acceleration_label)
        vbox_Indicators.addWidget(self.acceleration_LCD)
        vbox_Indicators.addWidget(position_label)
        hbox_position.addWidget(self.positionX_LCD)
        hbox_position.addWidget(self.positionY_LCD)
        vbox_Indicators.addLayout(hbox_position)
        vbox_Indicators.addLayout(vbox_Buttons)
        vbox_Buttons.addWidget(self.antenna_angle_label)
        vbox_Buttons.addWidget(self.text_box)
        vbox_Buttons.addWidget(self.button)
        vbox_Buttons.addWidget(self.button_reset)

        vbox_Buttons.addWidget(self.scroll_checkbox)
        vbox_Buttons.addWidget(self.plot_checkbox)

        vbox_LogoAndGraphs.addLayout(vbox_Logo)
        vbox_LogoAndGraphs.addLayout(hbox_Graphs)
        hbox_Window.addLayout(vbox_LogoAndGraphs)
        hbox_Window.addLayout(vbox_Indicators)

        """ Telemetry values """
        self.time_list = []
        self.temperature_list = []
        self.altitude_list = []
        self.velocity_list = []
        self.acceleration_list = []

        """ GPS values """
        self.latitude_list = []
        self.longitude_list = []

        """ Redundancy GPS values """
        self.redundancy_latitude_list = []
        self.redundancy_longitude_list = []

        self.rssi_list = []

        """Build main window"""
        self.setLayout(hbox_Window)
        self.setGeometry(100, 100, 1720, 968)
        self.setWindowTitle('MRT Ground Station')

        self.altitude_curve = self.altitude_graph.plot(self.time_list, self.altitude_list)
        self.rssi_curve = self.rssi_graph.plot(self.time_list, self.rssi_list)
        self.velocity_curve = self.velocity_graph.plot(self.time_list, self.velocity_list)
        self.acceleration_curve = self.acceleration_graph.plot(self.time_list, self.acceleration_list)
        if show_graphs is True:
            self.show()

    @pyqtSlot(list)
    def append_data(self, telemetry_data):
        """
        telemetry long data format: Slat,long,time,alt,vel,sat,acc,temp,gyro_x,RSSI,E\n
        backup GPS data: Slat,long,time,gps_alt,gps_speed,sat,RSSI,E\n
        """

        """ Append telemetry data to lists """
        if len(telemetry_data) == 2:
            self.antenna_angle = telemetry_data
        else:
            try:
                self.lat = float(telemetry_data[0])
                self.long = float(telemetry_data[1])
                self.time = float(telemetry_data[2])
                self.alt = float(telemetry_data[3])
                self.vel = float(telemetry_data[4])
                self.sat = float(telemetry_data[5])
                self.accel = 0
                self.temp = 0
                self.gyro_x = 0
                self.rssi = 0
                if len(telemetry_data) >= 9:
                    self.accel = float(telemetry_data[6])
                    self.temp = float(telemetry_data[7])
                    self.gyro_x = float(telemetry_data[8])
                    if len(telemetry_data) == 10:
                        self.rssi = float(telemetry_data[9])
                        if self.plotting_status:
                            self.rssi_list.append(float(self.rssi))
                elif len(telemetry_data) == 7:
                    self.rssi = float(telemetry_data[6])
                    if self.plotting_status:
                        self.rssi_list.append(float(self.rssi))
                if self.plotting_status:
                    self.time_list.append(float(self.time))
                    self.altitude_list.append(float(self.alt))
                    self.temperature_list.append(float(self.temp))
                    self.velocity_list.append(float(self.vel))
                    self.acceleration_list.append(float(self.accel))
            except:
                print('INVALID DATA SENT TO VIEW')

        """ Append GPS data to lists """
        try:
            if self.plotting_status:
                self.latitude_list.append(float(self.lat))
                self.longitude_list.append(float(self.long))
        except:
            print("latlong broken")

    @pyqtSlot()
    def plot_data(self):
        try:
            now = pg.ptime.time()
            fps = 1.0 / (now - self.lastUpdate)
            self.lastUpdate = now
            self.avgFps = self.avgFps * 0.8 + fps * 0.2
            self.fps_label.setText("Generating {0:3.2f} fps        Update interval: {1}".format(self.avgFps, self.graph_update_interval))
            self.antenna_angle_label.setText('XY:{}\nZ:{}'.format(str(self.antenna_angle[0])[0:self.antenna_precision], str(self.antenna_angle[1])[0:self.antenna_precision]))

            if self.plotting_status:
                if self.graph_update_count > self.graph_update_interval:
                    self.graph_update_count = 0
                    if self.optimize_fps:
                        if self.avgFps < (self.goal_fps-self.bounds):
                            self.graph_update_interval += 1
                        elif self.avgFps > (self.goal_fps+self.bounds):
                            self.graph_update_interval -= 1

                    self.position_graph.clear()

                    if len(self.altitude_list) > self.cutoff+1:
                        self.altitude_curve.setData(self.time_list[-self.cutoff:-1], self.altitude_list[-self.cutoff:-1], pen='r')
                        self.rssi_curve.setData(self.time_list[-self.cutoff:-1], self.altitude_list[-self.cutoff:-1], pen='r')
                        self.velocity_curve.setData(self.time_list[-self.cutoff:-1], self.velocity_list[-self.cutoff:-1], pen='r')
                        self.acceleration_curve.setData(self.time_list[-self.cutoff:-1], self.acceleration_list[-self.cutoff:-1], pen='r')

                        if self.scroll_status:
                            try:
                                self.altitude_graph.setRange(xRange=[self.time_list[-1] - graph_range, self.time_list[-1]])
                                self.rssi_graph.setRange(xRange=[self.time_list[-1] - graph_range, self.time_list[-1]])
                                self.velocity_graph.setRange(xRange=[self.time_list[-1] - graph_range, self.time_list[-1]])
                                self.acceleration_graph.setRange(xRange=[self.time_list[-1] - graph_range, self.time_list[-1]])
                            except:
                                print("Scrolling broke somehow")

                        self.position_graph.plot(self.latitude_list[-self.cutoff:-1], self.longitude_list[-self.cutoff:-1])
                        # if self.end_dots:
                        #     self.velocity_graph.plot([self.time], [self.vel], pen=None, symbol='o', symbolBrush=(0, 0, 255), symbolSize=6.5)
                        #     self.acceleration_graph.plot([self.time], [self.accel], pen=None, symbol='o', symbolBrush=(0, 0, 255), symbolSize=6.5)
                        #     self.altitude_graph.plot([self.time], [self.alt], pen=None, symbol='o', symbolBrush=(0, 0, 255), symbolSize=6.5)
                        # if len(self.time_list) == len(self.rssi_list):
                        #     self.rssi_graph.plot(self.time_list[-self.cutoff:-1], self.rssi_list[-self.cutoff:-1], pen='r')
                        #     if self.end_dots:
                        #         self.rssi_graph.plot([self.time], [self.rssi], pen=None, symbol='o', symbolBrush=(0, 0, 255), symbolSize=6.5)
                        # This line adds an X marking the last gps location
                        self.position_graph.plot([self.lat], [self.long], pen=None, symbol='o', symbolBrush=(255, 0, 0), symbolSize=6.5)
                else:
                    self.graph_update_count = self.graph_update_count + 1

            self.altitude_LCD.display(self.alt)
            self.rssi_LCD.display(self.rssi)
            self.velocity_LCD.display(self.vel)
            self.acceleration_LCD.display(self.accel)
            self.positionX_LCD.display(self.lat)
            self.positionY_LCD.display(self.long)

            self.timer.start(0)
        except:
            print("Problem with graphing")

    @pyqtSlot()
    def on_click(self):
        text_value = self.text_box.text()
        try:
            num_value = int(text_value)
            num_value = abs(num_value)
            if num_value < len(self.longitude_list):
                self.cutoff = num_value
            else:
                self.cutoff = 0
        except:
            print('Data limit {} is invalid \nInput a number between 0 and {}'.format(text_value, len(self.longitude_list)))
            self.cutoff = 0

    @pyqtSlot()
    def on_click_reset(self):
        """ Telemetry values """
        self.time_list = []
        self.temperature_list = []
        self.altitude_list = []
        self.velocity_list = []
        self.acceleration_list = []

        """ GPS values """
        self.latitude_list = []
        self.longitude_list = []

        """ Redundancy GPS values """
        self.redundancy_latitude_list = []
        self.redundancy_longitude_list = []

        self.rssi_list = []

    @pyqtSlot()
    def on_click_scrolling(self):
        if self.scroll_checkbox.isChecked():
            self.scroll_status = True
        else:
            self.scroll_status = False

    @pyqtSlot()
    def on_click_plotting(self):
        if self.plot_checkbox.isChecked():
            self.plotting_status = True
        else:
            self.plotting_status = False
Exemple #14
0
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)
Exemple #15
0
class Timer(QDialog):
    timeout = pyqtSignal()

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

        self.time = 0
        self.timeInterval = 1000  #默认秒

        self.timerUp = QTimer()
        self.timerUp.setInterval(self.timeInterval)
        self.timerUp.timeout.connect(self.updateUptime)

        self.timerDown = QTimer()
        self.timerDown.setInterval(self.timeInterval)
        self.timerDown.timeout.connect(self.updateDowntime)

        self.initUi()

        self.buttonStart.clicked.connect(self.timerUp.start)
        self.buttonStop.clicked.connect(self.timerUp.stop)
        self.buttonReset.clicked.connect(self.reset)
        self.buttonCountDown.clicked.connect(self.timerDown.start)
        self.buttonStopAlarm.clicked.connect(self.timerDown.stop)
        self.timeSpinBox.valueChanged.connect(self.settimer)

    def initUi(self):
        mainLayout = QVBoxLayout()
        self.setLayout(mainLayout)

        self.groupBox = QGroupBox("unit")
        self.radioButton1 = QRadioButton("s")
        self.radioButton1.toggled.connect(self.setUnit)
        self.radioButton2 = QRadioButton("0.1s")
        self.radioButton2.toggled.connect(self.setUnit)
        self.radioButton3 = QRadioButton("0.01s")
        self.radioButton3.toggled.connect(self.setUnit)
        self.radioButton4 = QRadioButton("1ms")
        self.radioButton4.toggled.connect(self.setUnit)
        self.radioButton1.setChecked(True)
        self.unitLayout = QHBoxLayout()
        self.unitLayout.addWidget(self.radioButton1)
        self.unitLayout.addWidget(self.radioButton2)
        self.unitLayout.addWidget(self.radioButton3)
        self.unitLayout.addWidget(self.radioButton4)
        self.groupBox.setLayout(self.unitLayout)
        mainLayout.addWidget(self.groupBox)

        self.buttonStart = QPushButton(self.tr("start"))
        mainLayout.addWidget(self.buttonStart)

        self.buttonStop = QPushButton(self.tr("stop"))
        mainLayout.addWidget(self.buttonStop)

        self.timeViewer = QLCDNumber()
        self.timeViewer.setFixedHeight(45)
        mainLayout.addWidget(self.timeViewer)

        self.timeForHuman = QLabel()
        mainLayout.addWidget(self.timeForHuman)

        self.buttonReset = QPushButton(self.tr("reset"))
        mainLayout.addWidget(self.buttonReset)

        self.timeSpinBox = QSpinBox()
        self.timeSpinBox.setRange(0, 10000)
        mainLayout.addWidget(self.timeSpinBox)
        self.buttonCountDown = QPushButton(self.tr("countdown"))
        mainLayout.addWidget(self.buttonCountDown)
        self.buttonStopAlarm = QPushButton(self.tr("stopalarm"))
        mainLayout.addWidget(self.buttonStopAlarm)

    def setUnit(self):
        if self.radioButton1.isChecked():
            self.timeInterval = 1000
        elif self.radioButton2.isChecked():
            self.timeInterval = 100
        elif self.radioButton3.isChecked():
            self.timeInterval = 10
        elif self.radioButton1.isChecked():
            self.timeInterval = 1
        self.timerUp.setInterval(self.timeInterval)
        self.timerDown.setInterval(self.timeInterval)

    def updateUptime(self):
        self.time += 1
        self.settimer(self.time)
        print(self.time)

    def updateDowntime(self):
        self.time = self.time - 1
        self.settimer(self.time)
        print(self.time)
        if self.time <= 0:
            self.timeout.emit()

    def settimer(self, int):
        self.time = int
        self.timeViewer.display(self.time)

        if self.timeInterval == 1000:
            self.timeForHuman.setText(
                time.strftime('%H hour %M minute %S second',
                              time.gmtime(self.time)))
        elif self.timeInterval == 100:
            self.timeForHuman.setText(
                time.strftime('%H hour %M minute %S second',
                              time.gmtime(self.time / 10)))
        elif self.timeInterval == 10:
            self.timeForHuman.setText(
                time.strftime('%H hour %M minute %S second',
                              time.gmtime(self.time / 100)))
        elif self.timeInterval == 1:
            self.timeForHuman.setText(
                time.strftime('%H hour %M minute %S second',
                              time.gmtime(self.time / 1000)))

    def reset(self):
        self.time = 0
        self.settimer(self.time)
Exemple #16
0
class Window(QWidget):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.setGeometry(100, 100, 800, 600)  # pos pos width height

        self.PortLabel = QLabel("Port:")
        self.LabelProd = QLabel("Production:")
        self.LabelLoad = QLabel("Load:")

        port_selectBox = QComboBox(self)
        ports = self.available_serial_ports()

        for port in ports:
            port_selectBox.addItem(port)

        self.buttonConnect = QPushButton('Connect')
        # self.button.clicked.connect(self.plot)

        self.b1 = QCheckBox("SerialRead")
        self.b1.setChecked(True)
        # self.b1.stateChanged.connect(self.myThread.btnstate(self.b1))

        self.b2 = QCheckBox("activateLog")
        self.b2.setChecked(True)
        # self.b2.stateChanged.connect(lambda:self.btnstate(self.b2))

        self.figure_bar = plt.figure()
        self.figure_timeseries = plt.figure()

        self.canvas_bar = FigureCanvas(self.figure_bar)
        self.canvas_timeseries = FigureCanvas(self.figure_timeseries)

        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        # self.toolbar = NavigationToolbar(self.canvas, self)

        # set the layout

        # self.b1.stateChanged.connect(self.SerialRead(self,b1))
        self.b1.stateChanged.connect(lambda: self.SerialRead(self.b1))
        self.b2.stateChanged.connect(self.SerialLog)

        self.lcdProd = QLCDNumber(self)
        self.lcdLoad = QLCDNumber(self)
        self.lcdProd.setFixedHeight(100)
        self.lcdLoad.setFixedHeight(100)

        # --------------------------- Layout

        col1 = QVBoxLayout()
        col1.addWidget(self.PortLabel)
        col1.addWidget(port_selectBox)
        col1.addWidget(self.buttonConnect)
        col1.addWidget(self.b1)
        col1.addWidget(self.b2)

        col2 = QVBoxLayout()
        col2.addWidget(self.LabelProd)
        col2.addWidget(self.lcdProd)
        col2.addWidget(self.LabelLoad)
        col2.addWidget(self.lcdLoad)

        toprow = QHBoxLayout()
        toprow.addLayout(col1)
        toprow.addLayout(col2)
        toprow.addWidget(self.canvas_bar)

        layout = QVBoxLayout()
        layout.addLayout(toprow)
        layout.addWidget(self.canvas_timeseries)

        # layout.addWidget(self.toolbar)
        # layout.addWidget(self.button)
        self.setLayout(layout)

        # ---------------------------------------------------

        self.wt = WorkerThread()  # This is the thread object
        self.wt.start()
        # Connect the signal from the thread to the slot_method
        self.wt.measurements_signals.connect(
            self.slot_method)  ### 3) connect to the slot
        app.aboutToQuit.connect(
            self.wt.stop)  # to stop the thread when closing the GUI

        timespan = 600
        load = [0] * timespan
        production = [550] * timespan
        pdc = [0] * timespan

    def slot_method(self, p, l):
        print("p=", p)
        print("l=", l)
        self.lcdProd.display(p)
        self.lcdLoad.display(l)
        self.update_chart_timeseries(p, l)
        self.update_chart_bar(p, l)

    def SerialRead(self, b):
        enable = b.isChecked()
        print("enable=" + str(enable))
        # self.myThread.start()

    def SerialLog(self, b2):
        print("b2")

    def threadDone(self):
        print("Done")

    #    def update_chart(self, produzione, carico):
    #        load.pop(0)
    #        load.append(carico)
    #        production.pop(0)
    #        production.append(produzione)
    #
    #        self.figure.clear() #questo è importante
    #        plt.plot(production, color="b")
    #        plt.plot(load, color="r")
    #        #plt.set_ylim([0,max(load, production)])
    #        plt.ylim(ymin=0)
    #        plt.legend(['PV', 'Load'], loc='upper left')
    #        self.canvas.draw()

    def update_chart_bar(self, produzione, carico):  # bar
        objects = ('Carico', 'Produzione', 'Immissione')
        y_pos = np.arange(len(objects))
        immissione = produzione - carico
        performance = [carico, produzione, immissione]

        self.figure_bar.clear()
        plt.figure(num=self.figure_bar.number)  # aggiunta da massimo maggi :)
        plt.bar(y_pos, performance, align='center', alpha=0.5)
        plt.xticks(y_pos, objects)
        plt.ylabel('Power [W]')
        plt.title('Power usage')  # is printing this in the wrong canvas
        self.canvas_bar.draw()

    def update_chart_timeseries(self, produzione, carico):  # time series
        load.pop(0)
        load.append(carico)
        production.pop(0)
        production.append(produzione)

        self.figure_timeseries.clear()  # questo è importante
        plt.figure(
            num=self.figure_timeseries.number)  # aggiunta da massimo maggi :)
        plt.plot(production, color="b")
        plt.plot(load, color="r")
        # plt.set_ylim([0,max(load, production)])
        plt.ylim(ymin=0)
        plt.legend(['PV', 'Load'], loc='upper left')
        self.canvas_timeseries.draw()

    def available_serial_ports(self):
        """ Lists serial port names

            :raises EnvironmentError:
                On unsupported or unknown platforms
            :returns:
                A list of the serial ports available on the system
        """
        if sys.platform.startswith('win'):
            ports = ['COM%s' % (i + 1) for i in range(256)]
        elif sys.platform.startswith('linux') or sys.platform.startswith(
                'cygwin'):
            # this excludes your current terminal "/dev/tty"
            ports = glob.glob('/dev/tty[A-Za-z]*')
        elif sys.platform.startswith('darwin'):
            ports = glob.glob('/dev/tty.*')
        else:
            raise EnvironmentError('Unsupported platform')

        result = []
        for port in ports:
            try:
                s = serial.Serial(port)
                s.close()
                result.append(port)
            except (OSError, serial.SerialException):
                pass
        return result
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()