class TriggeredAcquisition(BaseWidget): def __init__(self, parent=None, prefix='', bpm=''): super().__init__(parent=parent, prefix=prefix, bpm=bpm) self.setupui() mode = SiriusConnectionSignal(self.get_pvname('ACQBPMMode-Sts')) mode.new_value_signal[int].connect(self.toggle_multi_single) self._chans.append(mode) def setupui(self): vbl = QGridLayout(self) lab = QLabel('<h2>' + self.bpm + ' Triggered Acquisitions</h2>') lab.setAlignment(Qt.AlignCenter) vbl.addWidget(lab, 0, 0, 1, 2) self.stack = QStackedLayout() multi_pass = MultiTurnData(parent=self, acq_type='ACQ', prefix=self.prefix, bpm=self.bpm) multi_pass.setObjectName('multi_pass') single_pass = SinglePassData(parent=self, prefix=self.prefix, bpm=self.bpm) single_pass.setObjectName('single_pass') self.stack.addWidget(multi_pass) self.stack.addWidget(single_pass) vbl.addLayout(self.stack, 1, 0) config = ACQTrigConfigs(parent=self, prefix=self.prefix, bpm=self.bpm, data_prefix='ACQ') config.setObjectName('config') vbl.addWidget(config, 1, 1) self.setStyleSheet(""" #multi_pass{ min-width:50em; min-height:48em;} #single_pass{ min-width:50em; min-height:48em;} #config{ min-height:21em;}""") def toggle_multi_single(self, modeidx): self.stack.setCurrentIndex(modeidx)
def __init__(self, parent=None): super(RedisEditor, self).__init__(parent) self.empty = QWidget(self) self.item = RedisItemEditor(self) self.db = RedisDbEditor(self) self.db.setWindowFlags(Qt.Widget) layout = QStackedLayout(self) layout.addWidget(self.empty) layout.addWidget(self.item) layout.addWidget(self.db)
def __init__(self, parent=None): super(RedisItemEditor, self).__init__(parent) self.load_ui() self.__original_item = None self.__item = None ui = self.ui layout = QStackedLayout(ui.type_editor) layout.setContentsMargins(3, 3, 3, 3) self.none_editor = QWidget() self.simple_editor = SimpleEditor() self.hash_editor = MultiEditor() self.seq_editor = MultiEditor() self.seq_editor.ui.table.horizontalHeader().setVisible(False) self.set_editor = MultiEditor() self.set_editor.ui.table.horizontalHeader().setVisible(False) layout.addWidget(self.none_editor) layout.addWidget(self.simple_editor) layout.addWidget(self.hash_editor) layout.addWidget(self.seq_editor) layout.addWidget(self.set_editor) self.type_editor_map = { "none": self.none_editor, "string": self.simple_editor, "hash": self.hash_editor, "list": self.seq_editor, "set": self.set_editor, } ttl_validator = QIntValidator() ttl_validator.setBottom(-1) ui.ttl_value.setValidator(ttl_validator) ui.key_name.textChanged.connect(self.__on_key_name_changed) ui.key_name.returnPressed.connect(self.__on_key_name_applied) ui.ttl_value.textChanged.connect(self.__on_ttl_changed) ui.ttl_value.returnPressed.connect(self.__on_ttl_applied) ui.apply_button.clicked.connect(self.__on_apply) ui.refresh_button.clicked.connect(self.__on_refresh) ui.undo_button.clicked.connect(self.__on_undo) ui.persist_button.clicked.connect(self.__on_persist) ui.delete_button.clicked.connect(self.__on_delete)
class AlgorithmChoose(QWidget): finished = Signal() started = Signal() result = Signal(SegmentationResult) value_changed = Signal() progress_signal = Signal(str, int) algorithm_changed = Signal(str) def __init__( self, settings: BaseSettings, algorithms: typing.Dict[str, typing.Type[SegmentationAlgorithm]], parent=None ): super().__init__(parent) self.settings = settings self.algorithms = algorithms settings.algorithm_changed.connect(self.updated_algorithm) self.stack_layout = QStackedLayout() self.algorithm_choose = QComboBox() self.algorithm_dict: typing.Dict[str, BaseAlgorithmSettingsWidget] = {} self.algorithm_choose.currentTextChanged.connect(self.change_algorithm) self.add_widgets_to_algorithm() self.settings.image_changed.connect(self.image_changed) # self.setMinimumWidth(370) self.setContentsMargins(0, 0, 0, 0) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.algorithm_choose) layout.addLayout(self.stack_layout) self.setLayout(layout) def add_widgets_to_algorithm(self): self.algorithm_choose.blockSignals(True) self.algorithm_choose.clear() for name, val in self.algorithms.items(): self.algorithm_choose.addItem(name) widget = InteractiveAlgorithmSettingsWidget(self.settings, name, val, []) self.algorithm_dict[name] = widget widget.algorithm_thread.execution_done.connect(self.result.emit) widget.algorithm_thread.finished.connect(self.finished.emit) widget.algorithm_thread.started.connect(self.started.emit) widget.algorithm_thread.progress_signal.connect(self.progress_signal.emit) widget.values_changed.connect(self.value_changed.emit) self.stack_layout.addWidget(widget) name = self.settings.get("current_algorithm", "") self.algorithm_choose.blockSignals(False) if name: self.algorithm_choose.setCurrentText(name) def reload(self, algorithms=None): if algorithms is not None: self.algorithms = algorithms for _ in range(self.stack_layout.count()): widget: InteractiveAlgorithmSettingsWidget = self.stack_layout.takeAt(0).widget() widget.algorithm_thread.execution_done.disconnect() widget.algorithm_thread.finished.disconnect() widget.algorithm_thread.started.disconnect() widget.algorithm_thread.progress_signal.disconnect() widget.values_changed.disconnect() self.algorithm_dict = {} self.add_widgets_to_algorithm() def updated_algorithm(self): self.change_algorithm( self.settings.last_executed_algorithm, self.settings.get(f"algorithms.{self.settings.last_executed_algorithm}"), ) def recursive_get_values(self): result = {} for key, widget in self.algorithm_dict.items(): result[key] = widget.recursive_get_values() self.settings.set("algorithm_widget_state", update(self.settings.get("algorithm_widget_state", dict), result)) return result def change_algorithm(self, name, values: dict = None): self.settings.set("current_algorithm", name) widget = self.stack_layout.currentWidget() self.blockSignals(True) if name != widget.name: widget = self.algorithm_dict[name] self.stack_layout.setCurrentWidget(widget) widget.image_changed(self.settings.image) if hasattr(widget, "set_mask") and hasattr(self.settings, "mask"): widget.set_mask(self.settings.mask) elif values is None: self.blockSignals(False) return if values is not None: widget.set_values(values) self.algorithm_choose.setCurrentText(name) self.blockSignals(False) self.algorithm_changed.emit(name) def image_changed(self): current_widget: InteractiveAlgorithmSettingsWidget = self.stack_layout.currentWidget() if hasattr(self.settings, "mask") and hasattr(current_widget, "change_mask"): current_widget.change_mask() current_widget.image_changed(self.settings.image) def mask_changed(self): current_widget: InteractiveAlgorithmSettingsWidget = self.stack_layout.currentWidget() if hasattr(self.settings, "mask") and hasattr(current_widget, "change_mask"): current_widget.change_mask() def current_widget(self) -> InteractiveAlgorithmSettingsWidget: return self.stack_layout.currentWidget() def current_parameters(self) -> SegmentationProfile: widget = self.current_widget() return SegmentationProfile("", widget.name, widget.get_values()) def get_info_text(self): return self.current_widget().algorithm_thread.get_info_text()
class AlarmTreeEditorDisplay(Display): def __init__(self, parent=None): super(AlarmTreeEditorDisplay, self).__init__(parent=parent) self.app = QApplication.instance() # set up the ui self.setup_ui() # allow add and remove row self.add_button.clicked.connect(self.insertChild) self.remove_button.clicked.connect(self.removeItem) self.remove_button.setEnabled(True) # connect save changes self.button_box.accepted.connect(self.save_property_changes) # upon tree view selection, change the item view self.tree_view.selectionModel().selectionChanged.connect( self.handle_selection) self.tree_view.tree_model.dataChanged.connect(self.item_change) self.file_dialog = QFileDialog() self.open_config_action = QAction("Open", self) self.open_config_action.triggered.connect(self.open_file) self.toolbar.addAction(self.open_config_action) self.save_config_action = QAction("Save", self) self.save_config_action.triggered.connect(self.save_configuration) self.toolbar.addAction(self.save_config_action) # update configuration name self.tree_label.editingFinished.connect(self._update_config_name) # default open size self.resize(800, 600) self.config_tool = PhoebusConfigTool() def setup_ui(self): self.main_layout = QGridLayout() self.setLayout(self.main_layout) # add toolbar self.toolbar = QToolBar() self.main_layout.setMenuBar(self.toolbar) # create the tree view layout and add/remove buttons self.tree_view_layout = QVBoxLayout() self.tree_view = PyDMAlarmTree(self, config_name="UNITITLED", edit_mode=True) self.tree_view.setEditTriggers(QAbstractItemView.DoubleClicked) self.tree_view.setSelectionMode(QAbstractItemView.SingleSelection) self.tree_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.tree_view.setHeaderHidden(True) # Drag/drop self.tree_view.setDragDropMode(QAbstractItemView.InternalMove) self.tree_view.setDragEnabled(True) self.tree_view.setAcceptDrops(True) # view sizing self.tree_view.setColumnWidth(0, 160) self.tree_view.setColumnWidth(1, 160) self.tree_view.setColumnWidth(2, 160) # lable for tree view configuration_indicator = QLabel("Configuration:") self.tree_label = QLineEdit("Untitled") self.tree_label_layout = QHBoxLayout() self.tree_label_layout.addWidget(configuration_indicator) self.tree_label_layout.addWidget(self.tree_label) self.tree_view_layout.addLayout(self.tree_label_layout) self.tree_view_layout.addWidget(self.tree_view) # add/ remove buttons self.add_remove_layout = QHBoxLayout() spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.add_remove_layout.addItem(spacer) self.add_button = QPushButton("New", self) self.add_remove_layout.addWidget(self.add_button) self.remove_button = QPushButton("Remove", self) self.add_remove_layout.addWidget(self.remove_button) self.tree_view_layout.addLayout(self.add_remove_layout) # add the tree view to the window self.main_layout.addLayout(self.tree_view_layout, 0, 0) self.property_layout = QVBoxLayout() self.property_layout.addWidget(QLabel("Alarm Properties")) # crate property view self.property_data_layout = QStackedLayout() self.property_layout.addLayout(self.property_data_layout) self.property_widget_config = QWidget() self.property_widget_config.setWindowTitle("config") # create group widget self.property_widget_group = QWidget() self.property_widget_group.setWindowTitle("group") self.property_view_layout_group = QGridLayout() # add label self.label_edit_group = QLineEdit() self.label_label_group = QLabel("NAME") # add guidance self.guidance_edit_group = QLineEdit() self.guidance_label_group = QLabel("GUIDANCE") self.property_view_layout_group.addWidget(self.label_label_group, 1, 0) self.property_view_layout_group.addWidget(self.label_edit_group, 1, 1) self.property_view_layout_group.addWidget(self.guidance_label_group, 2, 0) self.property_view_layout_group.addWidget(self.guidance_edit_group, 2, 1) spacer = QSpacerItem(40, 200, QSizePolicy.Expanding, QSizePolicy.Minimum) self.property_view_layout_group.addItem(spacer, 3, 0) self.property_view_layout_group.addItem(spacer, 4, 0) self.property_view_layout_group.addItem(spacer, 5, 0) self.property_view_layout_group.addItem(spacer, 6, 0) self.property_view_layout_group.addItem(spacer, 7, 0) self.property_view_layout_group.addItem(spacer, 8, 0) # create pv widget self.property_widget_pv = QWidget() self.property_widget_pv.setWindowTitle("pv") self.property_view_layout_pv = QGridLayout() # add label self.label_edit_pv = QLineEdit() self.label_label_pv = QLabel("NAME") # add guidance self.guidance_edit_pv = QLineEdit() self.guidance_label_pv = QLabel("GUIDANCE") self.property_view_layout_pv.addWidget(self.label_label_pv, 1, 0) self.property_view_layout_pv.addWidget(self.label_edit_pv, 1, 1, 1, 3) self.property_view_layout_pv.addWidget(self.guidance_label_pv, 2, 0) self.property_view_layout_pv.addWidget(self.guidance_edit_pv, 2, 1, 1, 3) # add description self.description_edit = QLineEdit() self.description_label = QLabel("DESCRIPTION") self.property_view_layout_pv.addWidget(self.description_label, 3, 0) self.property_view_layout_pv.addWidget(self.description_edit, 3, 1, 1, 3) # add delay self.delay_edit = QLineEdit() self.delay_label = QLabel("DELAY") self.property_view_layout_pv.addWidget(self.delay_label, 4, 0) self.property_view_layout_pv.addWidget(self.delay_edit, 4, 1, 1, 3) self.delay_edit.setValidator(QIntValidator()) # add count self.count_edit = QLineEdit() self.count_label = QLabel("COUNT") self.property_view_layout_pv.addWidget(self.count_label, 5, 0) self.property_view_layout_pv.addWidget(self.count_edit, 5, 1, 1, 3) self.count_edit.setValidator(QIntValidator()) # add filter/force pv self.filter_edit = QLineEdit() self.filter_label = QLabel("ENABLING FILTER") self.property_view_layout_pv.addWidget(self.filter_label, 6, 0) self.property_view_layout_pv.addWidget(self.filter_edit, 6, 1, 1, 3) # enabled, latching, annunciating self.enabled_check = QCheckBox("ENABLED") self.annunciating_check = QCheckBox("ANNUNCIATING") self.latching_check = QCheckBox("LATCHING") self.property_view_layout_pv.addWidget(self.enabled_check, 7, 0) self.property_view_layout_pv.addWidget(self.annunciating_check, 7, 1) self.property_view_layout_pv.addWidget(self.latching_check, 7, 2) self.property_view_layout_pv.addItem(spacer, 8, 0) # create save button self.button_box = QDialogButtonBox(self) self.button_box.setOrientation(Qt.Horizontal) self.button_box.addButton("Save Properties", QDialogButtonBox.AcceptRole) self.property_layout.addWidget(self.button_box) # self.property_layout.addLayout(self.property_view_layout) self.property_widget_pv.setLayout(self.property_view_layout_pv) self.property_widget_group.setLayout(self.property_view_layout_group) self.property_data_layout.addWidget(self.property_widget_config) self.property_data_layout.addWidget(self.property_widget_pv) self.property_data_layout.addWidget(self.property_widget_group) self.main_layout.addLayout(self.property_layout, 0, 1) self.setWindowTitle("Alarm Tree Editor") self.tree_view.expandAll() def minimumSizeHint(self): # This is the default recommended size # for this screen return QSize(400, 200) def insertChild(self): index = self.tree_view.selectionModel().currentIndex() model = self.tree_view.model() if model.columnCount(index) == 0: if not model.insertColumn(0, index): return if not model.insertRow(0, index): return for column in range(model.columnCount(index)): child = model.index(0, column, index) model.set_data(child, label="NEW_ITEM", role=Qt.EditRole) def removeItem(self): index = self.tree_view.selectionModel().currentIndex() self.tree_view.model().removeRow(index.row(), index.parent()) @Slot() def save_property_changes(self): index = self.tree_view.selectionModel().currentIndex() item = self.tree_view.model().getItem(index) if item.is_group: guidance = self.guidance_edit_group.text() label = self.label_edit_group.text() else: guidance = self.guidance_edit_pv.text() label = self.label_edit_pv.text() self.tree_view.model().set_data( index, label=label, description=self.description_edit.text(), delay=self.delay_edit.text(), count=self.count_edit.text(), enabled=self.enabled_check.isChecked(), annunciating=self.annunciating_check.isChecked(), latching=self.latching_check.isChecked(), alarm_filter=self.filter_edit.text(), guidance=guidance, role=Qt.EditRole, ) @Slot() def handle_selection(self): self.remove_button.setEnabled( self.tree_view.selectionModel().hasSelection()) index = self.tree_view.selectionModel().currentIndex() item = self.tree_view.model().getItem(index) if item.is_group: self.guidance_edit_group.setText(item.guidance) self.label_edit_group.setText(item.label) else: self.guidance_edit_pv.setText(item.guidance) self.label_edit_pv.setText(item.label) if item.is_group: # black for configuration screen if not item.parent: self.property_data_layout.setCurrentWidget( self.property_widget_config) # otherwise show group screen and set all disables else: self.property_data_layout.setCurrentWidget( self.property_widget_group) self.description_edit.setEnabled(False) self.description_edit.setVisible(False) self.description_label.setVisible(False) self.count_edit.setEnabled(False) self.count_edit.setVisible(False) self.count_label.setVisible(False) self.delay_edit.setEnabled(False) self.delay_edit.setVisible(False) self.delay_label.setVisible(False) self.latching_check.setEnabled(False) self.latching_check.setVisible(False) self.annunciating_check.setEnabled(False) self.annunciating_check.setVisible(False) self.filter_edit.setEnabled(False) self.filter_edit.setVisible(False) self.filter_label.setVisible(False) # set pv enabled else: self.property_data_layout.setCurrentWidget(self.property_widget_pv) self.description_edit.setEnabled(True) self.description_edit.setVisible(True) self.description_label.setVisible(True) self.count_edit.setEnabled(True) self.count_edit.setVisible(True) self.count_label.setVisible(True) self.delay_edit.setEnabled(True) self.delay_edit.setVisible(True) self.delay_label.setVisible(True) self.latching_check.setEnabled(True) self.latching_check.setVisible(True) self.annunciating_check.setEnabled(True) self.annunciating_check.setVisible(True) self.filter_edit.setEnabled(True) self.filter_edit.setVisible(True) self.filter_label.setVisible(True) if item.enabled: self.enabled_check.setChecked(True) else: self.enabled_check.setChecked(False) if item.latching: self.latching_check.setChecked(True) else: self.latching_check.setChecked(False) if item.annunciating: self.annunciating_check.setChecked(True) else: self.annunciating_check.setChecked(False) @Slot() def item_change(self): index = self.tree_view.selectionModel().currentIndex() item = self.tree_view.model().getItem(index) if item.is_group: self.guidance_edit_group.setText(item.guidance) self.label_edit_group.setText(item.label) else: self.guidance_edit_pv.setText(item.guidance) self.label_edit_pv.setText(item.label) if item.is_group: if not item.parent(): self.property_data_layout.setCurrentWidget( self.property_widget_config) else: self.property_data_layout.setCurrentWidget( self.property_widget_group) self.description_edit.setEnabled(False) self.description_edit.setVisible(False) self.description_label.setVisible(False) self.count_edit.setEnabled(False) self.count_edit.setVisible(False) self.count_label.setVisible(False) self.delay_edit.setEnabled(False) self.delay_edit.setVisible(False) self.delay_label.setVisible(False) self.latching_check.setEnabled(False) self.latching_check.setVisible(False) self.annunciating_check.setEnabled(False) self.annunciating_check.setVisible(False) self.filter_edit.setEnabled(False) self.filter_edit.setVisible(False) self.filter_label.setVisible(False) else: self.delay_edit.setText(item.delay) self.count_edit.setText(item.count) if item.enabled: self.enabled_check.setChecked(True) else: self.enabled_check.setChecked(False) self.property_data_layout.setCurrentWidget(self.property_widget_pv) self.description_edit.setEnabled(True) self.description_edit.setVisible(True) self.description_label.setVisible(True) self.count_edit.setEnabled(True) self.count_edit.setVisible(True) self.count_label.setVisible(True) self.delay_edit.setEnabled(True) self.delay_edit.setVisible(True) self.delay_label.setVisible(True) self.latching_check.setEnabled(True) self.latching_check.setVisible(True) self.annunciating_check.setEnabled(True) self.annunciating_check.setVisible(True) self.filter_edit.setEnabled(True) self.filter_edit.setVisible(True) self.filter_label.setVisible(True) if item.latching: self.latching_check.setChecked(True) else: self.latching_check.setChecked(False) if item.annunciating: self.annunciating_check.setChecked(True) else: self.annunciating_check.setChecked(False) def ui_filepath(self): # No UI file is being used return None @Slot(bool) def open_file(self, checked): modifiers = QApplication.keyboardModifiers() try: curr_file = self.current_file() folder = os.path.dirname(curr_file) except Exception: folder = os.getcwd() filename = QFileDialog.getOpenFileName( self, "Open File...", folder, "XML (*.xml);; ALH Config (*.alhConfig)") filename = filename[0] if isinstance(filename, (list, tuple)) else filename if filename: filename = str(filename) # if alh file selected, open conversion prompt if filename[-9:] == "alhConfig": self.legacy_window = LegacyWindow(filename) self.legacy_window.exec_() if self.legacy_window.converted_filename: self.import_configuration( self.legacy_window.converted_filename) else: self.import_configuration(filename) def import_configuration(self, filename): nodes = self.config_tool.parse_config(filename) self.tree_view.model().import_hierarchy(nodes) self.tree_label.setText(self.tree_view.model()._nodes[0].label) @Slot() def save_configuration(self): modifiers = QApplication.keyboardModifiers() try: curr_file = self.current_file() folder = os.path.dirname(curr_file) except Exception: folder = os.getcwd() filename = QFileDialog.getSaveFileName(self, "Save File...", folder, "Configration files (*.xml)") filename = filename[0] if isinstance(filename, (list, tuple)) else filename self.config_tool.save_configuration(self.tree_view.model()._root_item, filename) def _update_config_name(self): name = self.tree_label.text() self.tree_view.model()._nodes[0].label = name def _import_legacy_file(self): convert_alh_to_phoebus()
class MainApp(QWidget): LANDSCAPE = 0 PORTRAIT = 1 stop_signal = Signal() quality_changed = Signal(str) style_changed = Signal(object) last_frame_changed = Signal(object) def __init__(self): QWidget.__init__(self) self.styles = load_styles() self.image = StyledCapture(QImage(256, 256, QImage.Format_RGB888), '') # placeholder self.freeze = None if isinstance(settings.CAPTURE_HANDLER, string_types): self.capture_handler = locate(settings.CAPTURE_HANDLER) else: self.capture_handler = settings.CAPTURE_HANDLER self.setup_ui() self.frame_grabber = FrameGrabber(settings.SIZES[0]) self.frame_thread = QThread() # self.frame_grabber.image_signal.connect(self.display_frame) self.frame_grabber.last_frame_signal.connect(self.last_frame) self.frame_grabber.moveToThread(self.frame_thread) self.frame_thread.started.connect(self.frame_grabber.grab) self.stop_signal.connect(self.frame_grabber.stop_work) self.quality_changed.connect(self.frame_grabber.change_size) self.frame_thread.start() self.image_processor = ImageProcessor(self.styles[0]) self.image_thread = QThread() self.image_processor.image_signal.connect(self.display_frame) self.image_processor.moveToThread(self.image_thread) self.image_thread.started.connect(self.image_processor.monitor_images) self.stop_signal.connect(self.image_processor.stop_work) self.style_changed.connect(self.image_processor.change_style) self.last_frame_changed.connect(self.image_processor.change_last_frame) self.image_thread.start() def closeEvent(self, event): self.stop_signal.emit() self.frame_thread.quit() self.image_thread.quit() self.frame_thread.wait() self.image_thread.wait() def setup_ui(self): """Initialize widgets.""" def switch_style(i): view = self.landscape_view if self.view_mode == MainApp.LANDSCAPE else self.portrait_view self.style_changed.emit(self.styles[i]) view.selected_style = self.styles[i] for i in range(min(len(self.styles), len(settings.STYLE_SHORTCUTS))): QShortcut(QKeySequence(settings.STYLE_SHORTCUTS[i]), self, lambda x=i: switch_style(x)) self.landscape_view = LandscapeView(self.styles) self.landscape_view.style_changed.connect(self.style_button_clicked) self.landscape_view.toggle_fullscreen_signal.connect( self.toggle_fullscreen) self.landscape_view.quality_changed.connect(self.quality_choice) self.portrait_view = PortraitView(self.styles) self.portrait_view.style_changed.connect(self.style_button_clicked) self.portrait_view.toggle_fullscreen_signal.connect( self.toggle_fullscreen) self.portrait_view.quality_changed.connect(self.quality_choice) self.main_layout = QStackedLayout() self.main_layout.addWidget(self.landscape_view) self.main_layout.addWidget(self.portrait_view) self.setLayout(self.main_layout) self.view_mode = MainApp.LANDSCAPE self.setStyleSheet('background-color:black;' 'font-family: Arial;' 'font-style: normal;' 'font-size: 12pt;' 'font-weight: bold;' 'color:white;') self.setWindowTitle('Stylize') def keyPressEvent(self, event): if event.key() == Qt.Key_Escape and not settings.KIOSK: if self.windowState() & Qt.WindowFullScreen: self.showNormal() elif event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return: self.image_capture() def last_frame(self, frame): self.last_frame_changed.emit(frame) def display_frame(self, image): self.image = image if not self.freeze: if self.view_mode == MainApp.LANDSCAPE: self.landscape_view.set_image(self.image.image) else: self.portrait_view.set_image(self.image.image) def resizeEvent(self, event): super(MainApp, self).resizeEvent(event) new_view_mode = MainApp.LANDSCAPE if self.width() >= self.height( ) else MainApp.PORTRAIT if self.view_mode != new_view_mode: old_view = self.portrait_view if new_view_mode == MainApp.LANDSCAPE else self.landscape_view new_view = self.landscape_view if new_view_mode == MainApp.LANDSCAPE else self.portrait_view new_view.quality = old_view.quality new_view.selected_style = old_view.selected_style self.view_mode = new_view_mode self.main_layout.setCurrentIndex(self.view_mode) def style_button_clicked(self, style): self.style_changed.emit(style) def toggle_fullscreen(self): if self.windowState() & Qt.WindowFullScreen: self.showNormal() else: self.showFullScreen() def quality_choice(self, quality): self.quality_changed.emit(quality) def image_capture(self): self.freeze = self.image.copy() # prevent background update try: self.capture_handler(self, self.freeze) except Exception: msg = QMessageBox(self) msg.setIcon(QMessageBox.Critical) msg.setText('Error during capture.') msg.setWindowFlags(Qt.FramelessWindowHint | Qt.Popup) msg.exec_() self.freeze = None
class PSDiag(SiriusMainWindow): """Power Supply Diagnostic.""" def __init__(self, parent=None, prefix=VACA_PREFIX): """Init.""" super().__init__(parent) self._prefix = prefix self.setWindowTitle('PS Diagnostics') self.setObjectName('ASApp') cor = _get_appropriate_color(section='AS') self.setWindowIcon(qta.icon('mdi.stethoscope', color=cor)) self._setupUi() self._initialized = False def _setupUi(self): # Leds Panel cw = QWidget(self) panel = QWidget(cw) panel_lay = QGridLayout() panel_lay.setVerticalSpacing(0) panel_lay.setHorizontalSpacing(5) panel.setLayout(panel_lay) # # Leds Header for i, lab in enumerate([ '', 'PS\nConn?', 'Power\nState', 'Interlock', 'OpMode\nSlowRef?', 'Current\nDiff']): label = QLabel(lab, panel, alignment=Qt.AlignCenter) label.setStyleSheet('min-width:3.4em; max-width:3.4em;') panel_lay.addWidget(label, 0, i) # # Leds panel _on = _PSConst.PwrStateSts.On _slowref = _PSConst.States.SlowRef _rmpwfm = _PSConst.States.RmpWfm i = 2 for sec in ['LI', 'TB', 'BO', 'TS', 'SI']: seclabel = QLabel('<h3>'+sec+'</h3>', panel) panel_lay.addWidget(seclabel, i, 0) i += 1 if sec == 'LI': for label, filt in lips2filters.items(): ps_label = QLabel( label, panel, alignment=Qt.AlignRight | Qt.AlignVCenter) psnames = PSSearch.get_psnames(filters=filt) ps_c2v = dict() ilk_c2v = dict() conn_chs = list() for name in psnames: pvn = _PVName(name).substitute(prefix=self._prefix) conn_chs.append(pvn.substitute(propty='PwrState-Sts')) ps_c2v[pvn.substitute(propty='PwrState-Sts')] = 1 ilk_c2v[pvn.substitute(propty='StatusIntlk-Mon')] = \ {'value': _PS_LI_INTLK, 'comp': 'lt'} f = 'LI-.*:PS-'+filt['dev'] conn_led = MyLedMultiConnection( filters=f, parent=panel, channels=conn_chs) ps_led = MyLedMultiChannel( filters=f, parent=panel, channels2values=ps_c2v) if 'Spect' in filt['dev']: intlk_led = LISpectIntlkLed(panel, filters=f) else: intlk_led = MyLedMultiChannel( filters=f, parent=panel, channels2values=ilk_c2v) suf = sec+filt['dev'].strip('.*')+'_led' conn_led.setObjectName('conn' + suf) ps_led.setObjectName('ps' + suf) intlk_led.setObjectName('intlk' + suf) panel_lay.addWidget(ps_label, i, 0) panel_lay.addWidget(conn_led, i, 1) panel_lay.addWidget(ps_led, i, 2) panel_lay.addWidget(intlk_led, i, 3) i += 1 else: l2f = sips2filters if sec == 'SI' else asps2filters for label, filt in l2f.items(): filt['sec'] = sec psnames = PSSearch.get_psnames(filters=filt) if not psnames: continue psconn_chs = list() ps_c2v = dict() ilk_c2v = dict() opm_c2v = dict() df_c2v = dict() for name in psnames: pvn = _PVName(name).substitute(prefix=self._prefix) ps_c2v[pvn.substitute(propty='PwrState-Sts')] = _on if name.dis == 'PS': psconn_chs.append( pvn.substitute(propty='Version-Cte')) ilk_c2v[pvn.substitute(propty='IntlkSoft-Mon')] = 0 ilk_c2v[pvn.substitute(propty='IntlkHard-Mon')] = 0 opm_pvn = pvn.substitute(propty='OpMode-Sts') if sec == 'BO': opm_c2v[opm_pvn] = { 'value': [_slowref, _rmpwfm], 'comp': 'in'} else: opm_c2v[opm_pvn] = _slowref df_c2v[pvn.substitute(propty='DiagStatus-Mon')] = \ {'value': 0, 'bit': 5} elif name.dis == 'PU': psconn_chs.append( pvn.substitute(propty='PwrState-Sts')) intlkcount = 7 if 'Sept' in name.dev else 8 for idx in range(1, intlkcount+1): ppty = 'Intlk'+str(idx)+'-Mon' pvn = pvn.substitute(propty=ppty) ilk_c2v[pvn] = 1 f = sec+'-'+filt['sub']+':'+psnames[0].dis+'-'+filt['dev'] ps_label = QLabel( label, panel, alignment=Qt.AlignRight | Qt.AlignVCenter) psconn_led = MyLedMultiConnection( filters=f, parent=panel, channels=psconn_chs) ps_led = MyLedMultiChannel( filters=f, parent=panel, channels2values=ps_c2v) intlk_led = MyLedMultiChannel( filters=f, parent=panel, channels2values=ilk_c2v) suf = sec+filt['dev'].strip('.*')+'_led' psconn_led.setObjectName('psconn' + suf) ps_led.setObjectName('ps' + suf) intlk_led.setObjectName('intlk' + suf) panel_lay.addWidget(ps_label, i, 0) panel_lay.addWidget(psconn_led, i, 1) panel_lay.addWidget(ps_led, i, 2) panel_lay.addWidget(intlk_led, i, 3) if psnames[0].dis == 'PS': opm_led = MyLedMultiChannel( filters=f, parent=panel, channels2values=opm_c2v) opm_led.setOnColor(PyDMLed.LightGreen) opm_led.setOffColor(PyDMLed.Yellow) diff_led = MyLedMultiChannel( filters=f, parent=panel, channels2values=df_c2v) opm_led.setObjectName('opm' + suf) diff_led.setObjectName('diff' + suf) panel_lay.addWidget(opm_led, i, 4) panel_lay.addWidget(diff_led, i, 5) i += 1 panel_lay.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored, QSzPlcy.MinimumExpanding), i, 0) i += 1 # Current State and Log Tables table_label2px = { 'Date': 110, 'Time': 85, 'Type': 70, 'PS Name': 145, 'Property': 85, 'Value': 120} channels = list() for ps in PSSearch.get_psnames(filters={'dis': 'PS'}): channels.append(_PVName(ps).substitute( prefix=self._prefix, propty='DiagCurrentDiff-Mon')) channels.append(_PVName(ps).substitute( prefix=self._prefix, propty='OpMode-Sts')) self._status = LogTable(cw, channels, table_label2px, is_status=True) self._status.setObjectName('status_table') self._status.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self._status.updated.connect(self._filter_table) self._log = LogTable(cw, channels, table_label2px) self._log.setObjectName('log_table') self._log.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self._tables_stack = QStackedLayout() self._tables_stack.addWidget(self._status) self._tables_stack.addWidget(self._log) self._rb_status = QRadioButton('Status', self) self._rb_status.setObjectName('rb_status') self._rb_status.setChecked(True) self._visible_table = self._status self._rb_status.toggled.connect(_partial(self._toggle_table, 0)) self._rb_log = QRadioButton('Log', self) self._rb_log.setObjectName('rb_log') self._rb_log.toggled.connect(_partial(self._toggle_table, 1)) for name, width in table_label2px.items(): attr = '_search_'+name.replace(' ', '').lower() setattr(self, attr, QLineEdit()) le = getattr(self, attr) le.setObjectName(name) le.setPlaceholderText(name + '...') le.editingFinished.connect(self._filter_table) width = str(width-1) if name == 'Value': le.setStyleSheet( '#'+name+'{min-width:'+width+'px;}') le.setSizePolicy(QSzPlcy.Expanding, QSzPlcy.Maximum) else: le.setStyleSheet( '#'+name+'{min-width:'+width+'px; max-width:'+width+'px;}') le.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum) self._scrollup_pb = QPushButton('↟', cw) self._scrollup_pb.setObjectName('scrollup_pb') self._scrollup_pb.clicked.connect(self._arrange_table) self._scrolldown_pb = QPushButton('↡', cw) self._scrolldown_pb.setObjectName('scrolldown_pb') self._scrolldown_pb.clicked.connect(self._arrange_table) tables_lay = QGridLayout() tables_lay.setVerticalSpacing(2) tables_lay.setHorizontalSpacing(0) tables_lay.addWidget(self._search_date, 0, 0) tables_lay.addWidget(self._search_time, 0, 1) tables_lay.addWidget(self._search_type, 0, 2) tables_lay.addWidget(self._search_psname, 0, 3) tables_lay.addWidget(self._search_property, 0, 4) tables_lay.addWidget(self._search_value, 0, 5) tables_lay.addWidget(self._scrollup_pb, 0, 6, alignment=Qt.AlignRight) tables_lay.addLayout(self._tables_stack, 1, 0, 1, 7) tables_lay.addWidget(self._rb_status, 2, 0, alignment=Qt.AlignLeft) tables_lay.addWidget(self._rb_log, 2, 1, alignment=Qt.AlignLeft) tables_lay.addWidget(self._scrolldown_pb, 2, 6, alignment=Qt.AlignRight) tables = QWidget(cw) tables.setObjectName('tables') tables.setLayout(tables_lay) # Connect signals for led in self.findChildren(QLed): led.shape = PyDMLed.ShapeMap.Round led.filterlog.connect(self._filter_table) led.warning.connect(self._log.add_log_slot) led.warning.connect(self._status.add_log_slot) led.normal.connect(self._status.remove_log_slot) # Layout window_title = QLabel('<h2>Power Supplies Diagnostics</h2>', cw, alignment=Qt.AlignCenter) layout = QGridLayout() layout.setVerticalSpacing(20) layout.setHorizontalSpacing(5) layout.addWidget(window_title, 0, 0, 1, 2) layout.addWidget(panel, 1, 0) layout.addWidget(tables, 1, 1) cw.setStyleSheet(""" #scrollup_pb, #scrolldown_pb{ max-height: 1em; max-width: 0.7em; color: #464646; } QLineEdit{ max-height: 1em; } #status_table, #log_table{ border: 1px solid #bebebe; } #tables{ min-width: 700px; } #rb_status, #rb_log{ min-width: 5em; max-width: 5em; max-height: 1em; }""") cw.setLayout(layout) self.setCentralWidget(cw) def _arrange_table(self): text = self.sender().text() if '↟' in text: self._visible_table.scrollToTop() elif '↡' in text: self._visible_table.scrollToBottom() def _filter_table(self, text=''): # identify first user interaction if isinstance(self.sender(), (QLineEdit, QLed)): self._initialized = True # ignore initializing if not self._initialized: return # set led's filter if isinstance(self.sender(), QLed): self.blockSignals(True) self._search_psname.setText(text) self.blockSignals(False) # get search filters pats = list() date_txt = self._search_date.text() time_txt = self._search_time.text() logtype_txt = self._search_type.text() psname_txt = self._search_psname.text() property_txt = self._search_property.text() value_txt = self._search_value.text() try: if date_txt: pats.append([_re.compile(date_txt, _re.I), 0]) if time_txt: pats.append([_re.compile(time_txt, _re.I), 1]) if logtype_txt: pats.append([_re.compile(logtype_txt, _re.I), 2]) if psname_txt: pats.append([_re.compile(psname_txt, _re.I), 3]) if property_txt: pats.append([_re.compile(property_txt, _re.I), 4]) if value_txt: pats.append([_re.compile(value_txt, _re.I), 5]) except Exception: return m = self._visible_table.model() for row in range(m.rowCount()): for pat, col in pats: if not pat.search(m.data(m.index(row, col))): self._visible_table.setRowHidden( row, self._visible_table.rootIndex(), True) break else: self._visible_table.setRowHidden( row, self._visible_table.rootIndex(), False) def _toggle_table(self, i, toggle): if not toggle: return self._tables_stack.setCurrentIndex(i) if i == 0: self._log.updated.disconnect(self._filter_table) self._status.updated.connect(self._filter_table) self._visible_table = self._status else: self._status.updated.disconnect(self._filter_table) self._log.updated.connect(self._filter_table) self._visible_table = self._log self._filter_table()