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)
def __init__(self, parent=None): """A :class:`~QtWidgets.QWidget` to view a :ref:`Configuration File <msl.equipment:configuration_file>`. Parameters ---------- parent : :class:`QtWidgets.QWidget`, optional The parent :class:`QtWidgets.QWidget`. Example ------- To view an example of the :class:`ConfigurationViewer`, run: >>> from msl.examples.qt.equipment import configuration_viewer # doctest: +SKIP >>> configuration_viewer.show() # doctest: +SKIP """ super(ConfigurationViewer, self).__init__(parent=parent) if not has_msl_equipment: raise ImportError( 'This class requires that MSL Equipment is installed') self.setAcceptDrops(True) self._dropped_path = None self._database = None # # selecting a configuration file # browse = Button(icon=QtWidgets.QStyle.SP_DialogOpenButton) browse.setToolTip('Select a configuration file') browse.set_left_click(self._browse_file) self._filebox = QtWidgets.QLineEdit() self._filebox.setToolTip('Drag \'n drop a configuration file') self._filebox.setReadOnly(True) select_layout = QtWidgets.QHBoxLayout() select_layout.addWidget(browse) select_layout.addWidget(self._filebox) select_layout.setSpacing(1) # # the filter field # self._filter = QtWidgets.QLineEdit() self._filter.setToolTip('Search filter for the database') self._filter.returnPressed.connect(self._apply_filter) filter_button = Button(icon=QtWidgets.QStyle.SP_FileDialogContentsView, tooltip='Apply filter') filter_button.set_left_click(self._apply_filter) clear_button = Button(icon=QtWidgets.QStyle.SP_LineEditClearButton, tooltip='Clear filter') clear_button.set_left_click(self._clear_filter) filter_layout = QtWidgets.QHBoxLayout() filter_layout.addWidget(filter_button) filter_layout.addWidget(self._filter) filter_layout.addWidget(clear_button) filter_layout.setSpacing(1) # # the Tree and Tables # self._equipment_records_table = _RecordTable(EquipmentRecord, self) self._connection_records_table = _RecordTable(ConnectionRecord, self) self._equipment_table = _RecordTable(EquipmentRecord, self, is_dict=True) self._constants_table = _ConstantsTable(self) self._tree = _Tree(self._equipment_records_table, self._connection_records_table) self._tree.sig_selected.connect(self._tree_item_selected) self._tree.setToolTip( 'Double click an item to select it.\n\nHold the CTRL key to select multiple items.' ) tab = QtWidgets.QTabWidget() tab.addTab(self._equipment_records_table, 'Equipment Records') tab.addTab(self._connection_records_table, 'Connection Records') tab.addTab(self._equipment_table, 'Equipment Tags') tab.addTab(self._constants_table, 'Constants') tab.addTab(Logger(), 'Log') splitter = QtWidgets.QSplitter() splitter.addWidget(self._tree) splitter.addWidget(tab) splitter.setStretchFactor(1, 1) # the tab expands to fill the full width splitter.setSizes((self._tree.sizeHint().width() * 1.1, 1)) main_layout = QtWidgets.QVBoxLayout() main_layout.addLayout(select_layout) main_layout.addLayout(filter_layout) main_layout.addWidget(splitter) self.setLayout(main_layout)