Esempio n. 1
0
class _Execute(QtCore.QThread):

    sig_error = QtCore.pyqtSignal(str)
    sig_update_row_color = QtCore.pyqtSignal(str, int)
    sig_highlight_row = QtCore.pyqtSignal(int)
    sig_update_reply = QtCore.pyqtSignal(int, str)
    sig_show_execute_icon = QtCore.pyqtSignal()

    def __init__(self, parent):
        QtCore.QThread.__init__(self)
        self.parent = parent
        self._error = False

    def run(self):
        if self._error:
            return

        for index, action, delay, message in self.parent._command_list:
            if self._error or self.parent._abort_execution:
                self.sig_show_execute_icon.emit()
                break

            self.sig_highlight_row.emit(index)
            try:
                if action == 'read':
                    if delay > 0:
                        time.sleep(delay)
                    reply = self.parent._conn.read()
                elif action == 'write':
                    num_bytes = self.parent._conn.write(message)
                    reply = '<sent {} bytes>'.format(num_bytes)
                elif action == 'query':
                    reply = self.parent._conn.query(message, delay)
                elif action == 'delay':
                    time.sleep(delay)
                    reply = ''
                else:
                    assert False, 'Method "{}" not implemented'.format(action)
                self.sig_update_reply.emit(index, reply.strip())
            except Exception:
                self._error = True
                self.sig_error.emit('Row {}: {}({})\n\n{}'.format(
                    index + 1, action, message, traceback.format_exc()))
                break
            finally:
                self.sig_update_row_color.emit(action, index)
