Esempio n. 1
0
    def _fillTable(self):

        self._widgets = []
        for track in self.tracks:

            item = QTreeWidgetItem([track['name'], 'ride'])

            self._list_widget.addTopLevelItem(item)

            cb = QComboBox()

            cb.addItems(['ride', 'run'])
            cb.setFocusPolicy(Qt.ClickFocus)
            cb.installEventFilter(self)

            self._list_widget.setItemWidget(item, 1, cb)
            self._widgets.append(cb)
Esempio n. 2
0
class MainWindowStart(QMainWindow, MainWindow_Pro.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindowStart, self).__init__(parent)
        # Mappers for connecting buttons and labels
        self.myMapper = QSignalMapper(self)
        self.myMapper_StyleSheet = QSignalMapper(self)
        # Load UI
        self.setupUi(self)

        self.regex_edits = QRegExp(r"(^[0]+$|^$)")
        self._filter = Filter()
        self.filename = QString()
        self.edit1_delayh.installEventFilter(self._filter)
        self.sizeLabel = QLabel()
        self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.statusBar1.addPermanentWidget(self.sizeLabel)
        self.statusBar1.setSizeGripEnabled(False)

        self.create_connections()
        self.assign_shortcuts()

        self.create_tool_bar()
        self.update_devices_list()
        # self.button_stop.clicked.connect(self.stop_all)
        # List of valve pushbuttons
        self.valve_list = [
            self.valve1, self.valve2, self.valve3, self.valve4, self.valve5,
            self.valve6, self.valve7, self.valve8
        ]

        # GroupBoxes for grouping labels and buttons on each row, used for applying StyleSheets
        self.group_boxes = [
            self.groupbox1, self.groupbox2, self.groupbox3, self.groupbox4,
            self.groupbox5, self.groupbox6, self.groupbox7, self.groupbox8
        ]
        # List of lineEdits
        self.lineEdits_list = [
            (self.edit1_delayh, self.edit1_delaym, self.edit1_delays,
             self.edit1_onh, self.edit1_onm, self.edit1_ons, self.edit1_offh,
             self.edit1_offm, self.edit1_offs, self.edit1_totalh,
             self.edit1_totalm, self.edit1_totals),
            (self.edit2_delayh, self.edit2_delaym, self.edit2_delays,
             self.edit2_onh, self.edit2_onm, self.edit2_ons, self.edit2_offh,
             self.edit2_offm, self.edit2_offs, self.edit2_totalh,
             self.edit2_totalm, self.edit2_totals),
            (self.edit3_delayh, self.edit3_delaym, self.edit3_delays,
             self.edit3_onh, self.edit3_onm, self.edit3_ons, self.edit3_offh,
             self.edit3_offm, self.edit3_offs, self.edit3_totalh,
             self.edit3_totalm, self.edit3_totals),
            (self.edit4_delayh, self.edit4_delaym, self.edit4_delays,
             self.edit4_onh, self.edit4_onm, self.edit4_ons, self.edit4_offh,
             self.edit4_offm, self.edit4_offs, self.edit4_totalh,
             self.edit4_totalm, self.edit4_totals),
            (self.edit5_delayh, self.edit5_delaym, self.edit5_delays,
             self.edit5_onh, self.edit5_onm, self.edit5_ons, self.edit5_offh,
             self.edit5_offm, self.edit5_offs, self.edit5_totalh,
             self.edit5_totalm, self.edit5_totals),
            (self.edit6_delayh, self.edit6_delaym, self.edit6_delays,
             self.edit6_onh, self.edit6_onm, self.edit6_ons, self.edit6_offh,
             self.edit6_offm, self.edit6_offs, self.edit6_totalh,
             self.edit6_totalm, self.edit6_totals),
            (self.edit7_delayh, self.edit7_delaym, self.edit7_delays,
             self.edit7_onh, self.edit7_onm, self.edit7_ons, self.edit7_offh,
             self.edit7_offm, self.edit7_offs, self.edit7_totalh,
             self.edit7_totalm, self.edit7_totals),
            (self.edit8_delayh, self.edit8_delaym, self.edit8_delays,
             self.edit8_onh, self.edit8_onm, self.edit8_ons, self.edit8_offh,
             self.edit8_offm, self.edit8_offs, self.edit8_totalh,
             self.edit8_totalm, self.edit8_totals)
        ]

        for index, editLabels in enumerate(self.lineEdits_list, 1):

            for index2, lineedits in enumerate(editLabels, 0):
                # Apply mapper (GUIObject, objectIndex)
                self.myMapper_StyleSheet.setMapping(
                    self.lineEdits_list[index - 1][index2], index - 1)
                # Connect mapper to signal
                (self.lineEdits_list[index - 1][index2]).textChanged.connect(
                    self.myMapper_StyleSheet.map)
                # Set event Filter, for detecting when Focus changes
                self.lineEdits_list[index - 1][index2].installEventFilter(
                    self._filter)
            # Set Mappers for buttons (1..8)
            self.myMapper.setMapping(self.valve_list[index - 1], index)
            # Connect mapper to signal for detecting clicks on buttons
            (self.valve_list[index - 1]).clicked.connect(self.myMapper.map)
        # Connect to signal for enabling labelEdits
        self.myMapper.mapped['int'].connect(self.enable_fields)
        # Connect to signal for changing color of groupbox used for visual indication
        self.myMapper_StyleSheet.mapped['int'].connect(self.valve_color_status)

    # Create Keyboard Shortcuts
    def assign_shortcuts(self):
        self.actionArchivo_Nuevo.setShortcut(QKeySequence.New)
        self.action_Abrir.setShortcut(QKeySequence.Open)
        self.action_Guardar.setShortcut(QKeySequence.Save)
        self.actionGuardar_Como.setShortcut(QKeySequence.SaveAs)
        self.action_Limpiar.setShortcut('Ctrl+L')
        self.actionVAL_508_Ayuda.setShortcut(QKeySequence.HelpContents)
        self.action_Salir.setShortcut(QKeySequence.Close)
        # self.actionPreferencias.setShortcut(QKeySequence.Preferences)

        self.action_Detener_USB.setShortcut('Ctrl+Shift+C')
        self.action_Ejecutar.setShortcut('Ctrl+Shift+X')
        self.action_Para_Valvulas.setShortcut('Ctrl+Shift+P')

    # Create connections to signals
    def create_connections(self):
        self.actionArchivo_Nuevo.triggered.connect(self.new_file)
        self.action_Abrir.triggered.connect(self.open_file)
        self.action_Guardar.triggered.connect(self.save_file)
        self.actionGuardar_Como.triggered.connect(self.save_file_as)
        self.action_Limpiar.triggered.connect(self.clean_fields)
        self.action_Salir.triggered.connect(self.close)
        self.actionVAL_508_Ayuda.triggered.connect(self.show_help)
        self.actionAcerca_de_VAL_508.triggered.connect(self.show_about)

        self.action_Detener_USB.triggered.connect(self.stop_usb)
        self.action_Ejecutar.triggered.connect(self.execute)
        self.action_Para_Valvulas.triggered.connect(self.stop_all)

    # Creation of About Dialog
    def show_about(self):
        about = aboutdialog.AboutDialog(self)
        about.show()

    # Creation of Help Form
    def show_help(self):
        form = helpform.HelpForm('Help.html', self)
        form.show()

    def new_file(self):
        self.filename = QString()
        self.clean_fields()

    # Close connection to arduino before closing Program
    def closeEvent(self, QCloseEvent):
        try:
            self.thread_connection.serial_connection.close()
            logging.debug("Thread running and killed at closing program")
        except AttributeError:
            logging.debug("Thread was not running when closing program OK")

    def clean_fields(self):
        for index, editLabels in enumerate(self.lineEdits_list, 1):
            for index2, lineedits in enumerate(editLabels, 0):
                self.lineEdits_list[index - 1][index2].setText('0')

    def save_file_as(self):
        filename_copy = self.filename
        logging.info("Current filename: %s" % self.filename)
        my_home = os.path.expanduser('~')
        self.filename = QFileDialog.getSaveFileName(
            self, self.tr('Guardar como'),
            os.path.join(my_home, "archivo.txt"), "", "",
            QFileDialog.DontUseNativeDialog)
        logging.info("Filename to save: %s" % self.filename)
        if not self.filename.isNull():
            if self.filename.endsWith(QString('.txt')):
                self.write_data_to_file('w')
            else:
                self.filename.append(QString('.txt'))
                messageBox = QMessageBox(self)
                messageBox.setStyleSheet(
                    'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
                messageBox.setWindowTitle(self.tr('Advertencia'))
                messageBox.setText(
                    self.tr(u"El archivo ya existe, ¿Reemplazar?"))
                messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
                messageBox.setIconPixmap(QPixmap(':/broken_file.png'))
                if messageBox.exec_() == QMessageBox.Yes:
                    self.write_data_to_file('w')
                else:
                    try:
                        while True:
                            self.filename = QFileDialog.getSaveFileName(
                                self, self.tr('Guardar como'),
                                os.path.join(my_home, "archivo.txt"), "", "",
                                QFileDialog.DontUseNativeDialog)
                            if self.filename.isNull():
                                raise Saved_Canceled()
                            else:
                                messageBox = QMessageBox(self)
                                messageBox.setStyleSheet(
                                    'QMessageBox QLabel {font: bold 14pt "Cantarell";}'
                                )
                                messageBox.setWindowTitle(
                                    self.tr('Advertencia'))
                                messageBox.setText(
                                    self.tr(
                                        u"El archivo ya existe, ¿Reemplazar?"))
                                messageBox.setStandardButtons(QMessageBox.Yes
                                                              | QMessageBox.No)
                                messageBox.setIconPixmap(
                                    QPixmap(':/broken_file.png'))
                                if messageBox.exec_() == QMessageBox.Yes:
                                    self.write_data_to_file('w')
                                    raise Saved_Accepted()
                    except Saved_Canceled:
                        self.filename = filename_copy
                    except Saved_Accepted:
                        pass
        logging.info("Current filename after operation: %s" % self.filename)

    def save_file(self):
        if self.filename.isNull():
            self.save_file_as()
        else:
            self.write_data_to_file('w')

    # Colect data for arduino
    def execute(self):
        string_data = ''
        list_strings = []
        if str(self.arduino_combobox.currentText()):
            self.statusBar1.showMessage(self.tr('Conectando...'))
            # Gather all  the contents of each row of valves and create a list of lists with them
            for elem_edit in self.lineEdits_list:
                # delay
                string_data = string_data + str(
                    ((int(elem_edit[0].text()) * 3600) +
                     (int(elem_edit[1].text()) * 60) +
                     (int(elem_edit[2].text()))) * 1000) + ';'
                # ON
                string_data = string_data + str(
                    ((int(elem_edit[3].text()) * 3600) +
                     (int(elem_edit[4].text()) * 60) +
                     (int(elem_edit[5].text()))) * 1000) + ';'
                # OFF
                string_data = string_data + str(
                    ((int(elem_edit[6].text()) * 3600) +
                     (int(elem_edit[7].text()) * 60) +
                     (int(elem_edit[8].text()))) * 1000) + ';'
                # Total
                string_data = string_data + str(
                    ((int(elem_edit[9].text()) * 3600) +
                     (int(elem_edit[10].text()) * 60) +
                     (int(elem_edit[11].text()))) * 1000) + ';'

                list_strings.append(string_data)
                string_data = ''

            # Start QThread for communicating with arduino
            self.thread_connection = Arduino_Communication(
                str(self.arduino_combobox.currentText()), list_strings)
            self.thread_connection.start()
            self.action_Ejecutar.setEnabled(False)
            self.action_Para_Valvulas.setEnabled(False)

            # Connect to current QThread instance in order to know the status of it's termination
            # This line used only when stopping current task
            self.thread_connection.finished.connect(self.finished_thread)
            self.thread_connection.connection_exit_status.connect(
                self.finished_thread)
        else:
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Advertencia'))
            messageBox.setText(self.tr("Arduino no seleccionado"))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_error.png'))
            messageBox.exec_()

    # Inform QThread to stop sending data to arduino
    def stop_usb(self):
        if str(self.arduino_combobox.currentText()):
            try:
                self.statusBar1.showMessage(self.tr(u'Conexión detenida'))
                if self.thread_connection.isRunning():
                    mutex.lock()
                    self.thread_connection.kill_serial = True
                    mutex.unlock()
            except AttributeError:
                logging.debug("Thread not running \'disconnected! \'")
        else:
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Advertencia'))
            messageBox.setText(self.tr("Arduino no seleccionado"))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_error.png'))
            messageBox.exec_()

    def enable_fields(self, index):
        hours_reg = QRegExp(r"0*[0-9]{1,3}")
        sec_reg = QRegExp(r"(0*[0-9])|(0*[0-5][0-9])")
        for counter, line_edit in enumerate(self.lineEdits_list[index - 1]):
            line_edit.setEnabled(self.valve_list[index - 1].isChecked())
            if counter % 3 == 0:
                line_edit.setValidator(QRegExpValidator(hours_reg, self))
            else:
                line_edit.setValidator(QRegExpValidator(sec_reg, self))

    def valve_color_status(self, index):
        logging.info("Checking color from valve button")
        for edit in self.lineEdits_list[index]:
            if edit.text().contains(self.regex_edits):
                self.group_boxes[index].setStyleSheet('''QGroupBox {
                                                      border: 2px solid;
                                                      border-color: rgba(255, 255, 255, 0);}'''
                                                      )
            else:
                self.group_boxes[index].setStyleSheet(
                    '''QGroupBox {background-color: rgba(103, 255, 126, 150);
                                                      border: 2px solid;
                                                      border-color: rgba(255, 255, 255, 255);}'''
                )
                break

    def create_tool_bar(self):
        self.label_arduino = QLabel(self.tr('Dispositivos: '))
        self.toolBar.addWidget(self.label_arduino)

        self.arduino_combobox = QComboBox()
        self.arduino_combobox.setToolTip(self.tr('Seleccionar Arduino'))
        self.arduino_combobox.setFocusPolicy(Qt.NoFocus)

        # Update List of Arduino devices
        self.reload = QAction(QIcon(":/reload.png"), self.tr("&Refrescar"),
                              self)
        self.reload.setShortcut(QKeySequence.Refresh)
        self.reload.setToolTip(self.tr('Refrescar Dispositivos'))
        self.reload.triggered.connect(self.update_devices_list)

        self.toolBar.addWidget(self.arduino_combobox)
        self.toolBar.addAction(self.reload)

    # Update current usb devices connected to PC
    def update_devices_list(self):
        device_list = serial.tools.list_ports.comports()
        current_arduino = self.arduino_combobox.currentText()
        self.arduino_combobox.clear()
        for device_index, device in enumerate(sorted(device_list)):
            self.arduino_combobox.addItem(device.device)
            if device.device == current_arduino:
                self.arduino_combobox.setCurrentIndex(device_index)

    # Stop current arduino task
    def stop_all(self):
        if str(self.arduino_combobox.currentText()):
            self.thread_connection = Arduino_Communication(
                str(self.arduino_combobox.currentText()))
            self.thread_connection.start()
            self.action_Ejecutar.setEnabled(False)
            self.action_Para_Valvulas.setEnabled(False)
            self.action_Detener_USB.setEnabled(False)
            self.thread_connection.finished.connect(self.finished_thread)
            self.thread_connection.connection_exit_status.connect(
                self.finished_thread)
        else:
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Advertencia'))
            messageBox.setText(self.tr("Arduino no seleccionado"))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_error.png'))
            messageBox.exec_()

    def open_file(self):
        try:
            my_home = os.path.expanduser('~')
            file_name = QFileDialog.getOpenFileName(
                self, self.tr('Abrir archivo'), my_home, '*.txt', '*.txt',
                QFileDialog.DontUseNativeDialog)
            logging.warning("file_name type: %s" % type(file_name))
            list_values = []
            if not file_name.isNull():
                with open(file_name) as fp:
                    for line in fp:
                        list_values.extend([line.replace('\n', '')])
                logging.info("List Content: %s" % list_values)
                count = 0
                for elems in self.lineEdits_list:
                    for inner_elem in elems:
                        if not unicode(list_values[count]).isdigit():
                            raise Uncompatible_Data()
                        inner_elem.setText(list_values[count])
                        count = count + 1
                self.filename = file_name
        except (IOError, OSError):
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Error'))
            messageBox.setText(self.tr('No se pudo abrir el archivo'))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/broken_file.png'))
            messageBox.exec_()
        except (IndexError, Uncompatible_Data):
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Error'))
            messageBox.setText(self.tr('Formato Incompatible'))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/broken_file.png'))
            messageBox.exec_()

    # Inform the user if we were able to send data successfully to arduino
    def finished_thread(self, error=None, message=''):
        if error == 'error':
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Error'))
            messageBox.setText(message)
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_error.png'))
            messageBox.exec_()
            return
        elif error == 'success':
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr(u'Éxito'))
            messageBox.setText(message)
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_success.png'))
            messageBox.exec_()
            return
        elif error == 'stopped':
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr(u'Éxito'))
            messageBox.setText(message)
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/success_general.png'))
            messageBox.exec_()
            return
        self.action_Ejecutar.setEnabled(True)
        self.action_Para_Valvulas.setEnabled(True)
        self.action_Detener_USB.setEnabled(True)
        self.statusBar1.showMessage(self.tr('Finalizado'))

    # Save data to disk
    def write_data_to_file(self, open_mode):
        progressDialog = QProgressDialog()
        progressDialog.setModal(True)
        progressDialog.setLabelText(self.tr('Guardando...'))
        progressDialog.setMaximum(8)
        progressDialog.setCancelButton(None)
        progressDialog.show()

        try:
            # File is closed automatically even on error
            with open(unicode(self.filename), open_mode) as file_obj:
                for count, elem_edit in enumerate(self.lineEdits_list, 1):
                    file_obj.write(''.join([str(elem_edit[0].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[1].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[2].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[3].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[4].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[5].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[6].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[7].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[8].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[9].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[10].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[11].text()), '\n']))
                    progressDialog.setValue(count)
        except (IOError, OSError):
            progressDialog.close()
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Error'))
            messageBox.setText(self.tr('Error al guardar'))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIcon(QMessageBox.Critical)
            messageBox.exec_()

        else:
            self.statusBar1.showMessage(self.tr('Guardado'), 3000)
