예제 #1
0
    def subscribe(self, icepap_addr, signal_name):
        """
        Creates a new subscription for signal values.

        icepap_addr - IcePAP driver number.
        signal_name - Signal name.
        Return - A positive integer id used when unsubscribing.
        """
        for ch in self.channels_subscribed.values():
            if ch.equals(icepap_addr, signal_name):
                msg = 'Channel already exists.\nAddr: ' \
                      '{}\nSignal: {}'.format(icepap_addr, signal_name)
                raise Exception(msg)
        channel = Channel(icepap_addr, signal_name)
        sn = QString(signal_name)
        cond_1 = sn.endsWith('Tgtenc')
        cond_2 = sn.endsWith('Shftenc')
        cond_3 = sn == 'DifAxMeasure'
        if cond_1 or cond_2 or cond_3:
            try:
                cfg = self.icepap_system[icepap_addr].get_cfg()
            except RuntimeError as e:
                msg = 'Failed to retrieve configuration parameters ' \
                      'for driver {}\n{}.'.format(icepap_addr, e)
                raise Exception(msg)
            if (cond_1 and cfg['TGTENC'].upper() == 'NONE') or \
                    (cond_2 and cfg['SHFTENC'].upper() == 'NONE'):
                msg = 'Signal {} is not mapped/valid.'.format(sn)
                raise Exception(msg)
            if cond_3:
                channel.set_measure_resolution(cfg)
        self.channel_id += 1
        self.channels_subscribed[self.channel_id] = channel
        return self.channel_id
예제 #2
0
    def saveProjectAs(self):
        ''' Save the project configuration under a different name '''
        try:
            # get the location for the new config file on disk
            start_dir = paths.OPUS_PROJECT_CONFIGS_PATH
            configDialog = QFileDialog()
            filter_str = QString("*.xml")
            fd = configDialog.getSaveFileName(self,QString("Save As..."),
                                              QString(start_dir), filter_str)
            # Check for cancel
            if not fd:
                return

            filename = QString(fd)
            # append xml extension if no extension was given
            if not filename.endsWith('.xml') and len(filename.split('.')) == 1:
                filename = filename + '.xml'

            if not self.saveProject(filename):
                return

            # hack: open the project right after save to properly change the
            # 'active project' related parameters
            self.openProject(filename)

        except:
            errorMessage = formatExceptionInfo(custom_message = \
                                               'Unexpected error saving config')
            QMessageBox.warning(self, 'Warning', errorMessage)
예제 #3
0
    def saveProjectAs(self):
        ''' Save the project configuration under a different name '''
        try:
            # get the location for the new config file on disk
            start_dir = paths.OPUS_PROJECT_CONFIGS_PATH
            configDialog = QFileDialog()
            filter_str = QString("*.xml")
            fd = configDialog.getSaveFileName(self, QString("Save As..."),
                                              QString(start_dir), filter_str)
            # Check for cancel
            if not fd:
                return

            filename = QString(fd)
            # append xml extension if no extension was given
            if not filename.endsWith('.xml') and len(filename.split('.')) == 1:
                filename = filename + '.xml'

            if not self.saveProject(filename):
                return

            # hack: open the project right after save to properly change the
            # 'active project' related parameters
            self.openProject(filename)

        except:
            errorMessage = formatExceptionInfo(custom_message = \
                                               'Unexpected error saving config')
            QMessageBox.warning(self, 'Warning', errorMessage)
예제 #4
0
 def send_to_process(self, qstr):
     if not isinstance(qstr, QString):
         qstr = QString(qstr)
     if not qstr.endsWith('\n'):
         qstr.append('\n')
     self.process.write(qstr.toLocal8Bit())
     self.process.waitForBytesWritten(-1)
예제 #5
0
 def send_to_process(self, qstr):
     if not isinstance(qstr, QString):
         qstr = QString(qstr)
     if not qstr.endsWith('\n'):
         qstr.append('\n')
     self.process.write(qstr.toLocal8Bit())
     self.process.waitForBytesWritten(-1)
예제 #6
0
 def send_to_process(self, qstr):
     if not isinstance(qstr, QString):
         qstr = QString(qstr)
     if not qstr.endsWith('\n'):
         qstr.append('\n')
     self.process.write(qstr.toLocal8Bit())
     self.process.waitForBytesWritten(-1)
     
     # Eventually write prompt faster (when hitting Enter continuously)
     # -- necessary/working on Windows only:
     if os.name == 'nt':
         self.write_error()