Esempio n. 2
0
class _Settings(QtWidgets.QDialog):

    sig_update_jog_tooltip = QtCore.pyqtSignal()

    def __init__(self, parent):
        """Display a QDialog to edit the settings"""
        super(_Settings, self).__init__(flags=QtCore.Qt.WindowCloseButtonHint)

        self.conn = parent._connection

        info = self.conn.get_hardware_info()
        self.setWindowTitle(
            info.modelNumber.decode('utf-8') + ' || ' +
            info.notes.decode('utf-8'))

        # move info
        max_vel, max_acc = self.conn.get_motor_velocity_limits()
        vel, acc = self.conn.get_vel_params()
        vel = self.conn.get_real_value_from_device_unit(vel, UnitType.VELOCITY)
        acc = self.conn.get_real_value_from_device_unit(
            acc, UnitType.ACCELERATION)
        backlash = self.conn.get_real_value_from_device_unit(
            self.conn.get_backlash(), UnitType.DISTANCE)

        # move widgets
        self.acc_spinbox = QtWidgets.QDoubleSpinBox()
        self.acc_spinbox.setMinimum(0)
        self.acc_spinbox.setMaximum(max_acc)
        self.acc_spinbox.setValue(acc)
        self.acc_spinbox.setToolTip(
            '<html><b>Range:</b><br>0 - {} mm/s<sup>2</sup></html>'.format(
                max_acc))

        self.vel_spinbox = QtWidgets.QDoubleSpinBox()
        self.vel_spinbox.setMinimum(0)
        self.vel_spinbox.setMaximum(max_vel)
        self.vel_spinbox.setValue(vel)
        self.vel_spinbox.setToolTip(
            '<html><b>Range:</b><br>0 - {} mm/s</html>'.format(max_vel))

        self.backlash_spinbox = QtWidgets.QDoubleSpinBox()
        self.backlash_spinbox.setMinimum(0)
        self.backlash_spinbox.setMaximum(5)
        self.backlash_spinbox.setValue(backlash)
        self.backlash_spinbox.setToolTip(
            '<html><b>Range:</b><br>0 - 5 mm</html>')

        move_group = QtWidgets.QGroupBox('Move Parameters')
        move_grid = QtWidgets.QGridLayout()
        move_grid.addWidget(QtWidgets.QLabel('Backlash'),
                            0,
                            0,
                            alignment=QtCore.Qt.AlignRight)
        move_grid.addWidget(self.backlash_spinbox, 0, 1)
        move_grid.addWidget(QtWidgets.QLabel('mm'),
                            0,
                            2,
                            alignment=QtCore.Qt.AlignLeft)
        move_grid.addWidget(QtWidgets.QLabel('Maximum Velocity'),
                            1,
                            0,
                            alignment=QtCore.Qt.AlignRight)
        move_grid.addWidget(self.vel_spinbox, 1, 1)
        move_grid.addWidget(QtWidgets.QLabel('mm/s'),
                            1,
                            2,
                            alignment=QtCore.Qt.AlignLeft)
        move_grid.addWidget(QtWidgets.QLabel('Acceleration'),
                            2,
                            0,
                            alignment=QtCore.Qt.AlignRight)
        move_grid.addWidget(self.acc_spinbox, 2, 1)
        move_grid.addWidget(QtWidgets.QLabel('mm/s<sup>2</sup>'),
                            2,
                            2,
                            alignment=QtCore.Qt.AlignLeft)
        move_group.setLayout(move_grid)

        # jog info
        jog_size = self.conn.get_real_value_from_device_unit(
            self.conn.get_jog_step_size(), UnitType.DISTANCE)
        vel, acc = self.conn.get_jog_vel_params()
        jog_vel = self.conn.get_real_value_from_device_unit(
            vel, UnitType.VELOCITY)
        jog_acc = self.conn.get_real_value_from_device_unit(
            acc, UnitType.ACCELERATION)

        # jog widgets
        min_jog, max_jog = 0.002, parent._max_pos_mm / 2.0
        self.jog_size_spinbox = QtWidgets.QDoubleSpinBox()
        self.jog_size_spinbox.setMinimum(min_jog)
        self.jog_size_spinbox.setMaximum(max_jog)
        self.jog_size_spinbox.setDecimals(3)
        self.jog_size_spinbox.setValue(jog_size)
        self.jog_size_spinbox.setToolTip(
            '<html><b>Range:</b><br>{} - {} mm</html>'.format(
                min_jog, max_jog))

        self.jog_acc_spinbox = QtWidgets.QDoubleSpinBox()
        self.jog_acc_spinbox.setMinimum(0)
        self.jog_acc_spinbox.setMaximum(max_acc)
        self.jog_acc_spinbox.setValue(jog_acc)
        self.jog_acc_spinbox.setToolTip(
            '<html><b>Range:</b><br>0 - {} mm/s<sup>2</sup></html>'.format(
                max_acc))

        self.jog_vel_spinbox = QtWidgets.QDoubleSpinBox()
        self.jog_vel_spinbox.setMinimum(0)
        self.jog_vel_spinbox.setMaximum(max_vel)
        self.jog_vel_spinbox.setValue(jog_vel)
        self.jog_vel_spinbox.setToolTip(
            '<html><b>Range:</b><br>0 - {} mm/s</html>'.format(max_vel))

        jog_group = QtWidgets.QGroupBox('Jog Parameters')
        jog_grid = QtWidgets.QGridLayout()
        jog_grid.addWidget(QtWidgets.QLabel('Step Size'),
                           0,
                           0,
                           alignment=QtCore.Qt.AlignRight)
        jog_grid.addWidget(self.jog_size_spinbox, 0, 1)
        jog_grid.addWidget(QtWidgets.QLabel('mm'),
                           0,
                           2,
                           alignment=QtCore.Qt.AlignLeft)
        jog_grid.addWidget(QtWidgets.QLabel('Maximum Velocity'),
                           1,
                           0,
                           alignment=QtCore.Qt.AlignRight)
        jog_grid.addWidget(self.jog_vel_spinbox, 1, 1)
        jog_grid.addWidget(QtWidgets.QLabel('mm/s'),
                           1,
                           2,
                           alignment=QtCore.Qt.AlignLeft)
        jog_grid.addWidget(QtWidgets.QLabel('Acceleration'),
                           2,
                           0,
                           alignment=QtCore.Qt.AlignRight)
        jog_grid.addWidget(self.jog_acc_spinbox, 2, 1)
        jog_grid.addWidget(QtWidgets.QLabel('mm/s<sup>2</sup>'),
                           2,
                           2,
                           alignment=QtCore.Qt.AlignLeft)
        jog_group.setLayout(jog_grid)

        hbox = QtWidgets.QHBoxLayout()
        hbox.addWidget(move_group)
        hbox.addWidget(jog_group)

        update_button = QtWidgets.QPushButton('Update')
        update_button.setToolTip('Update the device settings')
        update_button.clicked.connect(self.update_settings)

        cancel_button = QtWidgets.QPushButton('Cancel')
        cancel_button.setToolTip('Update the device settings')
        cancel_button.clicked.connect(self.close)

        info_button = QtWidgets.QPushButton()
        info_button.setIcon(get_icon('imageres|109'))
        info_button.clicked.connect(
            lambda: show_hardware_info(parent._connection))
        info_button.setToolTip('Display the hardware information')

        button_layout = QtWidgets.QGridLayout()
        button_layout.addWidget(cancel_button, 0, 0)
        button_layout.addItem(
            QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Expanding), 0, 1)
        button_layout.addWidget(update_button, 0, 2)
        button_layout.addWidget(info_button, 0, 3)

        vbox = QtWidgets.QVBoxLayout()
        vbox.addLayout(hbox)
        vbox.addLayout(button_layout)
        self.setLayout(vbox)

    def update_settings(self):
        vel = self.conn.get_device_unit_from_real_value(
            self.vel_spinbox.value(), UnitType.VELOCITY)
        acc = self.conn.get_device_unit_from_real_value(
            self.acc_spinbox.value(), UnitType.ACCELERATION)
        self.conn.set_vel_params(vel, acc)

        backlash = self.conn.get_device_unit_from_real_value(
            self.backlash_spinbox.value(), UnitType.DISTANCE)
        self.conn.set_backlash(backlash)

        jog_vel = self.conn.get_device_unit_from_real_value(
            self.jog_vel_spinbox.value(), UnitType.VELOCITY)
        jog_acc = self.conn.get_device_unit_from_real_value(
            self.jog_acc_spinbox.value(), UnitType.ACCELERATION)
        self.conn.set_jog_vel_params(jog_vel, jog_acc)

        jog_size = self.conn.get_device_unit_from_real_value(
            self.jog_size_spinbox.value(), UnitType.DISTANCE)
        self.conn.set_jog_step_size(jog_size)

        self.sig_update_jog_tooltip.emit()

        self.close()
