def show_record(record): """Create a :class:`QtWidgets.QDialog` to display the information about a record. Parameters ---------- record : :class:`~msl.equipment.record_types.EquipmentRecord` or :class:`~msl.equipment.record_types.ConnectionRecord` An Equipment Record or a Connection Record. """ dialog = QtWidgets.QDialog() dialog.setWindowFlags(QtCore.Qt.WindowCloseButtonHint) dialog.setWindowTitle(record.__class__.__name__.replace('R', ' R')) widget = QtWidgets.QTextEdit() widget.setReadOnly(True) widget.setLineWrapMode(QtWidgets.QTextEdit.NoWrap) widget.setText(record.to_yaml()) hbox = QtWidgets.QHBoxLayout() hbox.addWidget(widget) dialog.setLayout(hbox) size = widget.document().size() sb = widget.horizontalScrollBar().size().height() dialog.resize(int((size.width() + sb) * 1.1), int((size.height() + sb) * 1.1)) # add 10% dialog.exec_()
def show(): app = application() window = QtWidgets.QWidget() window.setWindowTitle('Toggle Switch Example') hbox = QtWidgets.QHBoxLayout() ts = ToggleSwitch(window) ts.toggled.connect(print_state) hbox.addWidget(ts) window.setLayout(hbox) window.show() app.exec_()
def __init__(self, parent=None): super(BlinkingLEDs, self).__init__(parent) self.setWindowTitle('Blinking LEDs') # The shape can be an enum value or member name (case in-sensitive) # The color can be anything that msl.qt.utils.to_qcolor() accepts params = [ { 'shape': LED.Circle, 'on_color': Qt.darkGreen, 'clickable': True }, { 'shape': 'rouNDed', 'on_color': (78, 82, 107) }, { 'shape': 2, 'on_color': 'cyan', 'clickable': True }, { 'shape': 'Triangle', 'on_color': '#6b3064' }, ] self.leds = [] layout = QtWidgets.QHBoxLayout() for kwargs in params: led = LED(**kwargs) led.toggled.connect(self.led_state_changed) led.clicked.connect(self.led_was_clicked) layout.addWidget(led) self.leds.append(led) self.setLayout(layout) self._timer = QtCore.QTimer() self._timer.timeout.connect(self.toggle_random_led) self._timer.start(200)
def show_hardware_info(connection): """Displays the hardware information about a Thorlabs_ :class:`~msl.equipment.resources.thorlabs.kinesis.motion_control.MotionControl` device in a :class:`QtWidgets.QDialog`. Parameters ---------- connection : :class:`~msl.equipment.resources.thorlabs.kinesis.motion_control.MotionControl` A Thorlabs Motion Control subclass. """ info = connection.get_hardware_info() dialog = QtWidgets.QDialog() dialog.setWindowFlags(QtCore.Qt.WindowCloseButtonHint) dialog.setWindowTitle(connection.__class__.__name__) widget = QtWidgets.QTextEdit() widget.setReadOnly(True) widget.setLineWrapMode(QtWidgets.QTextEdit.NoWrap) text = 'Serial Number: {}\n'.format(info.serialNumber) text += 'Model Number: {}\n'.format(info.modelNumber.decode('utf-8')) text += 'Type: {}\n'.format(info.type) text += 'Number of Channels: {}\n'.format(info.numChannels) text += 'Notes: {}\n'.format(info.notes.decode('utf-8')) text += 'Firmware Version: {}\n'.format( connection.to_version(info.firmwareVersion)) text += 'Hardware Version: {}\n'.format( connection.to_version(info.hardwareVersion)) text += 'Modification State: {}'.format(info.modificationState) widget.setText(text) hbox = QtWidgets.QHBoxLayout() hbox.addWidget(widget) dialog.setLayout(hbox) size = widget.document().size() pad = widget.horizontalScrollBar().size().height() * 1.1 dialog.resize(int(size.width() + pad), int(size.height() + pad)) dialog.exec_()
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 __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, client, **kwargs): super(Gui, self).__init__() self.path = kwargs.pop('path', None) self.client = client self.original_image = None self.delta = 0.01 # the amount to translate image on UP DOWN LEFT RIGHT key presses self.client_queue = {} # a queue of requests to send to the RPi zoom = kwargs.get('zoom') if zoom: self.zoom_history = [zoom] # (x, y, width, height) values between 0.0 and 1.0 else: self.zoom_history = [] self.ocr_params = { 'zoom': zoom, 'rotate': kwargs.get('rotate'), 'threshold': kwargs.get('threshold'), 'dilate': kwargs.get('dilate'), 'erode': kwargs.get('erode'), 'blur': kwargs.get('blur'), 'algorithm': kwargs.get('algorithm', 'tesseract').lower(), 'lang': kwargs.get('lang', 'eng').lower(), } self.ocr_label = QtWidgets.QLabel() self.ocr_label.setFont(QtGui.QFont('Helvetica', 14)) # the canvas widget to display the image self.graphics_view = pg.GraphicsView(background=None) self.view_box = pg.ViewBox(invertY=True, lockAspect=True, enableMouse=False, enableMenu=False) self.graphics_view.setCentralItem(self.view_box) self.canvas = pg.ImageItem(axisOrder='row-major') self.view_box.setMouseMode(pg.ViewBox.RectMode) self.view_box.addItem(self.canvas) self.view_box.mouseDragEvent = self.select_zoom graphing_layout = QtWidgets.QVBoxLayout() graphing_layout.addWidget(self.ocr_label, alignment=QtCore.Qt.AlignCenter) graphing_layout.addWidget(self.graphics_view) # the container for all the image-processing widgets self.image_processing_group = QtWidgets.QGroupBox('Image Processing') # rotate self.rotate_label = QtWidgets.QLabel('<html>Rotate [0°]</html>') self.rotate_slider = QtWidgets.QSlider(orientation=QtCore.Qt.Horizontal) self.rotate_slider.setToolTip('The angle to rotate the image') self.rotate_slider.setMinimum(-180) self.rotate_slider.setMaximum(180) self.rotate_slider.setSingleStep(1) self.rotate_slider.setPageStep(15) self.rotate_slider.valueChanged.connect(self.update_rotate) if self.ocr_params['rotate']: self.rotate_slider.setValue(self.ocr_params['rotate']) # Gaussian blur self.blur_label = QtWidgets.QLabel('Gaussian Blur [0]') self.blur_slider = QtWidgets.QSlider(orientation=QtCore.Qt.Horizontal) self.blur_slider.setToolTip('The pixel radius to use for the Gaussian blur') self.blur_slider.setMinimum(0) self.blur_slider.setMaximum(kwargs.pop('max_blur', 9)) self.blur_slider.setSingleStep(1) self.blur_slider.valueChanged.connect(self.update_blur) if self.ocr_params['blur']: self.blur_slider.setValue(self.ocr_params['blur']) # threshold self.threshold_label = QtWidgets.QLabel('Threshold [0]') self.threshold_checkbox = QtWidgets.QCheckBox() self.threshold_checkbox.setToolTip('Apply thresholding?') self.threshold_checkbox.clicked.connect(self.update_threshold_checkbox) self.threshold_slider = QtWidgets.QSlider(orientation=QtCore.Qt.Horizontal) self.threshold_slider.setToolTip('The threshold value') self.threshold_slider.setMinimum(0) self.threshold_slider.setMaximum(255) self.threshold_slider.setSingleStep(1) self.threshold_slider.valueChanged.connect(self.update_threshold) if self.ocr_params['threshold']: self.threshold_slider.setValue(self.ocr_params['threshold']) self.threshold_checkbox.setChecked(True) else: self.threshold_slider.setEnabled(False) self.threshold_checkbox.setChecked(False) # dilate self.dilate_label = QtWidgets.QLabel('Dilate [0]') self.dilate_slider = QtWidgets.QSlider(orientation=QtCore.Qt.Horizontal) self.dilate_spinbox = QtWidgets.QSpinBox() self.dilate_spinbox.setToolTip('The number of iterations to apply dilation at the specified radius') self.dilate_spinbox.setMinimum(1) self.dilate_spinbox.setMaximum(99) self.dilate_spinbox.setSingleStep(1) self.dilate_spinbox.valueChanged.connect(self.update_dilate_iter) self.dilate_slider.setToolTip('The pixel radius to use for dilation') self.dilate_slider.setMinimum(0) self.dilate_slider.setMaximum(kwargs.pop('max_dilate', 9)) self.dilate_slider.setSingleStep(1) self.dilate_slider.valueChanged.connect(self.update_dilate) if self.ocr_params['dilate']: self.dilate_slider.setValue(self.ocr_params['dilate']) # erode self.erode_label = QtWidgets.QLabel('Erode [0]') self.erode_slider = QtWidgets.QSlider(orientation=QtCore.Qt.Horizontal) self.erode_spinbox = QtWidgets.QSpinBox() self.erode_spinbox.setToolTip('The number of iterations to apply erosion at the specified radius') self.erode_spinbox.setMinimum(1) self.erode_spinbox.setMaximum(99) self.erode_spinbox.setSingleStep(1) self.erode_spinbox.valueChanged.connect(self.update_erode_iter) self.erode_slider.setToolTip('The pixel radius to use for erosion') self.erode_slider.setMinimum(0) self.erode_slider.setMaximum(kwargs.pop('max_erode', 9)) self.erode_slider.setSingleStep(1) self.erode_slider.valueChanged.connect(self.update_erode) if self.ocr_params['erode']: self.erode_slider.setValue(self.ocr_params['erode']) # image-processing layout ip_layout = QtWidgets.QGridLayout() ip_layout.addWidget(self.rotate_label, 0, 0) ip_layout.addWidget(self.rotate_slider, 0, 1) ip_layout.addWidget(self.blur_label, 1, 0) ip_layout.addWidget(self.blur_slider, 1, 1) ip_layout.addWidget(self.threshold_label, 2, 0) ip_layout.addWidget(self.threshold_slider, 2, 1) ip_layout.addWidget(self.threshold_checkbox, 2, 2) ip_layout.addWidget(self.dilate_label, 3, 0) ip_layout.addWidget(self.dilate_slider, 3, 1) ip_layout.addWidget(self.dilate_spinbox, 3, 2) ip_layout.addWidget(self.erode_label, 4, 0) ip_layout.addWidget(self.erode_slider, 4, 1) ip_layout.addWidget(self.erode_spinbox, 4, 2) self.image_processing_group.setLayout(ip_layout) # the container for all the camera widgets self.camera_config_group = QtWidgets.QGroupBox('Camera Settings') # ISO self.iso_combobox = QtWidgets.QComboBox() self.iso_combobox.setToolTip('The ISO setting of the camera') self.iso_combobox.addItems(['auto', '100', '200', '320', '400', '500', '640', '800']) iso = str(kwargs.pop('iso', 'auto')) if iso == '0': iso = 'auto' self.iso_combobox.setCurrentText(iso) self.update_iso(self.iso_combobox.currentText()) self.iso_combobox.currentTextChanged.connect(self.update_iso) self.iso_combobox.setEnabled(not self.path) # resolution self.resolution_combobox = QtWidgets.QComboBox() self.resolution_combobox.setToolTip('The resolution of the camera') self.resolution_combobox.addItems(['VGA', 'SVGA', 'XGA', '720p', 'SXGA', 'UXGA', '1080p', 'MAX']) self.resolution_combobox.setCurrentText(str(kwargs.pop('resolution', 'VGA'))) self.update_resolution(self.resolution_combobox.currentText()) self.resolution_combobox.currentTextChanged.connect(self.update_resolution) self.resolution_combobox.setEnabled(not self.path) # exposure mode self.exposure_mode_combobox = QtWidgets.QComboBox() self.exposure_mode_combobox.setToolTip('The exposure mode of the camera') self.exposure_mode_combobox.addItems(['off', 'auto', 'night', 'nightpreview', 'backlight', 'spotlight', 'sports', 'snow', 'beach', 'verylong', 'fixedfps', 'antishake', 'fireworks']) self.exposure_mode_combobox.setCurrentText(str(kwargs.pop('exposure_mode', 'auto'))) self.update_exposure_mode(self.exposure_mode_combobox.currentText()) self.exposure_mode_combobox.currentTextChanged.connect(self.update_exposure_mode) self.exposure_mode_combobox.setEnabled(not self.path) camera_layout = QtWidgets.QGridLayout() camera_layout.addWidget(QtWidgets.QLabel('ISO'), 0, 0) camera_layout.addWidget(self.iso_combobox, 0, 1) camera_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding), 0, 2) camera_layout.addWidget(QtWidgets.QLabel('Resolution'), 1, 0) camera_layout.addWidget(self.resolution_combobox, 1, 1) camera_layout.addWidget(QtWidgets.QLabel('Exposure Mode'), 2, 0) camera_layout.addWidget(self.exposure_mode_combobox, 2, 1) self.camera_config_group.setLayout(camera_layout) if self.client is None: self.iso_combobox.setEnabled(False) self.resolution_combobox.setEnabled(False) self.exposure_mode_combobox.setEnabled(False) # the container for all the OCR algorithm widgets self.ocr_config_group = QtWidgets.QGroupBox('OCR Algorithm Settings') # tesseract languages self.tess_lang_combobox = QtWidgets.QComboBox() self.tess_lang_combobox.addItems(['eng', 'letsgodigital']) self.tess_lang_combobox.currentTextChanged.connect(self.update_tess_lang) self.tess_lang_combobox.setToolTip('The language to use for Tesseract') # tesseract or ssocr self.tess_radio = QtWidgets.QRadioButton('Tesseract') self.tess_radio.setToolTip('Use Tesseract') self.tess_radio.toggled.connect(self.update_algorithm) self.ssocr_radio = QtWidgets.QRadioButton('SSOCR') self.ssocr_radio.setToolTip('Use SSOCR') self.ssocr_radio.toggled.connect(self.update_algorithm) if self.ocr_params['algorithm'] == 'ssocr': self.ssocr_radio.setChecked(True) else: self.tess_radio.setChecked(True) algo_layout = QtWidgets.QGridLayout() algo_layout.addWidget(self.tess_radio, 0, 0) algo_layout.addWidget(self.tess_lang_combobox, 0, 1) algo_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding), 0, 2) algo_layout.addWidget(self.ssocr_radio, 1, 0) self.ocr_config_group.setLayout(algo_layout) options_layout = QtWidgets.QVBoxLayout() options_layout.addWidget(self.image_processing_group) options_layout.addWidget(self.camera_config_group) options_layout.addWidget(self.ocr_config_group) options_layout.addStretch(1) layout = QtWidgets.QHBoxLayout() layout.addLayout(graphing_layout) layout.addLayout(options_layout) self.setLayout(layout) if self.path: self.setAcceptDrops(True) self.capture_thread = None self.original_image = utils.to_cv2(self.path) height, width = self.original_image.shape[:2] try: # could pass in an already-opened image object (which isn't a path) basename = os.path.basename(self.path) except OSError: basename = 'UNKNOWN' self.setWindowTitle('OCR || {} [{} x {}]'.format(basename, width, height)) else: self.setAcceptDrops(False) self.original_image = None self.capture_index = 0 self.setWindowTitle('OCR || Capture 0') self.capture_thread = Capture() self.capture_thread.add_callback(self.capture) self.capture_thread.start(self.client) self.apply_ocr()
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)