예제 #7
0
 def send_to_process(self, qstr):
     if not isinstance(qstr, QString):
         qstr = QString(qstr)
     if qstr[:-1] in ["clear", "cls", "CLS"]:
         self.shell.clear()
         self.send_to_process(QString(os.linesep))
         return
     if not qstr.endsWith('\n'):
         qstr.append('\n')
     if os.name == 'nt':
         self.process.write(unicode(qstr).encode('cp850'))
     else:
         self.process.write(qstr.toLocal8Bit())
     self.process.waitForBytesWritten(-1)
예제 #8
0
    def updateTable(self, id):
        filePath = QFileDialog.getOpenFileName(self, "请选择库", self.alloneEnv,
                                               "Library(*.lib)")
        if filePath.isEmpty():
            return
        fileinfo = QFileInfo(filePath)
        libPath = fileinfo.absoluteDir().absolutePath()
        libName = fileinfo.baseName()
        # 支持选择文件后与系统ALLONEDIR比较一下变成相对路径
        # 并且能够手动输入相对路径或包含$(ALLONEDIR)的相对路径
        env = QString(os.getenv('ALLONEDIR', '../..').replace('\\', '/'))
        if env.endsWith('/'):
            env.remove(env.lastIndexOf('/'), 1)
        if libPath.contains(env):
            libPath.replace(env, QString('$$ALLONEDIR'))

        self.tw_interface.setItem(id, 1, QTableWidgetItem(libPath))
        self.tw_interface.setItem(id, 0, QTableWidgetItem(libName))
예제 #9
0
파일: pqView.py 프로젝트: jlg234bob/PPQT
 def refresh(self, clearCache=False):
     # this could be first refresh for this book file, so set the
     # base URL for its images.
     sep = QChar(u'/')
     qsp = QString(IMC.bookDirPath)
     if not qsp.endsWith(sep):
         qsp.append(sep)
     self.baseURL = QUrl.fromLocalFile(qsp)
     # this might be the second or nth refresh of the book, note the
     # scroll position so we can restore it in loadEnds below. This
     # means that when you make a little edit at the end of a book, and
     # refresh the preview, you won't have to scroll down to the end
     # for the 500th time to see your changes.
     self.scrollPosition = self.webPage.mainFrame().scrollPosition()
     if clearCache:
         self.settings.clearMemoryCaches()
     # We are reloading our base page, so clear any history of prior links
     self.history.clear()
     self.preview.setHtml(IMC.editWidget.toPlainText(), self.baseURL)