Esempio n. 3
0
 class _Signaler(QtCore.QObject):
     """Used for sending a signal of the current position."""
     signal = QtCore.pyqtSignal()
class _Tree(QtWidgets.QTreeWidget):

    sig_selected = QtCore.pyqtSignal(str)

    def __init__(self, equipment_table, connection_table):
        """A Tree view of the options to use as filters for the devices."""
        super(_Tree, self).__init__()

        # configure the super class
        self.setColumnCount(1)
        self.header().close()
        self.header().setStretchLastSection(False)
        self.header().setSectionResizeMode(
            QtWidgets.QHeaderView.ResizeToContents)
        self.itemDoubleClicked.connect(self._item_clicked)

        self.equipment_table = equipment_table
        self.connection_table = connection_table
        self.skip_names = ('Alias', 'Asset Number', 'Description',
                           'Latest Report Number', 'Model', 'Serial')
        self.rename_map = {'Date Calibrated': 'Year Calibrated'}
        self.create_top_level()

    def create_top_level(self):
        top_level_names = []
        for name in self.equipment_table.header:
            if name in self.skip_names:
                continue
            if name in self.rename_map:
                name = self.rename_map[name]
            top_level_names.append(name)

        top_level_names.extend(['Backend',
                                'Interface'])  # for ConnectionRecord's

        for item in sorted(top_level_names):
            QtWidgets.QTreeWidgetItem(self, [item])

    def populate_tree(self):
        self.clear()
        self.create_top_level()

        for index in range(self.topLevelItemCount()):
            item = self.topLevelItem(index)
            name = item.text(0)
            if name == 'Manufacturer':
                values = {}
                for record in self.equipment_table.records_all:
                    if record.manufacturer and record.manufacturer not in values:
                        values[record.manufacturer] = [record.model]
                    else:
                        if record.model and record.model not in values[
                                record.manufacturer]:
                            values[record.manufacturer].append(record.model)
                item.setText(0, name + ' ({})'.format(len(values)))
                for manufacturer in sorted(values):
                    model_item = QtWidgets.QTreeWidgetItem(
                        item, [manufacturer])
                    for model in sorted(values[manufacturer]):
                        QtWidgets.QTreeWidgetItem(model_item, [model])
            elif name == 'Year Calibrated':
                years = []
                for record in self.equipment_table.records_all:
                    year = record.date_calibrated.year
                    if year > 1 and year not in years:
                        years.append(year)
                item.setText(0, name + ' ({})'.format(len(years)))
                for year in sorted(years)[::-1]:
                    QtWidgets.QTreeWidgetItem(item, [str(year)])
            elif name == 'Connection':
                bools = {'True': 0, 'False': 0}
                for record in self.equipment_table.records_all:
                    bools[str(record.connection is not None)] += 1
                item.setText(0, name + ' (2)')
                for key in sorted(bools):
                    QtWidgets.QTreeWidgetItem(item, [key])
            elif name == 'Calibration Cycle':
                cycles = []
                for record in self.equipment_table.records_all:
                    if record.calibration_cycle == 0:
                        continue
                    if int(record.calibration_cycle
                           ) == record.calibration_cycle:
                        cycle = int(record.calibration_cycle)
                    else:
                        cycle = record.calibration_cycle
                    if cycle not in cycles:
                        cycles.append(cycle)
                item.setText(0, name + ' ({})'.format(len(cycles)))
                for c in sorted(cycles):
                    QtWidgets.QTreeWidgetItem(item, [str(c)])
            else:
                if name == 'Backend' or name == 'Interface':
                    values = self._get_distinct_connection_records(name)
                else:
                    values = self._get_distinct_equipment_records(name)
                item.setText(0, name + ' ({})'.format(len(values)))
                for value in sorted(values):
                    QtWidgets.QTreeWidgetItem(item, [value])

    def _get_distinct_equipment_records(self, name):
        out = []
        attrib = name.lower().replace(' ', '_')
        for record in self.equipment_table.records_all:
            value = u'{}'.format(getattr(record, attrib))
            if value and value not in out:
                out.append(value)
        return out

    def _get_distinct_connection_records(self, name):
        out = []
        attrib = name.lower().replace(' ', '_')
        for record in self.connection_table.records_all:
            value = getattr(record, attrib).name
            if value and value not in out:
                out.append(value)
        return out

    def _item_clicked(self, item, column):
        num_parents = 0
        parent = item.parent()
        while parent is not None:
            parent = parent.parent()
            num_parents += 1

        if num_parents == 0:  # then a top-level item was clicked
            return

        if num_parents == 1:
            attrib_name = item.parent().text(column).split(
                ' (')[column].lower().replace(' ', '_')
            text = u'{}={}'.format(attrib_name, item.text(column))
        else:
            attrib_name = item.parent().parent().text(column).split(
                ' (')[column].lower().replace(' ', '_')
            text = u'{}={}, model={}'.format(attrib_name,
                                             item.parent().text(column),
                                             item.text(column))

        self.sig_selected.emit(text)