Esempio n. 3
0
class Window(QMainWindow):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        global time_start, x_arr, y_arr, arduino_connected
        # Flag variables
        self.filename = ''
        self.array_len = len(x_arr)
        self.clean_recorded_data = True
        self.recording_status = False
        self.file_saved = False
        self.recorded_list = []
        self.record_cell_start = None
        self.record_cell_end = None
        self.follow_plot = True
        # Window Properties
        self.setWindowTitle("Arduino Plotter")
        self.setWindowIcon(QIcon(":/window_icon.png"))
        self.resize(800, 600)
        # Plot Settings and Creation
        self.plot_settings = dict(plotLineWidth=1,
                                  horizontalGrid=True,
                                  verticalGrid=True,
                                  gridOpacity=1,
                                  lineColor='b',
                                  arrayPlotSize=25,
                                  serialBaud=115200,
                                  separator=' ')
        pg.setConfigOption('background', 'w')
        self.load_settings()
        self.createPlot()
        # Create Bars
        self.createBars()
        # Get list of arduino devices
        self.updateDevicesList()
        # Add Widgets to Main Window
        self.addWidgets()
        # Add bar to display status messages
        status = self.statusBar()
        self.sizeLabel = QLabel()
        self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        status.addPermanentWidget(self.sizeLabel)

        status.setSizeGripEnabled(False)

        # Start Thread & program time count(x axis)
        time_start = time.time()
        self.read_serial_thread = ReadSerialThread(
            self.arduino_combobox.currentText(),
            self.plot_settings['serialBaud'], self)
        self.read_serial_thread.start()
        self.update()

    def load_settings(self):
        settings = QSettings()
        self.plot_settings['horizontalGrid'] = settings.value(
            "horizontalGrid", self.plot_settings['horizontalGrid']).toBool()
        self.plot_settings['verticalGrid'] = settings.value(
            "verticalGrid", self.plot_settings['verticalGrid']).toBool()
        self.plot_settings['plotLineWidth'] = settings.value(
            "plotLineWidth", self.plot_settings['plotLineWidth']).toInt()[0]
        self.plot_settings['gridOpacity'] = settings.value(
            "gridOpacity", self.plot_settings['gridOpacity']).toFloat()[0]
        self.plot_settings['lineColor'] = unicode(
            settings.value("lineColor",
                           self.plot_settings['lineColor']).toString())
        self.plot_settings['arrayPlotSize'] = settings.value(
            "arrayPlotSize", self.plot_settings['arrayPlotSize']).toInt()[0]
        self.plot_settings['serialBaud'] = settings.value(
            "serialBaud", self.plot_settings['serialBaud']).toInt()[0]
        self.plot_settings['separator'] = settings.value(
            "separator", self.plot_settings['separator']).toString()