예제 #10
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)
예제 #11
0
class MovieContainer(object):
    """A MovieContainer holds a set of Movie objects.

    The movies are held in a canonicalized order based on their title
    and year, so if either of these fields is changed the movies must be
    re-sorted. For this reason (and to maintain the dirty flag), all
    updates to movies should be made through this class's updateMovie()
    method.
    """

    MAGIC_NUMBER = 0x3051E
    OLD_FILE_VERSION = 100
    FILE_VERSION = 101

    def __init__(self):
        self.__fname = QString()
        self.__movies = []
        self.__movieFromId = {}
        self.__dirty = False

    def key(self, title, year):
        text = str(title).lower()
        if text.startswith("a "):
            text = text[2:]
        elif text.startswith("an "):
            text = text[3:]
        elif text.startswith("the "):
            text = text[4:]
        parts = text.split(" ", 1)
        if parts[0].isdigit():
            text = "{0:08d} ".format(int(parts[0]))
            if len(parts) > 1:
                text += parts[1]
        return "{0}\t{1}".format(text.replace(" ", ""), year)

    def isDirty(self):
        return self.__dirty

    def setDirty(self, dirty=True):
        self.__dirty = dirty

    def clear(self, clearFilename=True):
        self.__movies = []
        self.__movieFromId = {}
        if clearFilename:
            self.__fname = QString()
        self.__dirty = False

    def movieFromId(self, id):
        """Returns the movie with the given Python ID."""
        return self.__movieFromId[id]

    def movieAtIndex(self, index):
        """Returns the index-th movie."""
        return self.__movies[index][1]

    def add(self, movie):
        """Adds the given movie to the list if it isn't already
        present. Returns True if added; otherwise returns False."""
        if id(movie) in self.__movieFromId:
            return False
        key = self.key(movie.title, movie.year)
        bisect.insort_left(self.__movies, [key, movie])
        self.__movieFromId[id(movie)] = movie
        self.__dirty = True
        return True

    def delete(self, movie):
        """Deletes the given movie from the list and returns True;
        returns False if the movie isn't in the list."""
        if id(movie) not in self.__movieFromId:
            return False
        key = self.key(movie.title, movie.year)
        i = bisect.bisect_left(self.__movies, [key, movie])
        del self.__movies[i]
        del self.__movieFromId[id(movie)]
        self.__dirty = True
        return True

    def updateMovie(self,
                    movie,
                    title,
                    year,
                    minutes=None,
                    location=None,
                    notes=None):
        if minutes is not None:
            movie.minutes = minutes
        if location is not None:
            movie.location = location
        if notes is not None:
            movie.notes = notes
        if title != movie.title or year != movie.year:
            key = self.key(movie.title, movie.year)
            i = bisect.bisect_left(self.__movies, [key, movie])
            self.__movies[i][0] = self.key(title, year)
            movie.title = title
            movie.year = year
            self.__movies.sort()
        self.__dirty = True

    def __iter__(self):
        for pair in iter(self.__movies):
            yield pair[1]

    def __len__(self):
        return len(self.__movies)

    def setFilename(self, fname):
        self.__fname = fname

    def filename(self):
        return self.__fname

    @staticmethod
    def formats():
        return "*.mqb"

    def save(self, fname=QString()):
        if not fname.isEmpty():
            self.__fname = fname
        if self.__fname.endsWith(".mqb"):
            return self.saveQDataStream()
        return False, "Failed to save: invalid file extension"

    def load(self, fname=QString()):
        if not fname.isEmpty():
            self.__fname = fname
        if self.__fname.endsWith(".mqb"):
            return self.loadQDataStream()
        return False, "Failed to load: invalid file extension"

    def saveQDataStream(self):
        error = None
        fh = None
        try:
            fh = QFile(self.__fname)
            if not fh.open(QIODevice.WriteOnly):
                raise IOError(str(fh.errorString()))
            stream = QDataStream(fh)
            stream.writeInt32(MovieContainer.MAGIC_NUMBER)
            stream.writeInt32(MovieContainer.FILE_VERSION)
            stream.setVersion(QDataStream.Qt_4_2)
            for key, movie in self.__movies:
                stream << movie.title
                stream.writeInt16(movie.year)
                stream.writeInt16(movie.minutes)
                stream << movie.acquired << movie.location \
                       << movie.notes
        except EnvironmentError as e:
            error = "Failed to save: {0}".format(e)
        finally:
            if fh is not None:
                fh.close()
            if error is not None:
                return False, error
            self.__dirty = False
            return True, "Saved {0} movie records to {1}".format(
                len(self.__movies),
                QFileInfo(self.__fname).fileName())

    def loadQDataStream(self):
        error = None
        fh = None
        try:
            fh = QFile(self.__fname)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(str(fh.errorString()))
            stream = QDataStream(fh)
            magic = stream.readInt32()
            if magic != MovieContainer.MAGIC_NUMBER:
                raise IOError("unrecognized file type")
            version = stream.readInt32()
            if version < MovieContainer.OLD_FILE_VERSION:
                raise IOError("old and unreadable file format")
            elif version > MovieContainer.FILE_VERSION:
                raise IOError("new and unreadable file format")
            old = False
            if version == MovieContainer.OLD_FILE_VERSION:
                old = True
            stream.setVersion(QDataStream.Qt_4_2)
            self.clear(False)
            while not stream.atEnd():
                title = QString()
                acquired = QDate()
                location = QString()
                notes = QString()
                stream >> title
                year = stream.readInt16()
                minutes = stream.readInt16()
                if old:
                    stream >> acquired >> notes
                else:
                    stream >> acquired >> location >> notes
                self.add(Movie(title, year, minutes, acquired, location,
                               notes))
        except EnvironmentError as e:
            error = "Failed to load: {0}".format(e)
        finally:
            if fh is not None:
                fh.close()
            if error is not None:
                return False, error
            self.__dirty = False
            return True, "Loaded {0} movie records from {1}".format(
                len(self.__movies),
                QFileInfo(self.__fname).fileName())

    def exportXml(self, fname):
        error = None
        fh = None
        try:
            fh = QFile(fname)
            if not fh.open(QIODevice.WriteOnly):
                raise IOError(str(fh.errorString()))
            stream = QTextStream(fh)
            stream.setCodec(CODEC)
            stream << ("<?xml version='1.0' encoding='{0}'?>\n"
                       "<!DOCTYPE MOVIES>\n"
                       "<MOVIES VERSION='1.0'>\n".format(CODEC))
            for key, movie in self.__movies:
                stream << ("<MOVIE YEAR='{0}' MINUTES='{1}' "
                           "ACQUIRED='{2}'>\n".format(movie.year,
                           movie.minutes,
                           movie.acquired.toString(Qt.ISODate))) \
                       << "<TITLE>" << Qt.escape(movie.title) \
                       << "</TITLE>\n" << "<LOCATION>"
                if not movie.location.isEmpty():
                    stream << "\n" << Qt.escape(movie.location)
                stream << "\n</LOCATION>\n" << "<NOTES>"
                if not movie.notes.isEmpty():
                    stream << "\n" << Qt.escape(encodedNewlines(movie.notes))
                stream << "\n</NOTES>\n</MOVIE>\n"
            stream << "</MOVIES>\n"
        except EnvironmentError as e:
            error = "Failed to export: {0}".format(e)
        finally:
            if fh is not None:
                fh.close()
            if error is not None:
                return False, error
            self.__dirty = False
            return True, "Exported {0} movie records to {1}".format(
                len(self.__movies),
                QFileInfo(fname).fileName())

    def importDOM(self, fname):
        dom = QDomDocument()
        error = None
        fh = None
        try:
            fh = QFile(fname)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(str(fh.errorString()))
            if not dom.setContent(fh):
                raise ValueError("could not parse XML")
        except (IOError, OSError, ValueError) as e:
            error = "Failed to import: {0}".format(e)
        finally:
            if fh is not None:
                fh.close()
            if error is not None:
                return False, error
        try:
            self.populateFromDOM(dom)
        except ValueError as e:
            return False, "Failed to import: {0}".format(e)
        self.__fname = QString()
        self.__dirty = True
        return True, "Imported {0} movie records from {1}".format(
            len(self.__movies),
            QFileInfo(fname).fileName())

    def populateFromDOM(self, dom):
        root = dom.documentElement()
        if root.tagName() != "MOVIES":
            raise ValueError("not a Movies XML file")
        self.clear(False)
        node = root.firstChild()
        while not node.isNull():
            if node.toElement().tagName() == "MOVIE":
                self.readMovieNode(node.toElement())
            node = node.nextSibling()

    def readMovieNode(self, element):
        def getText(node):
            child = node.firstChild()
            text = QString()
            while not child.isNull():
                if child.nodeType() == QDomNode.TextNode:
                    text += child.toText().data()
                child = child.nextSibling()
            return text.trimmed()

        year = intFromQStr(element.attribute("YEAR"))
        minutes = intFromQStr(element.attribute("MINUTES"))
        ymd = element.attribute("ACQUIRED").split("-")
        if ymd.count() != 3:
            raise ValueError("invalid acquired date {0}".format(
                str(element.attribute("ACQUIRED"))))
        acquired = QDate(intFromQStr(ymd[0]), intFromQStr(ymd[1]),
                         intFromQStr(ymd[2]))
        title = notes = None
        location = QString()
        node = element.firstChild()
        while title is None or notes is None:
            if node.isNull():
                raise ValueError("missing title or notes")
            if node.toElement().tagName() == "TITLE":
                title = getText(node)
            elif node.toElement().tagName() == "LOCATION":
                location = getText(node)
            elif node.toElement().tagName() == "NOTES":
                notes = getText(node)
            node = node.nextSibling()
        self.add(
            Movie(title, year, minutes, acquired, location,
                  decodedNewlines(notes)))

    def importSAX(self, fname):
        error = None
        fh = None
        try:
            handler = SaxMovieHandler(self)
            parser = QXmlSimpleReader()
            parser.setContentHandler(handler)
            parser.setErrorHandler(handler)
            fh = QFile(fname)
            input = QXmlInputSource(fh)
            self.clear(False)
            if not parser.parse(input):
                raise ValueError(handler.error)
        except (IOError, OSError, ValueError) as e:
            error = "Failed to import: {0}".format(e)
        finally:
            if fh is not None:
                fh.close()
            if error is not None:
                return False, error
            self.__fname = QString()
            self.__dirty = True
            return True, "Imported {0} movie records from {1}".format(
                len(self.__movies),
                QFileInfo(fname).fileName())