def on_click_set_part(self, ent_part: QLineEdit, combo_1: QComboBox, check: QCheckBox, ent_desc: QLineEdit, combo_2: QComboBox): # obtain part number num_part = ent_part.text() ent_part.setText(None) # obtain original part number if selected id_part_orig = 'NULL' if combo_1.isEnabled(): num_part_org = combo_1.currentText() sql1 = self.db.sql( "SELECT id_part FROM part WHERE num_part = '?';", [num_part_org]) print(sql1) out = self.db.get(sql1) for id in out: id_part_orig = id[0] combo_1.clear() combo_1.clearEditText() combo_1.setEnabled(False) # clear QCheckBox if check.isChecked(): check.setEnabled(False) # obtain part description description = ent_desc.text() ent_desc.setText(None) # obtain id_supplier from selected supplier on the QComboBox supplier = combo_2.currentText() sql2 = self.db.sql( "SELECT id_supplier FROM supplier WHERE name_supplier_short = '?';", [supplier]) print(sql2) out = self.db.get(sql2) for id in out: id_supplier = id[0] print(num_part) print(description) print(supplier) print(id_supplier) # insert new part to part table sql3 = self.db.sql( "INSERT INTO part VALUES(NULL, ?, ?, '?', '?', NULL, NULL);", [id_part_orig, id_supplier, num_part, description]) print(sql3) self.db.put(sql3)
def part_selection_change(self, combo: QComboBox, lab_supplier: QLabel, lab_desc: QLabel): num_part = combo.currentText() if len(num_part) == 0: return print(num_part) sql1 = self.db.sql( "SELECT id_part, id_supplier FROM part WHERE num_part = '?';", [num_part]) out = self.db.get(sql1) for id in out: id_part = id[0] id_supplier = id[1] print(id_part) print(id_supplier) sql3 = self.db.sql( "SELECT name_supplier_short FROM supplier WHERE id_supplier = ?;", [id_supplier]) out = self.db.get(sql3) for id in out: name_supplier_short = id[0] print(name_supplier_short) sql4 = self.db.sql("SELECT description FROM part WHERE id_part = ?;", [id_part]) out = self.db.get(sql4) for id in out: description = id[0] print(description) lab_supplier.setText(name_supplier_short) lab_desc.setText(description)
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)
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 InterpolateBadsDialog(QDialog): def __init__(self, parent): super().__init__(parent) self.setWindowTitle("Interpolate bad channels") vbox = QVBoxLayout(self) grid = QGridLayout() grid.addWidget(QLabel("Reset bads:"), 0, 0) self.reset_bads_checkbox = QCheckBox() self.reset_bads_checkbox.setChecked(True) grid.addWidget(self.reset_bads_checkbox, 0, 1) grid.addWidget(QLabel("Mode:"), 1, 0) self.mode_select = QComboBox() self.modes = {"Accurate": "accurate", "Fast": "fast"} self.mode_select.addItems(self.modes.keys()) self.mode_select.setCurrentText("Accurate") grid.addWidget(self.mode_select, 1, 1) grid.addWidget(QLabel("Origin (x, y, z):"), 2, 0) hbox = QHBoxLayout() self.x = QDoubleSpinBox() self.x.setValue(0) self.x.setDecimals(3) hbox.addWidget(self.x) self.y = QDoubleSpinBox() self.y.setValue(0) self.y.setDecimals(3) hbox.addWidget(self.y) self.z = QDoubleSpinBox() self.z.setValue(0.04) self.z.setDecimals(3) hbox.addWidget(self.z) grid.addLayout(hbox, 2, 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) @property def origin(self): x = float(self.x.value()) y = float(self.y.value()) z = float(self.z.value()) return x, y, z @property def mode(self): return self.mode_select.currentText() @property def reset_bads(self): return self.reset_bads_checkbox.isChecked()
class DeviceBox(QGroupBox): def __init__(self, controller, parent=None): super().__init__("Device", parent=parent) self.controller = controller self.is_connected = False layout = QVBoxLayout() self.setLayout(layout) self.button_refresh = QPushButton("Refresh") self.combobox_ports = QComboBox() self.button_connect = QPushButton("Connect") layout.addWidget(self.button_refresh) layout.addWidget(self.combobox_ports) layout.addWidget(self.button_connect) self.button_refresh.clicked.connect(self.refresh_ports) self.button_connect.clicked.connect(self.connect_to_device) def refresh_ports(self): self.combobox_ports.clear() self.combobox_ports.addItems(self.controller.get_ports_names()) def connect_to_device(self): if not self.is_connected: port = self.combobox_ports.currentText() self.controller.connect_to_device(port) else: self.controller.disconnect_device() self.is_connected = self.controller.is_device_connected() if self.is_connected: self.button_connect.setText("Disconnect") else: self.button_connect.setText("Connect")
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()
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 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 JobsWindow(QWidget): def __init__(self): super().__init__() self.quit_button = QPushButton("Quit", self) self.update_button = QPushButton("Update Data", self) self.enter_data = QPushButton("Enter Data", self) self.data_button = QPushButton("Run Data Visualization", self) self.back_button = QPushButton("Back", self) self.text_visualization_button = QPushButton("Text Visualization", self) self.map_visualization = QPushButton("Map Visualization", self) self.order_selector_text = QComboBox(self) self.data_selector_map = QComboBox(self) self.data_visualization_label = QLabel("Welcome to data visualization!", self) self.welcome_label = QLabel("Welcome to Jobs data Visualization.", self) self.list_control = None self.update_label_01 = QLabel("", self) self.update_label_02 = QLabel("", self) self.update_label_03 = QLabel("", self) self.update_label_04 = QLabel("", self) self.update_label_05 = QLabel("", self) self.update_label_06 = QLabel("", self) self.update_label_07 = QLabel("", self) self.update_label_08 = QLabel("", self) self.excel_label = QLabel("Excel Spreadsheet:", self) self.update_information = QLabel( "If you would like to update a single entry please select the table and enter all of its information.\n" "If you would like to import from a spreadsheet type it into the box on the right and select the table.\n" "When you are ready with which ever function press Enter Data.\n" "For any data you want to append make sure the id is None.\n" "Also only work from one method at a time and make sure he other is empty.", self) self.table_selection = QComboBox(self) self.update_box_01 = QLineEdit(self) self.update_box_02 = QLineEdit(self) self.update_box_03 = QLineEdit(self) self.update_box_04 = QLineEdit(self) self.update_box_05 = QLineEdit(self) self.update_box_06 = QLineEdit(self) self.update_box_07 = QLineEdit(self) self.update_box_08 = QLineEdit(self) self.update_excel_selection = QLineEdit(self) self.list_control = None self.setup_window() def setup_window(self): self.setWindowTitle("Jobs Window") display_list = QListWidget(self) self.list_control = display_list display_list.resize(500, 350) self.setGeometry(50, 50, 500, 500) self.quit_button.clicked.connect(QApplication.instance().quit) self.quit_button.resize(self.quit_button.sizeHint()) self.quit_button.move(415, 450) self.update_button.clicked.connect(self.update_data) self.update_button.move(200, 200) self.data_button.clicked.connect(self.run_data_visualization) self.data_button.move(175, 250) self.back_button.clicked.connect(self.go_back) self.back_button.move(25, 450) self.data_visualization_label.move(20, 400) self.text_visualization_button.move(400 - self.text_visualization_button.width(), 600) self.order_selector_text.move(self.text_visualization_button.x(), self.text_visualization_button.y()+self.text_visualization_button.height()+10) self.text_visualization_button.clicked.connect(self.text_visualization) self.map_visualization.move(self.text_visualization_button.x() + self.text_visualization_button.width(), self.text_visualization_button.y()) self.data_selector_map.move(self.map_visualization.x(), self.map_visualization.y()+self.map_visualization.height()+10) self.map_visualization.clicked.connect(self.run_map_visualization) self.welcome_label.move(150, 150) self.update_box_01.move(150, 30) self.update_box_02.move(150, 60) self.update_box_03.move(150, 90) self.update_box_04.move(150, 120) self.update_box_05.move(150, 150) self.update_box_06.move(150, 180) self.update_box_07.move(150, 210) self.update_box_08.move(150, 240) self.excel_label.move(340, 70) self.update_excel_selection.move(340, 90) self.update_information.move(25, 325) self.update_label_01.setGeometry(5, 30, 145, 20) self.update_label_02.setGeometry(5, 60, 145, 20) self.update_label_03.setGeometry(5, 90, 145, 20) self.update_label_04.setGeometry(5, 120, 145, 20) self.update_label_05.setGeometry(5, 150, 145, 20) self.update_label_06.setGeometry(5, 180, 145, 20) self.update_label_07.setGeometry(5, 210, 145, 20) self.update_label_08.setGeometry(5, 240, 145, 20) self.table_selection.setGeometry(10, 10, 145, 20) self.enter_data.move(10, 260) self.enter_data.clicked.connect(self.import_data) self.table_selection.addItem("---") self.table_selection.addItem("Schools") self.table_selection.addItem("Jobs") self.order_selector_text.addItem("---") self.order_selector_text.addItem("ASC") self.order_selector_text.addItem("DESC") self.data_selector_map.addItem("---") self.data_selector_map.addItem("Employment to Graduates") self.data_selector_map.addItem("Average Salary to Average Declining Balance Percent") self.table_selection.currentIndexChanged.connect(self.update_selection) self.hidden_at_start() self.show() def hidden_at_start(self): self.hide_update_boxes() self.list_control.hide() self.update_information.hide() self.map_visualization.hide() self.text_visualization_button.hide() self.data_visualization_label.hide() self.back_button.hide() self.table_selection.hide() self.enter_data.hide() self.update_excel_selection.hide() self.excel_label.hide() self.data_selector_map.hide() self.order_selector_text.hide() def hide_update_boxes(self): self.update_box_01.hide() self.update_box_02.hide() self.update_box_03.hide() self.update_box_04.hide() self.update_box_05.hide() self.update_box_06.hide() self.update_box_07.hide() self.update_box_08.hide() self.update_label_01.setText("") self.update_label_02.setText("") self.update_label_03.setText("") self.update_label_04.setText("") self.update_label_05.setText("") self.update_label_06.setText("") self.update_label_07.setText("") self.update_label_08.setText("") def update_data(self): self.update_button.hide() self.data_button.hide() self.back_button.show() self.welcome_label.hide() self.table_selection.show() self.enter_data.show() self.update_information.show() self.update_excel_selection.show() self.excel_label.show() def update_selection(self): self.hide_update_boxes() if self.table_selection.currentText() == "Jobs": self.update_box_01.show() self.update_label_01.setText("jobs_id") self.update_box_02.show() self.update_label_02.setText("state_name") self.update_box_03.show() self.update_label_03.setText("occupation_code") self.update_box_04.show() self.update_label_04.setText("tittle") self.update_box_05.show() self.update_label_05.setText("employment") self.update_box_06.show() self.update_label_06.setText("salary_25th_percentile") elif self.table_selection.currentText() == "Schools": self.update_box_01.show() self.update_label_01.setText("school_id") self.update_box_02.show() self.update_label_02.setText("name") self.update_box_03.show() self.update_label_03.setText("state_abrev") self.update_box_04.show() self.update_label_04.setText("size_2017") self.update_box_05.show() self.update_label_05.setText("size_2018") self.update_box_06.show() self.update_label_06.setText("earnings") self.update_box_07.show() self.update_label_07.setText("repayment_overall") self.update_box_08.show() self.update_label_08.setText("repayment_cohort") def import_data(self): if self.update_excel_selection.text() == "": if self.table_selection.currentText() == "Jobs": information_to_update = [self.update_box_01.text(), self.update_box_02.text(), self.update_box_03.text(), self.update_box_04.text(), self.update_box_05.text(), self.update_box_06.text()] jobs.update_data_from_list(information_to_update, "Jobs", "jobs_db.sqlite") elif self.table_selection.currentText() == "Schools": information_to_update = [self.update_box_01.text(), self.update_box_02.text(), self.update_box_03.text(), self.update_box_04.text(), self.update_box_05.text(), self.update_box_06.text(), self.update_box_07.text(), self.update_box_08.text()] jobs.update_data_from_list(information_to_update, "Schools", "jobs_db.sqlite") else: if self.table_selection.currentText() == "Jobs": jobs.update_data_from_excel(self.update_excel_selection.text(), "Jobs", "jobs_db.sqlite") elif self.table_selection.currentText() == "Schools": jobs.update_data_from_excel(self.update_excel_selection.text(), "Jobs", "jobs_db.sqlite") def run_data_visualization(self): self.update_button.hide() self.data_button.hide() self.data_visualization_label.show() self.back_button.show() self.setGeometry(50, 50, 800, 800) self.back_button.move(25, 750) self.quit_button.move(715, 750) self.welcome_label.hide() self.map_visualization.show() self.text_visualization_button.show() self.data_selector_map.show() self.order_selector_text.show() def go_back(self): self.back_button.hide() self.update_button.show() self.data_button.show() self.data_visualization_label.hide() self.setGeometry(50, 50, 500, 500) self.back_button.move(25, 450) self.quit_button.move(415, 450) self.welcome_label.show() self.hidden_at_start() def text_visualization(self): self.list_control.clear() conn, cursor = jobs.open_db("jobs_db.sqlite") if self.order_selector_text.currentText() == "ASC": data_visualization_per_state = jobs.query_run('''SELECT state_abrev, state_name, ''' + ''' total(jobs.employment) as employment, total(school.size_2018/4), round(avg(school.repayment_cohort),3) as repayment_cohort, round(avg(jobs.salary_25th_percentile)) as averge_entry_salary FROM school JOIN states using(state_abrev) JOIN jobs using(state_name) GROUP BY state_name ORDER BY employment ASC;''', cursor) elif self.order_selector_text.currentText() == "DESC": data_visualization_per_state = jobs.query_run('''SELECT state_abrev, state_name, ''' + ''' total(jobs.employment) as employment, total(school.size_2018/4), round(avg(school.repayment_cohort),3) as repayment_cohort, round(avg(jobs.salary_25th_percentile)) as averge_entry_salary FROM school JOIN states using(state_abrev) JOIN jobs using(state_name) GROUP BY state_name ORDER BY employment DESC;''', cursor) else: data_visualization_per_state = jobs.query_run('''SELECT state_abrev, state_name, ''' + ''' total(jobs.employment) as employment, total(school.size_2018/4), round(avg(school.repayment_cohort),3) as repayment_cohort, round(avg(jobs.salary_25th_percentile)) as averge_entry_salary FROM school JOIN states using(state_abrev) JOIN jobs using(state_name) GROUP BY state_name ;''', cursor) QListWidgetItem("State", listview=self.list_control) for state in data_visualization_per_state: state_display_data = f"{state[0]}, {state[1]}" grad_employ_data = f"Employment/Graduates: {state[2]/state[3]}" repayment_data = f"Average Entry Salary/Average Declining Balance Percent: {state[5]/state[4]}" state_item = QListWidgetItem(state_display_data, listview=self.list_control) grad_item = QListWidgetItem(grad_employ_data, listview=self.list_control) repayment_item = QListWidgetItem(repayment_data, listview=self.list_control) grad_item.setForeground(Qt.darkGreen) repayment_item.setForeground(Qt.blue) state_item.setForeground(Qt.white) state_item.setBackground(Qt.black) self.list_control.show() jobs.close_db(conn) def run_map_visualization(self): conn, cursor = jobs.open_db("jobs_db.sqlite") data_visualization_per_state = jobs.query_run('''SELECT state_abrev, state_name, ''' + ''' total(jobs.employment) as employment, total(school.size_2018/4), round(avg(school.repayment_cohort),3) as repayment_cohort, round(avg(jobs.salary_25th_percentile)) as averge_entry_salary FROM school JOIN states using(state_abrev) JOIN jobs using(state_name) GROUP BY state_name ;''', cursor) state_abrev = [] state_grads = [] state_repayment = [] for state in data_visualization_per_state: state_abrev.append(state[0]) state_grads.append(state[2]/state[3]) state_repayment.append(state[5]/state[4]) if self.data_selector_map.currentText() == "Graduates to Employment": us_map = px.Figure(data=px.Choropleth(locations=state_abrev, z=state_grads, locationmode='USA-states', colorbar_title="Employment/Graduates" )) us_map.update_layout(geo_scope='usa', title_text='Employment VS Graduates By State') us_map.show() elif self.data_selector_map.currentText() == "Average Declining Balance Percent": us_map = px.Figure(data=px.Choropleth(locations=state_abrev, z=state_repayment, locationmode='USA-states', colorbar_title="Salary/Average Percent" )) us_map.update_layout(geo_scope='usa', title_text='Average Salary VS Average ' 'Percent of People with Declining Loans') us_map.show() else: us_map = px.Figure(data=px.Choropleth(locations=state_abrev, z=state_grads, locationmode='USA-states', colorbar_title="Graduates" )) us_map.update_layout(geo_scope='usa', title_text='Graduates By State') us_map.show() jobs.close_db(conn) self.list_control.hide()
class UIManipulateROIWindow: def setup_ui(self, manipulate_roi_window_instance, rois, dataset_rtss, roi_color, signal_roi_manipulated): self.patient_dict_container = PatientDictContainer() self.rois = rois self.dataset_rtss = dataset_rtss self.signal_roi_manipulated = signal_roi_manipulated self.roi_color = roi_color self.roi_names = [] # Names of selected ROIs self.all_roi_names = [] # Names of all existing ROIs for roi_id, roi_dict in self.rois.items(): self.all_roi_names.append(roi_dict['name']) # Operation names self.single_roi_operation_names = [ "Expand", "Contract", "Inner Rind (annulus)", "Outer Rind (annulus)" ] self.multiple_roi_operation_names = [ "Union", "Intersection", "Difference" ] self.operation_names = self.multiple_roi_operation_names + \ self.single_roi_operation_names self.new_ROI_contours = None self.manipulate_roi_window_instance = manipulate_roi_window_instance self.dicom_view = DicomAxialView(metadata_formatted=True, is_four_view=True) self.dicom_preview = DicomAxialView(metadata_formatted=True, is_four_view=True) self.dicom_view.slider.valueChanged.connect( self.dicom_view_slider_value_changed) self.dicom_preview.slider.valueChanged.connect( self.dicom_preview_slider_value_changed) self.init_layout() QtCore.QMetaObject.connectSlotsByName(manipulate_roi_window_instance) def retranslate_ui(self, manipulate_roi_window_instance): _translate = QtCore.QCoreApplication.translate manipulate_roi_window_instance.setWindowTitle( _translate("ManipulateRoiWindowInstance", "OnkoDICOM - Draw Region Of Interest")) self.first_roi_name_label.setText( _translate("FirstROINameLabel", "ROI 1: ")) self.first_roi_name_dropdown_list.setPlaceholderText("ROI 1") self.first_roi_name_dropdown_list.addItems(self.all_roi_names) self.operation_name_label.setText( _translate("OperationNameLabel", "Operation")) self.operation_name_dropdown_list.setPlaceholderText("Operation") self.operation_name_dropdown_list.addItems(self.operation_names) self.second_roi_name_label.setText( _translate("SecondROINameLabel", "ROI 2: ")) self.second_roi_name_dropdown_list.setPlaceholderText("ROI 2") self.second_roi_name_dropdown_list.addItems(self.all_roi_names) self.manipulate_roi_window_instance_draw_button.setText( _translate("ManipulateRoiWindowInstanceDrawButton", "Draw")) self.manipulate_roi_window_instance_save_button.setText( _translate("ManipulateRoiWindowInstanceSaveButton", "Save")) self.manipulate_roi_window_instance_cancel_button.setText( _translate("ManipulateRoiWindowInstanceCancelButton", "Cancel")) self.margin_label.setText(_translate("MarginLabel", "Margin (mm): ")) self.new_roi_name_label.setText( _translate("NewROINameLabel", "New ROI Name")) self.ROI_view_box_label.setText("ROI") self.preview_box_label.setText("Preview") 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 ManipulateROIWindow 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.manipulate_roi_window_instance.setObjectName( "ManipulateRoiWindowInstance") self.manipulate_roi_window_instance.setWindowIcon(window_icon) # Creating a form box to hold all buttons and input fields self.manipulate_roi_window_input_container_box = QFormLayout() self.manipulate_roi_window_input_container_box.setObjectName( "ManipulateRoiWindowInputContainerBox") self.manipulate_roi_window_input_container_box.setLabelAlignment( Qt.AlignLeft) # Create a label for denoting the first ROI name self.first_roi_name_label = QLabel() self.first_roi_name_label.setObjectName("FirstROINameLabel") self.first_roi_name_dropdown_list = QComboBox() # Create an dropdown list for ROI name self.first_roi_name_dropdown_list.setObjectName( "FirstROINameDropdownList") self.first_roi_name_dropdown_list.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Minimum) self.first_roi_name_dropdown_list.resize( self.first_roi_name_dropdown_list.sizeHint().width(), self.first_roi_name_dropdown_list.sizeHint().height()) self.first_roi_name_dropdown_list.activated.connect( self.update_selected_rois) self.manipulate_roi_window_input_container_box.addRow( self.first_roi_name_label, self.first_roi_name_dropdown_list) # Create a label for denoting the operation self.operation_name_label = QLabel() self.operation_name_label.setObjectName("OperationNameLabel") self.operation_name_dropdown_list = QComboBox() # Create an dropdown list for operation name self.operation_name_dropdown_list.setObjectName( "OperationNameDropdownList") self.operation_name_dropdown_list.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Minimum) self.operation_name_dropdown_list.resize( self.operation_name_dropdown_list.sizeHint().width(), self.operation_name_dropdown_list.sizeHint().height()) self.operation_name_dropdown_list.activated.connect( self.operation_changed) self.manipulate_roi_window_input_container_box.addRow( self.operation_name_label, self.operation_name_dropdown_list) # Create a label for denoting the second ROI name self.second_roi_name_label = QLabel() self.second_roi_name_label.setObjectName("SecondROINameLabel") self.second_roi_name_label.setVisible(False) self.second_roi_name_dropdown_list = QComboBox() # Create an dropdown list for ROI name self.second_roi_name_dropdown_list.setObjectName( "SecondROINameDropdownList") self.second_roi_name_dropdown_list.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Minimum) self.second_roi_name_dropdown_list.resize( self.second_roi_name_dropdown_list.sizeHint().width(), self.second_roi_name_dropdown_list.sizeHint().height()) self.second_roi_name_dropdown_list.setVisible(False) self.second_roi_name_dropdown_list.activated.connect( self.update_selected_rois) self.manipulate_roi_window_input_container_box.addRow( self.second_roi_name_label, self.second_roi_name_dropdown_list) # Create a label for denoting the margin self.margin_label = QLabel() self.margin_label.setObjectName("MarginLabel") self.margin_label.setVisible(False) # Create input for the new ROI name self.margin_line_edit = QLineEdit() self.margin_line_edit.setObjectName("MarginInput") self.margin_line_edit.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.margin_line_edit.resize(self.margin_line_edit.sizeHint().width(), self.margin_line_edit.sizeHint().height()) self.margin_line_edit.setVisible(False) self.margin_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.manipulate_roi_window_input_container_box.addRow( self.margin_label, self.margin_line_edit) # Create a label for denoting the new ROI name self.new_roi_name_label = QLabel() self.new_roi_name_label.setObjectName("NewROINameLabel") # Create input for the new ROI name self.new_roi_name_line_edit = QLineEdit() self.new_roi_name_line_edit.setObjectName("NewROINameInput") self.new_roi_name_line_edit.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.new_roi_name_line_edit.resize( self.new_roi_name_line_edit.sizeHint().width(), self.new_roi_name_line_edit.sizeHint().height()) self.manipulate_roi_window_input_container_box.addRow( self.new_roi_name_label, self.new_roi_name_line_edit) # Create a spacer between inputs and buttons spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) spacer.setFocusPolicy(Qt.NoFocus) self.manipulate_roi_window_input_container_box.addRow(spacer) # Create a warning message when missing inputs self.warning_message = QWidget() self.warning_message.setContentsMargins(8, 5, 8, 5) warning_message_layout = QHBoxLayout() warning_message_layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignLeft) warning_message_icon = QLabel() warning_message_icon.setPixmap( QtGui.QPixmap( resource_path("res/images/btn-icons/alert_icon.png"))) warning_message_layout.addWidget(warning_message_icon) self.warning_message_text = QLabel() self.warning_message_text.setStyleSheet("color: red") warning_message_layout.addWidget(self.warning_message_text) self.warning_message.setLayout(warning_message_layout) self.warning_message.setVisible(False) self.manipulate_roi_window_input_container_box.addRow( self.warning_message) # Create a draw button self.manipulate_roi_window_instance_draw_button = QPushButton() self.manipulate_roi_window_instance_draw_button.setObjectName( "ManipulateRoiWindowInstanceDrawButton") self.manipulate_roi_window_instance_draw_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.manipulate_roi_window_instance_draw_button.resize( self.manipulate_roi_window_instance_draw_button.sizeHint().width(), self.manipulate_roi_window_instance_draw_button.sizeHint().height( )) self.manipulate_roi_window_instance_draw_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.manipulate_roi_window_instance_draw_button.clicked.connect( self.onDrawButtonClicked) self.manipulate_roi_window_input_container_box.addRow( self.manipulate_roi_window_instance_draw_button) # Create a horizontal box for saving and cancel the drawing self.manipulate_roi_window_cancel_save_box = QHBoxLayout() self.manipulate_roi_window_cancel_save_box.setObjectName( "ManipulateRoiWindowCancelSaveBox") # Create an exit button to cancel the drawing # Add a button to go back/exit from the application self.manipulate_roi_window_instance_cancel_button = QPushButton() self.manipulate_roi_window_instance_cancel_button.setObjectName( "ManipulateRoiWindowInstanceCancelButton") self.manipulate_roi_window_instance_cancel_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.manipulate_roi_window_instance_cancel_button.resize( self.manipulate_roi_window_instance_cancel_button.sizeHint().width( ), self.manipulate_roi_window_instance_cancel_button.sizeHint(). height()) self.manipulate_roi_window_instance_cancel_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.manipulate_roi_window_instance_cancel_button.clicked.connect( self.onCancelButtonClicked) self.manipulate_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.manipulate_roi_window_instance_cancel_button.setIcon(icon_cancel) self.manipulate_roi_window_cancel_save_box.addWidget( self.manipulate_roi_window_instance_cancel_button) # Create a save button to save all the changes self.manipulate_roi_window_instance_save_button = QPushButton() self.manipulate_roi_window_instance_save_button.setObjectName( "ManipulateRoiWindowInstanceSaveButton") self.manipulate_roi_window_instance_save_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.manipulate_roi_window_instance_save_button.resize( self.manipulate_roi_window_instance_save_button.sizeHint().width(), self.manipulate_roi_window_instance_save_button.sizeHint().height( )) self.manipulate_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.manipulate_roi_window_instance_save_button.setIcon(icon_save) self.manipulate_roi_window_instance_save_button.clicked.connect( self.onSaveClicked) self.manipulate_roi_window_cancel_save_box.addWidget( self.manipulate_roi_window_instance_save_button) self.manipulate_roi_window_input_container_box.addRow( self.manipulate_roi_window_cancel_save_box) # Creating a horizontal box to hold the ROI view and the preview self.manipulate_roi_window_instance_view_box = QHBoxLayout() self.manipulate_roi_window_instance_view_box.setObjectName( "ManipulateRoiWindowInstanceViewBoxes") # Font for the ROI view and preview's labels font = QFont() font.setBold(True) font.setPixelSize(20) # Creating the ROI view self.ROI_view_box_layout = QVBoxLayout() self.ROI_view_box_label = QLabel() self.ROI_view_box_label.setFont(font) self.ROI_view_box_label.setAlignment(Qt.AlignHCenter) self.ROI_view_box_layout.addWidget(self.ROI_view_box_label) self.ROI_view_box_layout.addWidget(self.dicom_view) self.ROI_view_box_widget = QWidget() self.ROI_view_box_widget.setLayout(self.ROI_view_box_layout) # Creating the preview self.preview_box_layout = QVBoxLayout() self.preview_box_label = QLabel() self.preview_box_label.setFont(font) self.preview_box_label.setAlignment(Qt.AlignHCenter) self.preview_box_layout.addWidget(self.preview_box_label) self.preview_box_layout.addWidget(self.dicom_preview) self.preview_box_widget = QWidget() self.preview_box_widget.setLayout(self.preview_box_layout) # Add View and Slider into horizontal box self.manipulate_roi_window_instance_view_box.addWidget( self.ROI_view_box_widget) self.manipulate_roi_window_instance_view_box.addWidget( self.preview_box_widget) # Create a widget to hold the image slice box self.manipulate_roi_window_instance_view_widget = QWidget() self.manipulate_roi_window_instance_view_widget.setObjectName( "ManipulateRoiWindowInstanceActionWidget") self.manipulate_roi_window_instance_view_widget.setLayout( self.manipulate_roi_window_instance_view_box) # Create a horizontal box for containing the input fields and the # viewports self.manipulate_roi_window_main_box = QHBoxLayout() self.manipulate_roi_window_main_box.setObjectName( "ManipulateRoiWindowMainBox") self.manipulate_roi_window_main_box.addLayout( self.manipulate_roi_window_input_container_box, 1) self.manipulate_roi_window_main_box.addWidget( self.manipulate_roi_window_instance_view_widget, 11) # Create a new central widget to hold the horizontal box layout self.manipulate_roi_window_instance_central_widget = QWidget() self.manipulate_roi_window_instance_central_widget.setObjectName( "ManipulateRoiWindowInstanceCentralWidget") self.manipulate_roi_window_instance_central_widget.setLayout( self.manipulate_roi_window_main_box) self.retranslate_ui(self.manipulate_roi_window_instance) self.manipulate_roi_window_instance.setStyleSheet(stylesheet) self.manipulate_roi_window_instance.setCentralWidget( self.manipulate_roi_window_instance_central_widget) QtCore.QMetaObject.connectSlotsByName( self.manipulate_roi_window_instance) def dicom_view_slider_value_changed(self): """ Display selected ROIs in dropbox when moving to another image slice """ self.display_selected_roi() if self.dicom_preview.slider.value() != self.dicom_view.slider.value(): self.dicom_preview.slider.setValue(self.dicom_view.slider.value()) def dicom_preview_slider_value_changed(self): """ Display generated ROI when moving to another image slice """ self.draw_roi() if self.dicom_preview.slider.value() != self.dicom_view.slider.value(): self.dicom_view.slider.setValue(self.dicom_preview.slider.value()) def onCancelButtonClicked(self): """ This function is used for canceling the drawing """ self.close() def onDrawButtonClicked(self): """ Function triggered when the Draw button is pressed from the menu. """ # Hide warning message self.warning_message.setVisible(False) # Check inputs selected_operation = self.operation_name_dropdown_list.currentText() roi_1 = self.first_roi_name_dropdown_list.currentText() roi_2 = self.second_roi_name_dropdown_list.currentText() new_roi_name = self.new_roi_name_line_edit.text() # Check the selected inputs and execute the operations if roi_1 != "" and new_roi_name != "" and \ self.margin_line_edit.text() != "" and \ selected_operation in self.single_roi_operation_names: # Single ROI operations dict_rois_contours = ROI.get_roi_contour_pixel( self.patient_dict_container.get("raw_contour"), [roi_1], self.patient_dict_container.get("pixluts")) roi_geometry = ROI.roi_to_geometry(dict_rois_contours[roi_1]) margin = float(self.margin_line_edit.text()) if selected_operation == self.single_roi_operation_names[0]: new_geometry = ROI.scale_roi(roi_geometry, margin) elif selected_operation == self.single_roi_operation_names[1]: new_geometry = ROI.scale_roi(roi_geometry, -margin) elif selected_operation == self.single_roi_operation_names[2]: new_geometry = ROI.rind_roi(roi_geometry, -margin) else: new_geometry = ROI.rind_roi(roi_geometry, margin) self.new_ROI_contours = ROI.geometry_to_roi(new_geometry) self.draw_roi() return True elif roi_1 != "" and roi_2 != "" and new_roi_name != "" and \ selected_operation in self.multiple_roi_operation_names: # Multiple ROI operations dict_rois_contours = ROI.get_roi_contour_pixel( self.patient_dict_container.get("raw_contour"), [roi_1, roi_2], self.patient_dict_container.get("pixluts")) roi_1_geometry = ROI.roi_to_geometry(dict_rois_contours[roi_1]) roi_2_geometry = ROI.roi_to_geometry(dict_rois_contours[roi_2]) # Execute the selected operation new_geometry = ROI.manipulate_rois(roi_1_geometry, roi_2_geometry, selected_operation.upper()) self.new_ROI_contours = ROI.geometry_to_roi(new_geometry) self.draw_roi() return True self.warning_message_text.setText("Not all values are specified.") self.warning_message.setVisible(True) return False def onSaveClicked(self): """ Save the new ROI """ # Get the name of the new ROI new_roi_name = self.new_roi_name_line_edit.text() # If the new ROI hasn't been drawn, draw the new ROI. Then if the new # ROI is drawn successfully, proceed to save the new ROI. if self.new_ROI_contours is None: if not self.onDrawButtonClicked(): return # Get a dict to convert SOPInstanceUID to slice id slice_ids_dict = get_dict_slice_to_uid(PatientDictContainer()) # Transform new_ROI_contours to a list of roi information rois_to_save = {} for uid, contour_sequence in self.new_ROI_contours.items(): slider_id = slice_ids_dict[uid] location = self.patient_dict_container.filepaths[slider_id] ds = pydicom.dcmread(location) slice_info = {'coords': contour_sequence, 'ds': ds} rois_to_save[slider_id] = slice_info roi_list = ROI.convert_hull_list_to_contours_data( rois_to_save, self.patient_dict_container) connectSaveROIProgress(self, roi_list, self.dataset_rtss, new_roi_name, self.roi_saved) def draw_roi(self): """ Draw the new ROI """ # Get the new ROI's name new_roi_name = self.new_roi_name_line_edit.text() # Check if the new ROI contour is None if self.new_ROI_contours is None: return # Get the info required to draw the new ROI slider_id = self.dicom_preview.slider.value() curr_slice = self.patient_dict_container.get("dict_uid")[slider_id] # Calculate the new ROI's polygon dict_ROI_contours = {} dict_ROI_contours[new_roi_name] = self.new_ROI_contours polygons = ROI.calc_roi_polygon(new_roi_name, curr_slice, dict_ROI_contours) # Set the new ROI color color = QtGui.QColor() color.setRgb(90, 250, 175, 200) pen_color = QtGui.QColor(color.red(), color.green(), color.blue()) pen = QtGui.QPen(pen_color) pen.setStyle(QtCore.Qt.PenStyle(1)) pen.setWidthF(2.0) # Draw the new ROI self.dicom_preview.update_view() for i in range(len(polygons)): self.dicom_preview.scene.addPolygon(polygons[i], pen, QtGui.QBrush(color)) def update_selected_rois(self): """ Get the names of selected ROIs """ # Hide warning message self.warning_message.setVisible(False) self.roi_names = [] if self.first_roi_name_dropdown_list.currentText() != "": self.roi_names.append( self.first_roi_name_dropdown_list.currentText()) if self.second_roi_name_dropdown_list.currentText() != "" and \ self.second_roi_name_dropdown_list.isVisible(): self.roi_names.append( self.second_roi_name_dropdown_list.currentText()) self.dict_rois_contours_axial = ROI.get_roi_contour_pixel( self.patient_dict_container.get("raw_contour"), self.roi_names, self.patient_dict_container.get("pixluts")) self.display_selected_roi() def display_selected_roi(self): """ Display selected ROIs """ # Get the info required to display the selected ROIs slider_id = self.dicom_view.slider.value() curr_slice = self.patient_dict_container.get("dict_uid")[slider_id] self.rois = self.patient_dict_container.get("rois") # Display the selected ROIs self.dicom_view.update_view() for roi_id, roi_dict in self.rois.items(): roi_name = roi_dict['name'] if roi_name in self.roi_names: polygons = ROI.calc_roi_polygon(roi_name, curr_slice, self.dict_rois_contours_axial) self.dicom_view.draw_roi_polygons(roi_id, polygons, self.roi_color) def operation_changed(self): """ Change the form when users select different operations """ # Hide warning message self.warning_message.setVisible(False) selected_operation = self.operation_name_dropdown_list.currentText() if selected_operation in self.single_roi_operation_names: self.second_roi_name_label.setVisible(False) self.second_roi_name_dropdown_list.setVisible(False) self.margin_label.setVisible(True) self.margin_line_edit.setVisible(True) self.update_selected_rois() else: self.second_roi_name_label.setVisible(True) self.second_roi_name_dropdown_list.setVisible(True) self.margin_label.setVisible(False) self.margin_line_edit.setVisible(False) self.update_selected_rois() def roi_saved(self, new_rtss): """ Create a new ROI in Structure Tab and notify user """ new_roi_name = self.new_roi_name_line_edit.text() self.signal_roi_manipulated.emit((new_rtss, {"draw": new_roi_name})) QMessageBox.about(self.manipulate_roi_window_instance, "Saved", "New contour successfully created!") self.close()
class Dialog_Dose(QDialog): """ This class creates the user input dialog for when Modifying or Adding a isodose level option for ISO2ROI functionality. """ def __init__(self, dose, notes): super(Dialog_Dose, self).__init__() # Class variables self.dose = dose self.notes = notes self.setWindowIcon( QtGui.QIcon("res/images/btn-icons/onkodicom_icon.png")) buttonBox = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self) self.iso_dose = QLineEdit() self.iso_dose.setText(self.dose) self.iso_unit = QComboBox() self.iso_unit.addItems(["cGy", "%"]) self.iso_notes = QLineEdit() self.iso_notes.setText(self.notes) # Input dialog layout layout = QFormLayout(self) layout.addRow(QLabel("Isodose Level:"), self.iso_dose) layout.addRow(QLabel("Unit:"), self.iso_unit) layout.addRow(QLabel("Notes:"), self.iso_notes) layout.addWidget(buttonBox) buttonBox.accepted.connect(self.accepting) buttonBox.rejected.connect(self.reject) self.setWindowTitle("Isodose Levels") def getInputs(self): """ Return the inputs from the dialog box. :return: tuple of dialog inputs - (isodose level, isodose unit, isodose name, isodose notes) """ # Get appropriate name for unit selected if self.iso_unit.currentText() == "%": iso_name = str('ISOp_' + self.iso_dose.text()) else: iso_name = str('ISO' + self.iso_dose.text()) # Return inputs from dialog box return (self.iso_dose.text(), self.iso_unit.currentText(), iso_name, self.iso_notes.text()) def accepting(self): """ Process the event when the user clicks "ok" in the dialog box. """ # Make sure the isodose level is a number if (self.iso_dose.text() != ''): if re.match(r'^\d+$', self.iso_dose.text()): self.accept() else: buttonReply = QMessageBox.warning( self, "Error Message", "The Isodose level should to be a number!", QMessageBox.Ok) if buttonReply == QMessageBox.Ok: pass # Make sure the isodose level is not blank else: buttonReply = QMessageBox.warning( self, "Error Message", "The Isodose field should not be empty!", QMessageBox.Ok) if buttonReply == QMessageBox.Ok: pass
class MyWidget(QWidget): def __init__(self): QWidget.__init__(self) self.init_ui() self.combobox.currentTextChanged.connect(self.slot_combo_textchanged) self.btn_open_conn.clicked.connect(self.slot_conn_clicked) self.btn_close_conn.clicked.connect(self.slot_conn_close) self.btn_status.clicked.connect(self.slot_send_status_packet) self.btn_head.clicked.connect(self.slot_send_head_packet) self.btn_motion.clicked.connect(self.slof_send_motion_packet) def slot_conn_close(self): #TODO 关闭其他窗口 self.fd.close() self.set_send_btn_statu(False) def slot_send_status_packet(self): statuswidget = StatusWidget(self.fd) statuswidget.show() def slot_send_head_packet(self): headwidget = HeadWidget(self.fd) headwidget.show() def slof_send_motion_packet(self): motionwidget = MotionWidget(self.fd) motionwidget.show() pass def init_ui(self): self.tuple_method = ("Connect to Server", "Connect to /dev") self.combobox = QComboBox() self.combobox.addItems(self.tuple_method) self.addr_edit = QLineEdit() self.port_edit = QLineEdit() self.btn_open_conn = QPushButton("Connect/Open") self.btn_close_conn = QPushButton("Close Conn") self.fd = None self.method_layout = QVBoxLayout() self.method_layout.addWidget(self.combobox) self.method_layout.addWidget(self.addr_edit) self.method_layout.addWidget(self.port_edit) self.method_layout.addWidget(self.btn_open_conn) self.method_layout.addWidget(self.btn_close_conn) self.btn_status = QPushButton("Send Status Packet") self.btn_head = QPushButton("Send Head Packet") self.btn_motion = QPushButton("Send Motion Packet") self.packet_layout = QVBoxLayout() self.packet_layout.addWidget(self.btn_status) self.packet_layout.addWidget(self.btn_head) self.packet_layout.addWidget(self.btn_motion) self.main_layout = QVBoxLayout() self.main_layout.addLayout(self.method_layout) self.main_layout.addLayout(self.packet_layout) self.setLayout(self.main_layout) self.set_send_btn_statu(False) def set_send_btn_statu(self, statu): self.btn_motion.setEnabled(statu) self.btn_head.setEnabled(statu) self.btn_status.setEnabled(statu) self.btn_close_conn.setEnabled(statu) self.btn_open_conn.setEnabled(True if statu == False else False) def slot_combo_textchanged(self, current_text): if current_text == "Connect to /dev": self.port_edit.setVisible(False) else: self.port_edit.setVisible(True) def slot_conn_clicked(self): # try: if self.combobox.currentText() == "Connect to /dev": self.fd = open(self.addr_edit.text(), "wb") elif self.combobox.currentText() == "Connect to Server": self.fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.fd.connect(("127.0.0.1", int(self.port_edit.text()))) # except : # pass # TODO except QMessageBox.information(self, "success", "connected") self.set_send_btn_statu(True)
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 ImageManipulation(QWidget): def __init__(self): super().__init__() # Declare Widgets self.edit_label = QLabel('Change your image') # set up list and combo box option self.my_list = ["Pick a value", "Luminosity", "Contrast", "Colorize", "Sepia", "Negative", "Grayscale", "None"] self.my_combo_box = QComboBox() self.my_combo_box.addItems(self.my_list) self.edit_btn = QPushButton("Edit") self.cancel_btn = QPushButton("Back") # Create U.I. Layout vbox = QVBoxLayout() vbox.addWidget(self.edit_label) vbox.addWidget(self.my_combo_box) vbox.addWidget(self.edit_btn) vbox.addWidget(self.cancel_btn) self.setLayout(vbox) # apply layout to this class # when button is clicked send lineedit and combo box info to on_submit self.edit_btn.clicked.connect(self.on_edit) self.cancel_btn.clicked.connect(self.on_back) @Slot() def on_edit(self): # set up im_edit as which filter the user chose im_edit = self.my_combo_box.currentText() ##TODO change to correct image input_image = Image.open("image.png") input_pixels = input_image.load() output_image = Image.new("RGB", input_image.size) draw = ImageDraw.Draw(output_image) # Options are: ["Pick a value", "Luminosity", "Contrast", "Colorize", "Sepia", "Negative", "Grayscale", "None"] if (im_edit == "Luminosity"): luminosity = 80 # Generate image for x in range(output_image.width): for y in range(output_image.height): r, g, b, a = input_pixels[x, y] r = int(r + luminosity) g = int(g + luminosity) b = int(b + luminosity) draw.point((x, y), (r, g, b)) #output_image.save("output.png") output_image.show() elif (im_edit == "Contrast"): # Find minimum and maximum luminosity imin = 255 imax = 0 for x in range(input_image.width): for y in range(input_image.height): r, g, b, a = input_pixels[x, y] i = (r + g + b) / 3 imin = min(imin, i) imax = max(imax, i) # Generate image for x in range(output_image.width): for y in range(output_image.height): r, g, b, a = input_pixels[x, y] # Current luminosity i = (r + g + b) / 3 # New luminosity ip = 255 * (i - imin) / (imax - imin) r = int(r * ip / i) g = int(g * ip / i) b = int(b * ip / i) draw.point((x, y), (r, g, b)) output_image.show() elif (im_edit == "Colorize"): # Square distance between 2 colors def distance2(color1, color2): r1, g1, b1 = color1 r2, g2, b2, a2 = color2 return (r1 - r2) ** 2 + (g1 - g2) ** 2 + (b1 - b2) ** 2 color_to_change = (0, 0, 255) threshold = 220 # Generate image for x in range(output_image.width): for y in range(output_image.height): r, g, b, a = input_pixels[x, y] if distance2(color_to_change, input_pixels[x, y]) < threshold ** 2: r = int(r * .5) g = int(g * 1.25) b = int(b * .5) draw.point((x, y), (r, g, b)) #output_image.save("output.png") output_image.show() elif (im_edit == "Sepia"): def sepia(pixel): if pixel[0] < 63: r,g,b = int(pixel[0]*1.1), pixel[1], int(pixel[2]*.9) elif pixel[0]>62 and pixel[0]<192: r,g,b = int(pixel[0]*1.15), pixel[1], int(pixel[2]*.85) else: r = int(pixel[0]*1.08) if r>255: r=255 g,b = pixel[1], pixel[2]//2 return r,g,b sepia_list = map(sepia, input_image.getdata()) output_image.putdata(list(sepia_list)) #output_image.save("output.png") output_image.show() elif (im_edit == "Negative"): negative_list = [(255-p[0], 255-p[1], 255-p[2]) for p in input_image.getdata()] output_image.putdata(negative_list) #output_image.save("output.png") output_image.show() elif (im_edit == "Grayscale"): new_list = [ ( (a[0]+a[1]+a[2])//3, ) * 3 for a in input_image.getdata() ] output_image.putdata(new_list) #output_image.save("output.png") output_image.show() else: #"Pick a value" or "None" input_image.show() @Slot() def on_back(self): print("back")
class PredictionWindow(QWidget): """Subwindow dedicated to random forest prediction functions.""" # Private Instance Attributes: # - _predict_btn: Button that signals for a prediction to be made. # - _predict_btn: Button that signals for the selected model to be deleted. # - _model: The RandomForest model currently loaded. # - _model_info: QPlainTextEdit widget displaying information about the selected model. # - _target_date: Calendar widget for the user to select a target prediction date. # -_plot_window: Window for displaying historical information with a prediction. _predict_btn: QDialogButtonBox _delete_btn: QDialogButtonBox _model: QComboBox _model_info: QPlainTextEdit _target_date: QCalendarWidget _plot_window: QMainWindow def __init__(self) -> None: super().__init__() main_layout = QGridLayout() button_box = self._create_button_box() main_layout.addWidget(self._create_options_group_box(), 0, 0) main_layout.addWidget(button_box, 1, 0) main_layout.setSizeConstraint(QLayout.SetMinimumSize) self.setLayout(main_layout) self._refresh_model_info() self.setWindowTitle('Predict') self._plot_window = QMainWindow() def show(self) -> None: """Override of QWidget's show() function. Refreshes window and then shows the window. """ self._refresh_lists() return super().show() @property def _selected_model(self) -> Union[RandomForest, None]: """Gets the currently selected model.""" model_name = self._model.currentText() if model_name != '': try: return load_model(model_name) except pickle.UnpicklingError: self._error_event(f'{model_name} is an invalid model.') return None else: return None def _create_button_box(self) -> QDialogButtonBox: """Creates the lower control buttons at the bottom of the window.""" button_box = QDialogButtonBox() self._predict_btn = button_box.addButton('Predict', QDialogButtonBox.ActionRole) self._delete_btn = button_box.addButton('Delete Model', QDialogButtonBox.ActionRole) refresh_btn = button_box.addButton('Refresh &Options', QDialogButtonBox.ActionRole) self._predict_btn.clicked.connect(self._predict) refresh_btn.clicked.connect(self._refresh_lists) self._delete_btn.clicked.connect(self._delete) return button_box def _create_options_group_box(self) -> QGroupBox: """Returns the group of prediction options.""" options_group_box = QGroupBox("Options") options_layout = QGridLayout() left_options = QGridLayout() right_options = QGridLayout() date_label = QLabel("Target Date:") self._target_date = QCalendarWidget() left_options.addWidget(date_label, 0, 0) left_options.addWidget(self._target_date, 1, 0, 1, 3) left_options.setColumnStretch(0, 1) self._model = QComboBox() self._model_info = QPlainTextEdit() self._model_info.setReadOnly(True) self._model.currentTextChanged.connect(self._refresh_model_info) self._refresh_lists() models_label = QLabel("Models:") info_label = QLabel("Model Information:") right_options.addWidget(models_label, 0, 0) right_options.addWidget(self._model, 1, 0) right_options.addWidget(info_label, 2, 0) right_options.addWidget(self._model_info, 3, 0) options_layout.addLayout(left_options, 0, 0) options_layout.addLayout(right_options, 0, 1) options_group_box.setLayout(options_layout) return options_group_box def _delete(self) -> None: """Deletes the currently selected dataset.""" self.setEnabled(False) name = self._model.currentText() warning = f'Are you sure you want to delete {name}?' response = QMessageBox.warning(self, self.tr("Delete Model"), warning, QMessageBox.Yes, QMessageBox.No) if response == QMessageBox.Yes: data_ingest.delete_data(name, file_type='model') self._refresh_lists() self.setEnabled(True) def _refresh_lists(self) -> None: """Refreshes avaliable datasets for training.""" self._model.clear() data_list = data_ingest.get_avaliable_data(search_type='model') self._model.addItems(data_list) def _refresh_model_info(self) -> None: """Refreshes avaliable features for the selected target.""" self._predict_btn.setEnabled(False) self._target_date.setEnabled(False) self._model_info.clear() model_name = self._model.currentText() model = self._selected_model if model is None: self._delete_btn.setEnabled(False) return None self._delete_btn.setEnabled(True) self._display_model_info(model) req_features = model.window.req_features avaliable_sym = data_ingest.get_avaliable_sym() if len(req_features - avaliable_sym) != 0: self._error_event( f'Missing required data for {model_name}: {req_features - avaliable_sym}' ) return None dfs = load_corresponding_dataframes(model) grouped_dataframe = data_ingest.create_grouped_dataframe(dfs) date_offset = pd.DateOffset(days=model.window.target_shift) self._target_date.setMaximumDate(grouped_dataframe.index.max() + date_offset) self._target_date.setMinimumDate(grouped_dataframe.index.min() + date_offset) self._target_date.setEnabled(True) self._predict_btn.setEnabled(True) return None def _display_model_info(self, model: RandomForest) -> None: """Updates model info box to display current model's information.""" self._model_info.appendPlainText( f'Target Feature Name: \n{model.window.target_lbl}') self._model_info.appendPlainText('Window Information:') self._model_info.appendPlainText( f'\t- Window Size: {model.window.window_size}') self._model_info.appendPlainText( f'\t- Target Shift: {model.window.target_shift}') self._model_info.appendPlainText( f'\t- Required Features: {model.window.req_features}') self._model_info.appendPlainText('Forest Information:') self._model_info.appendPlainText( f'\t- Number of Trees: {model.forest.n_trees}') self._model_info.appendPlainText( f'\t- Tree Max Depth: {model.forest.max_depth}') self._model_info.appendPlainText(f'\t- Seed: {model.forest.seed}') def _predict(self) -> None: """Creates a model prediction using the selected target date and model.""" self.setEnabled(False) self._predict_btn.setEnabled(False) model = self._selected_model if model is None: self.setEnabled(True) return None target_date = self._target_date.selectedDate().toPython() try: dfs = load_corresponding_dataframes(model) prediction_input = data_ingest.create_input( model.window.window_size, model.window.target_shift, target_date, dfs) except ce.MissingData: self._error_event( 'Missing required data. Could be that loaded datasets have holes.' ) self.setEnabled(True) return None prediction = model.predict(prediction_input) historical_dfs = load_corresponding_dataframes(model, 'target') if len(historical_dfs) == 0: self._prediction_historical_error(prediction) else: self._plot_prediction(historical_dfs, model, prediction, target_date) self._predict_btn.setEnabled(True) self.setEnabled(True) return None def _plot_prediction(self, historical_dfs: list[pd.DataFrame], model: RandomForest, prediction: ndarray, target_date: datetime.date) -> None: """Opens a window with a plot of the historical target data as well as the prediction the model made.""" hdf = historical_dfs[0] for frame in historical_dfs[1:]: hdf = hdf.combine_first(frame) window_end = target_date - \ pd.DateOffset(days=model.window.target_shift) window_start = window_end - pd.DateOffset(days=30 - 1) hdf = pd.Series( hdf.loc[window_end:window_start][model.window.target_lbl]) hdf_data = hdf.to_list() hdf_dates = hdf.index hdf_dates = [ts.to_pydatetime().timestamp() for ts in hdf_dates] b_axis = pg.DateAxisItem(orientation='bottom') b_axis.setLabel('Date') plot = PlotWidget(axisItems={'bottom': b_axis}) target_time = datetime.combine(target_date, datetime.min.time()) plot.addLegend() plot.plot(x=hdf_dates, y=hdf_data, name=f'Historical {model.window.target_lbl}') plot.plot(x=[target_time.timestamp()], y=prediction, pen=None, symbol='o', name=f'Predicted Value: {prediction[0]}') model_name = self._model.currentText() self._plot_window.setWindowTitle(f'{model_name} Prediction') self._plot_window.setCentralWidget(plot) self._plot_window.show() def _prediction_historical_error(self, prediction: list) -> None: """Displays a message for when historical target is unavalable such that a graph can't be made.""" QMessageBox.information( self, self.tr("Information"), f'Prediction was: {prediction}. \n ' 'Unable to display graph due to missing historical data.', QtWidgets.QMessageBox.Ok) def _error_event( self, error: str, choice: bool = False, btn: QMessageBox = QMessageBox.Abort ) -> Union[QMessageBox.Ignore, QMessageBox.Abort, None]: """Displays an error message with the given error.""" if choice: response = QMessageBox.critical(self, self.tr("Error"), error, btn, QMessageBox.Ignore) return response else: QMessageBox.critical(self, self.tr("Error"), error, QMessageBox.Ok) return None
class Window(QMainWindow): def __init__(self): QMainWindow.__init__(self) # Title and dimensions self.setWindowTitle("Patterns detection") self.setGeometry(0, 0, 800, 500) # Main menu bar self.menu = self.menuBar() self.menu_file = self.menu.addMenu("File") exit = QAction("Exit", self, triggered=qApp.quit) self.menu_file.addAction(exit) self.menu_about = self.menu.addMenu("&About") about = QAction("About Qt", self, shortcut=QKeySequence(QKeySequence.HelpContents), triggered=qApp.aboutQt) self.menu_about.addAction(about) # Create a label for the display camera self.label = QLabel(self) self.label.setFixedSize(640, 480) # Thread in charge of updating the image self.th = Thread(self) self.th.finished.connect(self.close) self.th.updateFrame.connect(self.setImage) # Model group self.group_model = QGroupBox("Trained model") self.group_model.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) model_layout = QHBoxLayout() self.combobox = QComboBox() for xml_file in os.listdir(cv2.data.haarcascades): if xml_file.endswith(".xml"): self.combobox.addItem(xml_file) model_layout.addWidget(QLabel("File:"), 10) model_layout.addWidget(self.combobox, 90) self.group_model.setLayout(model_layout) # Buttons layout buttons_layout = QHBoxLayout() self.button1 = QPushButton("Start") self.button2 = QPushButton("Stop/Close") self.button1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.button2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) buttons_layout.addWidget(self.button2) buttons_layout.addWidget(self.button1) right_layout = QHBoxLayout() right_layout.addWidget(self.group_model, 1) right_layout.addLayout(buttons_layout, 1) # Main layout layout = QVBoxLayout() layout.addWidget(self.label) layout.addLayout(right_layout) # Central widget widget = QWidget(self) widget.setLayout(layout) self.setCentralWidget(widget) # Connections self.button1.clicked.connect(self.start) self.button2.clicked.connect(self.kill_thread) self.button2.setEnabled(False) self.combobox.currentTextChanged.connect(self.set_model) @Slot() def set_model(self, text): self.th.set_file(text) @Slot() def kill_thread(self): print("Finishing...") self.button2.setEnabled(False) self.button1.setEnabled(True) self.th.cap.release() cv2.destroyAllWindows() self.status = False self.th.terminate() # Give time for the thread to finish time.sleep(1) @Slot() def start(self): print("Starting...") self.button2.setEnabled(True) self.button1.setEnabled(False) self.th.set_file(self.combobox.currentText()) self.th.start() @Slot(QImage) def setImage(self, image): self.label.setPixmap(QPixmap.fromImage(image))
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 ImageManipulation(QWidget): def __init__(self, img): super().__init__() # Declare Widgets self.edit_label = QLabel('Change your image') # set up list and combo box option self.my_list = [ "Pick a value", "Luminosity", "Contrast", "Colorize", "Sepia", "Negative", "Grayscale", "None" ] self.my_combo_box = QComboBox() self.my_combo_box.addItems(self.my_list) self.edit_btn = QPushButton("Edit") # Create U.I. Layout mbox = QHBoxLayout() vbox = QVBoxLayout() vbox.addWidget(self.edit_label) vbox.addWidget(self.my_combo_box) vbox.addWidget(self.edit_btn) mbox.addLayout(vbox) image = Image.open(requests.get(img['urls']['thumb'], stream=True).raw) editpath = "./editing/edit.jpg" image.save(editpath) self.lbl = QLabel() pix = QPixmap(editpath) self.lbl.setPixmap(pix) mbox.addWidget(self.lbl) self.setLayout(mbox) # apply layout to this class # when button is clicked send lineedit and combo box info to on_submit self.edit_btn.clicked.connect(self.on_edit) @Slot() def on_edit(self): # set up im_edit as which filter the user chose im_edit = self.my_combo_box.currentText() # take the image to edit and load it input_image = Image.open("./editing/edit.jpg") input_pixels = input_image.load() output_image = Image.new("RGB", input_image.size) draw = ImageDraw.Draw(output_image) # Options are: ["Pick a value", "Luminosity", "Contrast", "Colorize", "Sepia", "Negative", "Grayscale", "None"] # Luminostity brightens the image overall if (im_edit == "Luminosity"): luminosity = 80 # Generate image for x in range(output_image.width): for y in range(output_image.height): r, g, b = input_pixels[x, y] r = int(r + luminosity) g = int(g + luminosity) b = int(b + luminosity) draw.point((x, y), (r, g, b)) output_image.show() # Contrast makes the image slightly darker overall elif (im_edit == "Contrast"): # Find minimum and maximum luminosity imin = 255 imax = 0 for x in range(input_image.width): for y in range(input_image.height): r, g, b = input_pixels[x, y] i = (r + g + b) / 3 imin = min(imin, i) imax = max(imax, i) # Generate image for x in range(output_image.width): for y in range(output_image.height): r, g, b = input_pixels[x, y] # Current luminosity i = (r + g + b) / 3 # New luminosity ip = 255 * (i - imin) / (imax - imin) r = int(r * ip / i) g = int(g * ip / i) b = int(b * ip / i) draw.point((x, y), (r, g, b)) output_image.show() # Colorize increases one color in the image elif (im_edit == "Colorize"): # Square distance between 2 colors def distance2(color1, color2): r1, g1, b1 = color1 r2, g2, b2 = color2 return (r1 - r2)**2 + (g1 - g2)**2 + (b1 - b2)**2 color_to_change = (0, 0, 255) threshold = 220 # Generate image for x in range(output_image.width): for y in range(output_image.height): r, g, b = input_pixels[x, y] if distance2(color_to_change, input_pixels[x, y]) < threshold**2: r = int(r * .5) g = int(g * 1.25) b = int(b * .5) draw.point((x, y), (r, g, b)) output_image.show() # Sepia increases the red and decreases the blue value depending on the intensity elif (im_edit == "Sepia"): def sepia(pixel): if pixel[0] < 63: r, g, b = int(pixel[0] * 1.1), pixel[1], int(pixel[2] * .9) elif pixel[0] > 62 and pixel[0] < 192: r, g, b = int(pixel[0] * 1.15), pixel[1], int(pixel[2] * .85) else: r = int(pixel[0] * 1.08) if r > 255: r = 255 g, b = pixel[1], pixel[2] // 2 return r, g, b sepia_list = map(sepia, input_image.getdata()) output_image.putdata(list(sepia_list)) output_image.show() # Negative swaps the rgb values to their opposite counterparts elif (im_edit == "Negative"): negative_list = [(255 - p[0], 255 - p[1], 255 - p[2]) for p in input_image.getdata()] output_image.putdata(negative_list) output_image.show() # Grayscale averages the rgb values and creates the gray version of the image elif (im_edit == "Grayscale"): new_list = [((a[0] + a[1] + a[2]) // 3, ) * 3 for a in input_image.getdata()] output_image.putdata(new_list) output_image.show() else: #"Pick a value" or "None" input_image.show()