# Save settings values

    def closeEvent(self, event):
        settings = QSettings()
        settings.setValue('horizontalGrid',
                          QVariant(self.plot_settings['horizontalGrid']))
        settings.setValue('verticalGrid',
                          QVariant(self.plot_settings['verticalGrid']))
        settings.setValue('plotLineWidth',
                          QVariant(self.plot_settings['plotLineWidth']))
        settings.setValue('gridOpacity',
                          QVariant(self.plot_settings['gridOpacity']))
        settings.setValue('lineColor',
                          QVariant(self.plot_settings['lineColor']))
        settings.setValue('arrayPlotSize',
                          QVariant(self.plot_settings['arrayPlotSize']))
        settings.setValue('serialBaud',
                          QVariant(self.plot_settings['serialBaud']))
        settings.setValue('separator',
                          QVariant(self.plot_settings['separator']))

# Plot Creation

    def createPlot(self):
        self.plot_zone = pg.PlotWidget()
        self.pen = pg.mkPen(width=self.plot_settings['plotLineWidth'],
                            color=self.plot_settings['lineColor'][0])
        self.plot_zone.plotItem.showGrid(self.plot_settings['verticalGrid'],
                                         self.plot_settings['horizontalGrid'],
                                         self.plot_settings['gridOpacity'])
        self.plot_zone.plotItem.ctrlMenu = None
        self.plot_zone.setAutoPan(True)
        # self.plot_zone.plotItem.ctrlMenu
        # self.plot_zone.plotItem.enableAutoRange(enable=0.2)
        # self.plot_zone.autoRange()
        self.plot_zone.setXRange(0, 600)
        # self.plot_zone.setLabels(left=('Signal', 'V'), bottom=('Time'))
        self.plot_zone.setYRange(0, 5)
        #        self.plot_zone.setMouseEnabled(x=False)
        self.plot_zone.scene().contextMenu = None

