class TimebaseBox(QGroupBox): def __init__(self, controller, parent=None): super().__init__("Timebase", parent=parent) self.controller = controller layout = QVBoxLayout() self.setLayout(layout) self.timebase_options = [ "100 us", "200 us", "500 us", "1 ms", "2 ms", "5 ms", "10 ms", "20 ms", ] self.combobox_timebase = QComboBox() self.combobox_timebase.addItems(self.timebase_options) self.combobox_timebase.setCurrentIndex(7) layout.addWidget(QLabel("time/div (1 div = 1/10 graph)")) layout.addWidget(self.combobox_timebase) self.combobox_timebase.currentTextChanged.connect(self.set_timebase) def set_timebase(self): timebase = self.combobox_timebase.currentText() self.controller.set_timebase(timebase)
def setup_ui(self): super(SettingUI, self).setup_ui() max_width_label = QLabel(text="最大宽度", alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) max_width_combo = QComboBox() max_width_combo.addItems(Globals.max_width_arr) max_width_combo.setCurrentIndex(self.max_width_index) max_width_combo.currentIndexChanged.connect(self.on_combo_changed) size_label = QLabel(text="输出字号", alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) size_spin = QSpinBox() size_spin.setRange(10, 64) size_spin.setValue(Globals.config.get(Globals.UserData.font_size)) size_spin.valueChanged.connect(self.on_save_font_size) output_name_label = QLabel(text="输出名称", alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) output_name_edit = QLineEdit( Globals.config.get(Globals.UserData.font_save_name)) output_name_edit.textEdited.connect(self.on_output_name_edited) output_label = QLabel(text="输出目录", alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) output_line_edit = QLineEdit( Globals.config.get(Globals.UserData.output_dir)) output_line_edit.setReadOnly(True) output_line_edit.cursorPositionChanged.connect( self.on_output_choose_clicked) mode_1_radio = QRadioButton("图集模式") mode_2_radio = QRadioButton("字体模式") mode_1_radio.setChecked(True) mode_1_radio.toggled.connect(self.on_mode_1_radio_toggled) mode_radio_group = QButtonGroup(self) mode_radio_group.addButton(mode_1_radio, 0) mode_radio_group.addButton(mode_2_radio, 1) self.main_layout.setColumnStretch(1, 1) self.main_layout.setColumnStretch(3, 1) self.main_layout.addWidget(mode_1_radio, 0, 0, 1, 1) self.main_layout.addWidget(mode_2_radio, 0, 1, 1, 1) self.main_layout.addWidget(output_name_label, 1, 0, 1, 1) self.main_layout.addWidget(output_name_edit, 1, 1, 1, 1) self.main_layout.addWidget(max_width_label, 1, 2, 1, 1) self.main_layout.addWidget(max_width_combo, 1, 3, 1, 1) self.main_layout.addWidget(output_label, 2, 0, 1, 1) self.main_layout.addWidget(output_line_edit, 2, 1, 1, 1) self.main_layout.addWidget(size_label, 2, 2, 1, 1) self.main_layout.addWidget(size_spin, 2, 3, 1, 1) self.max_width_combo = max_width_combo self.size_spin = size_spin self.output_name_edit = output_name_edit self.output_line_edit = output_line_edit
def set_combo_with_value(combo: QtWidgets.QComboBox, value): """ Searches all items of the given combo for the given value and changes the current index to that one. :param combo: :param value: :return: """ combo.setCurrentIndex(combo.findData(value))
class SetSyncTimeWidget(QWidget): Sg_view_changed = Signal() def __init__(self, model: SettingsModel, parent=None): super(SetSyncTimeWidget, self).__init__(parent) self._time_list = ["5s", "10s", "15s", "15m", "30m", "45m"] self._time_in_sec = [] for curr_time in self._time_list: time_int = int(re.search(r'\d+', curr_time).group()) if 'm' in curr_time: time_int = time_int * 60 if 'h' in curr_time: time_int = time_int * 3600 self._time_in_sec.append(time_int) self._model = model self.setAccessibleName('InfoBox') self._titolo = QLabel() self._titolo.setText("Finestra Temporale") self._titolo.setAccessibleName('Title2') self.sottotitolo = QLabel() self.sottotitolo.setAccessibleName('Sottotitolo') self.sottotitolo.setText("Seleziona finestra temporale per la sincronizzazione") self.spaceLabel = QLabel(" ") self.time_box = QComboBox() self.time_box.wheelEvent = lambda event: None self.time_box.addItems(self._time_list) self.Sl_model_changed() layout = QVBoxLayout() layout.addWidget(self._titolo) layout.addWidget(self.sottotitolo) layout.addWidget(self.spaceLabel) layout.addWidget(self.time_box) self.setLayout(layout) # connect signal self.time_box.currentIndexChanged.connect(self.Sl_time_checked) @Slot() def Sl_time_checked(self): self.Sg_view_changed.emit() @Slot() def Sl_model_changed(self): time = self._model.get_sync_time() i: int = 0 for el in self._time_in_sec: if time == el: self.time_box.setCurrentIndex(i) i += 1
def setup_ui(self): super(FontUI, self).setup_ui() sys_radio = QRadioButton("系统字体") sys_radio.setChecked(True) font_combo = QComboBox() for item in self.system_fonts: font_combo.addItem(item[1]) font_combo.setCurrentIndex(0) font_combo.currentIndexChanged.connect(self.refresh_font) custom_radio = QRadioButton("自选字体") custom_radio.setCheckable(True) custom_radio.setChecked(False) custom_radio.toggled.connect(self.on_custom_radio_toggled) custom_edit = QLineEdit() custom_edit.setPlaceholderText("自定义字体(*.ttf, *.otf)") custom_edit.setReadOnly(True) custom_edit.setEnabled(False) custom_btn = QPushButton(text="浏览") custom_btn.setEnabled(False) custom_btn.clicked.connect(self.on_custom_clicked) font_group = QButtonGroup(self) font_group.addButton(sys_radio, 0) font_group.addButton(custom_radio, 1) font_group.setExclusive(True) input_label = QLabel("输出字符") input_edit = MLineEdit() import_btn = QPushButton(text="从文本文件导入") import_btn.clicked.connect(self.on_import_btn_clicked) self.main_layout.setColumnStretch(1, 1) self.main_layout.addWidget(sys_radio, 1, 0, 1, 1) self.main_layout.addWidget(font_combo, 1, 1, 1, 2) self.main_layout.addWidget(custom_radio, 2, 0, 1, 1) self.main_layout.addWidget(custom_edit, 2, 1, 1, 1) self.main_layout.addWidget(custom_btn, 2, 2, 1, 1) self.main_layout.addWidget(input_label, 3, 0, 1, 1) self.main_layout.addWidget(import_btn, 3, 2, 1, 1) self.main_layout.addWidget(input_edit, 4, 0, 1, 3) self.input_edit = input_edit self.font_combo = font_combo self.custom_btn = custom_btn self.custom_edit = custom_edit self.refresh_font()
class FindEventsDialog(QDialog): def __init__(self, parent, channels, default_stim): super().__init__(parent) self.setWindowTitle("Find Events") vbox = QVBoxLayout(self) grid = QGridLayout() grid.addWidget(QLabel("Stim channel:"), 0, 0) self.stimchan = QComboBox() self.stimchan.addItems(channels) self.stimchan.setCurrentIndex(default_stim) grid.addWidget(self.stimchan, 0, 1) grid.addWidget(QLabel("Consecutive"), 1, 0) self.consecutive = QCheckBox() self.consecutive.setChecked(True) grid.addWidget(self.consecutive, 1, 1) grid.addWidget(QLabel("Initial event"), 2, 0) self.initial_event = QCheckBox() self.initial_event.setChecked(True) grid.addWidget(self.initial_event, 2, 1) grid.addWidget(QLabel("Cast to unsigned integer"), 3, 0) self.uint_cast = QCheckBox() self.uint_cast.setChecked(True) grid.addWidget(self.uint_cast, 3, 1) grid.addWidget(QLabel("Minimum duration:"), 4, 0) self.minduredit = QSpinBox() self.minduredit.setMaximum(MAX_INT) grid.addWidget(self.minduredit, 4, 1) grid.addWidget(QLabel("Shortest event:"), 5, 0) self.shortesteventedit = QSpinBox() self.shortesteventedit.setMaximum(MAX_INT) grid.addWidget(self.shortesteventedit, 5, 1) vbox.addLayout(grid) buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) vbox.addWidget(buttonbox) buttonbox.accepted.connect(self.accept) buttonbox.rejected.connect(self.reject) vbox.setSizeConstraint(QVBoxLayout.SetFixedSize)
def _create_resource_type_combo(current_resource_type: ResourceType, parent: QWidget) -> QComboBox: """ :param current_resource_type: :param parent: :return: """ resource_type_combo = QComboBox(parent) for resource_type in ResourceType: if not resource_type.is_usable_for_requirement: continue resource_type_combo.addItem(resource_type.name, resource_type) if resource_type is current_resource_type: resource_type_combo.setCurrentIndex(resource_type_combo.count() - 1) return resource_type_combo
class KeyPressWidget(StepBaseWidget): def __init__(self, step: Steps.KeyPress, timeline): super(KeyPressWidget, self).__init__(step, timeline) detail_layout = self.ui.detailFrame.layout() # Key input self.key_label = QLabel("Key: ", self) self.key_line_edit = QLineEdit(self) self.key_line_edit.setMaxLength(1) self.key_line_edit.setText(self.step.key) self.key_line_edit.textChanged.connect(self.update_key) # Mod Input self.mod_label = QLabel("Mod: ", self) self.mod_combo = QComboBox(self) mod_list = ["None", "Ctrl", "Shift", "Alt", "Super"] self.mod_combo.addItems(mod_list) if self.step.mod: current_mod_index = mod_list.index(self.step.mod.capitalize()) self.mod_combo.setCurrentIndex(current_mod_index) self.mod_combo.currentIndexChanged.connect(self.update_mod) # Add to layout detail_layout.addWidget(self.key_label) detail_layout.addWidget(self.key_line_edit) detail_layout.addWidget(self.mod_label) detail_layout.addWidget(self.mod_combo) def update_key(self): if not self.key_line_edit.text(): self.key_line_edit.setText(" ") self.step.key = self.key_line_edit.text() def update_mod(self): if self.mod_combo.currentText() == "None": self.step.mod = None else: self.step.mod = self.mod_combo.currentText().lower()
class TriggerBox(QGroupBox): def __init__(self, controller, parent=None): super().__init__("Trigger", parent=parent) self.controller = controller self.setCheckable(True) self.setChecked(False) layout = QHBoxLayout() self.setLayout(layout) self.combobox_slope = QComboBox() self.combobox_slope.addItems(["Rising", "Falling", "Any"]) self.combobox_slope.setCurrentIndex(0) layout.addWidget(QLabel("Trigger slope")) layout.addWidget(self.combobox_slope) self.toggled.connect(self.controller.set_trigger_state) self.combobox_slope.currentTextChanged.connect( self.controller.set_trigger_slope)
def __init__( self, parent: QWidget, layout: QHBoxLayout, resource_database: ResourceDatabase, item: RequirementTemplate, ): self.parent = parent self.layout = layout self.resource_database = resource_database template_name_combo = QComboBox(parent) for template_name in sorted( resource_database.requirement_template.keys()): template_name_combo.addItem(template_name) if template_name == item.template_name: template_name_combo.setCurrentIndex( template_name_combo.count() - 1) self.template_name_combo = template_name_combo self.layout.addWidget(self.template_name_combo)
def _create_resource_name_combo( resource_database: ResourceDatabase, resource_type: ResourceType, current_resource: Optional[ResourceInfo], parent: QWidget, ) -> QComboBox: """ :param resource_database: :param current_resource: :param parent: :return: """ resource_name_combo = QComboBox(parent) for resource in sorted(resource_database.get_by_type(resource_type), key=lambda x: x.long_name): resource_name_combo.addItem(resource.long_name, resource) if resource is current_resource: resource_name_combo.setCurrentIndex(resource_name_combo.count() - 1) return resource_name_combo
class App(QWidget): def __init__(self): #init super(App, self).__init__() #▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ #parameters for the resume generation. self.params = { "White": 1.0, "Black": 1.0, "Hispanic": 1.0, "Asian": 1.0, "GenderRatio": 0.5, "TestSection": '', "TestMode": 2, "WorkPath": "", "BeginYear": "", "EndYear": "", "BeginMonth": "", "EndMonth": "", "BeginYearEdu": "", "EndYearEdu": "", "BeginMonthEdu": "", "EndMonthEdu": "" } #▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ #Dictionaries for UI buttons self.testModes = {"Before": 1, "After": 2, "Replace": 3} self.testSections = { "Address": 1, "Education": 2, "Work History": 3, "Skills": 4 } #▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ #Window sizing for application self.title = "COEHP Resume Generator" self.left = 10 self.top = 10 self.width = 100 self.height = 300 #▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ #Window is created here self.makeUI() #▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ #Function creates window and adds widgets def makeUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.createLayout() windowLayout = QGridLayout() windowLayout.addWidget(self.box0, 1, 1, 1, 1) windowLayout.addWidget(self.box4, 0, 0, 1, 1) windowLayout.addWidget(self.box6, 1, 0, 1, 1) windowLayout.addWidget(self.box7, 0, 1, 1, 1) windowLayout.addWidget(self.box5, 3, 0, 1, 2) windowLayout.addWidget(self.box8, 2, 0, 1, 2) windowLayout.setAlignment(QtCore.Qt.AlignTop) self.setLayout(windowLayout) self.show() #▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ #All QGroupBoxes for features are added here. def createLayout(self): self.box0 = QGroupBox("Timeframe") self.box4 = QGroupBox("Test Data") self.box6 = QGroupBox("Output Directory") self.box5 = QGroupBox("") self.box7 = QGroupBox("Demographic Settings") self.box8 = QGroupBox("Resume Layout") #Demographic Settings self.wPercent = QTextEdit("0.25") self.bPercent = QTextEdit("0.25") self.aPercent = QTextEdit("0.25") self.hPercent = QTextEdit("0.25") self.gPercent = QTextEdit("0.5") self.wLabel = QLabel("White %") self.bLabel = QLabel("Black %") self.aLabel = QLabel("Asian %") self.hLabel = QLabel("Hispanic %") self.gLabel = QLabel(" Gender Ratio") self.wPercent.setFixedSize(100, 30) self.bPercent.setFixedSize(100, 30) self.aPercent.setFixedSize(100, 30) self.hPercent.setFixedSize(100, 30) self.gPercent.setFixedSize(100, 30) #Resume Layout Settings self.testSectionLabel1 = QLabel("Test Location") self.testSectionLabel2 = QLabel("Section") self.testSectionLabel3 = QLabel("Location of Content") self.sectionSelect = QComboBox() self.sectionSelect.addItems( ["Address", "Education", "Work History", "Skills"]) self.sectionSelect.setFixedSize(300, 30) self.modeSelect = QComboBox() self.modeSelect.addItems(["Before", "After", "Replace"]) self.modeSelect.setFixedSize(300, 30) #Academic Year #First Semester self.monthBegin = QComboBox() self.monthBegin.addItems([ "January", "February", "March", "April", "May", "June", "July", "August", "September", "November", "December" ]) self.monthBegin.setFixedSize(100, 30) self.yearBeginLabel = QLabel("First Semester") self.yearBegin = QComboBox() self.yearBegin.setFixedSize(100, 30) for year in range(1970, 2050): self.yearBegin.addItem(str(year)) #Last Semester self.monthEnd = QComboBox() self.monthEnd.addItems([ "January", "February", "March", "April", "May", "June", "July", "August", "September", "November", "December" ]) self.monthEnd.setFixedSize(100, 30) self.yearEnd = QComboBox() self.yearEndLabel = QLabel("Semester of Graduation") for year in range(1970, 2050): self.yearEnd.addItem(str(year)) self.yearEnd.setFixedSize(100, 30) #Earliest relevant employment self.monthWorkBegin = QComboBox() self.monthWorkBegin.addItems([ "January", "February", "March", "April", "May", "June", "July", "August", "September", "November", "December" ]) self.monthBegin.setFixedSize(100, 30) self.yearWorkBeginLabel = QLabel( "Earliest Possible Date of Employment") self.yearWorkBegin = QComboBox() self.yearWorkBegin.setFixedSize(100, 30) for year in range(1970, 2050): self.yearWorkBegin.addItem(str(year)) #Latest relevant employment self.monthWorkEnd = QComboBox() self.monthWorkEnd.addItems([ "January", "February", "March", "April", "May", "June", "July", "August", "September", "November", "December" ]) self.monthWorkEnd.setFixedSize(100, 30) self.yearWorkEnd = QComboBox() self.yearWorkEndLabel = QLabel("Latest Possible Date of Employment") for year in range(1970, 2050): self.yearWorkEnd.addItem(str(year)) self.yearWorkEnd.setFixedSize(100, 30) currentYear = date.today().year index = currentYear - 1970 self.yearEnd.setCurrentIndex(index) self.yearBegin.setCurrentIndex(index) self.yearWorkBegin.setCurrentIndex(index) self.yearWorkEnd.setCurrentIndex(index) #Output Directory self.dirLabel = QLabel("Output Directory") self.currentDir = QTextEdit() self.currentDir.setText("Not Selected") self.currentDir.layout() self.currentDir.setFixedSize(300, 30) self.currentDir.setReadOnly(True) self.outputName = QTextEdit() self.outputLabel = QLabel("Output Folder Name") self.outputName.setText("None written") self.outputName.setToolTip( "Type in the name of the new Folder you would like to make for your Resume batch. \n Otherwise, this will use the current timestamp." ) self.outputName.setFixedSize(300, 30) #Select ouput folder button self.outputButton = QPushButton('Select Output Directory') self.outputButton.setToolTip( "Click here to tell the generator where to put this batch of Resumes when it is finished." ) self.outputButton.clicked.connect( lambda: self.openDir(self.currentDir)) self.currentTest = QTextEdit() self.currentTest.setText("SportsCollegeList.csv") #Output Directory self.workLabel = QLabel("Output Directory") self.currentWork = QTextEdit() self.currentWork.setText("SportsCollegeList.csv") self.currentWork.layout() self.currentWork.setFixedSize(300, 30) self.currentWork.setReadOnly(True) #Select work datafolder button self.workButton = QPushButton('Select Work Data (.CSV)') self.workButton.setToolTip( "Click here to select a source file for the employment information in this Resume Batch." ) self.workButton.clicked.connect(lambda: self.openDir(self.currentWork)) #Select School Data self.workLabel = QLabel("Output Directory") self.currentSchool = QTextEdit() self.currentSchool.setText("Not Selected") self.currentSchool.layout() self.currentSchool.setFixedSize(300, 30) self.currentSchool.setReadOnly(True) #Select work datafolder button self.schoolButton = QPushButton('Select Work Data (.CSV)') self.schoolButton.clicked.connect( lambda: self.openDir(self.currentWork)) #Select test data self.testLabel = QLabel("Output Directory") self.currentTest = QTextEdit() self.currentTest.setText("SportsCollegeList.csv") self.currentTest.layout() self.currentTest.setFixedSize(300, 30) self.currentTest.setReadOnly(True) self.testButton = QPushButton('Select Test Data (.CSV)') self.testButton.clicked.connect(lambda: self.openDir(self.currentTest)) #Generate Resumes button self.begin = QPushButton('Generate Resumes') self.begin.clicked.connect( lambda: self.beginTask(self.currentTest.toPlainText())) layout = QGridLayout() self.box0.setLayout(layout) layout.addWidget(self.yearBeginLabel, 0, 0, 1, 2) layout.addWidget(self.monthBegin, 1, 0, 1, 1) layout.addWidget(self.yearBegin, 1, 1, 1, 1) layout.addWidget(self.yearEndLabel, 2, 0, 1, 2) layout.addWidget(self.monthEnd, 3, 0, 1, 1) layout.addWidget(self.yearEnd, 3, 1, 1, 1) layout.addWidget(self.yearWorkBeginLabel, 4, 0, 1, 2) layout.addWidget(self.monthWorkBegin, 5, 0, 1, 1) layout.addWidget(self.yearWorkBegin, 5, 1, 1, 1) layout.addWidget(self.yearWorkEndLabel, 6, 0, 1, 2) layout.addWidget(self.monthWorkEnd, 7, 0, 1, 1) layout.addWidget(self.yearWorkEnd, 7, 1, 1, 1) layout1 = QGridLayout() self.box8.setLayout(layout1) layout1.addWidget(self.testSectionLabel1, 0, 0, 1, 1) layout1.addWidget(self.testSectionLabel3, 1, 0, 1, 1) layout1.addWidget(self.sectionSelect, 0, 1, 1, 1) layout1.addWidget(self.modeSelect, 1, 1, 1, 1) layout2 = QGridLayout() self.box7.setLayout(layout2) layout2.addWidget(self.wLabel, 0, 0, 1, 1) layout2.addWidget(self.bLabel, 1, 0, 1, 1) layout2.addWidget(self.hLabel, 0, 2, 1, 1) layout2.addWidget(self.aLabel, 2, 0, 1, 1) layout2.addWidget(self.wPercent, 0, 1, 1, 1) layout2.addWidget(self.bPercent, 1, 1, 1, 1) layout2.addWidget(self.hPercent, 0, 3, 1, 1) layout2.addWidget(self.aPercent, 2, 1, 1, 1) layout2.addWidget(self.gLabel, 3, 1, 1, 1) layout2.addWidget(self.gPercent, 3, 2, 1, 2) layout = QGridLayout() self.box5.setLayout(layout) layout.addWidget(self.begin, 0, 0, 1, 2) layout3 = QGridLayout() layout3.addWidget(self.testButton, 0, 0, 1, 2) layout3.addWidget(self.currentTest, 1, 0, 1, 2) self.box4.setLayout(layout3) layout4 = QGridLayout() layout4.addWidget(self.outputButton, 0, 0, 1, 2) layout4.addWidget(self.currentDir, 1, 0, 1, 2) layout4.addWidget(self.outputLabel, 2, 0, 1, 2) layout4.addWidget(self.outputName, 3, 0, 1, 2) self.box6.setLayout(layout4) #▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ # def openDir(self, target): fileName = QFileDialog() filenames = list() if fileName.exec_(): fileNames = fileName.selectedFiles() target.setText(fileNames[0]) #▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ # def beginTask(self, path): self.beginGen(path) def beginGen(self, path): self.params["White"] = self.wPercent.toPlainText() self.params["Black"] = self.bPercent.toPlainText() self.params["Hispanic"] = self.hPercent.toPlainText() self.params["Asian"] = self.aPercent.toPlainText() self.params["GenderRatio"] = self.gPercent.toPlainText() self.params["TestMode"] = str(self.modeSelect.currentText()) self.params["TestSection"] = str(self.sectionSelect.currentText()) self.params["BeginYear"] = str(self.yearWorkBegin.currentText()) self.params["EndYear"] = str(self.yearWorkEnd.currentText()) self.params["BeginMonth"] = str(self.monthWorkBegin.currentText()) self.params["EndMonth"] = str(self.monthWorkEnd.currentText()) self.params["workPath"] = "work.csv" self.params["BeginYearEdu"] = str(self.yearBegin.currentText()) self.params["EndYearEdu"] = str(self.yearEnd.currentText()) self.params["BeginMonthEdu"] = str(self.monthBegin.currentText()) self.params["EndMonthEdu"] = str(self.monthEnd.currentText()) print(self.params) Printer.begin(self.currentDir.toPlainText(), path, self.outputName.toPlainText(), self.params)
class RequirementEditor: _editor: Union[None, ResourceRequirementEditor, ArrayRequirementEditor, TemplateRequirementEditor] def __init__(self, parent: QWidget, parent_layout: QVBoxLayout, resource_database: ResourceDatabase, *, on_remove=None): self.parent = parent self.parent_layout = parent_layout self.resource_database = resource_database self._editor = None self._last_resource = None self._last_items = () self._last_comment = None self.line_layout = QHBoxLayout() self.line_layout.setAlignment(Qt.AlignLeft) self.parent_layout.addLayout(self.line_layout) if on_remove is not None: self.remove_button = QtWidgets.QToolButton(parent) self.remove_button.setText("X") self.remove_button.setMaximumWidth(20) self.remove_button.clicked.connect(on_remove) self.line_layout.addWidget(self.remove_button) else: self.remove_button = None self.requirement_type_combo = QComboBox(parent) self.requirement_type_combo.addItem("Resource", ResourceRequirement) self.requirement_type_combo.addItem("Or", RequirementOr) self.requirement_type_combo.addItem("And", RequirementAnd) if resource_database.requirement_template: self.requirement_type_combo.addItem("Template", RequirementTemplate) self.requirement_type_combo.setMaximumWidth(75) self.requirement_type_combo.activated.connect( self._on_change_requirement_type) self.line_layout.addWidget(self.requirement_type_combo) def create_specialized_editor(self, requirement: Requirement): self.requirement_type_combo.setCurrentIndex( self.requirement_type_combo.findData(type(requirement))) if isinstance(requirement, ResourceRequirement): self._editor = ResourceRequirementEditor(self.parent, self.line_layout, self.resource_database, requirement) elif isinstance(requirement, RequirementArrayBase): self._editor = ArrayRequirementEditor(self.parent, self.parent_layout, self.line_layout, self.resource_database, requirement) elif isinstance(requirement, RequirementTemplate): self._editor = TemplateRequirementEditor(self.parent, self.line_layout, self.resource_database, requirement) else: raise RuntimeError( f"Unknown requirement type: {type(requirement)} - {requirement}" ) def _on_change_requirement_type(self): current_requirement = self.current_requirement self._editor.deleteLater() if isinstance(current_requirement, ResourceRequirement): self._last_resource = current_requirement elif isinstance(current_requirement, RequirementArrayBase): self._last_items = current_requirement.items self._last_comment = current_requirement.comment elif isinstance(current_requirement, RequirementTemplate): pass else: raise RuntimeError( f"Unknown requirement type: {type(current_requirement)} - {current_requirement}" ) new_class = self.requirement_type_combo.currentData() if new_class == ResourceRequirement: if self._last_resource is None: new_requirement = _create_default_resource_requirement( self.resource_database) else: new_requirement = self._last_resource elif new_class == RequirementTemplate: new_requirement = _create_default_template_requirement( self.resource_database) else: new_requirement = new_class(self._last_items, self._last_comment) self.create_specialized_editor(new_requirement) def deleteLater(self): if self.remove_button is not None: self.remove_button.deleteLater() self.requirement_type_combo.deleteLater() if self._editor is not None: self._editor.deleteLater() @property def current_requirement(self) -> Requirement: return self._editor.current_requirement
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.proxyModel = QSortFilterProxyModel() self.proxyModel.setDynamicSortFilter(True) self.sourceGroupBox = QGroupBox("Original Model") self.proxyGroupBox = QGroupBox("Sorted/Filtered Model") self.sourceView = QTreeView() self.sourceView.setRootIsDecorated(False) self.sourceView.setAlternatingRowColors(True) self.proxyView = QTreeView() self.proxyView.setRootIsDecorated(False) self.proxyView.setAlternatingRowColors(True) self.proxyView.setModel(self.proxyModel) self.proxyView.setSortingEnabled(True) self.sortCaseSensitivityCheckBox = QCheckBox("Case sensitive sorting") self.filterCaseSensitivityCheckBox = QCheckBox("Case sensitive filter") self.filterPatternLineEdit = QLineEdit() self.filterPatternLineEdit.setClearButtonEnabled(True) self.filterPatternLabel = QLabel("&Filter pattern:") self.filterPatternLabel.setBuddy(self.filterPatternLineEdit) self.filterSyntaxComboBox = QComboBox() self.filterSyntaxComboBox.addItem("Regular expression", REGULAR_EXPRESSION) self.filterSyntaxComboBox.addItem("Wildcard", WILDCARD) self.filterSyntaxComboBox.addItem("Fixed string", FIXED_STRING) self.filterSyntaxLabel = QLabel("Filter &syntax:") self.filterSyntaxLabel.setBuddy(self.filterSyntaxComboBox) self.filterColumnComboBox = QComboBox() self.filterColumnComboBox.addItem("Subject") self.filterColumnComboBox.addItem("Sender") self.filterColumnComboBox.addItem("Date") self.filterColumnLabel = QLabel("Filter &column:") self.filterColumnLabel.setBuddy(self.filterColumnComboBox) self.filterPatternLineEdit.textChanged.connect(self.filterRegExpChanged) self.filterSyntaxComboBox.currentIndexChanged.connect(self.filterRegExpChanged) self.filterColumnComboBox.currentIndexChanged.connect(self.filterColumnChanged) self.filterCaseSensitivityCheckBox.toggled.connect(self.filterRegExpChanged) self.sortCaseSensitivityCheckBox.toggled.connect(self.sortChanged) sourceLayout = QHBoxLayout() sourceLayout.addWidget(self.sourceView) self.sourceGroupBox.setLayout(sourceLayout) proxyLayout = QGridLayout() proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3) proxyLayout.addWidget(self.filterPatternLabel, 1, 0) proxyLayout.addWidget(self.filterPatternLineEdit, 1, 1, 1, 2) proxyLayout.addWidget(self.filterSyntaxLabel, 2, 0) proxyLayout.addWidget(self.filterSyntaxComboBox, 2, 1, 1, 2) proxyLayout.addWidget(self.filterColumnLabel, 3, 0) proxyLayout.addWidget(self.filterColumnComboBox, 3, 1, 1, 2) proxyLayout.addWidget(self.filterCaseSensitivityCheckBox, 4, 0, 1, 2) proxyLayout.addWidget(self.sortCaseSensitivityCheckBox, 4, 2) self.proxyGroupBox.setLayout(proxyLayout) mainLayout = QVBoxLayout() mainLayout.addWidget(self.sourceGroupBox) mainLayout.addWidget(self.proxyGroupBox) self.setLayout(mainLayout) self.setWindowTitle("Basic Sort/Filter Model") self.resize(500, 450) self.proxyView.sortByColumn(1, Qt.AscendingOrder) self.filterColumnComboBox.setCurrentIndex(1) self.filterPatternLineEdit.setText("Andy|Grace") self.filterCaseSensitivityCheckBox.setChecked(True) self.sortCaseSensitivityCheckBox.setChecked(True) def setSourceModel(self, model): self.proxyModel.setSourceModel(model) self.sourceView.setModel(model) def filterRegExpChanged(self): syntax_nr = self.filterSyntaxComboBox.currentData() pattern = self.filterPatternLineEdit.text() if syntax_nr == WILDCARD: pattern = QRegularExpression.wildcardToRegularExpression(pattern) elif syntax_nr == FIXED_STRING: pattern = QRegularExpression.escape(pattern) regExp = QRegularExpression(pattern) if not self.filterCaseSensitivityCheckBox.isChecked(): options = regExp.patternOptions() options |= QRegularExpression.CaseInsensitiveOption regExp.setPatternOptions(options) self.proxyModel.setFilterRegularExpression(regExp) def filterColumnChanged(self): self.proxyModel.setFilterKeyColumn(self.filterColumnComboBox.currentIndex()) def sortChanged(self): if self.sortCaseSensitivityCheckBox.isChecked(): caseSensitivity = Qt.CaseSensitive else: caseSensitivity = Qt.CaseInsensitive self.proxyModel.setSortCaseSensitivity(caseSensitivity)
class RunICADialog(QDialog): def __init__(self, parent, nchan, methods): super().__init__(parent) self.setWindowTitle("Run ICA") vbox = QVBoxLayout(self) grid = QGridLayout() grid.addWidget(QLabel("Method:"), 0, 0) self.method = QComboBox() self.method.addItems(methods) self.method.setCurrentIndex(0) self.method.currentIndexChanged.connect(self.toggle_options) grid.addWidget(self.method, 0, 1) self.extended_label = QLabel("Extended:") grid.addWidget(self.extended_label, 1, 0) self.extended = QCheckBox() self.extended.setChecked(True) grid.addWidget(self.extended, 1, 1) self.ortho_label = QLabel("Orthogonal:") grid.addWidget(self.ortho_label, 2, 0) self.ortho = QCheckBox() self.ortho.setChecked(False) grid.addWidget(self.ortho, 2, 1) if "Picard" not in methods: self.ortho_label.hide() self.ortho.hide() grid.addWidget(QLabel("Number of components:"), 3, 0) self.n_components = QSpinBox() self.n_components.setRange(0, nchan) self.n_components.setValue(nchan) self.n_components.setAlignment(Qt.AlignRight) grid.addWidget(self.n_components, 3, 1) grid.addWidget(QLabel("Exclude bad segments:"), 4, 0) self.exclude_bad_segments = QCheckBox() self.exclude_bad_segments.setChecked(True) grid.addWidget(self.exclude_bad_segments, 4, 1) vbox.addLayout(grid) buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) vbox.addWidget(buttonbox) buttonbox.accepted.connect(self.accept) buttonbox.rejected.connect(self.reject) vbox.setSizeConstraint(QVBoxLayout.SetFixedSize) self.toggle_options() @Slot() def toggle_options(self): """Toggle extended options.""" if self.method.currentText() == "Picard": # enable extended and ortho self.extended_label.setEnabled(True) self.extended.setEnabled(True) self.ortho_label.setEnabled(True) self.ortho.setEnabled(True) elif self.method.currentText() == "Infomax": # enable extended self.extended_label.setEnabled(True) self.extended.setEnabled(True) self.ortho_label.setEnabled(False) self.ortho.setChecked(False) self.ortho.setEnabled(False) else: self.extended_label.setEnabled(False) self.extended.setChecked(False) self.extended.setEnabled(False) self.ortho_label.setEnabled(False) self.ortho.setChecked(False) self.ortho.setEnabled(False)
class VideoFinderAddLink(AddLinkWindow): running_thread = None threadPool = {} def __init__(self, parent, receiver_slot, settings, video_dict={}): super().__init__(parent, receiver_slot, settings, video_dict) self.setWindowTitle( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Video Finder')) self.size_label.hide() # empty lists for no_audio and no_video and video_audio files self.no_audio_list = [] self.no_video_list = [] self.video_audio_list = [] self.media_title = '' # add support for other languages locale = str(self.persepolis_setting.value('settings/locale')) QLocale.setDefault(QLocale(locale)) self.translator = QTranslator() if self.translator.load(':/translations/locales/ui_' + locale, 'ts'): QCoreApplication.installTranslator(self.translator) # extension_label self.extension_label = QLabel(self.link_frame) self.change_name_horizontalLayout.addWidget(self.extension_label) # Fetch Button self.url_submit_pushButtontton = QPushButton(self.link_frame) self.link_horizontalLayout.addWidget(self.url_submit_pushButtontton) # Status Box self.status_box_textEdit = QTextEdit(self.link_frame) self.status_box_textEdit.setMaximumHeight(150) self.link_verticalLayout.addWidget(self.status_box_textEdit) # Select format horizontal layout select_format_horizontalLayout = QHBoxLayout() # Selection Label self.select_format_label = QLabel(self.link_frame) select_format_horizontalLayout.addWidget(self.select_format_label) # Selection combobox self.media_comboBox = QComboBox(self.link_frame) self.media_comboBox.setMinimumWidth(200) select_format_horizontalLayout.addWidget(self.media_comboBox) # Duration label self.duration_label = QLabel(self.link_frame) select_format_horizontalLayout.addWidget(self.duration_label) self.format_selection_frame = QFrame(self) self.format_selection_frame.setLayout(select_format_horizontalLayout) self.link_verticalLayout.addWidget(self.format_selection_frame) # advanced_format_selection_checkBox self.advanced_format_selection_checkBox = QCheckBox(self) self.link_verticalLayout.addWidget( self.advanced_format_selection_checkBox) # advanced_format_selection_frame self.advanced_format_selection_frame = QFrame(self) self.link_verticalLayout.addWidget( self.advanced_format_selection_frame) advanced_format_selection_horizontalLayout = QHBoxLayout( self.advanced_format_selection_frame) # video_format_selection self.video_format_selection_label = QLabel( self.advanced_format_selection_frame) self.video_format_selection_comboBox = QComboBox( self.advanced_format_selection_frame) # audio_format_selection self.audio_format_selection_label = QLabel( self.advanced_format_selection_frame) self.audio_format_selection_comboBox = QComboBox( self.advanced_format_selection_frame) for widget in [ self.video_format_selection_label, self.video_format_selection_comboBox, self.audio_format_selection_label, self.audio_format_selection_comboBox ]: advanced_format_selection_horizontalLayout.addWidget(widget) # Set Texts self.url_submit_pushButtontton.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Fetch Media List')) self.select_format_label.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Select a format')) self.video_format_selection_label.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Video format:')) self.audio_format_selection_label.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Audio format:')) self.advanced_format_selection_checkBox.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Advanced options')) # Add Slot Connections self.url_submit_pushButtontton.setEnabled(False) self.change_name_lineEdit.setEnabled(False) self.ok_pushButton.setEnabled(False) self.download_later_pushButton.setEnabled(False) self.format_selection_frame.setEnabled(True) self.advanced_format_selection_frame.setEnabled(False) self.advanced_format_selection_checkBox.toggled.connect( self.advancedFormatFrame) self.url_submit_pushButtontton.clicked.connect(self.submitClicked) self.media_comboBox.activated.connect( partial(self.mediaSelectionChanged, 'video_audio')) self.video_format_selection_comboBox.activated.connect( partial(self.mediaSelectionChanged, 'video')) self.audio_format_selection_comboBox.activated.connect( partial(self.mediaSelectionChanged, 'audio')) self.link_lineEdit.textChanged.disconnect( super().linkLineChanged) # Should be disconnected. self.link_lineEdit.textChanged.connect(self.linkLineChangedHere) self.setMinimumSize(650, 480) self.status_box_textEdit.hide() self.format_selection_frame.hide() self.advanced_format_selection_frame.hide() self.advanced_format_selection_checkBox.hide() if 'link' in video_dict.keys() and video_dict['link']: self.link_lineEdit.setText(video_dict['link']) self.url_submit_pushButtontton.setEnabled(True) else: # check clipboard clipboard = QApplication.clipboard() text = clipboard.text() if (("tp:/" in text[2:6]) or ("tps:/" in text[2:7])): self.link_lineEdit.setText(str(text)) self.url_submit_pushButtontton.setEnabled(True) def advancedFormatFrame(self, button): if self.advanced_format_selection_checkBox.isChecked(): self.advanced_format_selection_frame.setEnabled(True) self.format_selection_frame.setEnabled(False) self.mediaSelectionChanged( 'video', int(self.video_format_selection_comboBox.currentIndex())) else: self.advanced_format_selection_frame.setEnabled(False) self.format_selection_frame.setEnabled(True) self.mediaSelectionChanged('video_audio', int(self.media_comboBox.currentIndex())) def getReadableSize(self, size): try: return '{:1.2f} MB'.format(int(size) / 1048576) except: return str(size) def getReadableDuration(self, seconds): try: seconds = int(seconds) hours = seconds // 3600 seconds = seconds % 3600 minutes = seconds // 60 seconds = seconds % 60 return '{:02d}:{:02d}:{:02d}'.format(hours, minutes, seconds) except: return str(seconds) # Define native slots def urlChanged(self, value): if ' ' in value or value == '': self.url_submit_pushButtontton.setEnabled(False) self.url_submit_pushButtontton.setToolTip( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Please enter a valid video link')) else: self.url_submit_pushButtontton.setEnabled(True) self.url_submit_pushButtontton.setToolTip('') def submitClicked(self, button=None): # Clear media list self.media_comboBox.clear() self.format_selection_frame.hide() self.advanced_format_selection_checkBox.hide() self.advanced_format_selection_frame.hide() self.video_format_selection_comboBox.clear() self.audio_format_selection_comboBox.clear() self.change_name_lineEdit.clear() self.threadPool.clear() self.change_name_checkBox.setChecked(False) self.video_audio_list.clear() self.no_video_list.clear() self.no_audio_list.clear() self.url_submit_pushButtontton.setEnabled(False) self.status_box_textEdit.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Fetching Media Info...')) self.status_box_textEdit.show() self.ok_pushButton.setEnabled(False) self.download_later_pushButton.setEnabled(False) dictionary_to_send = deepcopy(self.plugin_add_link_dictionary) # More options more_options = self.collectMoreOptions() for k in more_options.keys(): dictionary_to_send[k] = more_options[k] dictionary_to_send['link'] = self.link_lineEdit.text() fetcher_thread = MediaListFetcherThread(self.fetchedResult, dictionary_to_send, self) self.parent.threadPool.append(fetcher_thread) self.parent.threadPool[len(self.parent.threadPool) - 1].start() def fileNameChanged(self, value): if value.strip() == '': self.ok_pushButton.setEnabled(False) def mediaSelectionChanged(self, combobox, index): try: if combobox == 'video_audio': if self.media_comboBox.currentText() == 'Best quality': self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_audio_list[-1]['ext']) else: self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText( '.' + self.video_audio_list[index]['ext']) self.change_name_checkBox.setChecked(True) elif combobox == 'video': if self.video_format_selection_comboBox.currentText( ) != 'No video': self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_audio_list[index - 1]['ext']) self.change_name_checkBox.setChecked(True) else: if self.audio_format_selection_comboBox.currentText( ) != 'No audio': self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_video_list[ int(self.audio_format_selection_comboBox. currentIndex()) - 1]['ext']) self.change_name_checkBox.setChecked(True) else: self.change_name_lineEdit.setChecked(False) elif combobox == 'audio': if self.audio_format_selection_comboBox.currentText( ) != 'No audio' and self.video_format_selection_comboBox.currentText( ) == 'No video': self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_video_list[index - 1]['ext']) self.change_name_checkBox.setChecked(True) elif (self.audio_format_selection_comboBox.currentText() == 'No audio' and self.video_format_selection_comboBox.currentText() != 'No video') or ( self.audio_format_selection_comboBox.currentText() != 'No audio' and self.video_format_selection_comboBox.currentText() != 'No video'): self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_audio_list[ int(self.video_format_selection_comboBox.currentIndex( )) - 1]['ext']) self.change_name_checkBox.setChecked(True) elif self.audio_format_selection_comboBox.currentText( ) == 'No audio' and self.video_format_selection_comboBox.currentText( ) == 'No video': self.change_name_checkBox.setChecked(False) except Exception as ex: logger.sendToLog(ex, "ERROR") def fetchedResult(self, media_dict): self.url_submit_pushButtontton.setEnabled(True) if 'error' in media_dict.keys(): self.status_box_textEdit.setText('<font color="#f11">' + str(media_dict['error']) + '</font>') self.status_box_textEdit.show() else: # Show the media list # add no audio and no video options to the comboboxes self.video_format_selection_comboBox.addItem('No video') self.audio_format_selection_comboBox.addItem('No audio') self.media_title = media_dict['title'] if 'formats' not in media_dict.keys( ) and 'entries' in media_dict.keys(): formats = media_dict['entries'] formats = formats[0] media_dict['formats'] = formats['formats'] elif 'formats' not in media_dict.keys( ) and 'format' in media_dict.keys(): media_dict['formats'] = [media_dict.copy()] try: i = 0 for f in media_dict['formats']: no_audio = False no_video = False text = '' if 'acodec' in f.keys(): # only video, no audio if f['acodec'] == 'none': no_audio = True # resolution if 'height' in f.keys(): text = text + ' ' + '{}p'.format(f['height']) if 'vcodec' in f.keys(): # if f['vcodec'] == 'none' and f['acodec'] != 'none': # continue # No video, show audio bit rate if f['vcodec'] == 'none': text = text + '{}kbps'.format(f['abr']) no_video = True if 'ext' in f.keys(): text = text + ' ' + '.{}'.format(f['ext']) if 'filesize' in f.keys() and f['filesize']: # Youtube api does not supply file size for some formats, so check it. text = text + ' ' + '{}'.format( self.getReadableSize(f['filesize'])) else: # Start spider to find file size input_dict = deepcopy(self.plugin_add_link_dictionary) input_dict['link'] = f['url'] more_options = self.collectMoreOptions() for key in more_options.keys(): input_dict[key] = more_options[key] size_fetcher = FileSizeFetcherThread(input_dict, i) self.threadPool[str(i)] = { 'thread': size_fetcher, 'item_id': i } self.parent.threadPool.append(size_fetcher) self.parent.threadPool[len(self.parent.threadPool) - 1].start() self.parent.threadPool[len(self.parent.threadPool) - 1].FOUND.connect( self.findFileSize) # Add current format to the related comboboxes if no_audio: self.no_audio_list.append(f) self.video_format_selection_comboBox.addItem(text) elif no_video: self.no_video_list.append(f) self.audio_format_selection_comboBox.addItem(text) else: self.video_audio_list.append(f) self.media_comboBox.addItem(text) i = i + 1 self.status_box_textEdit.hide() if 'duration' in media_dict.keys(): self.duration_label.setText( 'Duration ' + self.getReadableDuration(media_dict['duration'])) self.format_selection_frame.show() self.advanced_format_selection_checkBox.show() self.advanced_format_selection_frame.show() self.ok_pushButton.setEnabled(True) self.download_later_pushButton.setEnabled(True) # if we have no options for separate audio and video, then hide advanced_format_selection... if len(self.no_audio_list) == 0 and len( self.no_video_list) == 0: self.advanced_format_selection_checkBox.hide() self.advanced_format_selection_frame.hide() # set index of comboboxes on best available quality. # we have both audio and video if len(self.no_audio_list) != 0 and len( self.no_video_list) != 0: self.media_comboBox.addItem('Best quality') self.media_comboBox.setCurrentIndex( len(self.video_audio_list)) self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_audio_list[-1]['ext']) self.change_name_checkBox.setChecked(True) # video and audio are not separate elif len(self.video_audio_list) != 0: self.media_comboBox.setCurrentIndex( len(self.video_audio_list) - 1) if len(self.no_audio_list) != 0: self.video_format_selection_comboBox.setCurrentIndex( len(self.no_audio_list)) if len(self.no_video_list) != 0: self.audio_format_selection_comboBox.setCurrentIndex( len(self.no_video_list)) # if we have only audio or we have only video then hide media_comboBox if len(self.video_audio_list) == 0: self.media_comboBox.hide() self.select_format_label.hide() # only video if len(self.no_video_list) != 0 and len( self.no_audio_list) == 0: self.mediaSelectionChanged( 'video', int(self.video_format_selection_comboBox. currentIndex())) self.advanced_format_selection_checkBox.setChecked( True) self.advanced_format_selection_checkBox.hide() # only audio elif len(self.no_video_list) == 0 and len( self.no_audio_list) != 0: self.mediaSelectionChanged( 'audio', int(self.audio_format_selection_comboBox. currentIndex())) self.advanced_format_selection_checkBox.setChecked( True) self.advanced_format_selection_checkBox.hide() # audio and video else: self.mediaSelectionChanged( 'video_audio', int(self.media_comboBox.currentIndex())) except Exception as ex: logger.sendToLog(ex, "ERROR") def findFileSize(self, result): try: item_id = self.threadPool[str(result['thread_key'])]['item_id'] if result['file_size'] and result['file_size'] != '0': text = self.media_comboBox.itemText(item_id) self.media_comboBox.setItemText( item_id, '{} - {}'.format(text, result['file_size'])) except Exception as ex: logger.sendToLog(ex, "ERROR") def linkLineChangedHere(self, lineEdit): if str(lineEdit) == '': self.url_submit_pushButtontton.setEnabled(False) else: self.url_submit_pushButtontton.setEnabled(True) # This method collects additional information like proxy ip, user, password etc. def collectMoreOptions(self): options = { 'ip': None, 'port': None, 'proxy_user': None, 'proxy_passwd': None, 'download_user': None, 'download_passwd': None } if self.proxy_checkBox.isChecked(): options['ip'] = self.ip_lineEdit.text() options['port'] = self.port_spinBox.value() options['proxy_user'] = self.proxy_user_lineEdit.text() options['proxy_passwd'] = self.proxy_pass_lineEdit.text() if self.download_checkBox.isChecked(): options['download_user'] = self.download_user_lineEdit.text() options['download_passwd'] = self.download_pass_lineEdit.text() # These info (keys) are required for spider to find file size, because spider() does not check if key exists. additional_info = [ 'header', 'load_cookies', 'user_agent', 'referer', 'out' ] for i in additional_info: if i not in self.plugin_add_link_dictionary.keys(): options[i] = None return options # user submitted information by pressing ok_pushButton, so get information # from VideoFinderAddLink window and return them to the mainwindow with callback! def okButtonPressed(self, download_later, button=None): link_list = [] # separate audio format and video format is selected. if self.advanced_format_selection_checkBox.isChecked(): if self.video_format_selection_comboBox.currentText( ) == 'No video' and self.audio_format_selection_comboBox.currentText( ) != 'No audio': # only audio link must be added to the link_list audio_link = self.no_video_list[ self.audio_format_selection_comboBox.currentIndex() - 1]['url'] link_list.append(audio_link) elif self.video_format_selection_comboBox.currentText( ) != 'No video' and self.audio_format_selection_comboBox.currentText( ) == 'No audio': # only video link must be added to the link_list video_link = self.no_audio_list[ self.video_format_selection_comboBox.currentIndex() - 1]['url'] link_list.append(video_link) elif self.video_format_selection_comboBox.currentText( ) != 'No video' and self.audio_format_selection_comboBox.currentText( ) != 'No audio': # video and audio links must be added to the link_list audio_link = self.no_video_list[ self.audio_format_selection_comboBox.currentIndex() - 1]['url'] video_link = self.no_audio_list[ self.video_format_selection_comboBox.currentIndex() - 1]['url'] link_list = [video_link, audio_link] elif self.video_format_selection_comboBox.currentText( ) == 'No video' and self.audio_format_selection_comboBox.currentText( ) == 'No audio': # no video and audio is selected! REALLY?!. user is DRUNK! close the window! :)) self.close() else: if self.media_comboBox.currentText() == 'Best quality': # the last item in no_video_list and no_audio_list are the best. video_link = self.no_audio_list[-1]['url'] audio_link = self.no_video_list[-1]['url'] link_list = [video_link, audio_link] else: audio_and_video_link = self.video_audio_list[ self.media_comboBox.currentIndex()]['url'] link_list.append(audio_and_video_link) # write user's new inputs in persepolis_setting for next time :) self.persepolis_setting.setValue('add_link_initialization/ip', self.ip_lineEdit.text()) self.persepolis_setting.setValue('add_link_initialization/port', self.port_spinBox.value()) self.persepolis_setting.setValue('add_link_initialization/proxy_user', self.proxy_user_lineEdit.text()) self.persepolis_setting.setValue( 'add_link_initialization/download_user', self.download_user_lineEdit.text()) # get proxy information if not (self.proxy_checkBox.isChecked()): ip = None port = None proxy_user = None proxy_passwd = None else: ip = self.ip_lineEdit.text() if not (ip): ip = None port = self.port_spinBox.value() if not (port): port = None proxy_user = self.proxy_user_lineEdit.text() if not (proxy_user): proxy_user = None proxy_passwd = self.proxy_pass_lineEdit.text() if not (proxy_passwd): proxy_passwd = None # get download username and password information if not (self.download_checkBox.isChecked()): download_user = None download_passwd = None else: download_user = self.download_user_lineEdit.text() if not (download_user): download_user = None download_passwd = self.download_pass_lineEdit.text() if not (download_passwd): download_passwd = None # check that if user limits download speed. if not (self.limit_checkBox.isChecked()): limit = 0 else: if self.limit_comboBox.currentText() == "KiB/s": limit = str(self.limit_spinBox.value()) + str("K") else: limit = str(self.limit_spinBox.value()) + str("M") # get start time for download if user set that. if not (self.start_checkBox.isChecked()): start_time = None else: start_time = self.start_time_qDataTimeEdit.text() # get end time for download if user set that. if not (self.end_checkBox.isChecked()): end_time = None else: end_time = self.end_time_qDateTimeEdit.text() # set name for file(s) if self.change_name_checkBox.isChecked(): name = str(self.change_name_lineEdit.text()) if name == '': name = 'video_finder_file' else: name = 'video_finder_file' # video finder always finds extension # but if it can't find file extension # use mp4 for extension. if str(self.extension_label.text()) == '': extension = '.mp4' else: extension = str(self.extension_label.text()) # did user select separate audio and video? if len(link_list) == 2: video_name = name + extension audio_name = name + '.' + \ str(self.no_video_list[self.audio_format_selection_comboBox.currentIndex() - 1]['ext']) name_list = [video_name, audio_name] else: name_list = [name + extension] # get number of connections connections = self.connections_spinBox.value() # get download_path download_path = self.download_folder_lineEdit.text() # referer if self.referer_lineEdit.text() != '': referer = self.referer_lineEdit.text() else: referer = None # header if self.header_lineEdit.text() != '': header = self.header_lineEdit.text() else: header = None # user_agent if self.user_agent_lineEdit.text() != '': user_agent = self.user_agent_lineEdit.text() else: user_agent = None # load_cookies if self.load_cookies_lineEdit.text() != '': load_cookies = self.load_cookies_lineEdit.text() else: load_cookies = None add_link_dictionary_list = [] if len(link_list) == 1: # save information in a dictionary(add_link_dictionary). add_link_dictionary = { 'referer': referer, 'header': header, 'user_agent': user_agent, 'load_cookies': load_cookies, 'out': name_list[0], 'start_time': start_time, 'end_time': end_time, 'link': link_list[0], 'ip': ip, 'port': port, 'proxy_user': proxy_user, 'proxy_passwd': proxy_passwd, 'download_user': download_user, 'download_passwd': download_passwd, 'connections': connections, 'limit_value': limit, 'download_path': download_path } add_link_dictionary_list.append(add_link_dictionary) else: video_add_link_dictionary = { 'referer': referer, 'header': header, 'user_agent': user_agent, 'load_cookies': load_cookies, 'out': name_list[0], 'start_time': start_time, 'end_time': end_time, 'link': link_list[0], 'ip': ip, 'port': port, 'proxy_user': proxy_user, 'proxy_passwd': proxy_passwd, 'download_user': download_user, 'download_passwd': download_passwd, 'connections': connections, 'limit_value': limit, 'download_path': download_path } audio_add_link_dictionary = { 'referer': referer, 'header': header, 'user_agent': user_agent, 'load_cookies': load_cookies, 'out': name_list[1], 'start_time': None, 'end_time': end_time, 'link': link_list[1], 'ip': ip, 'port': port, 'proxy_user': proxy_user, 'proxy_passwd': proxy_passwd, 'download_user': download_user, 'download_passwd': download_passwd, 'connections': connections, 'limit_value': limit, 'download_path': download_path } add_link_dictionary_list = [ video_add_link_dictionary, audio_add_link_dictionary ] # get category of download category = str(self.add_queue_comboBox.currentText()) del self.plugin_add_link_dictionary # return information to mainwindow self.callback(add_link_dictionary_list, download_later, category) # close window self.close()
def combo_set_to_value(combo: QtWidgets.QComboBox, item): combo.setCurrentIndex(combo.findData(item))
class UIDrawROIWindow: def setup_ui(self, draw_roi_window_instance, rois, dataset_rtss, signal_roi_drawn): """ this function is responsible for setting up the UI for DrawROIWindow param draw_roi_window_instance: the current drawing window instance. :param rois: the rois to be drawn :param dataset_rtss: the rtss to be written to :param signal_roi_drawn: the signal to be triggered when roi is drawn """ self.patient_dict_container = PatientDictContainer() self.rois = rois self.dataset_rtss = dataset_rtss self.signal_roi_drawn = signal_roi_drawn self.drawn_roi_list = {} self.standard_organ_names = [] self.standard_volume_names = [] self.standard_names = [] # Combination of organ and volume self.ROI_name = None # Selected ROI name self.target_pixel_coords = [] # This will contain the new pixel # coordinates specified by the min and max self.drawingROI = None self.slice_changed = False self.drawing_tool_radius = INITIAL_DRAWING_TOOL_RADIUS self.keep_empty_pixel = False # pixel density self.target_pixel_coords_single_array = [] # 1D array self.draw_roi_window_instance = draw_roi_window_instance self.colour = None self.ds = None self.zoom = 1.0 self.upper_limit = None self.lower_limit = None # is_four_view is set to True to stop the SUV2ROI button from appearing self.dicom_view = DicomAxialView(is_four_view=True) self.current_slice = self.dicom_view.slider.value() self.dicom_view.slider.valueChanged.connect(self.slider_value_changed) self.init_layout() QtCore.QMetaObject.connectSlotsByName(draw_roi_window_instance) def retranslate_ui(self, draw_roi_window_instance): """ this function retranslate the ui for draw roi window :param draw_roi_window_instance: the current drawing window instance. """ _translate = QtCore.QCoreApplication.translate draw_roi_window_instance.setWindowTitle( _translate("DrawRoiWindowInstance", "OnkoDICOM - Draw Region Of Interest")) self.roi_name_label.setText( _translate("ROINameLabel", "Region of Interest: ")) self.roi_name_line_edit.setText(_translate("ROINameLineEdit", "")) self.image_slice_number_label.setText( _translate("ImageSliceNumberLabel", "Slice Number: ")) self.image_slice_number_line_edit.setText( _translate("ImageSliceNumberLineEdit", str(self.dicom_view.current_slice_number))) self.image_slice_number_transect_button.setText( _translate("ImageSliceNumberTransectButton", "Transect")) self.image_slice_number_box_draw_button.setText( _translate("ImageSliceNumberBoxDrawButton", "Set Bounds")) self.image_slice_number_draw_button.setText( _translate("ImageSliceNumberDrawButton", "Draw")) self.image_slice_number_move_forward_button.setText( _translate("ImageSliceNumberMoveForwardButton", "")) self.image_slice_number_move_backward_button.setText( _translate("ImageSliceNumberMoveBackwardButton", "")) self.draw_roi_window_instance_save_button.setText( _translate("DrawRoiWindowInstanceSaveButton", "Save")) self.draw_roi_window_instance_cancel_button.setText( _translate("DrawRoiWindowInstanceCancelButton", "Cancel")) self.internal_hole_max_label.setText( _translate("InternalHoleLabel", "Maximum internal hole size (pixels): ")) self.internal_hole_max_line_edit.setText( _translate("InternalHoleInput", "9")) self.isthmus_width_max_label.setText( _translate("IsthmusWidthLabel", "Maximum isthmus width size (pixels): ")) self.isthmus_width_max_line_edit.setText( _translate("IsthmusWidthInput", "5")) self.min_pixel_density_label.setText( _translate("MinPixelDensityLabel", "Minimum density (pixels): ")) self.min_pixel_density_line_edit.setText( _translate("MinPixelDensityInput", "")) self.max_pixel_density_label.setText( _translate("MaxPixelDensityLabel", "Maximum density (pixels): ")) self.max_pixel_density_line_edit.setText( _translate("MaxPixelDensityInput", "")) self.toggle_keep_empty_pixel_label.setText( _translate("ToggleKeepEmptyPixelLabel", "Keep empty pixel: ")) self.draw_roi_window_viewport_zoom_label.setText( _translate("DrawRoiWindowViewportZoomLabel", "Zoom: ")) self.draw_roi_window_cursor_radius_change_label.setText( _translate("DrawRoiWindowCursorRadiusChangeLabel", "Cursor Radius: ")) self.draw_roi_window_instance_action_reset_button.setText( _translate("DrawRoiWindowInstanceActionClearButton", "Reset")) def init_layout(self): """ Initialize the layout for the DICOM View tab. Add the view widget and the slider in the layout. Add the whole container 'tab2_view' as a tab in the main page. """ # Initialise a DrawROIWindow 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() window_icon = QIcon() window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")), QIcon.Normal, QIcon.Off) self.draw_roi_window_instance.setObjectName("DrawRoiWindowInstance") self.draw_roi_window_instance.setWindowIcon(window_icon) # Creating a form box to hold all buttons and input fields self.draw_roi_window_input_container_box = QFormLayout() self.draw_roi_window_input_container_box. \ setObjectName("DrawRoiWindowInputContainerBox") self.draw_roi_window_input_container_box. \ setLabelAlignment(Qt.AlignLeft) # Create a label for denoting the ROI name self.roi_name_label = QLabel() self.roi_name_label.setObjectName("ROINameLabel") self.roi_name_line_edit = QLineEdit() # Create an input box for ROI name self.roi_name_line_edit.setObjectName("ROINameLineEdit") self.roi_name_line_edit.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.roi_name_line_edit.resize( self.roi_name_line_edit.sizeHint().width(), self.roi_name_line_edit.sizeHint().height()) self.roi_name_line_edit.setEnabled(False) self.draw_roi_window_input_container_box. \ addRow(self.roi_name_label, self.roi_name_line_edit) # Create horizontal box to store image slice number and backward, # forward buttons self.image_slice_number_box = QHBoxLayout() self.image_slice_number_box.setObjectName("ImageSliceNumberBox") # Create a label for denoting the Image Slice Number self.image_slice_number_label = QLabel() self.image_slice_number_label.setObjectName("ImageSliceNumberLabel") self.image_slice_number_box.addWidget(self.image_slice_number_label) # Create a line edit for containing the image slice number self.image_slice_number_line_edit = QLineEdit() self.image_slice_number_line_edit. \ setObjectName("ImageSliceNumberLineEdit") self.image_slice_number_line_edit. \ setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.image_slice_number_line_edit.resize( self.image_slice_number_line_edit.sizeHint().width(), self.image_slice_number_line_edit.sizeHint().height()) self.image_slice_number_line_edit.setCursorPosition(0) self.image_slice_number_line_edit.setEnabled(False) self.image_slice_number_box. \ addWidget(self.image_slice_number_line_edit) # Create a button to move backward to the previous image self.image_slice_number_move_backward_button = QPushButton() self.image_slice_number_move_backward_button. \ setObjectName("ImageSliceNumberMoveBackwardButton") self.image_slice_number_move_backward_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.image_slice_number_move_backward_button.resize(QSize(24, 24)) self.image_slice_number_move_backward_button.clicked. \ connect(self.onBackwardClicked) icon_move_backward = QtGui.QIcon() icon_move_backward.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/backward_slide_icon.png'))) self.image_slice_number_move_backward_button.setIcon( icon_move_backward) self.image_slice_number_box. \ addWidget(self.image_slice_number_move_backward_button) # Create a button to move forward to the next image self.image_slice_number_move_forward_button = QPushButton() self.image_slice_number_move_forward_button. \ setObjectName("ImageSliceNumberMoveForwardButton") self.image_slice_number_move_forward_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.image_slice_number_move_forward_button.resize(QSize(24, 24)) self.image_slice_number_move_forward_button.clicked. \ connect(self.onForwardClicked) icon_move_forward = QtGui.QIcon() icon_move_forward.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/forward_slide_icon.png'))) self.image_slice_number_move_forward_button.setIcon(icon_move_forward) self.image_slice_number_box. \ addWidget(self.image_slice_number_move_forward_button) self.draw_roi_window_input_container_box. \ addRow(self.image_slice_number_box) # Create a horizontal box for containing the zoom function self.draw_roi_window_viewport_zoom_box = QHBoxLayout() self.draw_roi_window_viewport_zoom_box.setObjectName( "DrawRoiWindowViewportZoomBox") # Create a label for zooming self.draw_roi_window_viewport_zoom_label = QLabel() self.draw_roi_window_viewport_zoom_label. \ setObjectName("DrawRoiWindowViewportZoomLabel") # Create an input box for zoom factor self.draw_roi_window_viewport_zoom_input = QLineEdit() self.draw_roi_window_viewport_zoom_input. \ setObjectName("DrawRoiWindowViewportZoomInput") self.draw_roi_window_viewport_zoom_input. \ setText("{:.2f}".format(self.zoom * 100) + "%") self.draw_roi_window_viewport_zoom_input.setCursorPosition(0) self.draw_roi_window_viewport_zoom_input.setEnabled(False) self.draw_roi_window_viewport_zoom_input. \ setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.draw_roi_window_viewport_zoom_input.resize( self.draw_roi_window_viewport_zoom_input.sizeHint().width(), self.draw_roi_window_viewport_zoom_input.sizeHint().height()) # Create 2 buttons for zooming in and out # Zoom In Button self.draw_roi_window_viewport_zoom_in_button = QPushButton() self.draw_roi_window_viewport_zoom_in_button. \ setObjectName("DrawRoiWindowViewportZoomInButton") self.draw_roi_window_viewport_zoom_in_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.draw_roi_window_viewport_zoom_in_button.resize(QSize(24, 24)) self.draw_roi_window_viewport_zoom_in_button. \ setProperty("QPushButtonClass", "zoom-button") icon_zoom_in = QtGui.QIcon() icon_zoom_in.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/zoom_in_icon.png'))) self.draw_roi_window_viewport_zoom_in_button.setIcon(icon_zoom_in) self.draw_roi_window_viewport_zoom_in_button.clicked. \ connect(self.onZoomInClicked) # Zoom Out Button self.draw_roi_window_viewport_zoom_out_button = QPushButton() self.draw_roi_window_viewport_zoom_out_button. \ setObjectName("DrawRoiWindowViewportZoomOutButton") self.draw_roi_window_viewport_zoom_out_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.draw_roi_window_viewport_zoom_out_button.resize(QSize(24, 24)) self.draw_roi_window_viewport_zoom_out_button. \ setProperty("QPushButtonClass", "zoom-button") icon_zoom_out = QtGui.QIcon() icon_zoom_out.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/zoom_out_icon.png'))) self.draw_roi_window_viewport_zoom_out_button.setIcon(icon_zoom_out) self.draw_roi_window_viewport_zoom_out_button.clicked. \ connect(self.onZoomOutClicked) self.draw_roi_window_viewport_zoom_box. \ addWidget(self.draw_roi_window_viewport_zoom_label) self.draw_roi_window_viewport_zoom_box. \ addWidget(self.draw_roi_window_viewport_zoom_input) self.draw_roi_window_viewport_zoom_box. \ addWidget(self.draw_roi_window_viewport_zoom_out_button) self.draw_roi_window_viewport_zoom_box. \ addWidget(self.draw_roi_window_viewport_zoom_in_button) self.draw_roi_window_input_container_box. \ addRow(self.draw_roi_window_viewport_zoom_box) self.init_cursor_radius_change_box() # Create field to toggle two options: Keep empty pixel or fill empty # pixel when using draw cursor self.toggle_keep_empty_pixel_box = QHBoxLayout() self.toggle_keep_empty_pixel_label = QLabel() self.toggle_keep_empty_pixel_label. \ setObjectName("ToggleKeepEmptyPixelLabel") # Create input for min pixel size self.toggle_keep_empty_pixel_combo_box = QComboBox() self.toggle_keep_empty_pixel_combo_box.addItems(["Off", "On"]) self.toggle_keep_empty_pixel_combo_box.setCurrentIndex(0) self.toggle_keep_empty_pixel_combo_box.setEnabled(False) self.toggle_keep_empty_pixel_combo_box. \ setObjectName("ToggleKeepEmptyPixelComboBox") self.toggle_keep_empty_pixel_combo_box. \ setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.toggle_keep_empty_pixel_combo_box.resize( self.toggle_keep_empty_pixel_combo_box.sizeHint().width(), self.toggle_keep_empty_pixel_combo_box.sizeHint().height()) self.toggle_keep_empty_pixel_combo_box.currentIndexChanged.connect( self.toggle_keep_empty_pixel_box_index_changed) self.toggle_keep_empty_pixel_box. \ addWidget(self.toggle_keep_empty_pixel_label) self.toggle_keep_empty_pixel_box. \ addWidget(self.toggle_keep_empty_pixel_combo_box) self.draw_roi_window_input_container_box. \ addRow(self.toggle_keep_empty_pixel_box) # Create a horizontal box for transect and draw button self.draw_roi_window_transect_draw_box = QHBoxLayout() self.draw_roi_window_transect_draw_box. \ setObjectName("DrawRoiWindowTransectDrawBox") # Create a transect button self.image_slice_number_transect_button = QPushButton() self.image_slice_number_transect_button. \ setObjectName("ImageSliceNumberTransectButton") self.image_slice_number_transect_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.image_slice_number_transect_button.resize( self.image_slice_number_transect_button.sizeHint().width(), self.image_slice_number_transect_button.sizeHint().height()) self.image_slice_number_transect_button.clicked. \ connect(self.transect_handler) icon_transect = QtGui.QIcon() icon_transect.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/transect_icon.png'))) self.image_slice_number_transect_button.setIcon(icon_transect) self.draw_roi_window_transect_draw_box. \ addWidget(self.image_slice_number_transect_button) # Create a bounding box button self.image_slice_number_box_draw_button = QPushButton() self.image_slice_number_box_draw_button. \ setObjectName("ImageSliceNumberBoxDrawButton") self.image_slice_number_box_draw_button.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.image_slice_number_box_draw_button.resize( self.image_slice_number_box_draw_button.sizeHint().width(), self.image_slice_number_box_draw_button.sizeHint().height()) self.image_slice_number_box_draw_button.clicked. \ connect(self.onBoxDrawClicked) icon_box_draw = QtGui.QIcon() icon_box_draw.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/draw_bound_icon.png'))) self.image_slice_number_box_draw_button.setIcon(icon_box_draw) self.draw_roi_window_transect_draw_box. \ addWidget(self.image_slice_number_box_draw_button) # Create a draw button self.image_slice_number_draw_button = QPushButton() self.image_slice_number_draw_button. \ setObjectName("ImageSliceNumberDrawButton") self.image_slice_number_draw_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.image_slice_number_draw_button.resize( self.image_slice_number_draw_button.sizeHint().width(), self.image_slice_number_draw_button.sizeHint().height()) self.image_slice_number_draw_button.clicked.connect(self.onDrawClicked) icon_draw = QtGui.QIcon() icon_draw.addPixmap( QtGui.QPixmap(resource_path('res/images/btn-icons/draw_icon.png'))) self.image_slice_number_draw_button.setIcon(icon_draw) self.draw_roi_window_transect_draw_box. \ addWidget(self.image_slice_number_draw_button) self.draw_roi_window_input_container_box. \ addRow(self.draw_roi_window_transect_draw_box) # Create a contour preview button self.row_preview_layout = QtWidgets.QHBoxLayout() self.button_contour_preview = QtWidgets.QPushButton("Preview contour") self.button_contour_preview.clicked.connect(self.onPreviewClicked) self.row_preview_layout.addWidget(self.button_contour_preview) self.draw_roi_window_input_container_box. \ addRow(self.row_preview_layout) icon_preview = QtGui.QIcon() icon_preview.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/preview_icon.png'))) self.button_contour_preview.setIcon(icon_preview) # Create input line edit for alpha value self.label_alpha_value = QtWidgets.QLabel("Alpha value:") self.input_alpha_value = QtWidgets.QLineEdit("0.2") self.input_alpha_value. \ setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.input_alpha_value.resize( self.input_alpha_value.sizeHint().width(), self.input_alpha_value.sizeHint().height()) self.input_alpha_value.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box. \ addRow(self.label_alpha_value, self.input_alpha_value) # Create a label for denoting the max internal hole size self.internal_hole_max_label = QLabel() self.internal_hole_max_label.setObjectName("InternalHoleLabel") # Create input for max internal hole size self.internal_hole_max_line_edit = QLineEdit() self.internal_hole_max_line_edit.setObjectName("InternalHoleInput") self.internal_hole_max_line_edit. \ setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.internal_hole_max_line_edit.resize( self.internal_hole_max_line_edit.sizeHint().width(), self.internal_hole_max_line_edit.sizeHint().height()) self.internal_hole_max_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box.addRow( self.internal_hole_max_label, self.internal_hole_max_line_edit) # Create a label for denoting the isthmus width size self.isthmus_width_max_label = QLabel() self.isthmus_width_max_label.setObjectName("IsthmusWidthLabel") # Create input for max isthmus width size self.isthmus_width_max_line_edit = QLineEdit() self.isthmus_width_max_line_edit.setObjectName("IsthmusWidthInput") self.isthmus_width_max_line_edit.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.isthmus_width_max_line_edit.resize( self.isthmus_width_max_line_edit.sizeHint().width(), self.isthmus_width_max_line_edit.sizeHint().height()) self.isthmus_width_max_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box.addRow( self.isthmus_width_max_label, self.isthmus_width_max_line_edit) # Create a label for denoting the minimum pixel density self.min_pixel_density_label = QLabel() self.min_pixel_density_label.setObjectName("MinPixelDensityLabel") # Create input for min pixel size self.min_pixel_density_line_edit = QLineEdit() self.min_pixel_density_line_edit.setObjectName("MinPixelDensityInput") self.min_pixel_density_line_edit.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.min_pixel_density_line_edit.resize( self.min_pixel_density_line_edit.sizeHint().width(), self.min_pixel_density_line_edit.sizeHint().height()) self.min_pixel_density_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box.addRow( self.min_pixel_density_label, self.min_pixel_density_line_edit) # Create a label for denoting the minimum pixel density self.max_pixel_density_label = QLabel() self.max_pixel_density_label.setObjectName("MaxPixelDensityLabel") # Create input for min pixel size self.max_pixel_density_line_edit = QLineEdit() self.max_pixel_density_line_edit.setObjectName("MaxPixelDensityInput") self.max_pixel_density_line_edit. \ setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.max_pixel_density_line_edit.resize( self.max_pixel_density_line_edit.sizeHint().width(), self.max_pixel_density_line_edit.sizeHint().height()) self.max_pixel_density_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box.addRow( self.max_pixel_density_label, self.max_pixel_density_line_edit) # Create a button to clear the draw self.draw_roi_window_instance_action_reset_button = QPushButton() self.draw_roi_window_instance_action_reset_button. \ setObjectName("DrawRoiWindowInstanceActionClearButton") self.draw_roi_window_instance_action_reset_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) reset_button = self.draw_roi_window_instance_action_reset_button self.draw_roi_window_instance_action_reset_button.resize( reset_button.sizeHint().width(), reset_button.sizeHint().height()) self.draw_roi_window_instance_action_reset_button.clicked. \ connect(self.onResetClicked) self.draw_roi_window_instance_action_reset_button. \ setProperty("QPushButtonClass", "fail-button") icon_clear_roi_draw = QtGui.QIcon() icon_clear_roi_draw.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/reset_roi_draw_icon.png'))) self.draw_roi_window_instance_action_reset_button. \ setIcon(icon_clear_roi_draw) self.draw_roi_window_input_container_box. \ addRow(self.draw_roi_window_instance_action_reset_button) # Create a horizontal box for saving and cancel the drawing self.draw_roi_window_cancel_save_box = QHBoxLayout() self.draw_roi_window_cancel_save_box. \ setObjectName("DrawRoiWindowCancelSaveBox") # Create an exit button to cancel the drawing # Add a button to go back/exit from the application self.draw_roi_window_instance_cancel_button = QPushButton() self.draw_roi_window_instance_cancel_button. \ setObjectName("DrawRoiWindowInstanceCancelButton") self.draw_roi_window_instance_cancel_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.draw_roi_window_instance_cancel_button.resize( self.draw_roi_window_instance_cancel_button.sizeHint().width(), self.draw_roi_window_instance_cancel_button.sizeHint().height()) self.draw_roi_window_instance_cancel_button. \ setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.draw_roi_window_instance_cancel_button.clicked. \ connect(self.onCancelButtonClicked) self.draw_roi_window_instance_cancel_button. \ setProperty("QPushButtonClass", "fail-button") icon_cancel = QtGui.QIcon() icon_cancel.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/cancel_icon.png'))) self.draw_roi_window_instance_cancel_button.setIcon(icon_cancel) self.draw_roi_window_cancel_save_box. \ addWidget(self.draw_roi_window_instance_cancel_button) # Create a save button to save all the changes self.draw_roi_window_instance_save_button = QPushButton() self.draw_roi_window_instance_save_button. \ setObjectName("DrawRoiWindowInstanceSaveButton") self.draw_roi_window_instance_save_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.draw_roi_window_instance_save_button.resize( self.draw_roi_window_instance_save_button.sizeHint().width(), self.draw_roi_window_instance_save_button.sizeHint().height()) self.draw_roi_window_instance_save_button. \ setProperty("QPushButtonClass", "success-button") icon_save = QtGui.QIcon() icon_save.addPixmap( QtGui.QPixmap(resource_path('res/images/btn-icons/save_icon.png'))) self.draw_roi_window_instance_save_button.setIcon(icon_save) self.draw_roi_window_instance_save_button.clicked. \ connect(self.onSaveClicked) self.draw_roi_window_cancel_save_box. \ addWidget(self.draw_roi_window_instance_save_button) self.draw_roi_window_input_container_box. \ addRow(self.draw_roi_window_cancel_save_box) # Creating a horizontal box to hold the ROI view and slider self.draw_roi_window_instance_view_box = QHBoxLayout() self.draw_roi_window_instance_view_box. \ setObjectName("DrawRoiWindowInstanceViewBox") # Add View and Slider into horizontal box self.draw_roi_window_instance_view_box.addWidget(self.dicom_view) # Create a widget to hold the image slice box self.draw_roi_window_instance_view_widget = QWidget() self.draw_roi_window_instance_view_widget.setObjectName( "DrawRoiWindowInstanceActionWidget") self.draw_roi_window_instance_view_widget.setLayout( self.draw_roi_window_instance_view_box) # Create a horizontal box for containing the input fields and the # viewport self.draw_roi_window_main_box = QHBoxLayout() self.draw_roi_window_main_box.setObjectName("DrawRoiWindowMainBox") self.draw_roi_window_main_box. \ addLayout(self.draw_roi_window_input_container_box, 1) self.draw_roi_window_main_box. \ addWidget(self.draw_roi_window_instance_view_widget, 11) # Create a new central widget to hold the vertical box layout self.draw_roi_window_instance_central_widget = QWidget() self.draw_roi_window_instance_central_widget. \ setObjectName("DrawRoiWindowInstanceCentralWidget") self.draw_roi_window_instance_central_widget.setLayout( self.draw_roi_window_main_box) self.retranslate_ui(self.draw_roi_window_instance) self.draw_roi_window_instance.setStyleSheet(stylesheet) self.draw_roi_window_instance. \ setCentralWidget(self.draw_roi_window_instance_central_widget) QtCore.QMetaObject.connectSlotsByName(self.draw_roi_window_instance) def slider_value_changed(self): """ actions to be taken when slider value changes """ image_slice_number = self.current_slice # save progress self.save_drawing_progress(image_slice_number) self.set_current_slice(self.dicom_view.slider.value()) def set_current_slice(self, slice_number): """ set the current slice :param slice_number: the slice number to be set """ self.image_slice_number_line_edit.setText(str(slice_number + 1)) self.current_slice = slice_number self.dicom_view.update_view() # check if this slice has any drawings before if self.drawn_roi_list.get(self.current_slice) is not None: self.drawingROI = self.drawn_roi_list[ self.current_slice]['drawingROI'] self.ds = self.drawn_roi_list[self.current_slice]['ds'] self.dicom_view.view.setScene(self.drawingROI) self.enable_cursor_radius_change_box() self.drawingROI.clear_cursor(self.drawing_tool_radius) else: self.disable_cursor_radius_change_box() self.ds = None def onZoomInClicked(self): """ This function is used for zooming in button """ self.dicom_view.zoom *= 1.05 self.dicom_view.update_view(zoom_change=True) if self.drawingROI \ and self.drawingROI.current_slice == self.current_slice: self.dicom_view.view.setScene(self.drawingROI) self.draw_roi_window_viewport_zoom_input.setText( "{:.2f}".format(self.dicom_view.zoom * 100) + "%") self.draw_roi_window_viewport_zoom_input.setCursorPosition(0) def onZoomOutClicked(self): """ This function is used for zooming out button """ self.dicom_view.zoom /= 1.05 self.dicom_view.update_view(zoom_change=True) if self.drawingROI \ and self.drawingROI.current_slice == self.current_slice: self.dicom_view.view.setScene(self.drawingROI) self.draw_roi_window_viewport_zoom_input. \ setText("{:.2f}".format(self.dicom_view.zoom * 100) + "%") self.draw_roi_window_viewport_zoom_input.setCursorPosition(0) def toggle_keep_empty_pixel_box_index_changed(self): self.keep_empty_pixel = self.toggle_keep_empty_pixel_combo_box. \ currentText() == "On" self.drawingROI.keep_empty_pixel = self.keep_empty_pixel def onCancelButtonClicked(self): """ This function is used for canceling the drawing """ self.closeWindow() def onBackwardClicked(self): """ This function is used when backward button is clicked """ image_slice_number = self.current_slice # save progress if self.save_drawing_progress(image_slice_number): # Backward will only execute if current image slice is above 0. if int(image_slice_number) > 0: # decrements slice by 1 and update slider to move to correct # position self.dicom_view.slider.setValue(image_slice_number - 1) def onForwardClicked(self): """ This function is used when forward button is clicked """ image_slice_number = self.current_slice # save progress if self.save_drawing_progress(image_slice_number): pixmaps = self.patient_dict_container.get("pixmaps_axial") total_slices = len(pixmaps) # Forward will only execute if current image slice is below the # total number of slices. if int(image_slice_number) < total_slices: # increments slice by 1 and update slider to move to correct # position self.dicom_view.slider.setValue(image_slice_number + 1) def onResetClicked(self): """ This function is used when reset button is clicked """ self.dicom_view.image_display() self.dicom_view.update_view() self.isthmus_width_max_line_edit.setText("5") self.internal_hole_max_line_edit.setText("9") self.min_pixel_density_line_edit.setText("") self.max_pixel_density_line_edit.setText("") if hasattr(self, 'bounds_box_draw'): delattr(self, 'bounds_box_draw') if hasattr(self, 'drawingROI'): delattr(self, 'drawingROI') self.ds = None def transect_handler(self): """ Function triggered when the Transect button is pressed from the menu. """ pixmaps = self.patient_dict_container.get("pixmaps_axial") id = self.current_slice dt = self.patient_dict_container.dataset[id] rowS = dt.PixelSpacing[0] colS = dt.PixelSpacing[1] dt.convert_pixel_data() MainPageCallClass().run_transect( self.draw_roi_window_instance, self.dicom_view.view, pixmaps[id], dt._pixel_array.transpose(), rowS, colS, is_roi_draw=True, ) def save_drawing_progress(self, image_slice_number): """ this function saves the drawing progress on current slice :param image_slice_number: the slice number to be saved """ if self.slice_changed: if hasattr(self, 'drawingROI') and self.drawingROI \ and self.ds is not None \ and len(self.drawingROI.target_pixel_coords) != 0: alpha = float(self.input_alpha_value.text()) pixel_hull_list = calculate_concave_hull_of_points( self.drawingROI.target_pixel_coords, alpha) coord_list = [] for pixel_hull in pixel_hull_list: coord_list.append(pixel_hull) self.drawn_roi_list[image_slice_number] = { 'coords': coord_list, 'ds': self.ds, 'drawingROI': self.drawingROI } self.slice_changed = False return True else: return True return True def on_transect_close(self): """ Function triggered when transect is closed """ if self.upper_limit and self.lower_limit: self.min_pixel_density_line_edit.setText(str(self.lower_limit)) self.max_pixel_density_line_edit.setText(str(self.upper_limit)) self.dicom_view.update_view() def onDrawClicked(self): """ Function triggered when the Draw button is pressed from the menu. """ pixmaps = self.patient_dict_container.get("pixmaps_axial") if self.min_pixel_density_line_edit.text() == "" \ or self.max_pixel_density_line_edit.text() == "": QMessageBox.about(self.draw_roi_window_instance, "Not Enough Data", "Not all values are specified or correct.") else: # Getting most updated selected slice id = self.current_slice dt = self.patient_dict_container.dataset[id] dt.convert_pixel_data() # Path to the selected .dcm file location = self.patient_dict_container.filepaths[id] self.ds = pydicom.dcmread(location) min_pixel = self.min_pixel_density_line_edit.text() max_pixel = self.max_pixel_density_line_edit.text() # If they are number inputs if min_pixel.isdecimal() and max_pixel.isdecimal(): min_pixel = int(min_pixel) max_pixel = int(max_pixel) if min_pixel >= max_pixel: QMessageBox.about( self.draw_roi_window_instance, "Incorrect Input", "Please ensure maximum density is " "atleast higher than minimum density.") self.drawingROI = Drawing( pixmaps[id], dt._pixel_array.transpose(), min_pixel, max_pixel, self.patient_dict_container.dataset[id], self.draw_roi_window_instance, self.slice_changed, self.current_slice, self.drawing_tool_radius, self.keep_empty_pixel, set()) self.slice_changed = True self.dicom_view.view.setScene(self.drawingROI) self.enable_cursor_radius_change_box() else: QMessageBox.about(self.draw_roi_window_instance, "Not Enough Data", "Not all values are specified or correct.") def onBoxDrawClicked(self): """ Function triggered when bounding box button is pressed """ id = self.current_slice dt = self.patient_dict_container.dataset[id] dt.convert_pixel_data() pixmaps = self.patient_dict_container.get("pixmaps_axial") self.bounds_box_draw = DrawBoundingBox(pixmaps[id], dt) self.dicom_view.view.setScene(self.bounds_box_draw) self.disable_cursor_radius_change_box() def onSaveClicked(self): """ Function triggered when Save button is clicked """ # Make sure the user has clicked Draw first if self.save_drawing_progress(image_slice_number=self.current_slice): self.saveROIList() def saveROIList(self): """ Function triggered when saving ROI list """ roi_list = ROI.convert_hull_list_to_contours_data( self.drawn_roi_list, self.patient_dict_container) if len(roi_list) == 0: QMessageBox.about(self.draw_roi_window_instance, "No ROI Detected", "Please ensure you have drawn your ROI first.") return # The list of points will need to be converted into a # single-dimensional array, as RTSTRUCT contour data is stored in # such a way. i.e. [x, y, z, x, y, z, x, y, z, ..., ...] Create a # popup window that modifies the RTSTRUCT and tells the user that # processing is happening. connectSaveROIProgress(self, roi_list, self.dataset_rtss, self.ROI_name, self.roi_saved) def roi_saved(self, new_rtss): """ Function to call save ROI and display progress """ self.signal_roi_drawn.emit((new_rtss, {"draw": self.ROI_name})) QMessageBox.about(self.draw_roi_window_instance, "Saved", "New contour successfully created!") self.closeWindow() def onPreviewClicked(self): """ function triggered when Preview button is clicked """ if hasattr(self, 'drawingROI') and self.drawingROI and len( self.drawingROI.target_pixel_coords) > 0: alpha = float(self.input_alpha_value.text()) polygon_list = calculate_concave_hull_of_points( self.drawingROI.target_pixel_coords, alpha) self.drawingROI.draw_contour_preview(polygon_list) else: QMessageBox.about(self.draw_roi_window_instance, "Not Enough Data", "Please ensure you have drawn your ROI first.") def set_selected_roi_name(self, roi_name): """ function to set selected roi name :param roi_name: roi name selected """ roi_exists = False patient_dict_container = PatientDictContainer() existing_rois = patient_dict_container.get("rois") number_of_rois = len(existing_rois) # Check to see if the ROI already exists for key, value in existing_rois.items(): if roi_name in value['name']: roi_exists = True if roi_exists: QMessageBox.about(self.draw_roi_window_instance, "ROI already exists in RTSS", "Would you like to continue?") self.ROI_name = roi_name self.roi_name_line_edit.setText(self.ROI_name) def onRadiusReduceClicked(self): """ function triggered when user reduce cursor radius """ self.drawing_tool_radius = max(self.drawing_tool_radius - 1, 4) self.draw_roi_window_cursor_radius_change_input.setText( str(self.drawing_tool_radius)) self.draw_roi_window_cursor_radius_change_input.setCursorPosition(0) self.draw_cursor_when_radius_changed() def onRadiusIncreaseClicked(self): """ function triggered when user increase cursor radius """ self.drawing_tool_radius = min(self.drawing_tool_radius + 1, 25) self.draw_roi_window_cursor_radius_change_input.setText( str(self.drawing_tool_radius)) self.draw_cursor_when_radius_changed() def draw_cursor_when_radius_changed(self): """ function to update drawing cursor when radius changed """ if self.drawingROI.cursor: self.drawingROI.draw_cursor( self.drawingROI.current_cursor_x + self.drawing_tool_radius, self.drawingROI.current_cursor_y + self.drawing_tool_radius, self.drawing_tool_radius) else: self.drawingROI.draw_cursor( (self.drawingROI.min_x + self.drawingROI.max_x) / 2, (self.drawingROI.min_y + self.drawingROI.max_y) / 2, self.drawing_tool_radius, True) def init_cursor_radius_change_box(self): """ function to init cursor radius change box """ # Create a horizontal box for containing the cursor radius changing # function self.draw_roi_window_cursor_radius_change_box = QHBoxLayout() self.draw_roi_window_cursor_radius_change_box.setObjectName( "DrawRoiWindowCursorRadiusChangeBox") # Create a label for cursor radius change self.draw_roi_window_cursor_radius_change_label = QLabel() self.draw_roi_window_cursor_radius_change_label.setObjectName( "DrawRoiWindowCursorRadiusChangeLabel") # Create an input box for cursor radius self.draw_roi_window_cursor_radius_change_input = QLineEdit() self.draw_roi_window_cursor_radius_change_input.setObjectName( "DrawRoiWindowCursorRadiusChangeInput") self.draw_roi_window_cursor_radius_change_input.setText(str(19)) self.draw_roi_window_cursor_radius_change_input.setCursorPosition(0) self.draw_roi_window_cursor_radius_change_input.setEnabled(False) self.draw_roi_window_cursor_radius_change_input.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Minimum) self.draw_roi_window_cursor_radius_change_input.resize( self.draw_roi_window_cursor_radius_change_input.sizeHint().width(), self.draw_roi_window_cursor_radius_change_input.sizeHint().height( )) # Create 2 buttons for increasing and reducing cursor radius # Increase Button self.draw_roi_window_cursor_radius_change_increase_button = \ QPushButton() self.draw_roi_window_cursor_radius_change_increase_button. \ setObjectName("DrawRoiWindowCursorRadiusIncreaseButton") self.draw_roi_window_cursor_radius_change_increase_button. \ setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.draw_roi_window_cursor_radius_change_increase_button.resize( QSize(24, 24)) self.draw_roi_window_cursor_radius_change_increase_button.setProperty( "QPushButtonClass", "zoom-button") icon_zoom_in = QtGui.QIcon() icon_zoom_in.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/zoom_in_icon.png'))) self.draw_roi_window_cursor_radius_change_increase_button.setIcon( icon_zoom_in) self.draw_roi_window_cursor_radius_change_increase_button.clicked. \ connect(self.onRadiusIncreaseClicked) # Reduce Button self.draw_roi_window_cursor_radius_change_reduce_button = QPushButton() self.draw_roi_window_cursor_radius_change_reduce_button.setObjectName( "DrawRoiWindowCursorRadiusReduceButton") self.draw_roi_window_cursor_radius_change_reduce_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.draw_roi_window_cursor_radius_change_reduce_button.resize( QSize(24, 24)) self.draw_roi_window_cursor_radius_change_reduce_button.setProperty( "QPushButtonClass", "zoom-button") icon_zoom_out = QtGui.QIcon() icon_zoom_out.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/zoom_out_icon.png'))) self.draw_roi_window_cursor_radius_change_reduce_button.setIcon( icon_zoom_out) self.draw_roi_window_cursor_radius_change_reduce_button.clicked. \ connect(self.onRadiusReduceClicked) self.draw_roi_window_cursor_radius_change_box.addWidget( self.draw_roi_window_cursor_radius_change_label) self.draw_roi_window_cursor_radius_change_box.addWidget( self.draw_roi_window_cursor_radius_change_input) self.draw_roi_window_cursor_radius_change_box.addWidget( self.draw_roi_window_cursor_radius_change_reduce_button) self.draw_roi_window_cursor_radius_change_box.addWidget( self.draw_roi_window_cursor_radius_change_increase_button) self.draw_roi_window_input_container_box.addRow( self.draw_roi_window_cursor_radius_change_box) self.draw_roi_window_cursor_radius_change_increase_button.setEnabled( False) self.draw_roi_window_cursor_radius_change_reduce_button.setEnabled( False) def disable_cursor_radius_change_box(self): """ function to disable cursor radius change box """ self.draw_roi_window_cursor_radius_change_reduce_button.setEnabled( False) self.draw_roi_window_cursor_radius_change_increase_button.setEnabled( False) self.toggle_keep_empty_pixel_combo_box.setEnabled(False) def enable_cursor_radius_change_box(self): """ function to enable cursor radius change box """ self.draw_roi_window_cursor_radius_change_reduce_button.setEnabled( True) self.draw_roi_window_cursor_radius_change_increase_button.setEnabled( True) self.toggle_keep_empty_pixel_combo_box.setEnabled(True) def closeWindow(self): """ function to close draw roi window """ self.drawn_roi_list = {} if hasattr(self, 'bounds_box_draw'): delattr(self, 'bounds_box_draw') if hasattr(self, 'drawingROI'): delattr(self, 'drawingROI') self.ds = None self.close()
class LocationDialog(QDialog): def __init__(self, parent=None): super(LocationDialog, self).__init__(parent) self.format_combo = QComboBox() self.format_combo.addItem("Native") self.format_combo.addItem("INI") self.scope_cCombo = QComboBox() self.scope_cCombo.addItem("User") self.scope_cCombo.addItem("System") self.organization_combo = QComboBox() self.organization_combo.addItem("Trolltech") self.organization_combo.setEditable(True) self.application_combo = QComboBox() self.application_combo.addItem("Any") self.application_combo.addItem("Application Example") self.application_combo.addItem("Assistant") self.application_combo.addItem("Designer") self.application_combo.addItem("Linguist") self.application_combo.setEditable(True) self.application_combo.setCurrentIndex(3) format_label = QLabel("&Format:") format_label.setBuddy(self.format_combo) scope_label = QLabel("&Scope:") scope_label.setBuddy(self.scope_cCombo) organization_label = QLabel("&Organization:") organization_label.setBuddy(self.organization_combo) application_label = QLabel("&Application:") application_label.setBuddy(self.application_combo) self.locations_groupbox = QGroupBox("Setting Locations") self.locations_table = QTableWidget() self.locations_table.setSelectionMode(QAbstractItemView.SingleSelection) self.locations_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.locations_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.locations_table.setColumnCount(2) self.locations_table.setHorizontalHeaderLabels(("Location", "Access")) self.locations_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) self.locations_table.horizontalHeader().resizeSection(1, 180) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.format_combo.activated.connect(self.update_locations) self.scope_cCombo.activated.connect(self.update_locations) self.organization_combo.lineEdit().editingFinished.connect(self.update_locations) self.application_combo.lineEdit().editingFinished.connect(self.update_locations) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) locations_layout = QVBoxLayout(self.locations_groupbox) locations_layout.addWidget(self.locations_table) mainLayout = QGridLayout(self) mainLayout.addWidget(format_label, 0, 0) mainLayout.addWidget(self.format_combo, 0, 1) mainLayout.addWidget(scope_label, 1, 0) mainLayout.addWidget(self.scope_cCombo, 1, 1) mainLayout.addWidget(organization_label, 2, 0) mainLayout.addWidget(self.organization_combo, 2, 1) mainLayout.addWidget(application_label, 3, 0) mainLayout.addWidget(self.application_combo, 3, 1) mainLayout.addWidget(self.locations_groupbox, 4, 0, 1, 2) mainLayout.addWidget(self.button_box, 5, 0, 1, 2) self.update_locations() self.setWindowTitle("Open Application Settings") self.resize(650, 400) def format(self): if self.format_combo.currentIndex() == 0: return QSettings.NativeFormat else: return QSettings.IniFormat def scope(self): if self.scope_cCombo.currentIndex() == 0: return QSettings.UserScope else: return QSettings.SystemScope def organization(self): return self.organization_combo.currentText() def application(self): if self.application_combo.currentText() == "Any": return '' return self.application_combo.currentText() def update_locations(self): self.locations_table.setUpdatesEnabled(False) self.locations_table.setRowCount(0) for i in range(2): if i == 0: if self.scope() == QSettings.SystemScope: continue actualScope = QSettings.UserScope else: actualScope = QSettings.SystemScope for j in range(2): if j == 0: if not self.application(): continue actualApplication = self.application() else: actualApplication = '' settings = QSettings(self.format(), actualScope, self.organization(), actualApplication) row = self.locations_table.rowCount() self.locations_table.setRowCount(row + 1) item0 = QTableWidgetItem() item0.setText(settings.fileName()) item1 = QTableWidgetItem() disable = not (settings.childKeys() or settings.childGroups()) if row == 0: if settings.isWritable(): item1.setText("Read-write") disable = False else: item1.setText("Read-only") self.button_box.button(QDialogButtonBox.Ok).setDisabled(disable) else: item1.setText("Read-only fallback") if disable: item0.setFlags(item0.flags() & ~Qt.ItemIsEnabled) item1.setFlags(item1.flags() & ~Qt.ItemIsEnabled) self.locations_table.setItem(row, 0, item0) self.locations_table.setItem(row, 1, item1) self.locations_table.setUpdatesEnabled(True)
class TableClothGenerator(QMainWindow): def __init__(self, parent=None): super().__init__(parent) # Main UI settings self.setWindowTitle('Tablecloth Generator') self.setWindowIcon(QIcon('icon.ico')) self.centralWidget = QWidget() self.setCentralWidget(self.centralWidget) self.resize(350, 350) self.center() self._createMenuBar() self.MainUI() def MainUI(self): # Obtain the configs fp_config = open(THISDIR + "\\config\\config.json", "r", encoding="utf-8") self.config = json.loads(fp_config.read()) fp_config.close() # Obtain and List the teams fp_teams = open(THISDIR + "\\config\\teams.json", "r", encoding="utf-8") conf_teams = json.loads(fp_teams.read()) fp_teams.close() self.teams = conf_teams["teams"] self.players = conf_teams["players"] # Obtain all images needed to create the tablecloth self.background = Image.open(THISDIR + "\\images\\mat.png") self.table_border = Image.open(THISDIR + "\\images\\table_border.png") self.tech_lines = Image.open(THISDIR + "\\images\\technical_lines.png") # Check if there's no configuration set up # and prompt to create/import one if self.config["total_teams"] == 0: self.no_config = QMessageBox.question(self, "No configuration", "No configuration has been found. Do you wish to set up a new one?", QMessageBox.Yes | QMessageBox.No) if self.no_config == QMessageBox.Yes: self.CreateTeamsWindow() self.bg_image = self.config["image_route"] self.players_combobox = QComboBox() self.UpdatePlayersList() self.players_combobox.setEditable(True) self.players_combobox.completer()\ .setCompletionMode(QCompleter.PopupCompletion) self.players_combobox.setInsertPolicy(QComboBox.NoInsert) # Set up the GUI self.statusBar().showMessage("Remember: Rig responsibly.") # Bottom (EAST) self.label_east = QLabel(self) self.label_east.setText("<h1>East Seat</h1>") self.label_east.setAlignment(QtCore.Qt.AlignCenter) self.image_east = QLabel(self) self.image_east.setPixmap(QPixmap("images/logos/team1.png")\ .scaled(100,100)) self.image_east.setAlignment(QtCore.Qt.AlignCenter) self.search_east = QLineEdit() self.search_east.setAlignment(QtCore.Qt.AlignCenter) self.search_east.editingFinished.connect( lambda: self.searchPlayer(self.search_east.text(), self.cloth_east)) self.cloth_east = QComboBox() self.cloth_east.setModel(self.players_combobox.model()) self.cloth_east.currentIndexChanged.connect( lambda: self.SwitchImage(self.cloth_east, self.image_east)) # Right (SOUTH) self.label_south = QLabel(self) self.label_south.setText("<h1>South Seat</h1>") self.label_south.setAlignment(QtCore.Qt.AlignCenter) self.image_south = QLabel(self) self.image_south.setPixmap(QPixmap("images/logos/team1.png")\ .scaled(100,100)) self.image_south.setAlignment(QtCore.Qt.AlignCenter) self.image_south.show() self.search_south = QLineEdit() self.search_south.setAlignment(QtCore.Qt.AlignCenter) self.search_south.editingFinished.connect( lambda: self.searchPlayer(self.search_south.text(), self.cloth_south)) self.cloth_south = QComboBox() self.cloth_south.setModel(self.players_combobox.model()) self.cloth_south.currentIndexChanged.connect( lambda: self.SwitchImage(self.cloth_south, self.image_south)) # Top (WEST) self.label_west = QLabel(self) self.label_west.setText("<h1>West Seat</h1>") self.label_west.setAlignment(QtCore.Qt.AlignCenter) self.image_west = QLabel(self) self.image_west.setPixmap(QPixmap("images/logos/team1.png")\ .scaled(100,100)) self.image_west.setAlignment(QtCore.Qt.AlignCenter) self.image_west.show() self.cloth_west = QComboBox() self.search_west = QLineEdit() self.search_west.setAlignment(QtCore.Qt.AlignCenter) self.search_west.editingFinished.connect( lambda: self.searchPlayer(self.search_west.text(), self.cloth_west)) self.cloth_west.setModel(self.players_combobox.model()) self.cloth_west.currentIndexChanged.connect( lambda: self.SwitchImage(self.cloth_west, self.image_west)) # Left (NORTH) self.label_north = QLabel(self) self.label_north.setText("<h1>North Seat</h1>") self.label_north.setAlignment(QtCore.Qt.AlignCenter) self.image_north = QLabel(self) self.image_north.setPixmap(QPixmap("images/logos/team1.png")\ .scaled(100,100)) self.image_north.setAlignment(QtCore.Qt.AlignCenter) self.image_north.show() self.cloth_north = QComboBox() self.search_north = QLineEdit() self.search_north.setAlignment(QtCore.Qt.AlignCenter) self.search_north.editingFinished.connect( lambda: self.searchPlayer(self.search_north.text(), self.cloth_north)) self.cloth_north.setModel(self.players_combobox.model()) self.cloth_north.currentIndexChanged.connect( lambda: self.SwitchImage(self.cloth_north, self.image_north)) # Technical lines self.technical_lines = QCheckBox("Show Technical lines", self) # Generate button self.generate = QPushButton(self) self.generate.setText("Generate Tablecloth") self.generate.clicked.connect(self.GeneratePreview) # Add custom mat self.custom_mat = QPushButton(self) self.custom_mat.setText("Add Mat") self.custom_mat.clicked.connect(self.MatDialog) # Create the layout grid_layout = QGridLayout() grid_layout.setAlignment(QtCore.Qt.AlignCenter) grid_layout.setAlignment(QtCore.Qt.AlignTop) # Labels East, West grid_layout.addWidget(self.label_east, 1, 1) grid_layout.addWidget(self.label_west, 1, 2) # Image preview East, West grid_layout.addWidget(self.image_east, 2, 1) grid_layout.addWidget(self.image_west, 2, 2) # Search player East, West grid_layout.addWidget(self.search_east, 3, 1) grid_layout.addWidget(self.search_west, 3, 2) # Player combobox East, West grid_layout.addWidget(self.cloth_east, 4, 1) grid_layout.addWidget(self.cloth_west, 4, 2) # Labes South, North grid_layout.addWidget(self.label_south, 5, 1) grid_layout.addWidget(self.label_north, 5, 2) # Image preview South, North grid_layout.addWidget(self.image_south, 6, 1) grid_layout.addWidget(self.image_north, 6, 2) # Search player South, North grid_layout.addWidget(self.search_south, 7, 1) grid_layout.addWidget(self.search_north, 7, 2) # Player combobox South, North grid_layout.addWidget(self.cloth_south, 8, 1) grid_layout.addWidget(self.cloth_north, 8, 2) # Technical lines grid_layout.addWidget(self.technical_lines, 9, 1) # Custom mat/bg grid_layout.addWidget(self.custom_mat, 10, 1) # Generate grid_layout.addWidget(self.generate, 10, 2) self.centralWidget.setLayout(grid_layout) # Create the window self.show() def _createMenuBar(self): # Settings and stuff for the toolbar menubar = QMenuBar(self) file_menu = QMenu("&File", self) file_menu.addAction("Create Team(s)", self.CreateTeamsWindow) file_menu.addAction("Edit Team(s)", self.EditTeamsWindow) file_menu.addAction("Exit", self.close) settings_menu = QMenu("&Settings", self) settings_menu.addAction("Version", self.SeeVersion) settings_menu.addAction("Help", self.GetHelp) menubar.addMenu(file_menu) menubar.addMenu(settings_menu) self.setMenuBar(menubar) def _createProgressBar(self): self.progress_bar = QProgressBar() self.progress_bar.minimum = 0 self.progress_bar.maximum = 100 self.progress_bar.setValue(0) self.progress_bar.setTextVisible(False) self.progress_bar.setGeometry(50, 50, 10, 10) self.progress_bar.setAlignment(QtCore.Qt.AlignRight) self.progress_bar.adjustSize() self.statusBar().addPermanentWidget(self.progress_bar) self.ChangeAppStatus(False) def SwitchImage(self, cloth, image): # It shows you the team logo. No way you can miss those, right? team_id = self.SearchTeamID(cloth, True) image.setPixmap(QPixmap( "images/logos/team%d.png" % team_id).scaled(100,100)) def searchPlayer(self, text, combobox): # It even searches the player for you. What more could you want? search_index = combobox.findText(text, QtCore.Qt.MatchContains) if search_index == -1: QMessageBox.warning(self, "Error", "No player found") else: combobox.setCurrentIndex(search_index) def CreateTeamsWindow(self): self.teamcreation_wid = EditionWidget() self.teamcreation_wid.resize(400, 200) self.teamcreation_wid.setWindowTitle("Teams configuration") self.new_config = {} id_label = QLabel(self) id_label.setText("Team ID: ") self.num_id = QLabel(self) current_id = str(self.config["total_teams"] + 1) self.num_id.setText(current_id) name_label = QLabel(self) name_label.setText("Team Name:") name_label.setFocus() self.name_input = QLineEdit(self) members_label = QLabel(self) members_label.setText("Members (write and press enter):") members_input = QLineEdit(self) members_input.editingFinished.connect( lambda: self.AddMember(members_input)) self.members_list = QListWidget(self) import_image = QPushButton(self) import_image.setText("Import Team Image") import_image.clicked.connect(self.ImportTeamImage) add_team = QPushButton(self) add_team.setText("Add Team") add_team.clicked.connect( lambda: self.addTeamFunction(self.name_input.text(), self.members_list)) import_config = QPushButton(self) import_config.setText("Import configuration") import_config.clicked.connect(self.importTeamFunction) config_lay = QGridLayout() config_lay.addWidget(id_label, 1, 0) config_lay.addWidget(self.num_id, 1, 1) config_lay.addWidget(name_label, 2, 0) config_lay.addWidget(self.name_input, 2, 1) config_lay.addWidget(members_label, 3, 0) config_lay.addWidget(members_input, 3, 1) config_lay.addWidget(self.members_list, 4, 0, 2, 2) config_lay.addWidget(add_team, 6, 0) config_lay.addWidget(import_image, 6, 1) config_lay.addWidget(import_config, 7, 0, 1, 2) self.teamcreation_wid.setLayout(config_lay) self.teamcreation_wid.setWindowModality(QtCore.Qt.ApplicationModal) self.teamcreation_wid.activateWindow() self.teamcreation_wid.raise_() self.teamcreation_wid.show() def addTeamFunction(self, name, members): fp_teams = open(THISDIR + "\\config\\teams.json", "r", encoding="utf-8") current_teams = json.loads(fp_teams.read()) fp_teams.close() team = {} current_teams["teams"].append(name) current_teams["players"][name] = [str(self.members_list.item(i).text())\ for i in range(self.members_list.count())] new_team = open(THISDIR + "\\config\\teams.json", "w+", encoding="utf-8") add_config = open(THISDIR + "\\config\\config.json", "w+", encoding="utf-8") self.teams = current_teams["teams"] self.players = current_teams["players"] self.config["total_teams"] += 1 new_id = self.config["total_teams"] + 1 self.num_id.setText(str(new_id)) add_config.write(json.dumps(self.config, indent=4)) new_team.write(json.dumps(current_teams, indent=4)) new_team.close() self.name_input.clear() self.members_list.clear() self.UpdatePlayersList() def ImportTeamImage(self): image_dialog = QFileDialog(self) image_dialog = QFileDialog.getOpenFileName(filter="Images (*.png)", selectedFilter="Images (*.png)") if image_dialog[0] != "": new_team_logo = Image.open(image_dialog[0]).convert("RGBA") if new_team_logo.size != (250, 250): new_team_logo.resize((250, 250)) new_team_logo.save(THISDIR+"\\images\\logos\\team%s.png"\ % self.num_id.text()) QMessageBox.information(self, "Team Image", "Team image added.") def importTeamFunction(self): file_dialog = QFileDialog(self) file_dialog = QFileDialog.getOpenFileName( filter="Team Files (*.json *.zip)", selectedFilter="Team Files (*.json *.zip)") if file_dialog[0] != "": if is_zipfile(file_dialog[0]): with ZipFile(file_dialog[0]) as zip_import: list_of_files = zip_import.namelist() for fimp in list_of_files: if fimp.startswith('logos'): zip_import.extract(fimp, path=THISDIR+'\\images\\') imported_teams = zip_import.read('teams.json') imported_teams = imported_teams.decode('utf-8') else: imported_teams = open(file_dialog[0], "r", encoding="utf-8").read() json_teams = json.loads(imported_teams) self.teams = json_teams["teams"] self.players = json_teams["players"] new_teams = open(THISDIR + "\\config\\teams.json", "w+", encoding="utf-8") new_teams.write(json.dumps(json_teams, indent=4)) new_teams.close() old_config = open(THISDIR + "\\config\\config.json", "r", encoding="utf-8").read() old_config = json.loads(old_config) old_config["total_teams"] = len(json_teams["teams"]) self.config = old_config new_config = open(THISDIR + "\\config\\config.json", "w+", encoding="utf-8") new_config.write(json.dumps(self.config, indent=4)) new_config.close() self.UpdatePlayersList() self.image_east.setPixmap(QPixmap("images/logos/team1.png")\ .scaled(100,100)) self.cloth_east.setModel(self.players_combobox.model()) self.image_south.setPixmap(QPixmap("images/logos/team1.png")\ .scaled(100,100)) self.cloth_south.setModel(self.players_combobox.model()) self.image_west.setPixmap(QPixmap("images/logos/team1.png")\ .scaled(100,100)) self.cloth_west.setModel(self.players_combobox.model()) self.image_north.setPixmap(QPixmap("images/logos/team1.png")\ .scaled(100,100)) self.cloth_north.setModel(self.players_combobox.model()) self.statusBar().showMessage("Teams imported successfully.") self.teamcreation_wid.close() def AddMember(self, member): self.members_list.addItem(member.text()) member.clear() def EditTeamsWindow(self): self.teamedit_wid = EditionWidget() self.teamedit_wid.resize(400, 320) self.teamedit_wid.setWindowTitle("Edit Teams") self.teams_list = QComboBox(self) self.teams_list.addItem("--- Select a team ---") for team in self.teams: self.teams_list.addItem(team) self.teams_list.currentIndexChanged.connect(self.UpdateTeamInfo) team_id_label = QLabel(self) team_id_label.setText("Team ID: ") self.config_team_id = QLabel(self) team_name_label = QLabel(self) team_name_label.setText("Team name: ") self.config_team_name = QLabel(self) team_members_label = QLabel(self) team_members_label.setText("Team members: ") self.config_team_members = QListWidget(self) add_member_label = QLabel(self) add_member_label.setText("Add new member: ") add_member_input = QLineEdit(self) add_member_input.editingFinished.connect(self.AddNewMember) delete_member = QPushButton(self) delete_member.setText("Delete member") delete_member.clicked.connect(self.DeleteMember) delete_team = QPushButton(self) delete_team.setText("Delete Team") delete_team.clicked.connect(self.DeleteTeam) save_changes = QPushButton(self) save_changes.setText("Save changes") save_changes.clicked.connect(self.SaveEdits) export_config = QPushButton(self) export_config.setText("Export Configuration") export_config.clicked.connect(self.ExportTeams) config_lay = QGridLayout() config_lay.addWidget(self.teams_list, 1, 0) config_lay.addWidget(team_id_label, 2, 0) config_lay.addWidget(self.config_team_id, 2, 1) config_lay.addWidget(team_name_label, 3, 0) config_lay.addWidget(self.config_team_name, 3, 1, 1, 2) config_lay.addWidget(team_members_label, 4, 0) config_lay.addWidget(self.config_team_members, 5, 0) config_lay.addWidget(add_member_label, 6, 0) config_lay.addWidget(add_member_input, 6, 1, 1, 2) config_lay.addWidget(delete_member, 7, 0) config_lay.addWidget(delete_team, 7, 1) config_lay.addWidget(save_changes, 8, 0) config_lay.addWidget(export_config, 8, 1) self.teamedit_wid.setLayout(config_lay) self.teamedit_wid.setWindowModality(QtCore.Qt.ApplicationModal) self.teamedit_wid.activateWindow() self.teamedit_wid.raise_() self.teamedit_wid.show() def UpdateTeamInfo(self): sender = self.sender() if sender.currentIndex() > 0: team_id = sender.currentIndex() self.config_team_id.setText(str(team_id)) self.config_team_name.setText(sender.currentText()) if self.config_team_members.count() > 0: self.config_team_members.clear() self.config_team_members.addItems( self.players[sender.currentText()]) def AddNewMember(self): sender = self.sender() self.config_team_members.addItem(sender.text()) sender.clear() def DeleteMember(self): list_members = self.config_team_members.selectedItems() if len(list_members) == 0: QMessageBox.warning(self, "Error", "No player selected") else: for member in list_members: self.config_team_members.takeItem( self.config_team_members.row(member)) def DeleteTeam(self): team_id = int(self.config_team_id.text()) is_last_item = self.teams[self.teams.index( self.config_team_name.text())] == (self.teams[len(self.teams)-1]) self.teams.pop(self.teams.index(self.config_team_name.text())) self.players.pop(self.config_team_name.text()) new_teamlist = {} new_teamlist["teams"] = self.teams new_teamlist["players"] = self.players current_teams = open(THISDIR + "\\config\\teams.json", "w+", encoding="utf-8") current_teams.write(json.dumps(new_teamlist, indent=4)) current_teams.close() if is_last_item == True: self.teams_list.setCurrentIndex(1) else: self.teams_list.setCurrentIndex(team_id+1) self.teams_list.removeItem(team_id) self.UpdatePlayersList() self.cloth_east.setModel(self.players_combobox.model()) self.cloth_south.setModel(self.players_combobox.model()) self.cloth_west.setModel(self.players_combobox.model()) self.cloth_north.setModel(self.players_combobox.model()) def ExportTeams(self): export_dir = self.config["save_route"] if self.config["save_route"] \ is not None else THISDIR exported_file = QFileDialog.getSaveFileName(self, "Save File", export_dir, "Save files (*.zip)") if exported_file[0] != "": export_filename = exported_file[0] if export_filename.endswith(".zip") is False: export_filename += ".zip" files_to_export = [] files_to_export.append("config\\teams.json") for root, directories, files in os.walk(THISDIR+"\\images\\logos"): for filename in files: filepath = os.path.join(root, filename) files_to_export.append(filepath) with ZipFile(export_filename, "w") as export_zip: for exp_file in files_to_export: export_name = exp_file if exp_file.endswith(".json"): split_name = exp_file.split("\\") export_name = split_name[-1] if exp_file.endswith(".png"): split_name = exp_file.split("\\") export_name = "\\logos\\" + split_name[-1] export_zip.write(exp_file, arcname=export_name) export_zip.close() if os.path.exists(export_filename): QMessageBox.information(self, "Export", "The export was successful") def SaveEdits(self): list_members = [str(self.config_team_members.item(i).text()) for i in \ range(self.config_team_members.count())] self.players[self.config_team_name.text()] = list_members new_teamlist = {} new_teamlist["teams"] = self.teams new_teamlist["players"] = self.players current_teams = open(THISDIR + "\\config\\teams.json", "w+", encoding="utf-8") current_teams.write(json.dumps(new_teamlist, indent=4)) current_teams.close() self.teamedit_wid.close() self.statusBar().showMessage("Settings saved.") def MatDialog(self): mat_dialog = QFileDialog(self) mat_dialog = QFileDialog.getOpenFileName(filter="Images (*.png *.jpg)", selectedFilter="Images (*.png *.jpg)") if mat_dialog[0] != "": self.GenerateMat(mat_dialog[0]) def GenerateMat(self, image): self.background = image background = Image.open(self.background).resize((2048,2048))\ .convert("RGBA") self.mat_thread = QThread() east_id = self.SearchTeamID(self.cloth_east, True) south_id = self.SearchTeamID(self.cloth_south, True) west_id = self.SearchTeamID(self.cloth_west, True) north_id = self.SearchTeamID(self.cloth_north, True) if self.config["save_route"] is None: save_to_route = THISDIR else: save_to_route = self.config["save_route"] self._createProgressBar() self.mat_worker = GenerateImageThread(background, self.table_border, east_id, south_id, west_id, north_id, self.technical_lines.isChecked(), save_to_route, self.bg_image, True) self.mat_worker.moveToThread(self.mat_thread) self.mat_thread.started.connect(self.mat_worker.run) self.mat_worker.update_progress.connect(self.UpdateStatus) self.mat_worker.finished.connect(self.mat_thread.quit) self.mat_worker.finished.connect(self.mat_worker.deleteLater) self.mat_thread.finished.connect(self.mat_thread.deleteLater) self.mat_thread.finished.connect(self.MatPreviewWindow) self.mat_thread.start() def MatPreviewWindow(self): self.statusBar().showMessage('Mat preview generated.') self.statusBar().removeWidget(self.progress_bar) # Now you can go back to rigging self.ChangeAppStatus(True) self.mat_wid = QWidget() self.mat_wid.resize(600, 600) self.mat_wid.setWindowTitle("Background preview") mat_preview_title = QLabel(self) mat_preview_title.setText("Selected image (1/4 scale)") mat_preview = QLabel(self) mat_preview.setPixmap(QPixmap(tempfile.gettempdir()+"\\Table_Dif.jpg")\ .scaled(512,512)) confirm = QPushButton(self) confirm.setText("Confirm") confirm.clicked.connect( lambda: self.ChangeMatImage(self.background)) vbox = QVBoxLayout() vbox.setAlignment(QtCore.Qt.AlignCenter) vbox.addWidget(mat_preview_title) vbox.addWidget(mat_preview) vbox.addWidget(confirm) self.mat_wid.setLayout(vbox) self.mat_wid.setWindowModality(QtCore.Qt.ApplicationModal) self.mat_wid.activateWindow() self.mat_wid.raise_() self.mat_wid.show() def ChangeMatImage(self, image): new_bg = Image.open(image) if new_bg.size != (2048, 2048): new_bg = new_bg.resize((2048, 2048)) if new_bg.mode != "RGBA": new_bg = new_bg.convert("RGBA") if self.config["save_route"] is not None: new_bg.save(self.config["save_route"]+"\\images\\mat.png") self.bg_image = self.config["save_route"]+"\\images\\mat.png" else: new_bg.save(THISDIR+"\\images\\mat.png") self.bg_image = THISDIR+"\\images\\mat.png" self.background = new_bg self.config["image_route"] = self.bg_image new_file = open(THISDIR + "\\config\\config.json", "w+", encoding="utf-8") new_file.write(json.dumps(self.config, indent=4)) new_file.close() self.statusBar().showMessage('New background added.') self.statusBar().removeWidget(self.progress_bar) self.ChangeAppStatus(True) self.mat_wid.close() def GeneratePreview(self): self.preview_thread = QThread() east_id = self.SearchTeamID(self.cloth_east, True) south_id = self.SearchTeamID(self.cloth_south, True) west_id = self.SearchTeamID(self.cloth_west, True) north_id = self.SearchTeamID(self.cloth_north, True) if self.config["save_route"] is None: save_to_route = THISDIR else: save_to_route = self.config["save_route"] self._createProgressBar() self.preview_worker = GenerateImageThread(self.background, self.table_border, east_id, south_id, west_id, north_id, self.technical_lines.isChecked(), save_to_route, self.bg_image, True) self.preview_worker.moveToThread(self.preview_thread) self.preview_thread.started.connect(self.preview_worker.run) self.preview_worker.update_progress.connect(self.UpdateStatus) self.preview_worker.finished.connect(self.preview_thread.quit) self.preview_worker.finished.connect(self.preview_worker.deleteLater) self.preview_thread.finished.connect(self.preview_thread.deleteLater) self.preview_thread.finished.connect(self.PreviewWindow) self.preview_thread.start() def PreviewWindow(self): self.statusBar().showMessage('Tablecloth preview generated.') self.statusBar().removeWidget(self.progress_bar) # Now you can go back to rigging self.ChangeAppStatus(True) self.preview_wid = QWidget() self.preview_wid.resize(600, 600) self.preview_wid.setWindowTitle("Tablecloth preview") tablecloth = QPixmap(tempfile.gettempdir()+"\\Table_Dif.jpg") tablecloth_preview_title = QLabel(self) tablecloth_preview_title.setText("Tablecloth preview (1/4 scale)") tablecloth_preview = QLabel(self) tablecloth_preview.setPixmap(tablecloth.scaled(512,512)) confirm = QPushButton(self) confirm.setText("Confirm") confirm.clicked.connect(self.GenerateImage) confirm.clicked.connect(self.preview_wid.close) vbox = QVBoxLayout() vbox.setAlignment(QtCore.Qt.AlignCenter) vbox.addWidget(tablecloth_preview_title) vbox.addWidget(tablecloth_preview) vbox.addWidget(confirm) self.preview_wid.setLayout(vbox) self.preview_wid.setWindowModality(QtCore.Qt.ApplicationModal) self.preview_wid.activateWindow() self.preview_wid.raise_() self.preview_wid.show() def GeneratedDialog(self): self.statusBar().showMessage('Tablecloth generated. Happy rigging!') self.statusBar().removeWidget(self.progress_bar) # Now you can go back to rigging self.ChangeAppStatus(True) mbox = QMessageBox() mbox.setWindowTitle("Tablecloth Generator") mbox.setText("Tablecloth Generated!") mbox.setStandardButtons(QMessageBox.Ok) mbox.exec() def UpdateStatus(self, status): self.progress_bar.setValue(status) def GenerateImage(self): self.statusBar().showMessage('Generating image...') self._createProgressBar() if self.config["save_route"] is None: self.config["save_route"] = THISDIR save_to_route = QFileDialog.getExistingDirectory(self, "Where to save the image", self.config["save_route"], QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) if self.config["save_route"] != save_to_route: temp_file = open(THISDIR + "\\config\\config.json", "r", encoding="utf-8") fp_teams = json.loads(temp_file.read()) fp_teams["save_route"] = save_to_route fp_teams["image_route"] = self.bg_image new_file = open(THISDIR + "\\config\\config.json", "w+", encoding="utf-8") new_file.write(json.dumps(fp_teams, indent=4)) new_file.close() self.background = Image.open(THISDIR + "\\images\\mat.png") self.table_border = Image.open(THISDIR + "\\images\\table_border.png") self.tech_lines = Image.open(THISDIR + "\\images\\technical_lines.png") self.thread = QThread() east_id = self.SearchTeamID(self.cloth_east, True) south_id = self.SearchTeamID(self.cloth_south, True) west_id = self.SearchTeamID(self.cloth_west, True) north_id = self.SearchTeamID(self.cloth_north, True) self.worker = GenerateImageThread(self.background, self.table_border, east_id, south_id, west_id, north_id, self.technical_lines.isChecked(), save_to_route, self.bg_image) self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.run) self.worker.update_progress.connect(self.UpdateStatus) self.worker.finished.connect(self.thread.quit) self.worker.finished.connect(self.worker.deleteLater) self.thread.finished.connect(self.thread.deleteLater) self.thread.finished.connect(self.GeneratedDialog) self.thread.start() def ChangeAppStatus(self, status): # True for enable, False for disable. self.cloth_east.setEnabled(status) self.search_east.setEnabled(status) self.cloth_south.setEnabled(status) self.search_south.setEnabled(status) self.cloth_west.setEnabled(status) self.search_west.setEnabled(status) self.cloth_north.setEnabled(status) self.search_north.setEnabled(status) self.generate.setEnabled(status) def SearchTeamID(self, cloth, plus_one=False): team_id = self.teams.index(cloth.itemData(cloth.currentIndex())) if plus_one: team_id += 1 return team_id def UpdatePlayersList(self): for team, members in self.players.items(): for member in members: self.players_combobox.addItem(member, team) def center(self): qr = self.frameGeometry() cp = QScreen().availableGeometry().center() qr.moveCenter(cp) def SeeVersion(self): git_url = "https://raw.githubusercontent.com/vg-mjg/tablecloth-" git_url += "generator/main/version.txt" with urllib.request.urlopen(git_url) as response: url_version = response.read().decode("utf-8") version = "Your version is up to date!" if url_version != VERSION: version = "Your version is outdated." version += "Please check the <a href='https://github.com/vg-mjg/" version += "tablecloth-generator/releases'>Github page</a>" version +=" for updates." version_message = QMessageBox(self) version_message.setWindowTitle("Checking version") version_message.setText("""<h1>Tablecloth generator</h1> <br> <b>Current Version:</b> %s<br> <b>Your Version:</b> %s<br> <i>%s</i> """ % (url_version, VERSION, version)) version_message.exec() def GetHelp(self): webbrowser.open("https://github.com/vg-mjg/tablecloth-generator/wiki")
class ItemRow: def __init__(self, parent: QWidget, parent_layout: QVBoxLayout, resource_database: ResourceDatabase, item: ResourceRequirement, rows: List["ItemRow"]): self.parent = parent self.resource_database = resource_database self._rows = rows rows.append(self) self.layout = QHBoxLayout() self.layout.setObjectName(f"Box layout for {item.resource.long_name}") parent_layout.addLayout(self.layout) self.resource_type_combo = _create_resource_type_combo( item.resource.resource_type, parent) self.resource_type_combo.setMinimumWidth(75) self.resource_type_combo.setMaximumWidth(75) self.resource_name_combo = _create_resource_name_combo( self.resource_database, item.resource.resource_type, item.resource, self.parent) self.negate_combo = QComboBox(parent) self.negate_combo.addItem("≥", False) self.negate_combo.addItem("<", True) self.negate_combo.setCurrentIndex(int(item.negate)) self.negate_combo.setMinimumWidth(40) self.negate_combo.setMaximumWidth(40) self.amount_edit = QLineEdit(parent) self.amount_edit.setValidator(QIntValidator(1, 10000)) self.amount_edit.setText(str(item.amount)) self.amount_edit.setMinimumWidth(45) self.amount_edit.setMaximumWidth(45) self.remove_button = QPushButton(parent) self.remove_button.setText("X") self.remove_button.setMaximumWidth(20) self.layout.addWidget(self.resource_type_combo) self.layout.addWidget(self.resource_name_combo) self.layout.addWidget(self.negate_combo) self.layout.addWidget(self.amount_edit) self.layout.addWidget(self.remove_button) self.resource_type_combo.currentIndexChanged.connect(self._update_type) self.remove_button.clicked.connect(self._delete_row) def _update_type(self): old_combo = self.resource_name_combo self.resource_name_combo = _create_resource_name_combo( self.resource_database, self.resource_type_combo.currentData(), None, self.parent) self.layout.replaceWidget(old_combo, self.resource_name_combo) old_combo.deleteLater() def _delete_row(self): self.resource_type_combo.deleteLater() self.resource_name_combo.deleteLater() self.negate_combo.deleteLater() self.amount_edit.deleteLater() self.remove_button.deleteLater() self.layout.deleteLater() self._rows.remove(self) @property def current_individual(self) -> ResourceRequirement: return ResourceRequirement(self.resource_name_combo.currentData(), int(self.amount_edit.text()), self.negate_combo.currentData())
class Window(QDialog): def __init__(self, parent=None): super(Window, self).__init__(parent) self.iconGroupBox = QGroupBox() self.iconLabel = QLabel() self.iconComboBox = QComboBox() self.showIconCheckBox = QCheckBox() self.messageGroupBox = QGroupBox() self.typeLabel = QLabel() self.durationLabel = QLabel() self.durationWarningLabel = QLabel() self.titleLabel = QLabel() self.bodyLabel = QLabel() self.typeComboBox = QComboBox() self.durationSpinBox = QSpinBox() self.titleEdit = QLineEdit() self.bodyEdit = QTextEdit() self.showMessageButton = QPushButton() self.minimizeAction = QAction() self.maximizeAction = QAction() self.restoreAction = QAction() self.quitAction = QAction() self.trayIcon = QSystemTrayIcon() self.trayIconMenu = QMenu() self.createIconGroupBox() self.createMessageGroupBox() self.iconLabel.setMinimumWidth(self.durationLabel.sizeHint().width()) self.createActions() self.createTrayIcon() self.showMessageButton.clicked.connect(self.showMessage) self.showIconCheckBox.toggled.connect(self.trayIcon.setVisible) self.iconComboBox.currentIndexChanged.connect(self.setIcon) self.trayIcon.messageClicked.connect(self.messageClicked) self.trayIcon.activated.connect(self.iconActivated) self.mainLayout = QVBoxLayout() self.mainLayout.addWidget(self.iconGroupBox) self.mainLayout.addWidget(self.messageGroupBox) self.setLayout(self.mainLayout) self.iconComboBox.setCurrentIndex(1) self.trayIcon.show() self.setWindowTitle("Systray") self.resize(400, 300) def setVisible(self, visible): self.minimizeAction.setEnabled(visible) self.maximizeAction.setEnabled(not self.isMaximized()) self.restoreAction.setEnabled(self.isMaximized() or not visible) super().setVisible(visible) def closeEvent(self, event): if not event.spontaneous() or not self.isVisible(): return if self.trayIcon.isVisible(): QMessageBox.information( self, "Systray", "The program will keep running in the system tray. " "To terminate the program, choose <b>Quit</b> in the context " "menu of the system tray entry.") self.hide() event.ignore() @Slot(int) def setIcon(self, index): icon = self.iconComboBox.itemIcon(index) self.trayIcon.setIcon(icon) self.setWindowIcon(icon) self.trayIcon.setToolTip(self.iconComboBox.itemText(index)) @Slot(str) def iconActivated(self, reason): if reason == QSystemTrayIcon.Trigger: pass if reason == QSystemTrayIcon.DoubleClick: self.iconComboBox.setCurrentIndex( (self.iconComboBox.currentIndex() + 1) % self.iconComboBox.count()) if reason == QSystemTrayIcon.MiddleClick: self.showMessage() @Slot() def showMessage(self): self.showIconCheckBox.setChecked(True) selectedIcon = self.typeComboBox.itemData( self.typeComboBox.currentIndex()) msgIcon = QSystemTrayIcon.MessageIcon(selectedIcon) if selectedIcon == -1: # custom icon icon = QIcon( self.iconComboBox.itemIcon(self.iconComboBox.currentIndex())) self.trayIcon.showMessage( self.titleEdit.text(), self.bodyEdit.toPlainText(), icon, self.durationSpinBox.value() * 1000, ) else: self.trayIcon.showMessage( self.titleEdit.text(), self.bodyEdit.toPlainText(), msgIcon, self.durationSpinBox.value() * 1000, ) @Slot() def messageClicked(self): QMessageBox.information( None, "Systray", "Sorry, I already gave what help I could.\n" "Maybe you should try asking a human?") def createIconGroupBox(self): self.iconGroupBox = QGroupBox("Tray Icon") self.iconLabel = QLabel("Icon:") self.iconComboBox = QComboBox() self.iconComboBox.addItem(QIcon(":/images/bad.png"), "Bad") self.iconComboBox.addItem(QIcon(":/images/heart.png"), "Heart") self.iconComboBox.addItem(QIcon(":/images/trash.png"), "Trash") self.showIconCheckBox = QCheckBox("Show icon") self.showIconCheckBox.setChecked(True) iconLayout = QHBoxLayout() iconLayout.addWidget(self.iconLabel) iconLayout.addWidget(self.iconComboBox) iconLayout.addStretch() iconLayout.addWidget(self.showIconCheckBox) self.iconGroupBox.setLayout(iconLayout) def createMessageGroupBox(self): self.messageGroupBox = QGroupBox("Balloon Message") self.typeLabel = QLabel("Type:") self.typeComboBox = QComboBox() self.typeComboBox.addItem("None", QSystemTrayIcon.NoIcon) self.typeComboBox.addItem( self.style().standardIcon(QStyle.SP_MessageBoxInformation), "Information", QSystemTrayIcon.Information, ) self.typeComboBox.addItem( self.style().standardIcon(QStyle.SP_MessageBoxWarning), "Warning", QSystemTrayIcon.Warning, ) self.typeComboBox.addItem( self.style().standardIcon(QStyle.SP_MessageBoxCritical), "Critical", QSystemTrayIcon.Critical, ) self.typeComboBox.addItem(QIcon(), "Custom icon", -1) self.typeComboBox.setCurrentIndex(1) self.durationLabel = QLabel("Duration:") self.durationSpinBox = QSpinBox() self.durationSpinBox.setRange(5, 60) self.durationSpinBox.setSuffix(" s") self.durationSpinBox.setValue(15) self.durationWarningLabel = QLabel( "(some systems might ignore this hint)") self.durationWarningLabel.setIndent(10) self.titleLabel = QLabel("Title:") self.titleEdit = QLineEdit("Cannot connect to network") self.bodyLabel = QLabel("Body:") self.bodyEdit = QTextEdit() self.bodyEdit.setPlainText( "Don't believe me. Honestly, I don't have a clue." "\nClick this balloon for details.") self.showMessageButton = QPushButton("Show Message") self.showMessageButton.setDefault(True) messageLayout = QGridLayout() messageLayout.addWidget(self.typeLabel, 0, 0) messageLayout.addWidget(self.typeComboBox, 0, 1, 1, 2) messageLayout.addWidget(self.durationLabel, 1, 0) messageLayout.addWidget(self.durationSpinBox, 1, 1) messageLayout.addWidget(self.durationWarningLabel, 1, 2, 1, 3) messageLayout.addWidget(self.titleLabel, 2, 0) messageLayout.addWidget(self.titleEdit, 2, 1, 1, 4) messageLayout.addWidget(self.bodyLabel, 3, 0) messageLayout.addWidget(self.bodyEdit, 3, 1, 2, 4) messageLayout.addWidget(self.showMessageButton, 5, 4) messageLayout.setColumnStretch(3, 1) messageLayout.setRowStretch(4, 1) self.messageGroupBox.setLayout(messageLayout) def createActions(self): self.minimizeAction = QAction("Minimize", self) self.minimizeAction.triggered.connect(self.hide) self.maximizeAction = QAction("Maximize", self) self.maximizeAction.triggered.connect(self.showMaximized) self.restoreAction = QAction("Restore", self) self.restoreAction.triggered.connect(self.showNormal) self.quitAction = QAction("Quit", self) self.quitAction.triggered.connect(qApp.quit) def createTrayIcon(self): self.trayIconMenu = QMenu(self) self.trayIconMenu.addAction(self.minimizeAction) self.trayIconMenu.addAction(self.maximizeAction) self.trayIconMenu.addAction(self.restoreAction) self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(self.quitAction) self.trayIcon = QSystemTrayIcon(self) self.trayIcon.setContextMenu(self.trayIconMenu)
class MineSweeper(QMainWindow): def __init__(self): super().__init__() self.undiscovered_color: str = "#000000" self.discovered_color: str = "#d9d9d9" self.win_timer_color: str = "#e30e0e" self.lose_timer_color: str = "#0cc431" self.curr_time = QTime(00,00,00) self.timer = QTimer() self.timer.timeout.connect(self.time) self.timer_already_started = False self.solved: bool = False self.player_ended: bool = False self.theme: str = "dark" self.list_of_mines: list = [] self.difficulty_slider_default_value: int = 2 self.number_of_mines: int = mines_number(NUMBER_OF_LABELS, self.difficulty_slider_default_value) self.create_GUI() def create_GUI(self) -> None: self.setWindowTitle("MineSweeper 1.1") self.win_massage = QMessageBox(self) self.win_massage.setText("Gratuluji, dokázal jsi nalézt všechny miny") self.setMouseTracking(True) centralWidget = QWidget(self) centralWidget.setStyleSheet("background: white") self.setCentralWidget(centralWidget) self.setFixedSize(X_WINDOW_SIZE + 20, Y_WINDOW_SIZE) layout = QGridLayout(centralWidget) layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) centralWidget.setLayout(layout) self.list_of_labels: list = [] self.list_of_mines = generate_mines(self.number_of_mines, X_SIZE, Y_SIZE) # RESET BUTTON self.reset_button = QPushButton(centralWidget) self.reset_button.setText("RESET") self.reset_button.clicked.connect(self.reset) self.reset_button.setStyleSheet("margin: 3px") self.reset_button.setMinimumSize(0, 50) # TIMER LABEL self.timer_label = QLabel(centralWidget) self.timer_label.setText(f"{self.curr_time.minute():0>2}:{self.curr_time.second():0>2}") self.timer_label.setAlignment(Qt.AlignHCenter) self.timer_label.setStyleSheet("font: 34px") # DIFFICULTY SLIDER self.difficulty_slider = QSlider(centralWidget) self.difficulty_slider.setOrientation(Qt.Horizontal) self.difficulty_slider.setFixedHeight(30) self.difficulty_slider.setRange(1, 10) self.difficulty_slider.setTickInterval(1) self.difficulty_slider.setValue(self.difficulty_slider_default_value) self.difficulty_slider.valueChanged.connect(self.difficulty_label_set) self.difficulty_slider.sliderReleased.connect(self.new_mines_set) # DIFFICULTY LABEL self.difficulty_label = QLabel(centralWidget) self.difficulty_label.setText(str(self.difficulty_slider_default_value)) self.difficulty_label.setAlignment(Qt.AlignCenter) self.difficulty_label.setStyleSheet("font: 20px") for i in range(Y_SIZE): row = [] for j in range(X_SIZE): if (i, j) in self.list_of_mines: mine = True else: mine = False label = Chunk(j, i, mine) label.setFixedSize(FIELD_SQUARE_SIZE, FIELD_SQUARE_SIZE) label.setStyleSheet(f"background: {self.undiscovered_color}; border: 1px solid grey") layout.addWidget(label, i, j) row.append(label) self.list_of_labels.append(row) self.color_theme_combobox = QComboBox(centralWidget) self.color_theme_combobox.addItem("Dark theme", "dark") self.color_theme_combobox.addItem("Light theme", "light") self.color_theme_combobox.addItem("Color theme", "colorful") self.color_theme_combobox.currentIndexChanged.connect(self.theme_change) self.color_theme_combobox.setMinimumHeight(FIELD_SQUARE_SIZE * 2) if self.theme == "dark": self.color_theme_combobox.setCurrentIndex(0) elif self.theme == "light": self.color_theme_combobox.setCurrentIndex(1) else: self.color_theme_combobox.setCurrentIndex(2) layout.addWidget(self.color_theme_combobox, Y_SIZE - 2, X_SIZE, 2, 1) layout.addWidget(self.timer_label, 0, X_SIZE, 3, 1) layout.addWidget(self.reset_button, 2, X_SIZE, 3, 1) layout.addWidget(self.difficulty_slider, Y_SIZE, 1, 1, X_SIZE - 2) layout.addWidget(self.difficulty_label, Y_SIZE, X_SIZE, 1, 1) self.mines_number_surroundings_calculate() def theme_change(self) -> None: if self.color_theme_combobox.currentData() == "light": self.undiscovered_color = LIGHT_THEME["undiscovered_color"] self.discovered_color = LIGHT_THEME["discovered_color"] self.win_timer_color = LIGHT_THEME["win_timer_color"] self.lose_timer_color = LIGHT_THEME["lose_timer_color"] self.theme = "light" if self.color_theme_combobox.currentData() == "dark": self.undiscovered_color = DARK_THEME["undiscovered_color"] self.discovered_color = DARK_THEME["discovered_color"] self.win_timer_color = DARK_THEME["win_timer_color"] self.lose_timer_color = DARK_THEME["lose_timer_color"] self.theme = "dark" if self.color_theme_combobox.currentData() == "colorful": self.undiscovered_color = COLOR_THEME["undiscovered_color"] self.discovered_color = COLOR_THEME["discovered_color"] self.win_timer_color = COLOR_THEME["win_timer_color"] self.lose_timer_color = COLOR_THEME["lose_timer_color"] self.theme = "colorful" for y in range(Y_SIZE): for x in range(X_SIZE): if self.list_of_labels[y][x].marked: pass elif not self.list_of_labels[y][x].discovered: self.list_of_labels[y][x].setStyleSheet(f"background: {self.undiscovered_color}; border: 1px solid grey") elif self.list_of_labels[y][x].discovered: self.list_of_labels[y][x].setStyleSheet(f"background: {self.discovered_color}; border: 1px solid grey") def difficulty_label_set(self): self.difficulty_label.setText(str(self.difficulty_slider.value())) def mousePressEvent(self, QMouseEvent) -> None: if not self.player_ended: y = QMouseEvent.pos().x() x = QMouseEvent.pos().y() if not (x > X_GRID_SIZE or y > Y_GRID_SIZE): x = closest_smaller_number(x, Y_POSSIBLE_VALUES) y = closest_smaller_number(y, X_POSSIBLE_VALUES) x = int(x // FIELD_SQUARE_SIZE) y = int(y // FIELD_SQUARE_SIZE) if QMouseEvent.button() == Qt.LeftButton: if self.list_of_labels[x][y].mine: self.stop_timer() if not self.player_ended: self.list_of_labels[x][y].discovered = True self.list_of_labels[x][y].setStyleSheet(f"background: {self.discovered_color}; border: 1px solid grey") self.list_of_labels[x][y].setPixmap(QPixmap("C:/Data/python/miny/pracovní verze/pictures/bomb_small.png")) self.win_massage.about(self, "PROHRA", "Tentokrát se to bohužel nepovedlo, snad to vyjde příště.") self.player_ended = True else: if not self.timer_already_started: self.start_timer() self.timer_already_started = True self.list_of_labels[x][y].discovered = True self.list_of_labels[x][y].setStyleSheet(f"background: {self.discovered_color}; border: 1px solid grey") self.reveal_area(y, x) self.solved_check() else: if not self.list_of_labels[x][y].discovered: if self.list_of_labels[x][y].marked: self.list_of_labels[x][y].setStyleSheet(f"background: {self.undiscovered_color}; border: 1px solid grey") self.list_of_labels[x][y].marked = False else: self.list_of_labels[x][y].setStyleSheet("background: orange; border: 1px solid grey") self.list_of_labels[x][y].marked = True def mines_number_surroundings_calculate(self) -> None: for x in range(X_SIZE): for y in range(Y_SIZE): self.list_of_labels[x][y].mines_number_surroundings = 0 for i in range(x - 1, x + 2): for j in range(y - 1, y + 2): try: if self.list_of_labels[i][j].mine and i >= 0 and j >= 0: if not (i == x and j == y): self.list_of_labels[x][y].mines_number_surroundings += 1 except IndexError: pass def new_mines_set(self): self.number_of_mines = mines_number(NUMBER_OF_LABELS, self.difficulty_slider.value()) self.list_of_mines = generate_mines(self.number_of_mines, X_SIZE, Y_SIZE) for y in range(Y_SIZE): for x in range(X_SIZE): if (y, x) in self.list_of_mines: self.list_of_labels[y][x].mine = True else: self.list_of_labels[y][x].mine = False self.mines_number_surroundings_calculate() self.label_set() def label_set(self) -> None: for y in range(Y_SIZE): for x in range(X_SIZE): if self.list_of_labels[y][x].discovered: if self.list_of_labels[y][x].mines_number_surroundings == 0: pass else: self.list_of_labels[y][x].setText(str(self.list_of_labels[y][x].mines_number_surroundings)) def reveal_area(self, x: int, y: int) -> None: if self.list_of_labels[y][x].mines_number_surroundings == 0: try: extract = self.list_of_labels[y - 1][x] if not extract.mine and Y_SIZE > y - 1 >= 0 and not extract.discovered: self.list_of_labels[y - 1][x].setStyleSheet(f"background: {self.discovered_color}; border: 1px solid grey") self.list_of_labels[y - 1][x].discovered = True if extract.mines_number_surroundings == 0: self.reveal_area(x, y - 1) except IndexError: pass try: extract = self.list_of_labels[y + 1][x] if not extract.mine and Y_SIZE > y + 1 >= 0 and not extract.discovered: self.list_of_labels[y + 1][x].setStyleSheet(f"background: {self.discovered_color}; border: 1px solid grey") self.list_of_labels[y + 1][x].discovered = True if extract.mines_number_surroundings == 0: self.reveal_area(x, y + 1) except IndexError: pass try: extract = self.list_of_labels[y][x + 1] if not extract.mine and X_SIZE > x + 1 >= 0 and not extract.discovered: self.list_of_labels[y][x + 1].setStyleSheet(f"background: {self.discovered_color}; border: 1px solid grey") self.list_of_labels[y][x + 1].discovered = True if extract.mines_number_surroundings == 0: self.reveal_area(x + 1, y) except IndexError: pass try: extract = self.list_of_labels[y][x - 1] if not extract.mine and X_SIZE - 1 > x - 1 >= 0 and not extract.discovered: self.list_of_labels[y][x - 1].setStyleSheet(f"background: {self.discovered_color}; border: 1px solid grey") self.list_of_labels[y][x - 1].discovered = True if extract.mines_number_surroundings == 0: self.reveal_area(x - 1, y) except IndexError: pass self.label_set() def solved_check(self) -> None: for element in self.list_of_labels: for part in element: if not part.mine and not part.discovered: return self.solved = True self.stop_timer() if not self.player_ended: self.player_ended = True self.win_massage.about(self, "VÝHRA", f"Gratuluji, zvládl/a jsi vyřešit tento problém. Zvládl/a jsi to za {self.curr_time.minute():0>2}:{self.curr_time.second():0>2}") # TIMER FUNCIONS def start_timer(self) -> None: self.difficulty_slider.setDisabled(True) self.timer.start(1000) def stop_timer(self) -> None: self.timer.stop() if not self.solved: self.timer_label.setStyleSheet(f"font: 34px; color: {self.win_timer_color}") else: self.timer_label.setStyleSheet(f"font: 34px; color: {self.lose_timer_color}") def time(self) -> None: self.curr_time = self.curr_time.addSecs(1) self.timer_label.setText(f"{self.curr_time.minute():0>2}:{self.curr_time.second():0>2}") #RESET def reset(self) -> None: self.timer = QTimer() self.curr_time = QTime(00,00,00) self.timer.timeout.connect(self.time) self.solved = False self.timer_already_started = False self.player_ended = False self.difficulty_slider.setDisabled(False) self.difficulty_slider_default_value = self.difficulty_slider.value() self.create_GUI()
class PlaylistPopup(QWidget): def __init__(self, result, parent=None): # Popup when "Add song to playlist" is clicked on # How this works is a QWidget that encompasses the entire window area, representing an unclickable translucent background. # Another QWidget is then contained inside that QWidget representing the popup. # result: (dict) Python dict containing information of the song clicked QWidget.__init__(self) self.setParent(parent) self.result = result # Signals are used to indicate to close the window self.SIGNALS = self.TranslucentWidgetSignals() # Make the window frameless and expanding. self.setWindowFlags(Qt.FramelessWindowHint) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Makes the window background colour translucent self.setAttribute(Qt.WA_StyledBackground) self.setStyleSheet( "PlaylistPopup { background-color: rgba(255, 255, 255, 0.5)}") # Sets the grid settings of the "background" and the "popup" layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) playlistAdd = QWidget(self) playlistAdd.setFixedSize(800, 300) playlistAdd.setStyleSheet( ".QWidget { background-color: rgba(255, 255, 255, 1)}") innerLayout = QGridLayout() innerLayout.setContentsMargins(20, 20, 20, 20) innerLayout.setSpacing(30) # Heading font font = QFont() font.setPointSize(24) # Default label font font2 = QFont() font2.setPointSize(16) # Heading label = QLabel("添加到播放列表/Add to Playlist", self) label.setAlignment(Qt.AlignCenter) label.setFont(font) innerLayout.addWidget(label, 0, 0) # Playlist selection self.comboBox = QComboBox(self) self.comboBox.setFont(font) playlists = DB.getPlaylists("") for playlist in playlists: self.comboBox.addItem(playlist["playlist_name"]) self.comboBox.setCurrentIndex(-1) innerLayout.addWidget(self.comboBox, 1, 0) # Textbox to create a new playlist self.textBox = QLineEdit(self) self.textBox.setFont(font2) self.textBox.setAlignment(Qt.AlignCenter) self.textBox.setPlaceholderText( "输入以创建新的播放列表/Type to create a new playlist") self.textBox.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) # TODO: resize textbox with window self.textBox.setFixedWidth(760) innerLayout.addWidget(self.textBox, 2, 0, Qt.AlignCenter) # Add actions for then the QComboBox or QLineEdit is changed. # This is done so there is only one action between "Add to existing Playlist" or "Add to new Playlist" self.comboBox.currentIndexChanged.connect(self.comboBoxChanged) self.textBox.textEdited.connect(self.textBoxChanged) # Confirm button confirmButton = QToolButton(self) confirmButton.setText("确认/Confirm") confirmButton.setFont(font) confirmButton.clicked.connect(self.processPlaylistRequest) innerLayout.addWidget(confirmButton, 3, 0, Qt.AlignCenter) # Exit button btn = QToolButton(self) btn.setFixedSize(44, 44) btn.setText("X") btn.setFont(font) btn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) btn.clicked.connect(lambda: self.SIGNALS.CLOSE.emit()) innerLayout.addWidget(btn, 0, 0, Qt.AlignRight) playlistAdd.setLayout(innerLayout) layout.addWidget(playlistAdd, 0, 0, Qt.AlignCenter) self.setLayout(layout) def comboBoxChanged(self): # Called when the ComboBox is changed # Clears the text in the "Create Playlist" TextBox if self.textBox.text() != "": self.textBox.setText("") def textBoxChanged(self): # Called when the TextBox is changed # Clears the selection in the "Add to Playlist" ComboBox if self.comboBox.currentIndex != -1: self.comboBox.setCurrentIndex(-1) def processPlaylistRequest(self): # Called when the Confirm button is clicked def addToPlaylist(self, playlistID): # Adds the song to the playlist # Get song ID song = self.result["song_id"] DB.addPlaylistSong(playlistID, song) if self.textBox.text() != "": # New playlist playlistName = self.textBox.text() counter = 1 while DB.checkPlaylist(playlistName): playlistName = "{} ({})".format(self.textBox.text(), counter) counter += 1 playlistID = DB.newPlaylist(playlistName)[0]["playlist_id"] addToPlaylist(self, playlistID) self.SIGNALS.CLOSE.emit() elif self.comboBox.currentIndex != -1: playlistID = DB.checkPlaylist( self.comboBox.currentText())[0]["playlist_id"] # Add to existing playlist addToPlaylist(self, playlistID) self.SIGNALS.CLOSE.emit() # Taken from https://stackoverflow.com/questions/44264852/pyside-pyqt-overlay-widget class TranslucentWidgetSignals(QtCore.QObject): CLOSE = QtCore.Signal()
class ImageFusionOptions(object): """ UI class that can be used by the AddOnOptions Class to allow the user customise their input parameters for auto-registration. """ def __init__(self, window_options): self.auto_image_fusion_frame = QtWidgets.QFrame() self.window = window_options self.moving_image = None self.fixed_image = None self.dict = {} self.setupUi() self.create_view() self.get_patients_info() def set_value(self, key, value): """ Stores values into a dictionary to the corresponding key. Parameters ---------- key (Any): value (Any): """ self.dict[key] = value def create_view(self): """ Create a table to hold all the ROI creation by isodose entries. """ self.auto_image_fusion_frame.setVisible(False) def setVisible(self, visibility): """ Custom setVisible function that will set the visibility of the GUI. Args: visibility (bool): flag for setting the GUI to visible """ self.auto_image_fusion_frame.setVisible(visibility) def setupUi(self): """ Constructs the GUI and sets the limit of each input field. """ # Create a vertical Widget to hold Vertical Layout self.vertical_layout_widget = QWidget() self.vertical_layout = QtWidgets.QVBoxLayout() # Create a Widget and set layout to a GridLayout self.gridLayoutWidget = QWidget() self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget) self.gridLayout.setSizeConstraint(QLayout.SetDefaultConstraint) self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setVerticalSpacing(0) # Create horizontal spacer in the middle of the grid hspacer = QtWidgets.QSpacerItem(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(hspacer, 0, 5, 16, 1) # Labels self.fixed_image_label = QLabel("Fixed Image: ") fixed_image_sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) fixed_image_sizePolicy.setHorizontalStretch(0) fixed_image_sizePolicy.setVerticalStretch(0) fixed_image_sizePolicy.setHeightForWidth( self.fixed_image_label.sizePolicy().hasHeightForWidth()) self.fixed_image_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.fixed_image_placeholder \ = QLabel("This is a placeholder for fixed image") self.fixed_image_placeholder.setWordWrap(False) self.fixed_image_placeholder.setText(str(self.fixed_image)) self.fixed_image_placeholder.setMaximumSize(200, 50) self.moving_image_label = QLabel("Moving Image: ") moving_image_label_sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) moving_image_label_sizePolicy.setHorizontalStretch(0) moving_image_label_sizePolicy.setVerticalStretch(0) moving_image_label_sizePolicy.setHeightForWidth( self.moving_image_label.sizePolicy().hasHeightForWidth()) self.moving_image_label.setSizePolicy(moving_image_label_sizePolicy) self.moving_image_placeholder = QLabel("This is a placeholder") self.moving_image_placeholder.setWordWrap(False) self.moving_image_placeholder.setText(str(self.moving_image)) self.moving_image_placeholder.setMaximumSize(200, 50) self.gridLayout.addWidget(self.fixed_image_label, 0, 0) self.gridLayout.addWidget(self.fixed_image_placeholder, 0, 1) self.gridLayout.addWidget(self.moving_image_label, 0, 2) self.gridLayout.addWidget(self.moving_image_placeholder, 0, 3) # Default Numbers self.default_numbers_label = QLabel("Default Numbers") self.default_numbers_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.default_numbers_label, 1, 0) self.default_number_spinBox = QSpinBox(self.gridLayoutWidget) self.default_number_spinBox.setRange(-2147483648, 2147483647) self.default_number_spinBox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.default_number_spinBox.setToolTip( "Default voxel value. Defaults to -1000.") self.gridLayout.addWidget(self.default_number_spinBox, 1, 1) # Final Interp self.interp_order_label = QLabel("Final Interp") self.interp_order_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.interp_order_label, 2, 0) self.interp_order_spinbox = QSpinBox(self.gridLayoutWidget) self.interp_order_spinbox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.interp_order_spinbox.setToolTip("The final interpolation order.") self.gridLayout.addWidget(self.interp_order_spinbox, 2, 1) # Metric self.metric_label = QLabel("Metric") self.metric_label.setAlignment(QtCore.Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.metric_label, 3, 0) self.metric_comboBox = QComboBox() self.metric_comboBox.addItem("correlation") self.metric_comboBox.addItem("mean_squares") self.metric_comboBox.addItem("mattes_mi") self.metric_comboBox.addItem("joint_hist_mi") self.metric_comboBox.setToolTip( "The metric to be optimised during image registration.") self.gridLayout.addWidget(self.metric_comboBox, 3, 1) # Number of Iterations self.no_of_iterations_label = QLabel("Number of Iterations") self.no_of_iterations_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.no_of_iterations_label, 4, 0) self.no_of_iterations_spinBox = QSpinBox(self.gridLayoutWidget) self.no_of_iterations_spinBox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.no_of_iterations_spinBox.setRange(0, 100) self.no_of_iterations_spinBox.setToolTip( "Number of iterations in each multi-resolution step.") self.gridLayout.addWidget(self.no_of_iterations_spinBox, 4, 1) # Shrink Factor self.shrink_factor_label = QLabel("Shrink Factor") self.shrink_factor_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.shrink_factor_label, 5, 0) self.shrink_factor_qLineEdit = QLineEdit() self.shrink_factor_qLineEdit.resize( self.shrink_factor_qLineEdit.sizeHint().width(), self.shrink_factor_qLineEdit.sizeHint().height()) self.shrink_factor_qLineEdit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[,]?[0-9]*[,]?[0-9]"))) self.shrink_factor_qLineEdit.setToolTip( "The multi-resolution downsampling factors. Can be up to three " "integer elements in an array. Example [8, 2, 1]") self.gridLayout.addWidget(self.shrink_factor_qLineEdit, 5, 1) # Optimiser self.optimiser_label = QLabel("Optimiser") self.optimiser_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.optimiser_label, 1, 2) self.optimiser_comboBox = QComboBox(self.gridLayoutWidget) self.optimiser_comboBox.addItem("lbfgsb") self.optimiser_comboBox.addItem("gradient_descent") self.optimiser_comboBox.addItem("gradient_descent_line_search") self.optimiser_comboBox.setToolTip( "The optimiser algorithm used for image registration.") self.gridLayout.addWidget(self.optimiser_comboBox, 1, 3) # Reg Method self.reg_method_label = QLabel("Reg Method") self.reg_method_label.setAlignment(QtCore.Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.reg_method_label, 2, 2) self.reg_method_comboBox = QComboBox() self.reg_method_comboBox.addItem("translation") self.reg_method_comboBox.addItem("rigid") self.reg_method_comboBox.addItem("similarity") self.reg_method_comboBox.addItem("affine") self.reg_method_comboBox.addItem("scaleversor") self.reg_method_comboBox.addItem("scaleskewversor") self.reg_method_comboBox.setToolTip( "The linear transformation model to be used for image " "registration.") self.gridLayout.addWidget(self.reg_method_comboBox, 2, 3) # Sampling Rate self.sampling_rate_label = QLabel("Sampling Rate") self.sampling_rate_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.sampling_rate_label, 3, 2) self.sampling_rate_spinBox = QDoubleSpinBox(self.gridLayoutWidget) self.sampling_rate_spinBox.setMinimum(0) self.sampling_rate_spinBox.setMaximum(1) self.sampling_rate_spinBox.setSingleStep(0.01) self.sampling_rate_spinBox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.sampling_rate_spinBox.setToolTip("The fraction of voxels sampled " "during each iteration.") self.gridLayout.addWidget(self.sampling_rate_spinBox, 3, 3) # Smooth Sigmas self.smooth_sigma_label = QLabel("Smooth Sigma") self.smooth_sigma_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.smooth_sigma_label, 4, 2) self.smooth_sigmas_qLineEdit = QLineEdit() self.smooth_sigmas_qLineEdit.resize( self.smooth_sigmas_qLineEdit.sizeHint().width(), self.smooth_sigmas_qLineEdit.sizeHint().height()) self.smooth_sigmas_qLineEdit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[,]?[0-9]*[,]?[0-9]"))) self.smooth_sigmas_qLineEdit.setToolTip( "The multi-resolution smoothing kernal scale (Gaussian). Can be " "up to three integer elements in an array. Example [4, 2, 1]") self.gridLayout.addWidget(self.smooth_sigmas_qLineEdit, 4, 3) # Label to hold warning labels. self.warning_label = QLabel() # Button for fast mode self.fast_mode_button = QtWidgets.QPushButton("Fast Mode") self.fast_mode_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.fast_mode_button.clicked.connect(self.set_fast_mode) # Add Widgets to the vertical layout self.vertical_layout.addWidget(self.fast_mode_button) self.vertical_layout.addWidget(self.gridLayoutWidget) self.vertical_layout.addWidget(self.warning_label) # Set layout of frame to the gridlayout widget self.auto_image_fusion_frame.setLayout(self.vertical_layout) def set_gridLayout(self): """ Set the UI based on the values taken from the JSON """ msg = "" # If-Elif statements for setting the dict # this can only be done in if-else statements. if self.dict["reg_method"] == "translation": self.reg_method_comboBox.setCurrentIndex(0) elif self.dict["reg_method"] == "rigid": self.reg_method_comboBox.setCurrentIndex(1) elif self.dict["reg_method"] == "similarity": self.reg_method_comboBox.setCurrentIndex(2) elif self.dict["reg_method"] == "affine": self.reg_method_comboBox.setCurrentIndex(3) elif self.dict["reg_method"] == "scaleversor": self.reg_method_comboBox.setCurrentIndex(4) elif self.dict["reg_method"] == "scaleskewversor": self.reg_method_comboBox.setCurrentIndex(5) else: msg += 'There was an error setting the reg_method value.\n' self.warning_label.setText(msg) if self.dict["metric"] == "coorelation": self.metric_comboBox.setCurrentIndex(0) elif self.dict["metric"] == "mean_squares": self.metric_comboBox.setCurrentIndex(1) elif self.dict["metric"] == "mattes_mi": self.metric_comboBox.setCurrentIndex(2) elif self.dict["metric"] == "joint_hist_mi": self.metric_comboBox.setCurrentIndex(3) else: msg += 'There was an error setting the metric value.\n' self.warning_label.setText(msg) if self.dict["optimiser"] == "lbfgsb": self.optimiser_comboBox.setCurrentIndex(0) elif self.dict["optimiser"] == "gradient_descent": self.optimiser_comboBox.setCurrentIndex(1) elif self.dict["optimiser"] == "gradient_descent_line_search": self.optimiser_comboBox.setCurrentIndex(2) else: msg += 'There was an error setting the optimiser value.\n' self.warning_label.setText(msg) # Check if all elements in list are ints if all(isinstance(x, int) for x in self.dict["shrink_factors"]): # Shrink_factors is stored as a list in JSON convert the list into # a string. shrink_factor_list_json = ', '.join( str(e) for e in self.dict["shrink_factors"]) self.shrink_factor_qLineEdit.setText(shrink_factor_list_json) else: msg += 'There was an error setting the Shrink Factors value.\n' self.warning_label.setText(msg) # Check if all elements in list are ints if all(isinstance(x, int) for x in self.dict["smooth_sigmas"]): # Since smooth_sigma is stored as a list in JSON convert the list # into a string. smooth_sigma_list_json = ', '.join( str(e) for e in self.dict["smooth_sigmas"]) self.smooth_sigmas_qLineEdit.setText(smooth_sigma_list_json) else: msg += 'There was an error setting the Smooth Sigmas value.\n' self.warning_label.setText(msg) try: self.sampling_rate_spinBox.setValue( float(self.dict["sampling_rate"])) except ValueError: msg += 'There was an error setting the Sampling Rate value.\n' self.warning_label.setText(msg) try: self.interp_order_spinbox.setValue(int(self.dict["final_interp"])) except ValueError: msg += 'There was an error setting the Final Interp value.\n' self.warning_label.setText(msg) try: self.no_of_iterations_spinBox.setValue( int(self.dict["number_of_iterations"])) except ValueError: msg += 'There was an error setting the Number of iterations ' \ 'value.\n' self.warning_label.setText(msg) try: self.default_number_spinBox.setValue( int(self.dict["default_value"])) except ValueError: msg += 'There was an error setting the Default Number' self.warning_label.setText(msg) def get_patients_info(self): """ Retrieve the patient's study description of the fixed image and for the moving image (if it exists). """ patient_dict_container = PatientDictContainer() if not patient_dict_container.is_empty(): filename = patient_dict_container.filepaths[0] dicom_tree_slice = DicomTree(filename) dict_tree = dicom_tree_slice.dict try: self.fixed_image = dict_tree["Series Instance UID"][0] except: self.fixed_image = "" self.warning_label.setText( 'Couldn\'t find the series instance ' 'UID for the Fixed Image.') moving_dict_container = MovingDictContainer() if not moving_dict_container.is_empty(): filename = moving_dict_container.filepaths[0] dicom_tree_slice = DicomTree(filename) dict_tree = dicom_tree_slice.dict try: self.moving_image = dict_tree["Series Instance UID"][0] except: self.moving_image = "" self.warning_label.setText( 'Couldn\'t find the series instance ' 'UID for the Moving Image.') if moving_dict_container.is_empty() and self.moving_image != "": self.moving_image = "" self.fixed_image_placeholder.setText(str(self.fixed_image)) self.moving_image_placeholder.setText(str(self.moving_image)) def get_values_from_UI(self): """ Sets values from the GUI to the dict that will be used to store the relevant parameters to imageFusion.json. """ self.dict["reg_method"] = str(self.reg_method_comboBox.currentText()) self.dict["metric"] = str(self.metric_comboBox.currentText()) self.dict["optimiser"] = str(self.optimiser_comboBox.currentText()) a_string = self.shrink_factor_qLineEdit.text().split(",") a_int = list(map(int, a_string)) self.dict["shrink_factors"] = a_int a_string = self.smooth_sigmas_qLineEdit.text().split(",") a_int = list(map(int, a_string)) self.dict["smooth_sigmas"] = a_int self.dict["sampling_rate"] = self.sampling_rate_spinBox.value() self.dict["final_interp"] = self.interp_order_spinbox.value() self.dict[ "number_of_iterations"] = self.no_of_iterations_spinBox.value() self.dict["default_value"] = self.default_number_spinBox.value() return self.dict def check_parameter(self): """ Check the number of values of the smooth sigma and shrink factors of that are parameters used for images fusion. """ len_smooth_sigmas = len(self.dict["smooth_sigmas"]) len_shrink_factor = len(self.dict["shrink_factors"]) if len_smooth_sigmas != len_shrink_factor: raise ValueError def set_fast_mode(self): """These settings are customised to be fast for images fusion.""" self.reg_method_comboBox.setCurrentIndex(1) self.metric_comboBox.setCurrentIndex(1) self.optimiser_comboBox.setCurrentIndex(1) self.shrink_factor_qLineEdit.setText("8") self.smooth_sigmas_qLineEdit.setText("10") self.sampling_rate_spinBox.setValue(0.25) self.interp_order_spinbox.setValue(2) self.no_of_iterations_spinBox.setValue(50) self.default_number_spinBox.setValue(-1000)
class DateRangeSelector(QWidget): changed = Signal(int, int) # emits signal when one or both dates were changed, "from" and "to" timestamps are sent def __init__(self, parent): QWidget.__init__(self, parent) self.report_ranges = { 'week': (self.tr("Week"), ManipulateDate.PreviousWeek), 'month': (self.tr("Month"), ManipulateDate.PreviousMonth), 'quarter': (self.tr("Quarter"), ManipulateDate.PreviousQuarter), 'year': (self.tr("Year"), ManipulateDate.PreviousYear), 'QTD': (self.tr("Quarter to date"), ManipulateDate.QuarterToDate), 'YTD': (self.tr("Year to date"), ManipulateDate.YearToDate), 'this_year': (self.tr("This year"), ManipulateDate.ThisYear), 'last_year': (self.tr("Previous year"), ManipulateDate.LastYear), 'all': (self.tr("All dates"), ManipulateDate.AllDates), } self._begin = 0 self._end = 0 self._items = [] self.changing_range = False self.layout = QHBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.range_combo = QComboBox(self) self.layout.addWidget(self.range_combo) self.from_label = QLabel(self.tr("From:"), parent=self) self.layout.addWidget(self.from_label) self.from_date = QDateEdit() self.from_date.setDisplayFormat("dd/MM/yyyy") self.from_date.setCalendarPopup(True) self.from_date.setTimeSpec(Qt.UTC) self.layout.addWidget(self.from_date) self.from_label = QLabel(self.tr("To:"), parent=self) self.layout.addWidget(self.from_label) self.to_date = QDateEdit() self.to_date.setDisplayFormat("dd/MM/yyyy") self.to_date.setCalendarPopup(True) self.to_date.setTimeSpec(Qt.UTC) self.layout.addWidget(self.to_date) self.setLayout(self.layout) self.setFocusProxy(self.range_combo) self.connect_signals_and_slots() def getConfig(self): return ';'.join(self._items) def setConfig(self, items_list): try: self._items = items_list.split(';') except AttributeError: self._items = [] for item in self._items: try: item_name = self.report_ranges[item][ITEM_NAME] self.range_combo.addItem(item_name, item) except KeyError: continue ItemsList = Property(str, getConfig, setConfig) def connect_signals_and_slots(self): self.range_combo.currentIndexChanged.connect(self.onRangeChange) self.from_date.dateChanged.connect(self.onFromChange) self.to_date.dateChanged.connect(self.onToChange) @Slot() def onRangeChange(self, index): item = self.range_combo.itemData(index) self._begin, self._end = self.report_ranges[item][ITEM_METHOD]() self.changing_range = True self.from_date.setDateTime(QDateTime.fromSecsSinceEpoch(self._begin, spec=Qt.UTC)) self.to_date.setDateTime(QDateTime.fromSecsSinceEpoch(self._end, spec=Qt.UTC)) self.changing_range = False self.changed.emit(self._begin, self._end) @Slot() def onFromChange(self): self._begin = self.from_date.date().startOfDay(Qt.UTC).toSecsSinceEpoch() if not self.changing_range: self.changed.emit(self._begin, self._end) @Slot() def onToChange(self): self._end = self.to_date.date().startOfDay(Qt.UTC).toSecsSinceEpoch() if not self.changing_range: self.changed.emit(self._begin, self._end) def setCurrentIndex(self, index): if index == self.range_combo.currentIndex(): self.onRangeChange(index) else: self.range_combo.setCurrentIndex(index)