def setupUi(self, Dialog, worker_text, show_output = False, icon=True): self.Dialog = Dialog self.Dialog.setObjectName("Dialog") Dialog.setWindowTitle("Lade...") Dialog.setStyleSheet( "background-color: {}; color: white".format(get_color(blue_7)) ) # Dialog.setSizePolicy(SizePolicy_fixed) # Dialog.setFixedSize(Dialog.size()) # Dialog.setWindowFlags(QtCore.Qt.FramelessWindowHint) if icon == True: pixmap = QtGui.QPixmap(logo_path) Dialog.setWindowIcon(QtGui.QIcon(logo_path)) Dialog.setWindowFlags( QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint ) else: Dialog.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.CustomizeWindowHint | QtCore.Qt.WindowTitleHint) # Dialog.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) gridLayout = create_new_gridlayout(Dialog) gridLayout.setSizeConstraint(QtWidgets.QHBoxLayout.SetFixedSize) if icon == True: pixmap = QtGui.QPixmap(logo_cria_button_path) # Dialog.setPixmap(pixmap.scaled(110, 110, QtCore.Qt.KeepAspectRatio)) image = QtWidgets.QLabel(Dialog) image.setObjectName("image") image.setPixmap(pixmap.scaled(30, 30, QtCore.Qt.KeepAspectRatio)) self.label = QtWidgets.QLabel(Dialog) self.label.setObjectName("label") self.label.setText(worker_text) self.label.setStyleSheet("padding: 20px") label_spinner = QtWidgets.QLabel(Dialog) self.label.setObjectName("label_spinner") label_spinner.setFixedSize(30, 30) spinner = QtWaitingSpinner(label_spinner) spinner.setRoundness(70.0) # spinner.setMinimumTrailOpacity(10.0) # spinner.setTrailFadePercentage(60.0) spinner.setNumberOfLines(15) spinner.setLineLength(8) # spinner.setLineWidth(5) spinner.setInnerRadius(5) # spinner.setRevolutionsPerSecond(2) spinner.setColor(QtCore.Qt.white) spinner.start() # starts spinning self.label.setAlignment(QtCore.Qt.AlignCenter) if icon == True: gridLayout.addWidget(image, 0,0,1,1) gridLayout.addWidget(self.label, 0,1,1,1) gridLayout.addWidget(label_spinner, 0,2,1,1) if show_output == True: self.plainTextEdit = QtWidgets.QPlainTextEdit(Dialog) self.plainTextEdit.setReadOnly(True) self.plainTextEdit.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.plainTextEdit.setPlainText("Creating PDF file ...") self.plainTextEdit.setFixedHeight(70) gridLayout.addWidget(self.plainTextEdit, 1,0,1,3)
def setupUi(self, Dialog, text): self.Dialog = Dialog self.Dialog.setObjectName("Dialog") Dialog.setWindowTitle("Lade...") Dialog.setStyleSheet( "background-color: {}; color: white".format("rgb(47, 69, 80)") ) Dialog.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint) # Dialog.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) horizontalLayout = QHBoxLayout(Dialog) horizontalLayout.setObjectName("horizontal") horizontalLayout.setSizeConstraint(QHBoxLayout.SetFixedSize) # if icon == True: # pixmap = QtGui.QPixmap(logo_cria_button_path) # # Dialog.setPixmap(pixmap.scaled(110, 110, Qt.KeepAspectRatio)) # image = QLabel(Dialog) # image.setObjectName("image") # image.setPixmap(pixmap.scaled(30, 30, Qt.KeepAspectRatio)) self.label = QLabel(Dialog) self.label.setObjectName("label") self.label.setText(text) self.label.setStyleSheet("padding: 20px") label_spinner = QLabel(Dialog) self.label.setObjectName("label_spinner") label_spinner.setFixedSize(30, 30) spinner = QtWaitingSpinner(label_spinner) spinner.setRoundness(70.0) # spinner.setMinimumTrailOpacity(10.0) # spinner.setTrailFadePercentage(60.0) spinner.setNumberOfLines(15) spinner.setLineLength(8) # spinner.setLineWidth(5) spinner.setInnerRadius(5) # spinner.setRevolutionsPerSecond(2) spinner.setColor(Qt.white) spinner.start() # starts spinning self.label.setAlignment(Qt.AlignCenter) # if icon == True: # horizontalLayout.addWidget(image) horizontalLayout.addWidget(self.label) horizontalLayout.addWidget(label_spinner)
class Demo(QWidget): sb_roundness = None sb_opacity = None sb_fadeperc = None sb_lines = None sb_line_length = None sb_line_width = None sb_inner_radius = None sb_rev_s = None btn_start = None btn_stop = None btn_pick_color = None spinner = None def __init__(self): super().__init__() self.init_ui() def init_ui(self): grid = QGridLayout() groupbox1 = QGroupBox() groupbox1_layout = QHBoxLayout() groupbox2 = QGroupBox() groupbox2_layout = QGridLayout() button_hbox = QHBoxLayout() self.setLayout(grid) self.setWindowTitle("QtWaitingSpinner Demo") self.setWindowFlags(Qt.Dialog) # SPINNER self.spinner = QtWaitingSpinner(self) # Spinboxes self.sb_roundness = QDoubleSpinBox() self.sb_opacity = QDoubleSpinBox() self.sb_fadeperc = QDoubleSpinBox() self.sb_lines = QSpinBox() self.sb_line_length = QDoubleSpinBox() self.sb_line_width = QDoubleSpinBox() self.sb_inner_radius = QDoubleSpinBox() self.sb_rev_s = QDoubleSpinBox() # set spinbox default values self.sb_roundness.setValue(70) self.sb_roundness.setRange(0, 9999) self.sb_opacity.setValue(15) self.sb_opacity.setRange(0, 9999) self.sb_fadeperc.setValue(70) self.sb_fadeperc.setRange(0, 9999) self.sb_lines.setValue(12) self.sb_lines.setRange(1, 9999) self.sb_line_length.setValue(10) self.sb_line_length.setRange(0, 9999) self.sb_line_width.setValue(5) self.sb_line_width.setRange(0, 9999) self.sb_inner_radius.setValue(10) self.sb_inner_radius.setRange(0, 9999) self.sb_rev_s.setValue(1) self.sb_rev_s.setRange(0.1, 9999) # Buttons self.btn_start = QPushButton("Start") self.btn_stop = QPushButton("Stop") self.btn_pick_color = QPushButton("Pick Color") # Connects self.sb_roundness.valueChanged.connect(self.set_roundness) self.sb_opacity.valueChanged.connect(self.set_opacity) self.sb_fadeperc.valueChanged.connect(self.set_fadeperc) self.sb_lines.valueChanged.connect(self.set_lines) self.sb_line_length.valueChanged.connect(self.set_line_length) self.sb_line_width.valueChanged.connect(self.set_line_width) self.sb_inner_radius.valueChanged.connect(self.set_inner_radius) self.sb_rev_s.valueChanged.connect(self.set_rev_s) self.btn_start.clicked.connect(self.spinner_start) self.btn_stop.clicked.connect(self.spinner_stop) self.btn_pick_color.clicked.connect(self.show_color_picker) # Layout adds groupbox1_layout.addWidget(self.spinner) groupbox1.setLayout(groupbox1_layout) groupbox2_layout.addWidget(QLabel("Roundness:"), *(1, 1)) groupbox2_layout.addWidget(self.sb_roundness, *(1, 2)) groupbox2_layout.addWidget(QLabel("Opacity:"), *(2, 1)) groupbox2_layout.addWidget(self.sb_opacity, *(2, 2)) groupbox2_layout.addWidget(QLabel("Fade Perc:"), *(3, 1)) groupbox2_layout.addWidget(self.sb_fadeperc, *(3, 2)) groupbox2_layout.addWidget(QLabel("Lines:"), *(4, 1)) groupbox2_layout.addWidget(self.sb_lines, *(4, 2)) groupbox2_layout.addWidget(QLabel("Line Length:"), *(5, 1)) groupbox2_layout.addWidget(self.sb_line_length, *(5, 2)) groupbox2_layout.addWidget(QLabel("Line Width:"), *(6, 1)) groupbox2_layout.addWidget(self.sb_line_width, *(6, 2)) groupbox2_layout.addWidget(QLabel("Inner Radius:"), *(7, 1)) groupbox2_layout.addWidget(self.sb_inner_radius, *(7, 2)) groupbox2_layout.addWidget(QLabel("Rev/s:"), *(8, 1)) groupbox2_layout.addWidget(self.sb_rev_s, *(8, 2)) groupbox2.setLayout(groupbox2_layout) button_hbox.addWidget(self.btn_start) button_hbox.addWidget(self.btn_stop) button_hbox.addWidget(self.btn_pick_color) grid.addWidget(groupbox1, *(1, 1)) grid.addWidget(groupbox2, *(1, 2)) grid.addLayout(button_hbox, *(2, 1)) self.spinner.start() self.show() def set_roundness(self): self.spinner.setRoundness(self.sb_roundness.value()) def set_opacity(self): self.spinner.setMinimumTrailOpacity(self.sb_opacity.value()) def set_fadeperc(self): self.spinner.setTrailFadePercentage(self.sb_fadeperc.value()) def set_lines(self): self.spinner.setNumberOfLines(self.sb_lines.value()) def set_line_length(self): self.spinner.setLineLength(self.sb_line_length.value()) def set_line_width(self): self.spinner.setLineWidth(self.sb_line_width.value()) def set_inner_radius(self): self.spinner.setInnerRadius(self.sb_inner_radius.value()) def set_rev_s(self): self.spinner.setRevolutionsPerSecond(self.sb_rev_s.value()) def spinner_start(self): self.spinner.start() def spinner_stop(self): self.spinner.stop() def show_color_picker(self): self.spinner.setColor(QColorDialog.getColor())
class Main(QWizard): def __init__(self): super(Main, self).__init__() # build UI self.ui = WizardUI() self.ui.setup_ui(self) # connect signals self.threadpool = QThreadPool() self.keytree_dir_dict = { 1: {'dirname': 'Home', 'dirparent': False, 'nfiles': 78, 'cumfiles': 123, 'childkeys': {2}, 'mtime': 1330884000.0, 'selection_state': 1, 'exclusion_state': 0, 'description': "Partial: some contents (files and/or folders) are relevant to the collection"}, 2: {'dirname': 'Work files', 'dirparent': 1, 'nfiles': 32, 'cumfiles': 45, 'childkeys': {3, 4}, 'mtime': 1330797600.0, 'selection_state': 1, 'exclusion_state': 0, 'description': "Partial: some contents (files and/or folders) are relevant to the collection"}, 3: {'dirname': 'Travel photos', 'dirparent': 2, 'nfiles': 6, 'cumfiles': 6, 'childkeys': set(), 'mtime': 1330624800.0, 'selection_state': 0, 'exclusion_state': 0, 'description': "Unchecked: this folder is simply not relevant to the collection"}, 4: {'dirname': 'Project A', 'dirparent': 2, 'nfiles': 1, 'cumfiles': 7, 'childkeys': {5, 6}, 'mtime': 1325527200.0, 'selection_state': 2, 'exclusion_state': 0, 'description': "Checked: this folder is relevant to the collection"}, 5: {'dirname': 'Drafts', 'dirparent': 4, 'nfiles': 2, 'cumfiles': 2, 'childkeys': set(), 'mtime': 1255891200.0, 'selection_state': 2, 'exclusion_state': 0, 'description': "Checked: this folder is relevant to the collection"}, 6: {'dirname': 'Bank transfer', 'dirparent': 4, 'nfiles': 4, 'cumfiles': 4, 'childkeys': set(), 'mtime': 1322202000.0, 'selection_state': 0, 'exclusion_state': 2, 'description': "Excluded: this folder is excluded (e.g., it contains sensitive information/work)"}, } self.demo_dir_dict = { 1: {'dirname': 'folder 1', 'dirparent': False, 'nfiles': 78, 'cumfiles': 123, 'childkeys': {2}, 'mtime': 1330884000.0, 'selection_state': None, 'exclusion_state': None}, 2: {'dirname': 'folder 2', 'dirparent': 1, 'nfiles': 32, 'cumfiles': 45, 'childkeys': {3, 4}, 'mtime': 1330797600.0, 'selection_state': None, 'exclusion_state': None}, 3: {'dirname': 'folder 3', 'dirparent': 2, 'nfiles': 6, 'cumfiles': 6, 'childkeys': set(), 'mtime': 1330624800.0, 'selection_state': None, 'exclusion_state': None}, 4: {'dirname': 'folder 4', 'dirparent': 2, 'nfiles': 1, 'cumfiles': 7, 'childkeys': {5, 6}, 'mtime': 1325527200.0, 'selection_state': None, 'exclusion_state': None}, 5: {'dirname': 'folder 5', 'dirparent': 4, 'nfiles': 2, 'cumfiles': 2, 'childkeys': set(), 'mtime': 1255891200.0, 'selection_state': None, 'exclusion_state': None}, 6: {'dirname': 'folder 6', 'dirparent': 4, 'nfiles': 4, 'cumfiles': 4, 'childkeys': set(), 'mtime': 1322202000.0, 'selection_state': None, 'exclusion_state': None}, } self.spinner = QtWaitingSpinner(self, True, True, Qt.ApplicationModal) self.spinner.setRoundness(70.0) self.spinner.setMinimumTrailOpacity(15.0) self.spinner.setTrailFadePercentage(70.0) self.spinner.setNumberOfLines(12) self.spinner.setLineLength(30) self.spinner.setLineWidth(10) self.spinner.setInnerRadius(15) self.spinner.setRevolutionsPerSecond(1) keytree = KeyTreeOperations( self.ui.og_tree_key, self.threadpool, self.spinner) tree0 = TreeOperations( self.ui.og_tree_0, self.threadpool, self.spinner) tree1 = TreeOperations( self.ui.og_tree_1, self.threadpool, self.spinner, self.ui.select_btn_1, self.ui.save_btn_1, self.ui.load_btn_1, self.ui.less_btn_1) keytree.load_dir_dicts(self.keytree_dir_dict, checkable=False, expand_all=True) tree0.load_dir_dicts(self.demo_dir_dict, expand_all=True) self.ui.reset_demo_btn.clicked.connect( lambda: tree0.refresh_treeview(tree0.og_model, tree0.og_tree, self.demo_dir_dict, expand_all=True)) tree1.select_btn.clicked.connect(lambda: self.select_tree_root(tree1)) tree1.save_btn.clicked.connect(lambda: self.save_collected_data(tree1)) tree1.load_btn.clicked.connect(lambda: self.load_collected_data(tree1)) tree1.less_btn.clicked.connect(lambda: self.expand_to_depth(tree1, 0)) self.ui.consent_savebutton.clicked.connect(self.save_consent) self.ui.wizardpage1.registerField("consentbox*", self.ui.consentbox) def select_tree_root(self, tree): dirpath = QFileDialog.getExistingDirectory( self, 'Select Folder', path_str(tree.root_path)) if dirpath: tree.root_path = Path(dirpath) tree.build_tree_structure_threaded(tree.root_path) else: tree.clear_root() tree.save_btn.setDisabled(True) tree.less_btn.setDisabled(True) def save_consent(self): formats = "Text (*.txt)" filename, extension = QFileDialog.getSaveFileName( self, 'Save File', path_str(Path('~').expanduser() / 'my_consent.txt'), formats) if filename != '': with open(filename, 'w', encoding='utf8') as file: consent_txt = (self.ui.welcomelabel.text() + self.ui.consentbox.text() + self.ui.reblabel.text()) doc = QTextDocument() doc.setHtml(consent_txt) consent_plaintext = doc.toPlainText() file.write(consent_plaintext) def make_super_dict(self, dict_list, name_list): super_dict = dict() if len(dict_list) == len(name_list): for dict_, name in zip(dict_list, name_list): super_dict[name] = dict_ return super_dict else: print('Mismatch in number of dicts and supplied names.') def save_collected_data(self, tree): formats = "JavaScript Object Notation (*.json)" filename, extension = QFileDialog.getSaveFileName( self, 'Save File', path_str(Path('~').expanduser() / 'my_folder_data.json'), formats) if filename != '': anon_dir_dict = _pickle.loads(_pickle.dumps(tree.og_dir_dict)) tree.save_checkstates_root(anon_dir_dict) json_serializable(anon_dir_dict) super_dict = self.make_super_dict( [anon_dir_dict, self.ui.textarea_wp3_0.toPlainText()], ['dir_dict', 'software_choice']) with open(filename, 'w', encoding='utf8') as file: json.dump(super_dict, file, indent=4) def load_collected_data(self, tree): formats = "JavaScript Object Notation (*.json)" filename, extension = QFileDialog.getOpenFileName( self, 'Load File', path_str(Path('~').expanduser()), formats) if filename != '': with open(filename, 'r', encoding='utf8') as file: super_dict = json.load(file) self.ui.textarea_wp3_0.setPlainText(super_dict['software_choice']) tree.og_dir_dict = super_dict['dir_dict'] dict_readable(tree.og_dir_dict) tree.anon_dir_dict = _pickle.loads(_pickle.dumps(tree.og_dir_dict)) tree.refresh_treeview(tree.og_model, tree.og_tree, tree.og_dir_dict) tree.save_btn.setEnabled(True) tree.less_btn.setEnabled(True) def expand_to_depth(self, tree, depth): tree.og_tree.expandToDepth(depth)
class LoginDialog(QtWidgets.QDialog, Ui_Dialog): def __init__(self, parent=None): super(LoginDialog, self).__init__(parent) self.initUI() self.session = Utility().session self.userName = None def initUI(self): self.setupUi(self) self.setFixedSize(QSize(self.width(), self.height())) self.setWindowIcon(QIcon('Pictures/loginIcon.png')) self.setWindowTitle('12306登录') self.loginButton.setText('立即登录') # self.userNameEdit.setClearButtonEnabled(True) #设置清空按钮 self.setLineEditIcon(self.passwordEdit, 'Pictures/password_new.png') self.setLineEditIcon(self.userNameEdit, 'Pictures/user_new.png') self.userNameEdit.textChanged.connect(self.isLoginable) self.passwordEdit.textChanged.connect(self.isLoginable) self.loginButton.clicked.connect(self.login) self.initSettings() self.setupStyleSheet() self.isLoginable() self.initSpinner() self.initMessageLabel() self.remberCheckBox.stateChanged.connect(self.setupRememberCheck) def setupRememberCheck(self, state): if state == Qt.Checked: self.remberCheckBox.setStyleSheet(rememberBoxStyle + 'QCheckBox{color:#d81e06}') self.settings.setValue('isChecked', True) self.settings.setValue('username', self.userNameEdit.text()) self.settings.setValue('password', self.passwordEdit.text()) else: self.remberCheckBox.setStyleSheet(rememberBoxStyle + 'QCheckBox{color:white}') self.settings.setValue('isChecked', False) self.settings.sync() def isLoginable(self): self.messageLabel.hide() if self.userNameEdit.text() == '' or self.passwordEdit.text() == '': self.loginButton.setStyleSheet( 'QPushButton{color:white;background-color:rgba(0,0,0,0.5);border:1px;border-radius:5px;}' ) self.loginButton.setEnabled(False) else: self.loginButton.setStyleSheet( 'QPushButton{color:white;background-color:rgb(250,80,0);border-radius:5px}' ) self.loginButton.setEnabled(True) def login(self): self.spinner.start() runnable = RequestRunnable(target=self.login12306) self.pool = QThreadPool.globalInstance() self.pool.start(runnable) def login12306(self): # step 1: check验证码 self.captchaCheck() # step 2: login loginData = { 'username': self.userNameEdit.text(), 'password': self.passwordEdit.text(), 'appid': 'otn' } result = self.session.post(API.login, data=loginData).json() if result['result_code'] != 0: # 出错的话,显示错误信息 self.messageLabel.setText('出错啦:' + result['result_message']) self.messageLabel.show() self.spinner.stop() return # step 3:checkuser data = {'_json_att': ''} self.session.post(API.checkUser, data=data) # step 4: uamtk data = {'appid': 'otn'} uamtk_res = self.session.post(API.uamtk, data=data) newapptk = uamtk_res.json()['newapptk'] # step 5: uamauthclient clientData = {'tk': newapptk} uamauthclient_res = self.session.post(API.uamauthclient, data=clientData) username = uamauthclient_res.json()['username'] self.userName = username # step 6: initMy12306 html = self.session.get(API.initMy12306).text genderStr = re.findall(r'<div id="my12306page".*?</span>(.*?)</h3>', html, re.S)[0].replace('\n', '').split(',')[0] print("恭喜{}成功登录12306网站".format(username)) if genderStr: self.accept() # 获取验证码正确答案 def getCaptchaAnswer(self): response = self.session.get(API.captchaImage) if response.status_code == 200: print('验证码图片请求成功') with open(const.captchaFilePath, 'wb') as f: f.write(response.content) # 写入文件 else: print('验证码图片下载失败, 正在重试...') self.getCaptchaAnswer() # 递归 try: img = open(const.captchaFilePath, 'rb').read() # 读取文件图片 answerStr, cjyAnswerDict = const.chaoJiYing.PostPic(img, 9004) return answerStr, cjyAnswerDict # 返回自己写的验证码信息和平台反应的信息 except Exception as e: print(str(e)) def captchaCheck(self): answer, cjyAnswerDict = self.getCaptchaAnswer() # ca = Captcha(self) # ca.show() # answer = ca.coordinates data = { 'login_site': 'E', # 固定的 'rand': 'sjrand', # 固定的 'answer': answer # 验证码对应的坐标,两个为一组,跟选择顺序有关,有几个正确的,输入几个 } result = self.session.post(API.captchaCheck, data=data).json() if result['result_code'] == '4': print('验证码验证成功') else: print('验证码验证失败') picID = cjyAnswerDict['pic_id'] # 报错到打码平台 const.chaoJiYing.ReportError(picID) self.captchaCheck() return def setLineEditIcon(self, lineEdit, iconPath): action = QAction(lineEdit) action.setIcon(QIcon(iconPath)) lineEdit.addAction(action, QLineEdit.TrailingPosition) #LeadingPosition def setupStyleSheet(self): self.setStyleSheet('QDialog{border-image:url(Pictures/loginBg.png)}') self.bgLabel.setStyleSheet( 'QLabel{background-color:rgba(0,0,0,0.25);border-radius:5px}' ) # 设置透明背景色 if self.settings.value('isChecked') == 'true': self.remberCheckBox.setStyleSheet('QCheckBox{color:#d81e06}' + rememberBoxStyle) else: self.remberCheckBox.setStyleSheet('QCheckBox{color:white}' + rememberBoxStyle) self.userNameEdit.setStyleSheet(lineEditStyle) self.passwordEdit.setStyleSheet(lineEditStyle) def initSettings(self): self.settings = QSettings('Honeywell', '12306Train') if self.settings.value('isChecked') == 'true': self.remberCheckBox.setChecked(True) self.userNameEdit.setText(self.settings.value('username')) self.passwordEdit.setText(self.settings.value('password')) else: self.remberCheckBox.setChecked(False) def initMessageLabel(self): self.messageLabel.adjustSize() self.messageLabel.setGeometry(QRect(70, 15, 360, 50)) self.messageLabel.setWordWrap(True) self.messageLabel.setScaledContents(True) self.messageLabel.setStyleSheet( 'QLabel{background-color:rgb(255,0,79);color:white;font:9pt;padding-left:5px;padding-right:5px;}' ) # border-radius:5px # height = self.messageLabel.fontMetrics().boundingRect(self.messageLabel.text()).height() self.messageLabel.hide() def initSpinner(self): self.spinner = QtWaitingSpinner(self, centerOnParent=True, disableParentWhenSpinning=True) self.spinner.setNumberOfLines(15) # self.spinner.setColor(QColor(81, 4, 71)) self.spinner.setInnerRadius(20) # 设置内圆大小 self.spinner.setLineLength(15) # 设置线长 self.spinner.setLineWidth(5) # 设置线宽 self.spinner.setTrailFadePercentage(80)
class Window(QWidget): sig_abort_workers = pyqtSignal() def __init__(self, val, screenwidth, screenheight, parent=None): super().__init__(parent) self.setWindowTitle("qtube") app_exit_shortcuts = ["Ctrl+Q", "Ctrl+W"] for sc in app_exit_shortcuts: exitshortcut = QShortcut(QKeySequence(sc), self) exitshortcut.activated.connect(self.exit_seq) backshortcut = QShortcut(QKeySequence('Alt+Left'), self) backshortcut.activated.connect(self.on_back_clicked) self.setStyleSheet("background-color: " + BACKGROUND_COLOR + ";") self.mygroupbox = QGroupBox('') self.mygroupbox.setStyleSheet("color: " + FOREGROUND_COLOR + "; font-family: " + FONT + "; font-style: italic") self.myform = QFormLayout() labellist = [] combolist = [] self.mygroupbox.setLayout(self.myform) self.scroll = QScrollArea() self.scroll.setWidget(self.mygroupbox) self.scroll.setWidgetResizable(True) self.scroll.setStyleSheet("color: " + FOREGROUND_COLOR + ";") self.history = { 'urls': [], 'title_boxes': [], 'data': [], 'page_numbers': [] } self.downloaded_videos = {'paths': [], 'short_titles': []} self.search = '' self.spinner = QtWaitingSpinner(self, False) self.spinner.setRoundness(70.0) self.spinner.setMinimumTrailOpacity(15.0) self.spinner.setTrailFadePercentage(70.0) self.spinner.setNumberOfLines(10) self.spinner.setLineLength(10) self.spinner.setLineWidth(4) self.spinner.setInnerRadius(4) self.spinner.setRevolutionsPerSecond(1.5) self.spinner.setColor(QColor(FOREGROUND_COLOR)) # multi-threading QThread.currentThread().setObjectName( 'main') # threads can be named, useful for log output self.__workers_done = [] self.__threads = [] self.line = QLineEdit(self) self.line.returnPressed.connect(self.clickMethod) self.line.setStyleSheet("color: " + FOREGROUND_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + FOREGROUND_COLOR + "; font-family: " + FONT + ";") active_buttons = [] self.inactive_buttons = [] self.search_button = QPushButton() self.search_button.setText('Search') self.search_button.clicked.connect(self.clickMethod) active_buttons.append(self.search_button) self.home_button = QPushButton() self.home_button.setText('Home') self.home_button.clicked.connect(self.on_home_clicked) self.inactive_buttons.append(self.home_button) self.play_playlist_button = QPushButton() self.play_playlist_button.setText('Play All') self.play_playlist_button.clicked.connect( self.on_play_playlist_clicked) active_buttons.append(self.play_playlist_button) self.back_button = QPushButton() self.back_button.setText('Back') self.back_button.clicked.connect(self.on_back_clicked) self.inactive_buttons.append(self.back_button) for b in active_buttons: b.setStyleSheet("color: " + FOREGROUND_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + FOREGROUND_COLOR + "; font-family: " + FONT + ";") b.setCursor(Qt.PointingHandCursor) for b in self.inactive_buttons: b.setStyleSheet("color: " + INACTIVE_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + INACTIVE_COLOR + "; font-family: " + FONT + ";") self.download_label = QLabel() self.download_label.setText('0 downloads') self.download_label.setMaximumSize(QSize(110, 20)) self.download_label.setStyleSheet("color: " + INACTIVE_COLOR + "; background-color: " + BACKGROUND_COLOR + "; font-family: " + FONT + ";") self.download_selector = QComboBox() self.download_selector.setStyleSheet("color: " + INACTIVE_COLOR + "; background-color: " + BACKGROUND_COLOR + "; font-family: " + FONT + ";") self.download_selector.currentIndexChanged.connect( self.select_download) self.download_to_play = '' self.play_downloaded_button = QPushButton() self.play_downloaded_button.setText('Play') self.play_downloaded_button.clicked.connect(self.on_play_downloaded) self.play_downloaded_button.setMaximumSize(QSize(50, 20)) self.play_downloaded_button.setStyleSheet("color: " + INACTIVE_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + INACTIVE_COLOR + "; font-family: " + FONT + ";") self.container = VideoContainer(PLAYER_SIZE) self.container.setAttribute(Qt.WA_DontCreateNativeAncestors) self.container.setAttribute(Qt.WA_NativeWindow) #self.container.sig_height.connect(self.resizeWindow) self.player = mpv.MPV( wid=str(int(self.container.winId())), ytdl=True, input_default_bindings=True, input_vo_keyboard=True, keep_open=True, reset_on_next_file='pause', osd_bar=True, ) script_dir = str(Path.home()) + '/.config/mpv/scripts/' [ self.player.command('load-script', script_dir + script) for script in os.listdir(script_dir) ] player_exit_shortcuts = ['q', 'ctrl+q', 'ctrl+w'] for sc in player_exit_shortcuts: self.player.register_key_binding(sc, self.exit_seq) self.player.register_key_binding('f', self.fullscreen) self.player.register_key_binding('esc', self.fullscreen_off) self.isFullScreen = False self.player.register_key_binding('WHEEL_LEFT', 'seek 1') self.player.register_key_binding('WHEEL_RIGHT', 'seek -1') searchbarlayout = QHBoxLayout() searchbarlayout.addWidget(self.line) searchbarlayout.addWidget(self.search_button) searchbarlayout.addWidget(self.spinner) searchbar = QWidget() searchbar.setLayout(searchbarlayout) buttonrowlayout = QHBoxLayout() buttonrowlayout.addWidget(self.back_button) buttonrowlayout.addWidget(self.home_button) buttonrowlayout.addWidget(self.play_playlist_button) buttonrow = QWidget() buttonrow.setLayout(buttonrowlayout) downloadrowlayout = QHBoxLayout() downloadrowlayout.addWidget(self.download_label) downloadrowlayout.addWidget(self.download_selector) downloadrowlayout.addWidget(self.play_downloaded_button) downloadrow = QWidget() downloadrow.setLayout(downloadrowlayout) sublayout = QVBoxLayout() sublayout.addWidget(searchbar) sublayout.addWidget(buttonrow) sublayout.addWidget(self.scroll) sublayout.addWidget(downloadrow) self.left = QWidget() self.left.setLayout(sublayout) self.left.setFixedWidth(LIST_WIDTH) biglayout = QHBoxLayout(self) biglayout.addWidget(self.left) biglayout.addWidget(self.container) biglayout.setContentsMargins(0, 0, 0, 0) self.move(int((screenwidth - PLAYER_SIZE.width() - LIST_WIDTH) / 2), int((screenheight - PLAYER_SIZE.height()) / 2)) # load home page data self.spinner.start() idx = 'Home' worker = Worker(idx, HOME_URL, search=False) thread = QThread() thread.setObjectName('thread_' + idx) worker.moveToThread(thread) worker.sig_data.connect(self.on_click_data_received) self.sig_abort_workers.connect(worker.abort) thread.started.connect(worker.grabData) thread.start() self.__threads.append((thread, worker)) def fullscreen(self, blank, blank2): if not self.isFullScreen: self.left.setFixedWidth(0) self.showFullScreen() self.isFullScreen = True time.sleep(.5) def fullscreen_off(self, blank, blank2): if self.isFullScreen: self.showNormal() self.left.setFixedWidth(LIST_WIDTH) self.isFullScreen = False time.sleep(.5) # @pyqtSlot(int) # def resizeWindow(self, newheight): # self.setFixedHeight(newheight) def clickMethod(self): self.spinner.start() self.search = self.line.text() print('searching "' + self.search + '"...') idx = 'clickMethod' worker = Worker(idx, self.search) thread = QThread() thread.setObjectName('thread_' + idx) self.__threads.append((thread, worker)) worker.moveToThread(thread) worker.sig_data.connect(self.on_click_data_received) self.sig_abort_workers.connect(worker.abort) thread.started.connect(worker.grabData) thread.start() @pyqtSlot(dict) def on_click_data_received(self, data): self.data = sort_dict_lists_by_list(data, 'titles') search_term = self.search if len(self.history['data']) == 0: title_box = data['page_title'] elif len(search_term) > 25: title_box = 'results: "' + search_term[:22] + '..."' else: title_box = 'results: "' + search_term + '"' if len(self.history['data']) > 0: for b in self.inactive_buttons: b.setStyleSheet("color: " + FOREGROUND_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + FOREGROUND_COLOR + "; font-family: " + FONT + ";") b.setCursor(Qt.PointingHandCursor) self.history['data'].append(self.data) self.history['title_boxes'].append(title_box) self.history['urls'].append(self.data['playlist_url']) self.history['page_numbers'].append(1) self.populate() groupbox = QGroupBox(title_box) groupbox.setLayout(self.myform) groupbox.setStyleSheet("color: " + FOREGROUND_COLOR + "; font-family: " + FONT + ";font-style: italic") self.scroll.setWidget(groupbox) self.spinner.stop() def populate(self): labellist = [] combolist = [] form = QFormLayout() for i, img in enumerate(self.data['thumb_paths']): if self.data['titles'][i] is not None: title = '\n'.join( textwrap.wrap(self.data['titles'][i], TEXT_LENGTH)[:2]) if len(self.data['titles'][i]) > TEXT_LENGTH * 2: title = title + '...' else: # catch errors from youtube-dl failing to capture video title title = '[TITLE MISSING]' text = title + '\n' + self.data['durations'][ i] + ' | ' + self.data['dates'][i] + '\n' + self.data['views'][ i] + ' views | ' + self.data['ratings'][i] + ' likes' descLabel = DescriptionLabel(self.data['urls'][i], self.data['titles'][i]) descLabel.setText(text) descLabel.setMaximumWidth(TEXT_WIDTH) descLabel.video_clicked.connect(self.on_video_clicked) descLabel.download_clicked.connect(self.on_download_clicked) labellist.append(descLabel) imagelabel = ImageLabel(self.data['urls'][i], self.data['titles'][i]) pixmap = QPixmap(img) pixmap = pixmap.scaled(THUMB_SIZE, FLAGS) imagelabel.setPixmap(pixmap) imagelabel.video_clicked.connect(self.on_video_clicked) imagelabel.download_clicked.connect(self.on_download_clicked) combolist.append(imagelabel) # form.addRow(combolist[i], labellist[i]) number_of_pages = math.ceil(self.data['total_videos'] / NUM_RESULTS) if number_of_pages > 1: current_page = self.history['page_numbers'][-1] pages = [] if current_page <= 3 or number_of_pages <= 5: page_range = ['<'] page_range.extend([i for i in range(1, number_of_pages + 1)]) page_range.append('>') else: page_range = ['<', 1] if number_of_pages - current_page < 3: page_range.extend([ i for i in range(number_of_pages - 3, number_of_pages + 1) ]) else: page_range.extend([i + current_page - 1 for i in range(4)]) page_range.append('>') for i in page_range: active = (i != current_page ) and not (i == '<' and current_page == 1) and not ( i == '>' and current_page == number_of_pages) page = PageLabel(i, active) page.page_clicked.connect(self.get_next_page) pages.append(page) layout = QHBoxLayout() for p in pages: layout.addWidget(p) page_selector = QWidget() page_selector.setLayout(layout) form.addRow(QLabel('Pages: '), page_selector) self.myform = form def exit_seq(self, blank=None, blank2=None): app.quit() def on_video_clicked(self): label = self.sender() self.url = label.url self.player.play(self.url) #self.player.command('show-text', label.title) def on_download_clicked(self): label = self.sender() idx = label.title worker = Worker(idx, label.url, label=self.download_label) thread = QThread() thread.setObjectName('thread_' + idx) self.__threads.append( (thread, worker)) # need to store worker too otherwise will be gc'd worker.moveToThread(thread) worker.sig_msg.connect(self.on_download_complete) self.sig_abort_workers.connect(worker.abort) # get read to start worker: thread.started.connect(worker.download) thread.start( ) # this will emit 'started' and start thread's event loop @pyqtSlot(str) def on_download_complete(self, title): title_short = title[:20] vid_path = [ DOWNLOAD_LOCATION + file for file in os.listdir(DOWNLOAD_LOCATION) if file.startswith(title) ][0] self.downloaded_videos['short_titles'].append(title_short) self.downloaded_videos['paths'].append(vid_path) self.download_label.setText( str(len(self.downloaded_videos['paths'])) + ' downloads') self.download_label.setStyleSheet("color: " + FOREGROUND_COLOR + "; background-color: " + BACKGROUND_COLOR + "; font-family: " + FONT + ";") self.download_selector.insertItem(0, title_short, vid_path) self.download_selector.setStyleSheet("color: " + FOREGROUND_COLOR + "; background-color: " + BACKGROUND_COLOR + "; font-family: " + FONT + ";") self.download_selector.setCurrentIndex(0) self.play_downloaded_button.setStyleSheet("color: " + FOREGROUND_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + FOREGROUND_COLOR + "; font-family: " + FONT + ";") self.play_downloaded_button.setCursor(Qt.PointingHandCursor) def on_home_clicked(self): if not (HOME_URL in self.history['urls'][-1] and self.history['page_numbers'][-1] == 1): print('loading homepage...') self.search = '' self.data = self.history['data'][0] self.history['data'].append(self.data) self.history['title_boxes'].append(self.data['page_title']) self.history['urls'].append(self.data['playlist_url']) self.history['page_numbers'].append(1) self.populate() groupbox = QGroupBox(self.data['page_title']) groupbox.setLayout(self.myform) groupbox.setStyleSheet("color: " + FOREGROUND_COLOR + "; font-family: " + FONT + ";font-style: italic") self.scroll.setWidget(groupbox) self.home_button.setStyleSheet("color: " + INACTIVE_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + INACTIVE_COLOR + "; font-family: " + FONT + ";") self.home_button.setCursor(Qt.ArrowCursor) else: print('already home') def on_play_playlist_clicked(self): self.url = self.history['urls'][-1] self.player.play(self.url) #TODO: add mpv options to limit playlist items to number of search results def on_back_clicked(self): if len(self.history['urls']) > 1: #self.search = '' self.history['urls'].pop(-1) self.history['page_numbers'].pop(-1) self.history['data'].pop(-1) self.data = self.history['data'][-1] self.populate() self.history['title_boxes'].pop(-1) groupbox = QGroupBox(self.history['title_boxes'][-1]) groupbox.setLayout(self.myform) groupbox.setStyleSheet("color: " + FOREGROUND_COLOR + "; font-family: " + FONT + ";font-style: italic") self.scroll.setWidget(groupbox) print('returning to page ' + self.history['urls'][-1] + '...') if len(self.history['urls']) == 1: for b in self.inactive_buttons: b.setStyleSheet("color: " + INACTIVE_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + INACTIVE_COLOR + "; font-family: " + FONT + ";") b.setCursor(Qt.ArrowCursor) elif HOME_URL not in self.history['urls'][-1]: self.home_button.setStyleSheet("color: " + FOREGROUND_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + FOREGROUND_COLOR + "; font-family: " + FONT + ";") self.home_button.setCursor(Qt.PointingHandCursor) else: self.home_button.setStyleSheet("color: " + INACTIVE_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + INACTIVE_COLOR + "; font-family: " + FONT + ";") self.home_button.setCursor(Qt.ArrowCursor) else: print('could not go back') def on_play_downloaded(self): if len(self.downloaded_videos['paths']) > 0: self.player.play(self.download_to_play) else: print('no videos downloaded yet') def select_download(self, index): print('queued ' + self.download_selector.itemData(index)) self.download_to_play = self.download_selector.itemData(index) def get_next_page(self): self.spinner.start() search_term = self.search try: sender = self.sender() if sender.page == '<': next_page_number = self.history['page_numbers'][-1] - 1 elif sender.page == '>': next_page_number = self.history['page_numbers'][-1] + 1 else: next_page_number = sender.page except: next_page_number = self.history['page_numbers'][-1] + 1 self.history['page_numbers'].append(next_page_number) url = self.history['urls'][-1] self.history['urls'].append(url) title_box = re.sub(r' page \d+$', '', self.history['title_boxes'][-1]) if next_page_number > 1: title_box = title_box[:29] + ' page ' + str(next_page_number) self.history['title_boxes'].append(title_box) data_limits = [ NUM_RESULTS * (next_page_number - 1), NUM_RESULTS * next_page_number ] idx = 'get_next_page' worker = Worker(idx, url, search=False, limit=data_limits) thread = QThread() thread.setObjectName('thread_' + idx) self.__threads.append((thread, worker)) worker.moveToThread(thread) worker.sig_data.connect(self.on_next_page_received) self.sig_abort_workers.connect(worker.abort) thread.started.connect(worker.grabData) thread.start() @pyqtSlot(dict) def on_next_page_received(self, data): search_term = self.search self.data = data self.history['data'].append(self.data) for b in self.inactive_buttons: b.setStyleSheet("color: " + FOREGROUND_COLOR + "; background-color: " + BACKGROUND_COLOR + "; border: 1px solid " + FOREGROUND_COLOR + "; font-family: " + FONT + ";") b.setCursor(Qt.PointingHandCursor) self.populate() groupbox = QGroupBox(self.history['title_boxes'][-1]) groupbox.setLayout(self.myform) groupbox.setStyleSheet("color: " + FOREGROUND_COLOR + "; font-family: " + FONT + ";font-style: italic") self.scroll.setWidget(groupbox) self.spinner.stop() @pyqtSlot() def abort_workers(self): self.sig_abort_workers.emit() for thread, worker in self.__threads: # note nice unpacking by Python, avoids indexing thread.quit( ) # this will quit **as soon as thread event loop unblocks** thread.wait() # <- so you need to wait for it to *actually* quit # even though threads have exited, there may still be messages on the main thread's # queue (messages that threads emitted before the abort): self.log.append('All threads exited')
class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setWindowTitle("GTHEAT 0.2 - A Cool Program") self.setStyleSheet("background-color: white;") self.resize(1280, 768) self.setContentsMargins(3, 3, 3, 3) self.setStatusBar(QStatusBar()) self.statusBar().setStyleSheet("border-top: 1px solid black") self.settings = QSettings("GT FRC", "GTHEAT") self._markerSize = 14 self.mainGraph = MplCanvas(self, width=2, height=6, dpi=100) self._create_toolbar() # Create all the layouts self.mainLayout = QVBoxLayout() self.mainGraphLayout = QFormLayout() self.smallGraphsLayout = QHBoxLayout() self.leftPanelLayout = QVBoxLayout() self.LeftPanelAndMainLayout = QHBoxLayout() self.axesModifierLayout = QGridLayout() self.heatVisLayout = QGridLayout() self.heatVisFrame = QFrame() self.axesModifierFrame = QFrame() self.checkboxFrame = QFrame() self.checkboxLayout = QGridLayout() self.chiExpFrame = QFrame() self.chiExpLayout = QVBoxLayout() self.leftPanelFrame = QFrame() self.checkboxAndAxesModifierLayout = QVBoxLayout() # Set main widget and layout self.mainGraphLayout.addWidget(self.mainGraph) self.mainWidget = QWidget() self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) # Set geometries self.mainGraphLayout.setGeometry(QRect(220, 159, 551, 501)) self.checkboxFrame.setMaximumSize(250, 150) self.axesModifierFrame.setMaximumSize(250, 150) self.smallGraphsLayout.setGeometry(QRect(50, 30, 930, 20)) # Set widgets self._setNoDataGraphs() self._create_visc_modifiers() self._create_checkboxes() self._create_axis_modifiers() self._create_exp_checkboxes() # Add layouts self.checkboxAndAxesModifierLayout.addWidget(self.axesModifierFrame) self.checkboxAndAxesModifierLayout.addWidget(self.heatVisFrame) self.checkboxAndAxesModifierLayout.addWidget(self.chiExpFrame) self.checkboxAndAxesModifierLayout.addWidget(self.checkboxFrame) self.leftPanelFrame.setLayout(self.checkboxAndAxesModifierLayout) self.leftPanelLayout.addWidget(self.leftPanelFrame) self.LeftPanelAndMainLayout.addLayout(self.leftPanelLayout) self.LeftPanelAndMainLayout.addLayout(self.mainGraphLayout, stretch=1) self.mainLayout.addLayout(self.smallGraphsLayout) self.mainLayout.addLayout(self.LeftPanelAndMainLayout) def _setNoDataGraphs(self): smallHeight = 1 smallWidth = 3 self.shotDensityGraphs = MplCanvas(self, width=smallWidth, height=smallHeight, dpi=100) self.smallGraphsLayout.addWidget(self.shotDensityGraphs) self.shotTempGraph = MplCanvas(self, width=smallWidth, height=smallHeight, dpi=100) self.smallGraphsLayout.addWidget(self.shotTempGraph) self.shotRadiusGraph = MplCanvas(self, width=smallWidth, height=smallHeight, dpi=100) self.smallGraphsLayout.addWidget(self.shotRadiusGraph) self.shotVelocityGraph = MplCanvas(self, width=smallWidth, height=smallHeight, dpi=100) self.smallGraphsLayout.addWidget(self.shotVelocityGraph) self.shotSomethingGraph = MplCanvas(self, width=smallWidth, height=smallHeight, dpi=100) self.smallGraphsLayout.addWidget(self.shotSomethingGraph) def _setSmallGraphs(self, shot: chi_i): """ :param shot: The chi_i shot data """ plt.close() plt.ioff() self.shotDensityGraphs.updateFig(shot.rho, [shot.n.i.fsa, shot.n.e.fsa], yFormatter=FormatStrFormatter('%.0E')) self.shotTempGraph.updateFig(shot.rho, [shot.T.i.ev.fsa, shot.T.e.ev.fsa], yFormatter=FormatStrFormatter('%.0E')) self.shotRadiusGraph.updateFig(shot.rho, shot.gyro_rad_ion, yFormatter=FormatStrFormatter('%.0E')) self.shotVelocityGraph.updateFig(shot.rho, shot.vth, yFormatter=FormatStrFormatter('%.0E')) self.shotSomethingGraph.updateFig( shot.rho, shot.vth, yFormatter=FormatStrFormatter('%.0E')) def onOpenGT3Started(self, s): fileName = QFileDialog.getOpenFileName(self, str("Open File"), os.getcwd(), str("GT3 files (*)")) if path.exists(fileName[0]): self.gt3 = GT3loaderDialog(fileName, parent=self) # type: QWidget self.chi_i = self.gt3.chi_i # type: chi_i self.shot = self.gt3.shot # type: gt3 self.rho = self.gt3.rho self._setSmallGraphs(self.chi_i) self.mainGraph.updateFig(self.rho, self.shot.rtrans.chi.i.chi4, yFormatter=FormatStrFormatter('%.1f')) xAxisMin = self.XAxisMin.value() xAxisMax = self.XAxisMax.value() yAxisMin = self.YAxisMin.value() yAxisMax = self.YAxisMax.value() self.mainGraph.axes.set_xlim((xAxisMin, xAxisMax)) self.mainGraph.axes.set_ylim((yAxisMin, yAxisMax)) self.setCentralWidget(self.mainWidget) self._enable_checkboxes(True) self._enable_axis_modifiers(True) self._enable_exp_checkboxes(True) self.save_fig_action.setEnabled(True) # Enable Shot Data file menu self.open_velocity_graphs_action.setEnabled(True) self.open_temperature_graphs_action.setEnabled(True) self.open_scale_length_graphs_action.setEnabled(True) self.open_flux_graphs_action.setEnabled(True) self.open_electric_field_action.setEnabled(True) self.open_collisionality_action.setEnabled(True) self.open_density_graph_action.setEnabled(True) else: pass def _createSpinner(self): self.spinner = QtWaitingSpinner(parent=self) self.spinner.setRoundness(70.0) self.spinner.setMinimumTrailOpacity(15.0) self.spinner.setTrailFadePercentage(70.0) self.spinner.setNumberOfLines(12) self.spinner.setLineLength(10) self.spinner.setLineWidth(5) self.spinner.setInnerRadius(10) self.spinner.setRevolutionsPerSecond(1) self.spinner.setColor(QColor(81, 4, 71)) # def createMainGraph(self): # # self.graphWidget = pg.PlotWidget() # self.graphWidget.setBackground('w') # self.graphWidget.setXRange(0.85, 1.0) def mainReplot(self, int): neo = self.neoCheckbox.isChecked() itg12 = self.itg12Checkbox.isChecked() itg32 = self.itg32Checkbox.isChecked() gyro = self.gyroBohmCheckbox.isChecked() DA = self.driftAlfenCheckbox.isChecked() sum = self.combinedCheckbox.isChecked() chi1 = self.chi1RadioButton.isChecked() chi2 = self.chi2RadioButton.isChecked() chi3 = self.chi3RadioButton.isChecked() chi4 = self.chi4RadioButton.isChecked() chiAll = self.chiShowAllButton.isChecked() viscTor = self.heatVisTor.value() viscPol = self.heatVisPol.value() viscChi = self.shot.rtrans._calc_chi_i_visc(vpolS=viscPol, vtorS=viscTor) s = self._markerSize if chiAll: self.mainGraph.updateFig(self.rho, None, color="black", keepLims=True, yFormatter=FormatStrFormatter('%.1f')) self.mainGraph.add_scatter(self.rho, self.shot.rtrans.chi.i.chi1, color="red", marker="x", s=s) self.mainGraph.add_scatter(self.rho, self.shot.rtrans.chi.i.chi2, color="green", marker="X", s=s) self.mainGraph.add_scatter(self.rho, self.shot.rtrans.chi.i.chi3, color="blue", marker="^", s=s) self.mainGraph.add_scatter(self.rho, viscChi, color="black", marker="2", s=s) else: if chi1: self.mainGraph.updateFig(self.rho, self.shot.rtrans.chi.i.chi1, yFormatter=FormatStrFormatter('%.1f'), keepLims=True, color="red", marker="x", s=s) if chi2: self.mainGraph.updateFig(self.rho, self.shot.rtrans.chi.i.chi2, yFormatter=FormatStrFormatter('%.1f'), keepLims=True, color="green", marker="X", s=s) if chi3: self.mainGraph.updateFig(self.rho, self.shot.rtrans.chi.i.chi3, yFormatter=FormatStrFormatter('%.1f'), keepLims=True, color="blue", marker="^", s=s) if chi4: self.mainGraph.updateFig(self.rho, viscChi, yFormatter=FormatStrFormatter('%.1f'), keepLims=True, color="black", marker="2", s=s) if sum: self.mainGraph.add_scatter(self.rho, self.chi_i.plot_chis_custom(neo=neo, bohm=gyro, itg12=itg12, itg32=itg32, DA=DA, sum=True, show=False), color="red") else: if neo: self.mainGraph.add_scatter(self.rho, self.chi_i.neo_chi, color="red", s=s) if itg12: self.mainGraph.add_scatter(self.rho, self.chi_i.chi_itg_TS_12, color="green", s=s) if itg32: self.mainGraph.add_scatter(self.rho, self.chi_i.chi_itg_TS_32, color="purple", s=s) if DA: self.mainGraph.add_scatter(self.rho, self.chi_i.chi_DA, color="yellow", s=s) if gyro: self.mainGraph.add_scatter(self.rho, self.chi_i.gyro_bohm, color="blue", s=s) def _create_visc_modifiers(self): self.heatVisTor = QDoubleSpinBox() self.heatVisPol = QDoubleSpinBox() self.heatVisTorLabel = MathTextLabel(r"$V_{\phi}^s$", 14) self.heatVisPolLabel = MathTextLabel(r"$V_{\theta}^s$", 14) self.heatVisTor.setSingleStep(0.01) self.heatVisTor.setRange(-1.0, 1.0) self.heatVisTor.setValue(0.1) self.heatVisPol.setSingleStep(0.01) self.heatVisPol.setRange(-1.0, 1.0) self.heatVisPol.setValue(0.1) self.heatVisTor.valueChanged.connect(self.mainReplot) self.heatVisPol.valueChanged.connect(self.mainReplot) self.heatVisLayout.addWidget(self.heatVisTorLabel, 0, 0) self.heatVisLayout.addWidget(self.heatVisPolLabel, 0, 1) self.heatVisLayout.addWidget(self.heatVisTor, 1, 0) self.heatVisLayout.addWidget(self.heatVisPol, 1, 1) self.heatVisFrame.setLayout(self.heatVisLayout) #self.heatVisLayout.setAlignment(Qt.AlignVCenter) self.heatVisFrame.setFrameStyle(QFrame.StyledPanel) shadow = QGraphicsDropShadowEffect() shadow.setBlurRadius(15) self.heatVisFrame.setGraphicsEffect(shadow) def _create_axis_modifiers(self): self.XAxisMin = QDoubleSpinBox() self.XAxisMin.setSingleStep(0.01) self.XAxisMin.setRange(0.0, 1.0) self.XAxisMin.setValue(0.85) self.XAxisMax = QDoubleSpinBox() self.XAxisMax.setRange(0.0, 1.0) self.XAxisMax.setSingleStep(0.01) self.XAxisMax.setValue(1.0) self.YAxisMax = QDoubleSpinBox() self.YAxisMax.setSingleStep(1.0) self.YAxisMax.setValue(10.0) self.YAxisMax.setMaximum(1000.) self.YAxisMin = QDoubleSpinBox() self.YAxisMin.setSingleStep(1.0) self.YAxisMin.setMinimum(-100.) self.YAxisMin.setValue(0.0) self.LogScale = QCheckBox() self.LogScale.setChecked(False) self.XAxisLabel = QLabel("X-axis") self.YAxisLabel = QLabel("Y-axis") self.LogAxisLabel = QLabel("Log Scale") self.XAxisMin.valueChanged.connect(self.mainGraph.updateXMin) self.XAxisMax.valueChanged.connect(self.mainGraph.updateXMax) self.YAxisMin.valueChanged.connect(self.mainGraph.updateYMin) self.YAxisMax.valueChanged.connect(self.mainGraph.updateYMax) self.LogScale.stateChanged.connect(self.mainGraph.set_logPlot) self.axesModifierLayout.addWidget(self.XAxisLabel, 0, 0) self.axesModifierLayout.addWidget(self.XAxisMin, 1, 0) self.axesModifierLayout.addWidget(self.XAxisMax, 1, 1) self.axesModifierLayout.addWidget(self.YAxisLabel, 2, 0) self.axesModifierLayout.addWidget(self.YAxisMin, 3, 0) self.axesModifierLayout.addWidget(self.YAxisMax, 3, 1) self.axesModifierLayout.addWidget(self.LogAxisLabel, 0, 2) self.axesModifierLayout.addWidget(self.LogScale, 1, 2) self.axesModifierLayout.setAlignment(Qt.AlignVCenter) self.axesModifierFrame.setLayout(self.axesModifierLayout) self.axesModifierFrame.setFrameStyle(QFrame.StyledPanel) shadow = QGraphicsDropShadowEffect() shadow.setBlurRadius(15) self.axesModifierFrame.setGraphicsEffect(shadow) self._enable_axis_modifiers(False) def _enable_checkboxes(self, en=True): self.neoCheckbox.setEnabled(en) self.gyroBohmCheckbox.setEnabled(en) self.itg12Checkbox.setEnabled(en) self.itg32Checkbox.setEnabled(en) self.driftAlfenCheckbox.setEnabled(en) self.combinedCheckbox.setEnabled(en) def _enable_exp_checkboxes(self, en=True): self.chi1RadioButton.setEnabled(en) self.chi2RadioButton.setEnabled(en) self.chi3RadioButton.setEnabled(en) self.chi4RadioButton.setEnabled(en) self.chiShowAllButton.setEnabled(en) def _enable_axis_modifiers(self, en=True): self.XAxisMin.setEnabled(en) self.XAxisMax.setEnabled(en) self.YAxisMin.setEnabled(en) self.YAxisMax.setEnabled(en) def _create_checkboxes(self): self.combinedCheckbox = QCheckBox(text="Sum Exp. Chis") self.neoCheckbox = QCheckBox(text="Neoclassical") self.neoCheckbox.setStyleSheet("color: red") self.gyroBohmCheckbox = QCheckBox(text="Gyro-Bohm") self.gyroBohmCheckbox.setStyleSheet("color: blue") self.itg12Checkbox = QCheckBox(text="ITG (1/2)") self.itg12Checkbox.setStyleSheet("color: green") self.itg32Checkbox = QCheckBox(text="ITG (3/2)") self.itg32Checkbox.setStyleSheet("color:purple") self.driftAlfenCheckbox = QCheckBox(text="Drift-Alfven") self.driftAlfenCheckbox.setStyleSheet("color: yellow") self._enable_checkboxes(False) self.combinedCheckbox.stateChanged.connect(self.mainReplot) self.neoCheckbox.stateChanged.connect(self.mainReplot) self.itg32Checkbox.stateChanged.connect(self.mainReplot) self.itg12Checkbox.stateChanged.connect(self.mainReplot) self.gyroBohmCheckbox.stateChanged.connect(self.mainReplot) self.driftAlfenCheckbox.stateChanged.connect(self.mainReplot) self.checkboxLayout.addWidget(self.neoCheckbox, 0, 0) self.checkboxLayout.addWidget(self.gyroBohmCheckbox, 0, 1) self.checkboxLayout.addWidget(self.itg12Checkbox, 1, 0) self.checkboxLayout.addWidget(self.itg32Checkbox, 1, 1) self.checkboxLayout.addWidget(self.driftAlfenCheckbox, 2, 0) self.checkboxLayout.addWidget(self.combinedCheckbox, 2, 1) self.checkboxLayout.setAlignment(Qt.AlignVCenter) self.checkboxFrame.setLayout(self.checkboxLayout) self.checkboxFrame.setFrameStyle(QFrame.StyledPanel) shadow = QGraphicsDropShadowEffect() shadow.setBlurRadius(15) self.checkboxFrame.setGraphicsEffect(shadow) def _create_exp_checkboxes(self): self.chi1RadioButton = QRadioButton(r"$q^{cond} = Q^{tot}$") self.chi2RadioButton = QRadioButton(r"$q^{cond} = Q^{tot} - Q^{conv}$") self.chi3RadioButton = QRadioButton( r"$q^{cond} = Q^{tot} - Q^{conv} - Q^{heatin}$") self.chi4RadioButton = QRadioButton( r"$q^{cond} = Q^{tot} - Q^{conv} - Q^{heatin} - Q^{visc}$") self.chiShowAllButton = QRadioButton("Show All") self.chiShowAllButton.setChecked(True) # self.chi1RadioButton = QCheckBox(r"$q^{cond} = Q^{tot}$") # self.chi2RadioButton = QCheckBox(r"$q^{cond} = Q^{tot} - Q^{conv}$") # self.chi3RadioButton = QCheckBox(r"$q^{cond} = Q^{tot} - Q^{conv} - Q^{heatin}$") # self.chi4RadioButton = QCheckBox(r"$q^{cond} = Q^{tot} - Q^{conv} - Q^{heatin} - Q^{visc}$") # self.chiShowAllButton = QCheckBox("Show All") self.chi1RadioButton.setStyleSheet("color: red") self.chi2RadioButton.setStyleSheet("color: green") self.chi3RadioButton.setStyleSheet("color: blue") self.chi4RadioButton.setStyleSheet("color: black") self._enable_exp_checkboxes(False) self.chi1RadioButton.toggled.connect(self.mainReplot) self.chi2RadioButton.toggled.connect(self.mainReplot) self.chi3RadioButton.toggled.connect(self.mainReplot) self.chi4RadioButton.toggled.connect(self.mainReplot) self.chiShowAllButton.toggled.connect(self.mainReplot) self.chiExpLayout.addWidget(self.chi1RadioButton) self.chiExpLayout.addWidget(self.chi2RadioButton) self.chiExpLayout.addWidget(self.chi3RadioButton) self.chiExpLayout.addWidget(self.chi4RadioButton) self.chiExpLayout.addWidget(self.chiShowAllButton) self.chiExpLayout.setAlignment(Qt.AlignVCenter) self.chiExpFrame.setLayout(self.chiExpLayout) self.chiExpFrame.setFrameStyle(QFrame.StyledPanel) shadow = QGraphicsDropShadowEffect() shadow.setBlurRadius(15) self.chiExpFrame.setGraphicsEffect(shadow) def _create_toolbar(self): # Set the toolbar self.toolbar = QToolBar("The Main Toolbar") #Set icon size self.toolbar.setIconSize(QSize(16, 16)) # Create the toolbar self.toolbar = QToolBar("GTHEAT Toolbar") # Set icon size self.toolbar.setIconSize(QSize(16, 16)) self.addToolBar(self.toolbar) # Create actions self.open_GT3_action = QAction("Open GT3 File", self) self.open_GT3_action.setIcon(self.style().standardIcon( QStyle.SP_DirOpenIcon)) self.open_GT3_action.setStatusTip("Open a GT3 File") self.open_GT3_action.triggered.connect(self.onOpenGT3Started) self.save_fig_action = QAction("Save Figure", self) self.save_fig_action.setIcon(self.style().standardIcon( QStyle.SP_DialogSaveButton)) self.save_fig_action.setStatusTip("Save Figure") self.save_fig_action.triggered.connect(self.saveFigureDialog) self.save_fig_action.setEnabled(False) self.set_preferences_action = QAction("Set Preferences", self) self.set_preferences_action.setStatusTip("Set Preferences") self.set_preferences_action.triggered.connect(self.set_preferences) self.open_velocity_graphs_action = QAction("Velocity Graphs", self) self.open_velocity_graphs_action.setStatusTip("Velocity Graphs") self.open_velocity_graphs_action.triggered.connect( self.open_velocity_graphs) self.open_velocity_graphs_action.setEnabled(False) self.open_temperature_graphs_action = QAction("Temperature Graphs", self) self.open_temperature_graphs_action.setStatusTip("Temperature Graphs") self.open_temperature_graphs_action.triggered.connect( self.open_temperature_graphs) self.open_temperature_graphs_action.setEnabled(False) self.open_scale_length_graphs_action = QAction( "Gradient Scale Lengths", self) self.open_scale_length_graphs_action.setStatusTip( "Gradient Scale Lengths") self.open_scale_length_graphs_action.triggered.connect( self.open_scale_length_graphs) self.open_scale_length_graphs_action.setEnabled(False) self.open_flux_graphs_action = QAction("Particle and Heat Fluxes", self) self.open_flux_graphs_action.setStatusTip("Particle and Heat Fluxes") self.open_flux_graphs_action.triggered.connect(self.open_flux_graphs) self.open_flux_graphs_action.setEnabled(False) self.open_electric_field_action = QAction("Electric field") self.open_electric_field_action.setStatusTip("Radial electric field") self.open_electric_field_action.triggered.connect( self.open_electric_field_graphs) self.open_electric_field_action.setEnabled(False) self.open_collisionality_action = QAction("Collisionality") self.open_collisionality_action.setStatusTip("Collisionality") self.open_collisionality_action.triggered.connect( self.open_collisionality_graphs) self.open_collisionality_action.setEnabled(False) self.open_density_graph_action = QAction("Densities") self.open_density_graph_action.setStatusTip("Density profiles") self.open_density_graph_action.triggered.connect( self.open_density_graphs) self.open_density_graph_action.setEnabled(False) exitAct = QAction(QIcon('exit.png'), '&Exit', self) exitAct.setShortcut('Ctrl+Q') exitAct.setStatusTip('Exit application') exitAct.triggered.connect(qApp.quit) #Add toolbar actions self.toolbar.addAction(self.open_GT3_action) self.toolbar.addAction(self.save_fig_action) menu = self.menuBar() menu.setNativeMenuBar(False) file_menu = menu.addMenu(u"&File") file_menu.addAction(self.open_GT3_action) file_menu.addAction(exitAct) edit_menu = menu.addMenu(u"&Edit") edit_menu.addAction(self.set_preferences_action) shot_menu = menu.addMenu(u"&Shot Data") shot_menu.addAction(self.open_velocity_graphs_action) shot_menu.addAction(self.open_temperature_graphs_action) shot_menu.addAction(self.open_scale_length_graphs_action) shot_menu.addAction(self.open_flux_graphs_action) shot_menu.addAction(self.open_electric_field_action) shot_menu.addAction(self.open_density_graph_action) shot_menu.addAction(self.open_collisionality_action) def open_velocity_graphs(self): velocities = [ GraphContainer(self.chi_i.rho, [ self.chi_i.shot.rtrans.vpol_D.val, self.chi_i.shot.rtrans.vpol_C.val ], title="Poloidal Velocity", legend=[r"$V^D_{\theta}$", r"$V^C_{\theta}$"]), GraphContainer(self.chi_i.rho, [ self.chi_i.shot.rtrans.vtor_C_total.val, self.chi_i.shot.rtrans.vtor_D_total.val ], title="Toroidal Velocity", legend=[r"$V^D_{\phi}$", r"$V^C_{\phi}$"]) ] velocity_graph = GraphPopout(velocities, grid=len(velocities), title="Shot Velocities") velocity_graph.show() def open_density_graphs(self): densities = [ GraphContainer(self.chi_i.rho, [ self.chi_i.shot.rtrans._n.D.val / (1E20), self.chi_i.shot.rtrans._n.e.val / (1E20) ], title="Densities", legend=[r"$n_D$", r"$n_e$"]) ] density_graph = GraphPopout(densities, grid=len(densities), title="Density (x10^20 m^-3)") density_graph.show() def open_temperature_graphs(self): temperatures = [ GraphContainer(self.chi_i.rho, [ self.chi_i.shot.core.T.i.ev.fsa.val, self.chi_i.shot.core.T.e.ev.fsa.val ], title="Temperatures", legend=[r"$T_i$", r"$T_e$"]) ] temperature_graph = GraphPopout(temperatures, grid=len(temperatures), title="Shot Temperatures") temperature_graph.show() def open_scale_length_graphs(self): scale_lengths = [ GraphContainer( self.chi_i.rho, [self.chi_i.T.i.J.L.fsa.val, self.chi_i.T.e.J.L.fsa.val], title="Scale Lengths", legend=[r"$L_{T_i}$", r"$L_{T_e}$"]), GraphContainer( self.chi_i.rho, [self.chi_i.n.i.L.fsa.val, self.chi_i.n.e.L.fsa.val], title="Scale Lengths", legend=[r"$L_{n_i}$", r"$L_{n_e}$"]) ] scale_length_graph = GraphPopout(scale_lengths, grid=len(scale_lengths), title="Gradient Scale Lengths") scale_length_graph.show() def open_flux_graphs(self): fluxes = [ GraphContainer(self.chi_i.rho, [self.chi_i.shot.rtrans.gamma.D.diff.val / (1E20)], title="Ion Particle Flux", legend=[r"$\Gamma_{j,r}[10E20]$"]), GraphContainer(self.chi_i.rho, [self.chi_i.shot.rtrans.Q.D.diff.val], title="Heat Flux", legend=[r"$Q_{r,j}$"]) ] flux_graphs = GraphPopout(fluxes, grid=len(fluxes), title="Particle/Heat fluxes") flux_graphs.show() def open_electric_field_graphs(self): field = [ GraphContainer(self.chi_i.rho, [self.chi_i.shot.core.E_r.fsa], title="Electric Field", legend=[r"$E_r$"]) ] field_graphs = GraphPopout(field, grid=len(field), title="Electric Field") field_graphs.show() def open_collisionality_graphs(self): field = [ GraphContainer(self.chi_i.rho, [self.chi_i.shot.rtrans.nustar], title="Collisionality", legend=[r"$\nu^*$"]) ] field_graphs = GraphPopout(field, grid=len(field), title="Collisionality") field_graphs.show() def saveFigureDialog(self): #f = QFileDialog.getOpenFileName(self, str("Save Figure"), os.getcwd(), str("Image Files (*)")) f = QFileDialog.getSaveFileName(self, str("Save Figure"), os.getcwd(), str("PNG (.png)")) self.mainGraph._saveFig(f[0]) def set_preferences(self, triggered): settings = self.settings preferences_dialog = PreferencesDialog() preferences_dialog.setupUi(self) if preferences_dialog.exec_(): print("YAY") else: print("F**K")