# Create Bars
# TODO Add Info button

    def createBars(self):
        # Create Bar1
        controls_toolbar = self.addToolBar("Controls")
        controls_toolbar.setObjectName("ControlsToolBar")
        # Create Bar2
        arduino_toolbar = self.addToolBar("Arduino")
        arduino_toolbar.setObjectName("ArduinoToolBar")
        # Add Elements to Bar1
        # Record & Pause
        self.record_pause = QAction(QIcon(":/rec.png"), "&Rec", self)
        self.record_pause.setShortcut("Ctrl+R")
        self.record_pause.setToolTip('Record')
        self.record_pause.triggered.connect(self.recording)
        # Stop
        self.stop = QAction(QIcon(":/stop.png"), "&Detener", self)
        self.stop.setShortcut("Ctrl+Alt+D")
        self.stop.setToolTip('Stop')
        self.stop.triggered.connect(self.stopRecording)
        # Save
        self.save_file = QAction(QIcon(":/save.png"), "&Save", self)
        self.save_file.setShortcut(QKeySequence.Save)
        self.save_file.setToolTip('Save')
        self.save_file.triggered.connect(self.saveFile)
        # Save As
        self.save_as = QAction(QIcon(":/save_as.png"), "Save As", self)
        self.save_as.setShortcut(QKeySequence.SaveAs)
        self.save_as.setToolTip('Save As')
        self.save_as.triggered.connect(self.saveFileAs)
        # Configurations
        self.configurations = QAction(QIcon(":/configs.png"),
                                      "&Configurations", self)
        self.configurations.setShortcut("Ctrl+Alt+S")
        self.configurations.setToolTip('Settings')
        self.configurations.triggered.connect(self.changeSettings)

        # Add buttons to bar
        controls_toolbar.addAction(self.record_pause)
        controls_toolbar.addAction(self.stop)
        controls_toolbar.addAction(self.save_file)
        controls_toolbar.addAction(self.save_as)
        controls_toolbar.addAction(self.configurations)

        # Arduino ComboBox
        self.arduino_combobox = QComboBox()
        self.arduino_combobox.setToolTip('Select Arduino')
        self.arduino_combobox.setFocusPolicy(Qt.NoFocus)
        self.arduino_combobox.activated.connect(self.updateChoosenArduino)

        # Update List of Arduino devices
        self.reload = QAction(QIcon(":/reload.png"), "Reload", self)
        self.reload.setShortcut(QKeySequence.Refresh)
        self.reload.setToolTip('Reload Devices')
        self.reload.triggered.connect(self.updateDevicesList)
        # Timer Label
        self.timer_label = QLabel()
        self.timer_label.setText(' 00:00')

        # Info button for dialog
        self.info = QAction(QIcon(":/info.png"), "Reload", self)
        self.info.setShortcut(QKeySequence.HelpContents)
        self.info.setToolTip('Help')
        self.info.triggered.connect(self.showInfo)

        # Follow checkbox
        self.follow_label = QLabel("Follow Plot")
        self.follow_checkbox = QCheckBox()
        # self.arduino_combobox.setToolTip('Select Arduino')
        self.follow_checkbox.setFocusPolicy(Qt.NoFocus)
        self.follow_checkbox.clicked.connect(self.change_follow_status)
        self.follow_checkbox.setChecked(True)

        arduino_toolbar.addWidget(self.arduino_combobox)
        arduino_toolbar.addAction(self.reload)
        arduino_toolbar.addWidget(self.timer_label)
        arduino_toolbar.addAction(self.info)
        arduino_toolbar.addWidget(self.follow_checkbox)
        arduino_toolbar.addWidget(self.follow_label)

