def setHeaderIcon(self): """Updates header icons to match data enabled state""" if np.all(self._data.enabled): self.header_icon = path_for('checked.png') elif np.any(self._data.enabled): self.header_icon = path_for('intermediate.png') else: self.header_icon = path_for('unchecked.png') self.headerDataChanged.emit(QtCore.Qt.Horizontal, 3, 3)
def __init__(self, parent): super().__init__(parent) self.parent = parent self.parent_model = parent.presenter.model self.parent.scenes.switchToSampleScene() layout = QtWidgets.QHBoxLayout() self.list_widget = QtWidgets.QListWidget() self.list_widget.setAlternatingRowColors(True) self.list_widget.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection) self.list_widget.setMinimumHeight(300) self.list_widget.setSpacing(2) self.list_widget.itemSelectionChanged.connect(self.onMultiSelection) self.updateSampleList() layout.addWidget(self.list_widget) button_layout = QtWidgets.QVBoxLayout() self.delete_button = create_tool_button( icon_path=path_for('cross.png'), style_name='ToolButton', tooltip='Delete Sample', status_tip='Remove selected sample from project') self.delete_button.clicked.connect(self.removeSamples) button_layout.addWidget(self.delete_button) self.merge_button = create_tool_button( icon_path=path_for('merge.png'), style_name='ToolButton', tooltip='Merge Samples', status_tip= 'Combine vertices of selected samples to form single sample') self.merge_button.clicked.connect(self.mergeSamples) button_layout.addWidget(self.merge_button) self.priority_button = create_tool_button( icon_path=path_for('check.png'), style_name='ToolButton', tooltip='Set Main Sample', status_tip='Set selected sample as main sample') self.priority_button.clicked.connect(self.changeMainSample) button_layout.addWidget(self.priority_button) layout.addSpacing(10) layout.addLayout(button_layout) main_layout = QtWidgets.QVBoxLayout() main_layout.addLayout(layout) main_layout.addStretch(1) self.setLayout(main_layout) self.parent_model.sample_changed.connect(self.updateSampleList) self.title = 'Samples' self.setMinimumWidth(450)
def updateSampleList(self): """Updates the sample keys in the list widget""" self.list_widget.clear() samples = self.parent_model.sample.keys() if samples: self.list_widget.addItems(samples) self.list_widget.item(0).setIcon(QtGui.QIcon( path_for('check.png')))
def createPositionerForm(self): """Creates the form inputs for the detector positioner""" title = FormTitle('Detector Position') self.main_layout.addWidget(title) self.position_form_group = FormGroup(FormGroup.Layout.Grid) for index, link in enumerate(self.detector.positioner.links): if link.type == Link.Type.Revolute: unit = 'degrees' offset = math.degrees(link.set_point) lower_limit = math.degrees(link.lower_limit) upper_limit = math.degrees(link.upper_limit) else: unit = 'mm' offset = link.set_point lower_limit = link.lower_limit upper_limit = link.upper_limit pretty_label = link.name.replace('_', ' ').title() control = FormControl(pretty_label, offset, desc=unit, required=True, number=True) control.form_lineedit.setDisabled(link.locked) if not link.ignore_limits: control.range(lower_limit, upper_limit) limits_button = create_tool_button( tooltip='Disable Joint Limits', style_name='MidToolButton', icon_path=path_for('limit.png'), checkable=True, status_tip=f'Ignore joint limits of {pretty_label}', checked=link.ignore_limits) limits_button.clicked.connect(self.ignoreJointLimits) limits_button.setProperty('link_index', index) control.extra = [limits_button] self.position_form_group.addControl(control) self.position_form_group.group_validation.connect( self.formValidation) self.main_layout.addWidget(self.position_form_group) button_layout = QtWidgets.QHBoxLayout() self.move_detector_button = QtWidgets.QPushButton('Move Detector') self.move_detector_button.clicked.connect( self.moveDetectorsButtonClicked) button_layout.addWidget(self.move_detector_button) button_layout.addStretch(1) self.main_layout.addLayout(button_layout)
def createPositionerForm(self): """Creates the form inputs for the jaw positioner""" title = FormTitle(f'{self.instrument.jaws.name} Position') self.main_layout.addWidget(title) self.position_form_group = FormGroup(FormGroup.Layout.Grid) for index in self.instrument.jaws.positioner.order: link = self.instrument.jaws.positioner.links[index] if link.type == Link.Type.Revolute: unit = 'degrees' offset = math.degrees(link.set_point) lower_limit = math.degrees(link.lower_limit) upper_limit = math.degrees(link.upper_limit) else: unit = 'mm' offset = link.set_point lower_limit = link.lower_limit upper_limit = link.upper_limit control = FormControl(link.name.title(), offset, desc=unit, required=True, number=True) control.form_lineedit.setDisabled(link.locked) if not link.ignore_limits: control.range(lower_limit, upper_limit) limits_button = create_tool_button( tooltip='Disable Joint Limits', style_name='MidToolButton', icon_path=path_for('limit.png'), checkable=True, status_tip=f'Ignore joint limits of {link.name}', checked=link.ignore_limits) limits_button.clicked.connect(self.ignoreJointLimits) limits_button.setProperty('link_index', index) control.extra = [limits_button] self.position_form_group.addControl(control) self.position_form_group.group_validation.connect( self.formValidation) self.main_layout.addWidget(self.position_form_group) button_layout = QtWidgets.QHBoxLayout() self.move_jaws_button = QtWidgets.QPushButton('Move Jaws') self.move_jaws_button.clicked.connect(self.moveJawsButtonClicked) button_layout.addWidget(self.move_jaws_button) button_layout.addStretch(1) self.main_layout.addLayout(button_layout)
def __init__(self): super().__init__() self.filename = '' self.saved_text = '' self.initialized = False self.file_watcher = QtCore.QFileSystemWatcher() self.file_watcher.directoryChanged.connect( lambda: self.lazyInstrumentUpdate()) self.controls = Controls(self) self.main_splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical) self.setCentralWidget(self.main_splitter) self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal) self.splitter.setChildrenCollapsible(False) self.main_splitter.addWidget(self.splitter) self.main_splitter.setStretchFactor(0, 2) self.message = QtWidgets.QTextEdit('') self.message.setReadOnly(True) self.message.setFontFamily('courier') self.message.setStyleSheet( 'QTextEdit {background-color: white; color: red; font-size: 12px; ' 'padding-left: 10px; background-position: top left}') self.message.setMinimumHeight(100) self.main_splitter.addWidget(self.message) self.gl_widget = OpenGLRenderer(self) self.gl_widget.custom_error_handler = self.sceneSizeErrorHandler self.scene = SceneManager(self, self.gl_widget, False) self.scene.changeVisibility(Attributes.Beam, True) self.animate_instrument.connect(self.scene.animateInstrument) self.editor = Editor(self) self.editor.textChanged.connect(self.lazyInstrumentUpdate) self.splitter.addWidget(self.gl_widget) self.splitter.addWidget(self.editor) self.setMinimumSize(1024, 800) self.setTitle() self.setWindowIcon(QtGui.QIcon(path_for('editor-logo.png'))) self.initActions() self.initMenus() self.timer = QtCore.QTimer() self.timer.timeout.connect(self.useWorker) self.worker = InstrumentWorker(self)
def createPositionerWidget(self, positioner, add_base_button=False): """Creates the form widget for the given positioner :param positioner: serial manipulator :type positioner: SerialManipulator :param add_base_button: indicates base button should be shown :type add_base_button: bool :return: positioner widget :rtype: QtWidgets.QWidget """ widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) title = FormTitle(positioner.name) layout.addWidget(title) if add_base_button: base_button = create_tool_button(tooltip='Change Base Matrix', style_name='MidToolButton') import_base_action = QtWidgets.QAction('Import Base Matrix', self) import_base_action.setStatusTip( f'Import base transformation matrix for {positioner.name}') import_base_action.triggered.connect( lambda ignore, n=positioner.name: self.importPositionerBase(n)) compute_base_action = QtWidgets.QAction('Calculate Base Matrix', self) compute_base_action.setStatusTip( f'Calculate base transformation matrix for {positioner.name}') compute_base_action.triggered.connect( lambda ignore, n=positioner.name: self.computePositionerBase(n )) export_base_action = QtWidgets.QAction('Export Base Matrix', self) export_base_action.setStatusTip( f'Export base transformation matrix for {positioner.name}') export_base_action.triggered.connect( lambda ignore, n=positioner.name: self.exportPositionerBase(n)) base_button.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup) base_button.addActions( [import_base_action, compute_base_action, export_base_action]) base_button.setDefaultAction(import_base_action) base_button.setIcon(QtGui.QIcon(path_for('base.png'))) title.addHeaderControl(base_button) reset_button = create_tool_button( tooltip='Reset Base Matrix', style_name='MidToolButton', status_tip= f'Reset base transformation matrix of {positioner.name}', icon_path=path_for('refresh.png'), hide=True) reset_button.clicked.connect( lambda ignore, n=positioner.name: self.resetPositionerBase(n)) title.addHeaderControl(reset_button) reset_button.setVisible( positioner.base is not positioner.default_base) self.base_reset_buttons[positioner.name] = reset_button form_group = FormGroup(FormGroup.Layout.Grid) order_offset = len(self.positioner_form_controls) for index in positioner.order: link = positioner.links[index] if link.type == Link.Type.Revolute: unit = 'degrees' offset = math.degrees(link.set_point) lower_limit = math.degrees(link.lower_limit) upper_limit = math.degrees(link.upper_limit) else: unit = 'mm' offset = link.set_point lower_limit = link.lower_limit upper_limit = link.upper_limit control = FormControl(link.name.title(), offset, desc=unit, required=True, number=True) control.form_lineedit.setDisabled(link.locked) if not link.ignore_limits: control.range(lower_limit, upper_limit) lock_button = create_tool_button( tooltip='Lock Joint', style_name='MidToolButton', status_tip=f'Lock {link.name} joint in {positioner.name}', icon_path=path_for('lock.png'), checkable=True, checked=link.locked) lock_button.clicked.connect(self.lockJoint) lock_button.setProperty('link_index', index + order_offset) limits_button = create_tool_button( tooltip='Disable Joint Limits', style_name='MidToolButton', status_tip=f'Ignore joint limits of {link.name}', icon_path=path_for('limit.png'), checkable=True, checked=link.ignore_limits) limits_button.clicked.connect(self.ignoreJointLimits) limits_button.setProperty('link_index', index + order_offset) control.extra = [lock_button, limits_button] form_group.addControl(control) form_group.group_validation.connect(self.formValidation) self.positioner_form_controls.append(control) layout.addWidget(form_group) widget.setLayout(layout) self.positioner_forms.append(form_group) return widget
def __init__(self, parent): super().__init__(parent) self.parent = parent self.parent_model = parent.presenter.model self.parent.scenes.switchToSampleScene() self.main_layout = QtWidgets.QVBoxLayout() layout = QtWidgets.QHBoxLayout() layout.addWidget(QtWidgets.QLabel('Alignment:')) self.alignment_combobox = QtWidgets.QComboBox() self.alignment_combobox.setView(QtWidgets.QListView()) self.alignment_combobox.activated.connect(self.onComboBoxActivated) layout.addWidget(self.alignment_combobox, 4) layout.addSpacing(10) self.detector_combobox = QtWidgets.QComboBox() self.detector_combobox.setView(QtWidgets.QListView()) self.detector_combobox.addItems( list(self.parent_model.instrument.detectors.keys())) self.detector_combobox.activated.connect(self.onComboBoxActivated) if len(self.parent_model.instrument.detectors) > 1: layout.addWidget(QtWidgets.QLabel('Detector:')) layout.addWidget(self.detector_combobox, 4) size = self.detector_combobox.iconSize() self.detector_combobox.setItemIcon( 0, create_icon(settings.value(settings.Key.Vector_1_Colour), size)) self.detector_combobox.setItemIcon( 1, create_icon(settings.value(settings.Key.Vector_2_Colour), size)) self.delete_vector_action = QtWidgets.QAction("Delete Vectors", self) self.delete_vector_action.triggered.connect(self.deleteVectors) self.delete_vector_action.setStatusTip( 'Remove (zero) selected vectors or all vectors in current alignment' ) self.delete_alignment_action = QtWidgets.QAction( "Delete Alignment", self) self.delete_alignment_action.triggered.connect(self.deleteAlignment) self.delete_alignment_action.setStatusTip( 'Remove selected vector alignment') delete_menu = QtWidgets.QMenu() delete_menu.addAction(self.delete_vector_action) delete_menu.addAction(self.delete_alignment_action) self.delete_alignment_button = create_tool_button( icon_path=path_for('cross.png'), style_name='ToolButton', status_tip='Remove measurement vectors or alignments') self.delete_alignment_button.setPopupMode( QtWidgets.QToolButton.InstantPopup) self.delete_alignment_button.setMenu(delete_menu) layout.addStretch(1) layout.addWidget(self.delete_alignment_button) layout.setAlignment(self.delete_alignment_button, QtCore.Qt.AlignBottom) self.main_layout.addLayout(layout, 0) self.table = QtWidgets.QTableWidget() self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.table.setColumnCount(3) self.table.setHorizontalHeaderLabels(['X', 'Y', 'Z']) self.table.setAlternatingRowColors(True) self.table.setMinimumHeight(300) self.table.setMaximumHeight(500) self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) self.table.horizontalHeader().setSectionResizeMode( QtWidgets.QHeaderView.Stretch) self.table.horizontalHeader().setMinimumSectionSize(40) self.table.horizontalHeader().setDefaultSectionSize(40) self.updateWidget() self.main_layout.addWidget(self.table, 20) self.main_layout.addStretch(1) self.setLayout(self.main_layout) self.title = 'Measurement Vectors' self.setMinimumWidth(450) self.parent_model.measurement_vectors_changed.connect( self.updateWidget) self.parent.scenes.rendered_alignment_changed.connect( self.updateWidget)
def __init__(self, point_type, parent): super().__init__(parent) self.parent = parent self.parent_model = parent.presenter.model self.parent.scenes.switchToSampleScene() self.point_type = point_type self.attribute = Attributes.Fiducials if point_type == PointType.Fiducial else Attributes.Measurements self.selected = None layout = QtWidgets.QHBoxLayout() self.table_view = QtWidgets.QTableView() self.table_model = PointModel(self.points.copy()) self.table_model.edit_completed.connect(self.editPoints) self.table_view.setItemDelegate(LimitTextDelegate()) self.table_view.horizontalHeader().sectionClicked.connect( self.table_model.toggleCheckState) self.table_view.setModel(self.table_model) self.table_view.setSelectionBehavior( QtWidgets.QAbstractItemView.SelectRows) self.table_view.setAlternatingRowColors(True) self.table_view.setMinimumHeight(300) self.table_view.horizontalHeader().setSectionResizeMode( QtWidgets.QHeaderView.Stretch) self.table_view.horizontalHeader().setSectionResizeMode( 3, QtWidgets.QHeaderView.Fixed) self.table_view.horizontalHeader().setMinimumSectionSize(40) self.table_view.horizontalHeader().setDefaultSectionSize(40) layout.addWidget(self.table_view) button_layout = QtWidgets.QVBoxLayout() self.delete_button = create_tool_button( icon_path=path_for('cross.png'), style_name='ToolButton', tooltip='Delete Points', status_tip='Remove selected points from project') self.delete_button.clicked.connect(self.deletePoints) button_layout.addWidget(self.delete_button) self.move_up_button = create_tool_button( icon_path=path_for('arrow-up.png'), style_name='ToolButton', tooltip='Move Point Index Up', status_tip='Swap point index with previous point') self.move_up_button.clicked.connect(lambda: self.movePoint(-1)) button_layout.addWidget(self.move_up_button) self.move_down_button = create_tool_button( icon_path=path_for('arrow-down.png'), style_name='ToolButton', tooltip='Move Point Index Down', status_tip='Swap point index with next point') self.move_down_button.clicked.connect(lambda: self.movePoint(1)) button_layout.addWidget(self.move_down_button) layout.addSpacing(10) layout.addLayout(button_layout) self.main_layout = QtWidgets.QVBoxLayout() self.main_layout.addLayout(layout) self.main_layout.addStretch(1) self.setLayout(self.main_layout) self.title = f'{self.point_type.value} Points' self.setMinimumWidth(450) self.table_view.selectionModel().selectionChanged.connect( self.onMultiSelection) if self.point_type == PointType.Fiducial: self.parent_model.fiducials_changed.connect(self.updateTable) elif self.point_type == PointType.Measurement: self.parent_model.measurement_points_changed.connect( self.updateTable)
def __init__(self, sample, parent): super().__init__() self.parent = parent self.main_layout = QtWidgets.QVBoxLayout() self.main_layout.setContentsMargins(0, 0, 0, 0) self.vertices = None self.initial_plane = None self.final_plane_normal = None layout = QtWidgets.QHBoxLayout() self.table_widget = QtWidgets.QTableWidget() self.table_widget.setShowGrid(False) self.table_widget.setAlternatingRowColors(True) self.table_widget.setEditTriggers( QtWidgets.QAbstractItemView.NoEditTriggers) self.table_widget.setColumnCount(3) self.table_widget.setFixedHeight(150) self.table_widget.verticalHeader().setVisible(False) self.table_widget.setHorizontalHeaderLabels(['X', 'Y', 'Z']) self.table_widget.setSelectionBehavior( QtWidgets.QAbstractItemView.SelectRows) self.table_widget.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection) self.table_widget.selectionModel().selectionChanged.connect( self.selection) self.table_widget.horizontalHeader().setSectionResizeMode( QtWidgets.QHeaderView.Stretch) layout.addWidget(self.table_widget) button_layout = QtWidgets.QVBoxLayout() self.select_button = create_tool_button( icon_path=path_for('select.png'), checkable=True, checked=True, status_tip='Normal scene manipulation with the mouse', tooltip='Normal Mode', style_name='ToolButton') self.select_button.clicked.connect(lambda: self.togglePicking(False)) button_layout.addWidget(self.select_button) self.pick_button = create_tool_button( icon_path=path_for('point.png'), checkable=True, status_tip='Select 3D points that define the plane', tooltip='Pick Point Mode', style_name='ToolButton') self.pick_button.clicked.connect(lambda: self.togglePicking(True)) button_layout.addWidget(self.pick_button) self.delete_button = create_tool_button( icon_path=path_for('cross.png'), style_name='ToolButton', status_tip='Remove selected points from the scene', tooltip='Delete Points') self.delete_button.clicked.connect(self.removePicks) button_layout.addWidget(self.delete_button) layout.addSpacing(10) layout.addLayout(button_layout) self.main_layout.addLayout(layout) self.main_layout.addSpacing(10) self.main_layout.addWidget(QtWidgets.QLabel('Select Final Plane:')) self.plane_combobox = QtWidgets.QComboBox() self.plane_combobox.setView(QtWidgets.QListView()) self.plane_combobox.addItems([p.value for p in PlaneOptions]) self.plane_combobox.currentTextChanged.connect(self.setPlane) self.main_layout.addWidget(self.plane_combobox) self.createCustomPlaneBox() self.setPlane(self.plane_combobox.currentText()) button_layout = QtWidgets.QHBoxLayout() self.execute_button = QtWidgets.QPushButton('Align Planes') self.execute_button.clicked.connect(self.executeButtonClicked) button_layout.addWidget(self.execute_button) button_layout.addStretch(1) self.main_layout.addLayout(button_layout) self.main_layout.addStretch(1) self.setLayout(self.main_layout) self.parent.gl_widget.pick_added.connect(self.addPicks) self.selected_sample = sample