class SelectROIPopUp(QDialog): signal_roi_name = QtCore.Signal(str) def __init__(self): QDialog.__init__(self) if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" stylesheet = open(resource_path(self.stylesheet_path)).read() self.setStyleSheet(stylesheet) self.standard_names = [] self.init_standard_names() self.setWindowTitle("Select A Region of Interest To Draw") self.setMinimumSize(350, 180) self.icon = QtGui.QIcon() self.icon.addPixmap( QtGui.QPixmap(resource_path("res/images/icon.ico")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.setWindowIcon(self.icon) self.explanation_text = QLabel("Search for ROI:") self.input_field = QLineEdit() self.input_field.textChanged.connect(self.on_text_edited) self.button_area = QWidget() self.cancel_button = QPushButton("Cancel") self.cancel_button.clicked.connect(self.on_cancel_clicked) self.begin_draw_button = QPushButton("Begin Draw Process") self.begin_draw_button.clicked.connect(self.on_begin_clicked) self.button_layout = QHBoxLayout() self.button_layout.addWidget(self.cancel_button) self.button_layout.addWidget(self.begin_draw_button) self.button_area.setLayout(self.button_layout) self.list_label = QLabel() self.list_label.setText("Select a Standard Region of Interest") self.list_of_ROIs = QListWidget() for standard_name in self.standard_names: self.list_of_ROIs.addItem(standard_name) self.layout = QVBoxLayout() self.layout.addWidget(self.explanation_text) self.layout.addWidget(self.input_field) self.layout.addWidget(self.list_label) self.layout.addWidget(self.list_of_ROIs) self.layout.addWidget(self.button_area) self.setLayout(self.layout) self.list_of_ROIs.clicked.connect(self.on_roi_clicked) def init_standard_names(self): """ Create two lists containing standard organ and standard volume names as set by the Add-On options. """ with open(data_path('organName.csv'), 'r') as f: standard_organ_names = [] csv_input = csv.reader(f) header = next(f) # Ignore the "header" of the column for row in csv_input: standard_organ_names.append(row[0]) with open(data_path('volumeName.csv'), 'r') as f: standard_volume_names = [] csv_input = csv.reader(f) next(f) # Ignore the "header" of the column for row in csv_input: standard_volume_names.append(row[1]) self.standard_names = standard_organ_names + standard_volume_names def on_text_edited(self, text): """ function triggered when text in the ROI popup is edited ------- :param text: text in the pop up """ self.list_of_ROIs.clear() text_upper_case = text.upper() for item in self.standard_names: if item.startswith(text) or item.startswith(text_upper_case): self.list_of_ROIs.addItem(item) def on_roi_clicked(self): """ function triggered when an ROI is clicked """ self.begin_draw_button.setEnabled(True) self.begin_draw_button.setFocus() def on_begin_clicked(self): """ function to start the draw ROI function """ # If there is a ROI Selected if self.list_of_ROIs.currentItem() is not None: roi = self.list_of_ROIs.currentItem() self.roi_name = str(roi.text()) # Call function on UIDrawWindow so it has selected ROI self.signal_roi_name.emit(self.roi_name) self.close() def on_cancel_clicked(self): """ function to cancel the operation """ self.close()
class RenameROIWindow(QDialog): def __init__(self, standard_volume_names, standard_organ_names, rtss, roi_id, roi_name, rename_signal, suggested_text="", *args, **kwargs): super(RenameROIWindow, self).__init__(*args, **kwargs) if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" stylesheet = open(resource_path(self.stylesheet_path)).read() self.setStyleSheet(stylesheet) self.standard_volume_names = standard_volume_names self.standard_organ_names = standard_organ_names self.rtss = rtss self.roi_id = roi_id self.roi_name = roi_name self.rename_signal = rename_signal self.suggested_text = suggested_text self.setWindowTitle("Rename Region of Interest") self.setMinimumSize(300, 90) self.icon = QtGui.QIcon() self.icon.addPixmap(QtGui.QPixmap( resource_path("res/images/icon.ico")), QtGui.QIcon.Normal, QtGui.QIcon.Off) # adding icon self.setWindowIcon(self.icon) self.explanation_text = QLabel("Enter a new name:") self.input_field = QLineEdit() self.input_field.setText(self.suggested_text) self.input_field.textChanged.connect(self.on_text_edited) self.feedback_text = QLabel() self.button_area = QWidget() self.cancel_button = QPushButton("Cancel") self.cancel_button.clicked.connect(self.close) self.rename_button = QPushButton("Rename") self.rename_button.clicked.connect(self.on_rename_clicked) self.button_layout = QHBoxLayout() self.button_layout.addWidget(self.cancel_button) self.button_layout.addWidget(self.rename_button) self.button_area.setLayout(self.button_layout) self.list_label = QLabel() self.list_label.setText("List of Standard Region of Interests") # Populating the table of ROIs self.list_of_ROIs = QListWidget() self.list_of_ROIs.addItem( "------------Standard Organ Names------------") for organ in self.standard_organ_names: self.list_of_ROIs.addItem(organ) self.list_of_ROIs.addItem( "------------Standard Volume Names------------") for volume in self.standard_volume_names: self.list_of_ROIs.addItem(volume) self.list_of_ROIs.clicked.connect(self.on_ROI_clicked) self.layout = QVBoxLayout() self.layout.addWidget(self.explanation_text) self.layout.addWidget(self.input_field) self.layout.addWidget(self.feedback_text) self.layout.addWidget(self.button_area) self.layout.addWidget(self.list_label) self.layout.addWidget(self.list_of_ROIs) self.setLayout(self.layout) def on_text_edited(self, text): self.rename_button.setDefault(True) if text in self.standard_volume_names or text in self.standard_organ_names: self.feedback_text.setStyleSheet("color: green") self.feedback_text.setText("Entered text is in standard names") elif text.upper() in self.standard_volume_names or text.upper( ) in self.standard_organ_names: self.feedback_text.setStyleSheet("color: orange") self.feedback_text.setText( "Entered text exists but should be in capitals") elif text == "": self.feedback_text.setText("") else: self.feedback_text.setStyleSheet("color: red") self.feedback_text.setText("Entered text is not in standard names") for item in self.standard_volume_names: if text.startswith(item): self.feedback_text.setStyleSheet("color: green") self.feedback_text.setText("Entered text is in standard names") else: upper_text = text.upper() if upper_text.startswith(item): self.feedback_text.setStyleSheet("color: orange") self.feedback_text.setText( "Entered text exists but should be in capitals") def on_rename_clicked(self): self.new_name = self.input_field.text() progress_window = RenameROIProgressWindow(self, QtCore.Qt.WindowTitleHint) progress_window.signal_roi_renamed.connect(self.on_roi_renamed) progress_window.start_renaming(self.rtss, self.roi_id, self.new_name) progress_window.show() def on_roi_renamed(self, new_rtss): self.rename_signal.emit((new_rtss, { "rename": [self.roi_name, self.new_name] })) QtWidgets.QMessageBox.about( self, "Saved", "Region of interest successfully renamed!") self.close() def on_ROI_clicked(self): clicked_ROI = self.list_of_ROIs.currentItem() # Excluding headers from being clicked. if not str(clicked_ROI.text()).startswith("------------Standard"): self.input_field.setText(str(clicked_ROI.text()))
class ProgramList(QWidget): onProgramEditRequest = Signal(Program) def __init__(self, parent): super().__init__(parent) self._programsLabel = QLabel("Programs") self._programsList = QListWidget() self._programsList.itemClicked.connect(self.SelectProgram) self._programsList.itemDoubleClicked.connect(self.EditProgram) AppGlobals.Instance().onChipModified.connect(self.SyncInstances) self._instances: Dict[Program, ProgramInstance] = {} self._newButton = QPushButton("Create New Program") self._newButton.clicked.connect(self.NewProgram) layout = QVBoxLayout() layout.addWidget(self._programsLabel) layout.addWidget(self._programsList) layout.addWidget(self._newButton) self.setLayout(layout) AppGlobals.Instance().onChipOpened.connect(self.SyncInstances) def EditProgram(self, selectedProgram: 'ProgramListItem'): self.onProgramEditRequest.emit(selectedProgram.program) def SelectProgram(self, selectedProgram: 'ProgramListItem'): contextDisplay = ProgramContextDisplay(self.topLevelWidget(), selectedProgram.instance, self._programsList) contextDisplay.onDelete.connect(self.DeleteProgram) contextDisplay.onEdit.connect(self.onProgramEditRequest) def SyncInstances(self): for program in AppGlobals.Chip().programs: if program not in self._instances: self._instances[program] = ProgramInstance(program) for program in self._instances.copy(): if program not in AppGlobals.Chip().programs: del self._instances[program] else: self._instances[program].SyncParameters() self.RefreshList() def NewProgram(self): newProgram = Program() AppGlobals.Chip().programs.append(newProgram) AppGlobals.Instance().onChipModified.emit() for item in [ self._programsList.item(row) for row in range(self._programsList.count()) ]: if item.program is newProgram: self._programsList.setCurrentItem(item) self.onProgramEditRequest.emit(newProgram) return def ProgramItem(self, program: Program): matches = [ item for item in [ self._programsList.item(row) for row in range(self._programsList.count()) ] if item.program is program ] if matches: return matches[0] def RefreshList(self): self._programsList.blockSignals(True) self._programsList.clear() for program in AppGlobals.Chip().programs: self._programsList.addItem( ProgramListItem(program, self._instances[program])) self._programsList.blockSignals(False) def DeleteProgram(self, program: Program): if QMessageBox.question( self, "Confirm Deletion", "Are you sure you want to delete " + program.name + "?") is QMessageBox.Yes: AppGlobals.Chip().programs.remove(program) AppGlobals.Instance().onChipModified.emit() def keyPressEvent(self, event) -> None: if event.key() == Qt.Key.Key_Delete: if self._programsList.currentItem(): self.DeleteProgram(self._programsList.currentItem().program)