# Show Info(Help) dialog

    def showInfo(self):
        self.info_dialog = InfoDialog(self)
        self.info_dialog.show()

    def change_follow_status(self):
        if self.follow_checkbox.isChecked():
            self.follow_plot = True
        else:
            self.follow_plot = False

# Update arduino list

    def updateDevicesList(self):
        device_list = serial.tools.list_ports.comports()
        current_arduino = self.arduino_combobox.currentText()
        self.arduino_combobox.clear()
        device_index = 0
        for device in sorted(device_list):
            self.arduino_combobox.addItem(device.device)
            if device.device == current_arduino:
                self.arduino_combobox.setCurrentIndex(device_index)
            device_index = device_index + 1

# Update selected arduino

    def updateChoosenArduino(self):
        self.restart_values()

# Add Widgets

    def addWidgets(self):
        self.widget = QWidget()
        self.setCentralWidget(self.widget)
        vbox_layout = QVBoxLayout()
        vbox_layout.addWidget(self.plot_zone)
        vbox_layout.setContentsMargins(5, 5, 5, 0)
        self.widget.setLayout(vbox_layout)

# Saves indexes of recorded items, thus saves memory

    def recording(self):
        global time_start, x_arr, y_arr, arduino_connected
        status = self.statusBar()
        # If recording is "Stopped" clear data and start recording
        if self.clean_recorded_data:
            mutex.lock()
            del self.recorded_list[:]
            del x_arr[:]
            del y_arr[:]
            self.array_len = 0
            width_visible = self.plot_zone.visibleRange().width()
            height_visible = self.plot_zone.visibleRange().height()
            bottom_visible = self.plot_zone.visibleRange().top()
            # self.plot_zone.visibleRange().setRect(0, 0, 150, 10)
            # print self.plot_zone.visibleRange()
            rect_me = QRectF(0, 0, width_visible, 5)
            self.plot_zone.setRange(rect=rect_me,
                                    disableAutoRange=True,
                                    xRange=(0, (0 + width_visible)),
                                    padding=0,
                                    yRange=(bottom_visible,
                                            bottom_visible + height_visible))
            self.clean_recorded_data = False
            mutex.unlock()

