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)
Beispiel #2
0
    def __init__(self, connection, parent=None):
        """
        A :class:`~QtWidgets.QWidget` for a :class:`~msl.equipment.connection_message_based.ConnectionMessageBased`
        connection.

        This widget allows for reading/writing messages from/to equipment.

        Parameters
        ----------
        connection : :class:`~msl.equipment.connection_message_based.ConnectionMessageBased`
            The connection to the equipment.
        parent : :class:`QtWidgets.QWidget`
            The parent widget.

        Example
        -------
        To view an example of the :class:`MessageBased` widget that will send messages to a
        *dummy* :class:`~msl.equipment.record_types.EquipmentRecord` in demo mode, run:

        >>> from msl.examples.qt.equipment import message_based # doctest: +SKIP
        >>> message_based.show() # doctest: +SKIP
        """
        super(MessageBased, self).__init__(parent=parent)

        r = connection.equipment_record
        self.setWindowTitle('{} || {} || {}'.format(r.manufacturer, r.model,
                                                    r.serial))
        self.setAcceptDrops(True)

        self._conn = connection
        self._dropped_commands = []
        self._abort_execution = False
        self._command_list = []

        self._header = ['Action', 'Delay', 'Message', 'Reply']
        self._actions = ['write', 'read', 'query', 'delay']
        self._table = QtWidgets.QTableWidget(0, len(self._header), self)
        self._table.setHorizontalHeaderLabels(self._header)
        self._table.horizontalHeader().setStretchLastSection(True)
        self._table.horizontalHeader().setContextMenuPolicy(
            QtCore.Qt.CustomContextMenu)
        self._table.horizontalHeader().customContextMenuRequested.connect(
            self._show_horizontal_popup_menu)
        self._table.verticalHeader().setContextMenuPolicy(
            QtCore.Qt.CustomContextMenu)
        self._table.verticalHeader().customContextMenuRequested.connect(
            self._show_vertical_popup_menu)

        self._timeout_spinbox = QtWidgets.QDoubleSpinBox()
        self._timeout_spinbox.setToolTip(
            '<html>The timeout value to use for <i>read</i> commands</html>')
        self._timeout_spinbox.setRange(0, 999999999)
        if 'ConnectionPyVISA' in '{}'.format(
                connection.__class__.__bases__):  # a PyVISA connection
            self._timeout_spinbox.setSuffix(' ms')
            self._timeout_spinbox.setDecimals(0)
        else:
            self._timeout_spinbox.setSuffix(' s')
            self._timeout_spinbox.setDecimals(2)
        try:
            self._timeout_spinbox.setValue(self._conn.timeout)
        except TypeError:  # in case the connection is established in demo mode
            self._timeout_spinbox.setValue(0)
        self._timeout_spinbox.valueChanged.connect(self._update_timeout)

        self._use_rows = QtWidgets.QLineEdit()
        self._use_rows.setToolTip(
            'Enter the rows to execute or leave blank to execute all rows.\nFor example: 1,3,5-8'
        )

        self._execute_icon = get_icon(QtWidgets.QStyle.SP_ArrowRight)
        self._continuous_icon = get_icon(QtWidgets.QStyle.SP_BrowserReload)
        self._abort_icon = get_icon(QtWidgets.QStyle.SP_BrowserStop)
        self._clear_icon = get_icon(QtWidgets.QStyle.SP_DialogResetButton)
        self._remove_icon = get_icon(QtWidgets.QStyle.SP_DialogCancelButton)
        self._insert_before_icon = get_icon(QtWidgets.QStyle.SP_DialogOkButton)
        # create an insert_after_icon by transforming the insert_before_icon
        size = self._insert_before_icon.availableSizes()[-1]
        pixmap = self._insert_before_icon.pixmap(size).transformed(
            QtGui.QTransform().scale(-1, 1))
        self._insert_after_icon = QtGui.QIcon(pixmap)

        self._execute_thread = _Execute(self)
        self._execute_thread.finished.connect(self._check_if_looping)
        self._execute_thread.sig_error.connect(self._execute_error)
        self._execute_thread.sig_update_row_color.connect(
            self._update_row_appearance)
        self._execute_thread.sig_highlight_row.connect(self._highlight_row)
        self._execute_thread.sig_update_reply.connect(self._update_reply)
        self._execute_thread.sig_show_execute_icon.connect(
            self._show_execute_icon)

        self._loop_checkbox = QtWidgets.QCheckBox()
        self._loop_checkbox.setToolTip('Run continuously?')
        self._loop_checkbox.clicked.connect(self._show_execute_icon)

        save_icon = get_icon(QtWidgets.QStyle.SP_DriveFDIcon)
        self._save_button = QtWidgets.QPushButton(save_icon, 'Save')
        self._save_button.setToolTip('Save the table to a tab-delimited file')
        self._save_button.clicked.connect(self._save)

        self._info_button = QtWidgets.QPushButton(
            get_icon(QtWidgets.QStyle.SP_FileDialogInfoView), '')
        self._info_button.setToolTip(
            'Display the information about the equipment')
        self._info_button.clicked.connect(
            lambda clicked, record=r: show_record(record))

        self._status_label = QtWidgets.QLabel()

        self._execute_button = QtWidgets.QPushButton()
        self._execute_button.clicked.connect(self._execute_start)
        self._show_execute_icon()

        self._status_label.setText('Create a new Execution Table or\n'
                                   'Drag & Drop or Copy & Paste\n'
                                   'a previous Execution Table')

        execute_widget = QtWidgets.QWidget()
        grid = QtWidgets.QGridLayout()
        grid.addWidget(QtWidgets.QLabel('Timeout'),
                       1,
                       0,
                       alignment=QtCore.Qt.AlignRight)
        grid.addWidget(self._timeout_spinbox, 1, 1, 1, 2)
        grid.addWidget(QtWidgets.QLabel('Rows'),
                       2,
                       0,
                       alignment=QtCore.Qt.AlignRight)
        grid.addWidget(self._use_rows, 2, 1, 1, 2)
        grid.addWidget(self._execute_button, 3, 0, 1, 2)
        grid.addWidget(self._loop_checkbox,
                       3,
                       2,
                       1,
                       1,
                       alignment=QtCore.Qt.AlignLeft)
        grid.addWidget(self._save_button, 4, 0, 1, 2)
        grid.addWidget(self._info_button, 4, 2, 1, 1)
        grid.addWidget(self._status_label,
                       5,
                       0,
                       1,
                       3,
                       alignment=QtCore.Qt.AlignBottom)
        grid.setRowStretch(5, 1)
        execute_widget.setLayout(grid)

        self._create_row()
        self._table.resizeColumnsToContents()

        splitter = QtWidgets.QSplitter()
        splitter.addWidget(self._table)
        splitter.addWidget(execute_widget)
        splitter.setStretchFactor(0, 1)
        splitter.setChildrenCollapsible(False)
        splitter.setSizes([1, 0])

        hbox = QtWidgets.QHBoxLayout()
        hbox.addWidget(splitter)
        self.setLayout(hbox)