# Start Recording
        if not self.recording_status:
            self.record_pause.setIcon(QIcon(':/pause.png'))
            status.showMessage('Recording')
            mutex.lock()
            if x_arr:
                self.record_cell_start = len(x_arr) - 1
            else:
                self.record_cell_start = len(x_arr)
            self.recording_status = True
            mutex.unlock()
        else:
            # Pause Recording
            self.record_pause.setIcon(QIcon(':/rec.png'))
            status.showMessage('Paused')
            mutex.lock()
            # Check if x_arr has no data
            if x_arr:
                self.record_cell_end = len(x_arr) - 1
            else:
                self.record_cell_end = len(x_arr)
            self.recorded_list.append(
                [self.record_cell_start, self.record_cell_end])
            self.recording_status = False
            mutex.unlock()

# Update Arduino status and plot

    def update(self):
        global x_arr, y_arr, arduino_connected
        #        self.plot_zone.sceneObj.sigMouseHover.connect(self.me)
        if arduino_connected:
            self.sizeLabel.setText('Arduino Connected')
            self.sizeLabel.setStyleSheet('color:green')
            mutex.lock()
            #            print ("dasdasd",len(x_arr))
            #            print ("self", self.array_len)
            #if not len(x_arr) % self.plot_settings['arrayPlotSize'] and len(x_arr) != 0:
            #print self.array_len
            if len(x_arr) - self.array_len >= 50 and len(x_arr) != 0:
                self.array_len = len(x_arr)
                try:
                    self.plot_zone.plot(
                        x_arr[:-(self.plot_settings['arrayPlotSize'] + 1)],
                        y_arr[:-(self.plot_settings['arrayPlotSize'] + 1)],
                        clear=True,
                        pen=self.pen)
                except Exception:
                    if len(x_arr) > len(y_arr):
                        x_arr.pop()
                    else:
                        y_arr.pop()
                    self.plot_zone.plot(
                        x_arr[:-(self.plot_settings['arrayPlotSize'] + 1)],
                        y_arr[:-(self.plot_settings['arrayPlotSize'] + 1)],
                        clear=True,
                        pen=self.pen)
                #self.plot_zone.setXRange(x_arr[-1:][0] - self.plot_zone.visibleRange().width(), x_arr[-1:][0])
                if self.follow_plot:
                    if not (self.plot_zone.visibleRange().left() <
                            x_arr[-1:][0] <
                            self.plot_zone.visibleRange().right()):
                        width_visible = self.plot_zone.visibleRange().width()
                        height_visible = self.plot_zone.visibleRange().height()
                        bottom_visible = self.plot_zone.visibleRange().top()
                        # self.plot_zone.visibleRange().setRect(0, 0, 150, 10)
                        #                    print self.plot_zone.visibleRange()
                        rect_me = QRectF(x_arr[-1:][0], 0, width_visible, 5)
                        #print rect_me
                        #self.plot_zone.setXRange(x_arr[-1:][0], x_arr[-1:][0] + self.range_x)
                        #self.plot_zone.setRange()
                        #print "MOVE"
                        #print bottom_visible
                        #print height_visible
                        #dest = self.plot_zone.visibleRange().width()
                        #print range_x
                        #print dest
                        #print x_arr[-1:][0]
                        self.plot_zone.setRange(
                            rect=rect_me,
                            disableAutoRange=True,
                            xRange=(x_arr[-1:][0],
                                    (x_arr[-1:][0] + width_visible)),
                            padding=0,
                            yRange=(bottom_visible,
                                    bottom_visible + height_visible))
                        #self.plot_zone.sceneObj.sigMouseClicked.connect(self.me)

                        #self.plot_zone.sceneObj.mouseMoveEvent(3)
                        #print self.plot_zone.visibleRange()
                        #range_me = self.plot_zone.visibleRange()

                    #self.plot_zone.sigRangeChanged.connect(self.me)
                    #self.plot_zone.sigYRangeChanged.connect(self.me)
            mutex.unlock()
        else:
            self.sizeLabel.setText('Arduino Disconnected')
            self.sizeLabel.setStyleSheet('color:red')

# Updates the GUI timer
        time_to_display = int(round(time.time() - time_start, 2))
        if time_to_display >= 60:
            self.timer_label.setText(' ' + str(time_to_display / 60) + ":" +
                                     str(time_to_display % 60))
        else:
            if len(str(time_to_display)) == 1:
                self.timer_label.setText(" " + '0' + ':0' +
                                         str(time_to_display))
            else:
                self.timer_label.setText(" " + '0' + ':' +
                                         str(time_to_display))

# Call myself every 50milliseconds
        timer = QTimer()
        timer.singleShot(100, self.update)

# Stops recording

    def stopRecording(self):
        mutex.lock()
        if self.recording_status:
            if x_arr:
                self.record_cell_end = len(x_arr) - 1
            else:
                self.record_cell_end = len(x_arr)
            self.recorded_list.append(
                [self.record_cell_start, self.record_cell_end])
        mutex.unlock()
        self.clean_recorded_data = True
        self.recording_status = False

        self.record_pause.setIcon(QIcon(':/rec.png'))
        status = self.statusBar()
        status.showMessage('Stopped')

# Save file method

    def saveFile(self):
        if not self.file_saved:
            self.saveFileAs()
        else:
            self.writeDataToFile('w')

# Save as method

    def saveFileAs(self):
        my_home = os.path.expanduser('~')
        self.filename = QFileDialog.getSaveFileName(
            self, 'Save As', os.path.join(my_home, "new_file.dat"), "", "",
            QFileDialog.DontUseNativeDialog)
        self.writeDataToFile('w')

# Write data to file

    def writeDataToFile(self, open_mode):
        global x_arr, y_arr
        try:
            if self.filename:
                file_obj = open(self.filename, open_mode)
                for pair in self.recorded_list:
                    list_x = x_arr[pair[0]:pair[1]]
                    list_y = y_arr[pair[0]:pair[1]]

                    for elem in zip(list_x, list_y):
                        #                       TODO Check if separator works
                        file_obj.write(
                            str(elem[0]) + self.plot_settings['separator'] +
                            str(elem[1]) + '\n')
                file_obj.close()
                self.file_saved = True
        except (IOError, OSError) as error_file:
            message = QMessageBox.critical(self, 'Message', str(error_file),
                                           QMessageBox.Ok)
            #           message.show()
            self.filename = ''
            self.file_saved = False

# Create and show settings dialog

    def changeSettings(self):
        self.settings_dialog = SettingsDialog(self.plot_settings,
                                              self.refreshSettings, self)
        self.settings_dialog.show()

# Refresh settings

    def refreshSettings(self):
        self.pen = pg.mkPen(width=self.plot_settings['plotLineWidth'],
                            color=self.plot_settings['lineColor'][0])
        self.plot_zone.plotItem.showGrid(self.plot_settings['verticalGrid'],
                                         self.plot_settings['horizontalGrid'],
                                         self.plot_settings['gridOpacity'])

# Restart values and kills when new arduino connection is selected

    def restart_values(self):
        global x_arr, y_arr
        print('killing')
        self.read_serial_thread.__del__()
        mutex.lock()
        self.array_len = 0
        del x_arr[:]
        del y_arr[:]
        #print x_arr
        del self.recorded_list[:]
        #print "clean"
        width_visible = self.plot_zone.visibleRange().width()
        height_visible = self.plot_zone.visibleRange().height()
        bottom_visible = self.plot_zone.visibleRange().top()
        # self.plot_zone.visibleRange().setRect(0, 0, 150, 10)
        #print self.plot_zone.visibleRange()
        rect_me = QRectF(0, 0, width_visible, 5)
        self.plot_zone.setRange(rect=rect_me,
                                disableAutoRange=True,
                                xRange=(0, (0 + width_visible)),
                                padding=0,
                                yRange=(bottom_visible,
                                        bottom_visible + height_visible))
        mutex.unlock()
        #print  "clean out"
        self.read_serial_thread = ReadSerialThread(
            self.arduino_combobox.currentText(),
            self.plot_settings['serialBaud'], self)
        self.read_serial_thread.start()
Esempio n. 4
0
 def createEditor(self, parent, option, index):
     editor = QComboBox(parent)
     # Note: Qt.AscendingOrder == 0 and Qt.DescendingOrder == 1
     editor.addItems(["Ascending", "Descending"])
     editor.setFocusPolicy(Qt.StrongFocus)
     return editor
Esempio n. 5
0
class Ui_dev_client(object):
    def setupUi(self, dev_client):
        dev_client.resize(935, 660)
        dev_client.setWindowTitle(QApplication.translate("dev_client", "DevClient"))

        self.centralwidget = QWidget(dev_client)
        dev_client.setCentralWidget(self.centralwidget)

        main_layout = QGridLayout(self.centralwidget)
        main_layout.setContentsMargins(5, 5, 5, 3)
        main_layout.setSpacing(3)
        main_layout.setColumnStretch(0, 1)
        main_layout.setRowStretch(1, 1)

        top_layout = QHBoxLayout()
        top_layout.setContentsMargins(0, 0, 0, 0)
        top_layout.setSpacing(5)

        top_label_conn = QLabel()
        top_label_conn.setText(QApplication.translate("dev_client", "Connection"))
        top_layout.addWidget(top_label_conn)

        self.list_conn = QComboBox()
        self.list_conn.setFixedSize(145, 26)
        self.list_conn.setFocusPolicy(Qt.NoFocus)
        top_layout.addWidget(self.list_conn)

        self.list_account = QComboBox()
        self.list_account.setFixedSize(145, 26)
        self.list_account.setFocusPolicy(Qt.NoFocus)
        top_layout.addWidget(self.list_account)

        top_layout.addItem(QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
        top_label_account = QLabel()
        top_label_account.setText(QApplication.translate("dev_client", "Account"))
        top_layout.addWidget(top_label_account)

        self.button_connect = QPushButton()
        self.button_connect.setFixedSize(105, 26)
        self.button_connect.setFocusPolicy(Qt.NoFocus)
        self.button_connect.setIcon(QIcon(":/images/connect.png"))
        self.button_connect.setIconSize(QSize(16, 16))
        self.button_connect.setText(QApplication.translate("dev_client", "Connect"))
        top_layout.addWidget(self.button_connect)

        self.button_option = QPushButton()
        self.button_option.setFixedSize(105, 26)
        self.button_option.setFocusPolicy(Qt.NoFocus)
        self.button_option.setIcon(QIcon(":/images/option.png"))
        self.button_option.setIconSize(QSize(16, 16))
        self.button_option.setText(QApplication.translate("dev_client", "Option"))
        top_layout.addWidget(self.button_option)
        main_layout.addLayout(top_layout, 0, 0)

        right_layout = QVBoxLayout()
        right_layout.setContentsMargins(0, 0, 0, 0)
        right_layout.addItem(QSpacerItem(40, 29, QSizePolicy.Minimum, QSizePolicy.Fixed))

        self.rightpanel = QWidget()
        self.rightpanel.setMinimumWidth(225)
        right_layout.addWidget(self.rightpanel)
        main_layout.addLayout(right_layout, 0, 1, 3, 1)

        self.output_splitter = QSplitter(self.centralwidget)
        self.output_splitter.setOrientation(Qt.Vertical)
        self.output_splitter.setHandleWidth(3)
        self.output_splitter.setChildrenCollapsible(False)

        self.text_output = QTextEdit(self.output_splitter)
        self.text_output.setMinimumWidth(690)
        self.text_output.setFocusPolicy(Qt.NoFocus)
        self.text_output.setAutoFillBackground(True)
        self.text_output.setUndoRedoEnabled(False)
        self.text_output.setReadOnly(True)

        self.text_output_noscroll = QTextEdit(self.output_splitter)
        self.text_output_noscroll.setMinimumWidth(690)
        self.text_output_noscroll.setFocusPolicy(Qt.NoFocus)
        self.text_output_noscroll.setAutoFillBackground(True)
        self.text_output_noscroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.text_output_noscroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.text_output_noscroll.setUndoRedoEnabled(False)
        self.text_output_noscroll.setReadOnly(True)
        main_layout.addWidget(self.output_splitter, 1, 0)

        bottom_layout = QHBoxLayout()
        bottom_layout.setContentsMargins(0, 0, 0, 0)
        bottom_layout.setSpacing(5)

        self.text_input = QComboBox()
        self.text_input.setMinimumWidth(660)
        self.text_input.setFixedHeight(25)
        self.text_input.setEditable(True)
        self.text_input.addItem("")
        bottom_layout.addWidget(self.text_input)

        self.toggle_splitter = QPushButton()
        self.toggle_splitter.setFixedSize(25, 25)
        self.toggle_splitter.setFocusPolicy(Qt.NoFocus)
        self.toggle_splitter.setIcon(QIcon(":/images/split-window.png"))
        bottom_layout.addWidget(self.toggle_splitter)
        main_layout.addLayout(bottom_layout, 2, 0)