class Integration(Page): """ The integration page. """ NAME = 'OS Integration' def __init__(self, parent=None): super().__init__(parent) self._url_scheme_chk = None # type:QCheckBox self._url_scheme_text = None # type:QLineEdit self._init_widgets() self._load_config() def _init_widgets(self): # os integration os_integration = QGroupBox("OS integration") self._url_scheme_chk = QCheckBox("Register angr URL scheme (angr://).") self._url_scheme_text = QLineEdit() self._url_scheme_text.setReadOnly(True) url_scheme_lbl = QLabel("Currently registered to:") os_layout = QVBoxLayout() os_layout.addWidget(self._url_scheme_chk) os_layout.addWidget(url_scheme_lbl) os_layout.addWidget(self._url_scheme_text) os_integration.setLayout(os_layout) layout = QVBoxLayout() layout.addWidget(os_integration) layout.addStretch() self.setLayout(layout) def _load_config(self): scheme = AngrUrlScheme() try: registered, register_as = scheme.is_url_scheme_registered() self._url_scheme_chk.setChecked(registered) self._url_scheme_text.setText(register_as) except NotImplementedError: # the current OS is not supported self._url_scheme_chk.setDisabled(True) def save_config(self): scheme = AngrUrlScheme() try: registered, _ = scheme.is_url_scheme_registered() if registered != self._url_scheme_chk.isChecked(): # we need to do something if self._url_scheme_chk.isChecked(): scheme.register_url_scheme() else: scheme.unregister_url_scheme() except NotImplementedError: # the current OS is not supported pass
def _layout(self): layout = QFormLayout(self) self.setLayout(layout) layout.addRow( None, QLabel("RuneKit needs to be restarted for changes to take effect", self), ) tooltip_label = QLabel("Display tooltips as", self) tooltip_field = QComboBox(self) selected = int( self.settings.value("settings/tooltip", AutoNotifier.METHOD_NOTIFICATION)) selected_idx = 0 for idx, method in enumerate(AutoNotifier.availableMethods().items()): tooltip_field.insertItem(idx, method[1]) if method[0] == selected: selected_idx = idx tooltip_field.setCurrentIndex(selected_idx) tooltip_field.currentIndexChanged.connect(self.preview_tooltip) tooltip_field.currentIndexChanged.connect(self.on_tooltip_change) layout.addRow(tooltip_label, tooltip_field) border_field = QCheckBox("Styled window border", self) border_field.setDisabled(sys.platform == "darwin") border_field.setChecked( (self.settings.value("settings/styledBorder", "true") == "true") and sys.platform != "darwin") border_field.stateChanged.connect(self.on_change_styled_border) layout.addRow(None, border_field)
def _layout(self): layout = QFormLayout(self) self.setLayout(layout) tooltip_label = QLabel("Display tooltips as", self) tooltip_field = QComboBox(self) tooltip_field.insertItem(0, "Disabled") tooltip_field.insertItem(1, "Notification") # XXX: Check support tooltip_field.insertItem(2, "Cursor tooltip") tooltip_field.currentIndexChanged.connect(self.preview_tooltip) layout.addRow(tooltip_label, tooltip_field) border_field = QCheckBox("Styled window border", self) border_field.setDisabled(sys.platform == "darwin") border_field.setChecked(sys.platform != "darwin") layout.addRow(None, border_field) # I think this doesn't belong to "Interface" # either rename it to settings or make separate game tab capturei_label = QLabel("Capture interval", self) capturei_layout = QHBoxLayout() capturei_field = QSpinBox(self) capturei_field.setRange(100, 2000) capturei_field.setSingleStep(100) capturei_field.setValue(100) capturei_layout.addWidget(capturei_field, 1) capturei_unit = QLabel("ms", self) capturei_layout.addWidget(capturei_unit, 0) layout.addRow(capturei_label, capturei_layout)
class TrainingPanel(Panel): def __init__(self, datasets, testing_panel, threads): super().__init__() if isinstance(testing_panel, TestingPanel): self.testing_panel = testing_panel else: raise TypeError('"testing_panel" must be the instance of ' '"TestingPanel"') self.datasets = datasets self.threads = threads self.__set_execution_ui() self.__set_options_ui() self.__set_outputs_ui() self.__set_graphic_ui() def __set_execution_ui(self): group_box = QGroupBox('Training Execution') inner_layout = QHBoxLayout() group_box.setLayout(inner_layout) self.data_selector = QComboBox() self.data_selector.addItems(list(self.datasets.keys())) self.data_selector.setStatusTip('Select the training dataset.') self.start_btn = QPushButton('Train') self.start_btn.setStatusTip('Start training.') self.start_btn.clicked.connect(self.__run) self.stop_btn = QPushButton('Stop') self.stop_btn.setStatusTip('Force the training stop running.') self.stop_btn.setDisabled(True) self.multicore_cb = QCheckBox('Multicore') self.multicore_cb.setStatusTip('Use multiprocessing in calculating ' 'fitting for populations.') self.multicore_cb.setChecked(True) inner_layout.addWidget(self.data_selector, 1) inner_layout.addWidget(self.start_btn) inner_layout.addWidget(self.stop_btn) inner_layout.addWidget(self.multicore_cb) self._layout.addWidget(group_box) def __set_options_ui(self): group_box = QGroupBox('Training Options') inner_layout = QFormLayout() group_box.setLayout(inner_layout) self.iter_times = QSpinBox() self.iter_times.setRange(1, 1000000) self.iter_times.setValue(200) self.iter_times.setStatusTip('The total iterating times for training.') self.population_size = QSpinBox() self.population_size.setRange(1, 100000) self.population_size.setValue(100) self.population_size.setStatusTip('The population size for the PSO.') self.inertia_weight = QDoubleSpinBox() self.inertia_weight.setRange(0, 50) self.inertia_weight.setValue(1) self.inertia_weight.setSingleStep(0.1) self.inertia_weight.setStatusTip('The inertia weight of the velocity ' ' for each individual.') self.cognitive_const_rand_upper = QDoubleSpinBox() self.cognitive_const_rand_upper.setRange(0, 50) self.cognitive_const_rand_upper.setValue(2) self.cognitive_const_rand_upper.setSingleStep(0.1) self.cognitive_const_rand_upper.setStatusTip( 'The random upper bound for cognitive accelerate constant.') self.social_const_rand_upper = QDoubleSpinBox() self.social_const_rand_upper.setRange(0, 50) self.social_const_rand_upper.setValue(3) self.social_const_rand_upper.setSingleStep(0.1) self.social_const_rand_upper.setStatusTip( 'The random upper bound for social accelerate constant.') self.v_max = QDoubleSpinBox() self.v_max.setRange(0.5, 100) self.v_max.setValue(5) self.v_max.setSingleStep(1) self.v_max.setStatusTip('The maximum of velocity for each individual.') self.nneuron = QSpinBox() self.nneuron.setRange(1, 100) self.nneuron.setValue(6) self.nneuron.setStatusTip('The number of RBFN neuron.') self.sd_max = QDoubleSpinBox() self.sd_max.setRange(0.01, 20) self.sd_max.setValue(10) self.sd_max.setSingleStep(0.1) self.sd_max.setStatusTip('The random range maximum of standard ' 'deviation of each neuron in RBFN (only for ' 'initialization).') inner_layout.addRow('Iterating Times:', self.iter_times) inner_layout.addRow('Population Size:', self.population_size) inner_layout.addRow('Inertia Weight:', self.inertia_weight) inner_layout.addRow('Cognitive Const Upper:', self.cognitive_const_rand_upper) inner_layout.addRow('Social Const Upper:', self.social_const_rand_upper) inner_layout.addRow('Maximum of Velocity:', self.v_max) inner_layout.addRow('Number of Neuron:', self.nneuron) inner_layout.addRow('Maximum of SD:', self.sd_max) self._layout.addWidget(group_box) def __set_outputs_ui(self): group_box = QGroupBox('Training Details') inner_layout = QFormLayout() group_box.setLayout(inner_layout) self.current_iter_time = QLabel('--') self.current_error = QLabel('--') self.avg_error = QLabel('--') self.global_best_error = QLabel('--') self.total_best_error = QLabel('--') self.progressbar = QProgressBar() self.current_iter_time.setAlignment(Qt.AlignCenter) self.current_error.setAlignment(Qt.AlignCenter) self.avg_error.setAlignment(Qt.AlignCenter) self.global_best_error.setAlignment(Qt.AlignCenter) self.total_best_error.setAlignment(Qt.AlignCenter) self.current_iter_time.setStatusTip('The current iterating time of ' 'the PSO.') self.current_error.setStatusTip('The current error from the fitting ' 'function. ("( )": normalized error)') self.avg_error.setStatusTip('The average error from the fitting ' 'function in current iteration. ("( )": ' 'normalized error)') self.global_best_error.setStatusTip( 'The error of global best individual from the fitting function in ' 'current iteration. ("( )": normalized error)') self.total_best_error.setStatusTip( 'The error of total best individual from the fitting function in ' 'training. ("( )": normalized error)') inner_layout.addRow('Current Iterating Time:', self.current_iter_time) inner_layout.addRow('Current Error:', self.current_error) inner_layout.addRow('Average Error:', self.avg_error) inner_layout.addRow('Global Best Error:', self.global_best_error) inner_layout.addRow('Total Best Error:', self.total_best_error) inner_layout.addRow(self.progressbar) self._layout.addWidget(group_box) def __set_graphic_ui(self): group_box = QGroupBox('Error Line Charts:') inner_layout = QVBoxLayout() group_box.setLayout(inner_layout) self.err_chart = ErrorLineChart(1) self.err_chart.setStatusTip('The history of error from the fitting ' 'of the PSO for each data.') self.__err_x = 1 self.iter_err_chart = ErrorLineChart( 3, ('Avg', 'Global Best', 'Total Best')) self.iter_err_chart.setStatusTip('The history of average and least ' 'error from the fitting of the PSO ' 'for each iteration.') self.iter_err_chart.setMinimumHeight(150) inner_layout.addWidget(QLabel('Current Error')) inner_layout.addWidget(self.err_chart) inner_layout.addWidget(QLabel('Average Error')) inner_layout.addWidget(self.iter_err_chart) self._layout.addWidget(group_box) @Slot() def __init_widgets(self): self.start_btn.setDisabled(True) self.stop_btn.setEnabled(True) self.multicore_cb.setDisabled(True) self.data_selector.setDisabled(True) self.iter_times.setDisabled(True) self.population_size.setDisabled(True) self.inertia_weight.setDisabled(True) self.cognitive_const_rand_upper.setDisabled(True) self.social_const_rand_upper.setDisabled(True) self.v_max.setDisabled(True) self.nneuron.setDisabled(True) self.sd_max.setDisabled(True) self.err_chart.clear() self.iter_err_chart.clear() self.__err_x = 1 @Slot() def __reset_widgets(self): self.start_btn.setEnabled(True) self.stop_btn.setDisabled(True) self.multicore_cb.setEnabled(True) self.data_selector.setEnabled(True) self.iter_times.setEnabled(True) self.population_size.setEnabled(True) self.inertia_weight.setEnabled(True) self.cognitive_const_rand_upper.setEnabled(True) self.social_const_rand_upper.setEnabled(True) self.v_max.setEnabled(True) self.nneuron.setEnabled(True) self.sd_max.setEnabled(True) self.progressbar.setMinimum(0) self.progressbar.setMaximum(100) @Slot() def __indicate_busy(self): self.progressbar.setMinimum(0) self.progressbar.setMaximum(0) @Slot(int) def __show_current_iter_time(self, value): self.current_iter_time.setText(str(value + 1)) self.progressbar.setValue(value + 1) @Slot(float) def __show_current_error(self, value): self.current_error.setText('{:.5f} ({:.5f})'.format(value, value / 40)) self.err_chart.append_point(self.__err_x, value) self.__err_x += 1 @Slot(float, float, float) def __show_iter_error(self, avg, glob, total): self.avg_error.setText('{:.5f} ({:.5f})'.format(avg, avg / 40)) self.global_best_error.setText( '{:.5f} ({:.5f})'.format(glob, glob / 40)) self.total_best_error.setText( '{:.5f} ({:.5f})'.format(total, total / 40)) self.iter_err_chart.append_point( int(self.current_iter_time.text()), total, 2) self.iter_err_chart.append_point( int(self.current_iter_time.text()), glob, 1) self.iter_err_chart.append_point( int(self.current_iter_time.text()), avg, 0) def __run(self): self.progressbar.setMaximum(self.iter_times.value()) self.__current_dataset = self.datasets[ self.data_selector.currentText()] self.__pso = PSO(self.iter_times.value(), self.population_size.value(), self.inertia_weight.value(), self.cognitive_const_rand_upper.value(), self.social_const_rand_upper.value(), self.v_max.value(), self.nneuron.value(), self.__current_dataset, self.sd_max.value(), is_multicore=self.multicore_cb.isChecked()) self.threads.append(self.__pso) self.stop_btn.clicked.connect(self.__pso.stop) self.__pso.started.connect(self.__init_widgets) self.__pso.finished.connect(self.__reset_widgets) self.__pso.sig_current_iter_time.connect(self.__show_current_iter_time) self.__pso.sig_current_error.connect(self.__show_current_error) self.__pso.sig_iter_error.connect(self.__show_iter_error) self.__pso.sig_indicate_busy.connect(self.__indicate_busy) self.__pso.sig_console.connect(self.testing_panel.print_console) self.__pso.sig_rbfn.connect(self.testing_panel.load_rbfn) self.__pso.start()
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.users = None self.camera = None self.playing = False self.frames = None self.capturing = False self.capture_frame = None self.flag_recognize = False self.model = None # key:user_id, value:((x,y,w,h),name,color,welcome_msg) self.recognized_faces = {} self.lbl_viewer = None self.btn_open_camera = None self.btn_close_camera = None self.btn_open_video = None self.btn_close_video = None self.cb_recognize = None self.btn_sync_face = None self.btn_capture = None self.lbl_capture_pic = None self.btn_capture_save = None self.init_ui() self.train_model() if os.path.exists('faces{}tmp'.format(os.sep)): shutil.rmtree('faces{}tmp'.format(os.sep)) def init_ui(self): self.setFixedSize(Config.width, Config.height) qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) self.setWindowIcon(QIcon('icons/icon.png')) self.setWindowTitle('客户端') menu_bar = self.menuBar() menu_bar.setNativeMenuBar(False) manage_menu = menu_bar.addMenu("信息管理") client_login_action = manage_menu.addAction("服务器连接") client_login_action.triggered.connect(self.manage_client_login) user_action = manage_menu.addAction("用户管理") user_action.triggered.connect(self.manage_user) setting_menu = menu_bar.addMenu("设置") server_action = setting_menu.addAction("服务器") server_action.triggered.connect(self.setting_server) dimension_action = setting_menu.addAction("窗口尺寸") dimension_action.triggered.connect(self.setting_dimension) help_menu = menu_bar.addMenu("帮助") client_register_action = help_menu.addAction("客户端注册") client_register_action.triggered.connect(self.help_client_register) status_bar = self.statusBar() status_bar.showMessage("欢迎使用客户端") self.lbl_viewer = QLabel(self) self.lbl_viewer.setGeometry(QRect(10, 26, Config.width - 130, Config.height - 60)) self.lbl_viewer.setText('没有图像') font = QFont() font.setPointSize(20) self.lbl_viewer.setFont(font) self.lbl_viewer.setAlignment(Qt.AlignCenter) self.lbl_viewer.setFrameShape(QFrame.StyledPanel) self.btn_open_camera = QPushButton(self) self.btn_open_camera.setGeometry(QRect(Config.width - 110, 10, 100, 26)) self.btn_open_camera.setText('打开摄像头') self.btn_open_camera.clicked.connect(self.btn_click) self.btn_close_camera = QPushButton(self) self.btn_close_camera.setGeometry(QRect(Config.width - 110, 46, 100, 26)) self.btn_close_camera.setText('关闭摄像头') self.btn_close_camera.setDisabled(True) self.btn_close_camera.clicked.connect(self.btn_click) self.btn_open_video = QPushButton(self) self.btn_open_video.setGeometry(QRect(Config.width - 110, 82, 100, 26)) self.btn_open_video.setText('播放视频') self.btn_open_video.clicked.connect(self.btn_click) self.btn_close_video = QPushButton(self) self.btn_close_video.setGeometry(QRect(Config.width - 110, 118, 100, 26)) self.btn_close_video.setText('停止播放') self.btn_close_video.setDisabled(True) self.btn_close_video.clicked.connect(self.btn_click) self.cb_recognize = QCheckBox(self) self.cb_recognize.setText('启动识别') self.cb_recognize.setDisabled(True) self.cb_recognize.setGeometry(QRect(Config.width - 108, 154, 100, 26)) self.cb_recognize.clicked.connect(self.cb_click) self.btn_sync_face = QPushButton(self) self.btn_sync_face.setGeometry(QRect(Config.width - 110, 190, 100, 26)) self.btn_sync_face.setText("同步数据") self.btn_sync_face.clicked.connect(self.btn_click) self.btn_capture = QPushButton(self) self.btn_capture.setGeometry(QRect(Config.width - 110, Config.height - 200, 100, 26)) self.btn_capture.setText('截屏') self.btn_capture.setDisabled(True) self.btn_capture.clicked.connect(self.btn_click) self.lbl_capture_pic = QLabel(self) self.lbl_capture_pic.setGeometry(QRect(Config.width - 110, Config.height - 160, 100, 100)) self.lbl_capture_pic.setAlignment(Qt.AlignCenter) self.lbl_capture_pic.setFrameShape(QFrame.StyledPanel) self.btn_capture_save = QPushButton(self) self.btn_capture_save.setGeometry(QRect(Config.width - 110, Config.height - 60, 100, 26)) self.btn_capture_save.setText('保存截图') self.btn_capture_save.setDisabled(True) self.btn_capture_save.clicked.connect(self.btn_click) def btn_click(self): btn = self.sender() if btn == self.btn_open_camera: self.btn_open_camera.setDisabled(True) self.btn_close_camera.setDisabled(False) self.btn_capture.setDisabled(False) self.cb_recognize.setDisabled(False) self.camera = cv2.VideoCapture(0) self.frames = collections.deque(maxlen=33) self.start_play() elif btn == self.btn_close_camera: self.stop_play() self.btn_open_camera.setDisabled(False) self.btn_close_camera.setDisabled(True) self.btn_capture.setDisabled(True) self.cb_recognize.setDisabled(True) elif btn == self.btn_sync_face: self.btn_sync_face.setDisabled(True) self.sync_data() elif btn == self.btn_capture: self.capturing = True self.btn_capture_save.setDisabled(False) elif btn == self.btn_capture_save: AddUserFace(self.capture_frame).exec_() self.train_model() def cb_click(self): cb = self.sender() if cb == self.cb_recognize: if cb.isChecked(): self.flag_recognize = True else: self.flag_recognize = False def start_play(self): self.playing = True play_thread = Thread(target=self.play) play_thread.start() recognize_thread = Thread(target=self.recognize) recognize_thread.start() def stop_play(self): self.playing = False def play(self): while self.camera.isOpened(): try: if not self.playing: break ret, frame = self.camera.read() if ret: if self.flag_recognize: self.frames.appendleft(frame.copy()) faces = self.recognized_faces.copy() for user_id in faces: face = faces[user_id] x, y, w, h = face[0] cv2.rectangle(frame, (x, y), (x + w, y + h), tuple(list(map(int, face[2].split(',')))), 1, cv2.LINE_AA) if Config.show_name: cv2.putText(frame, face[1], (x, y - 15), cv2.FONT_HERSHEY_SIMPLEX, 2, tuple(list(map(int, face[2].split(',')))), 2) if Config.show_match_result: cv2.putText(frame, 'Match degree:' + str(face[3]), (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 2, tuple(list(map(int, face[2].split(',')))), 2) img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) image = QImage(img, img.shape[1], img.shape[0], img.shape[1] * 3, QImage.Format_RGB888) pix_map = QPixmap.fromImage(image) pix_map = pix_map.scaled(Config.width - 130, Config.height - 60, Qt.KeepAspectRatio) self.lbl_viewer.setPixmap(pix_map) # 保存截图 if self.capturing: self.capture_frame = frame.copy() pix_map = pix_map.scaled(100, 100, Qt.KeepAspectRatio) self.lbl_capture_pic.setPixmap(pix_map) self.capturing = False except Exception as e: print(e) self.lbl_viewer.clear() self.camera.release() def recognize(self): classifier = HaarcascadeDetective().get_face_classifier() while self.playing: try: if len(self.frames) == 0: time.sleep(0.05) continue if self.flag_recognize: frame = self.frames.pop() faces = classifier.get_faces_position(frame) self.recognized_faces.clear() for (x, y, w, h) in faces: face = frame[y:y + h, x:x + w] if self.model is not None: gray = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY) params = self.model.predict(gray) user = self.find_user_by_id(params[0]) if user is not None: self.recognized_faces[user[1]] = ((x, y, w, h), user[2], user[3], int(params[1])) else: self.recognized_faces['-1'] = ((x, y, w, h), 'No this user', '255,0,0', 0) else: self.recognized_faces['-2'] = ((x, y, w, h), 'No model', '255,0,0', 0) except Exception as e: print(e) def sync_data(self): client = DbHelper.query_client() if client is None: Tool.show_msg_box('客户端尚未认证!') self.btn_sync_face.setDisabled(False) return shutil.rmtree('faces') os.mkdir('faces') DbHelper.delete_users() users = Tool.user_face_list(client[0]) if users is not None: for user in users: user_id = DbHelper.insert_user(user['rowId'], user['name'], user['color'], user['clientId']) faces = user['faces'] for face in faces: Tool.download_face(face['rowId'], str(user_id)) self.btn_sync_face.setDisabled(False) # 重新训练模型 self.train_model() def train_model(self): self.users = DbHelper.query_users() y, x = [], [] faces_dir = os.listdir('faces') for user_dir in faces_dir: if user_dir == 'tmp': continue faces = os.listdir('faces{}{}'.format(os.sep, user_dir)) for face in faces: y.append(int(user_dir)) im = cv2.imread('faces{}{}{}{}'.format(os.sep, user_dir, os.sep, face), 0) x.append(np.asarray(im, dtype=np.uint8)) if len(x) != 0 and len(y) != 0: self.model = cv2.face.LBPHFaceRecognizer_create() self.model.train(np.asarray(x), np.asarray(y, dtype=np.int64)) def find_user_by_id(self, user_id): for user in self.users: if user[0] == user_id: return user def closeEvent(self, *args, **kwargs): self.playing = False if os.path.exists('faces{}tmp'.format(os.sep)): shutil.rmtree('faces{}tmp'.format(os.sep)) @staticmethod def manage_client_login(): ClientLogin().exec_() @staticmethod def manage_user(): AddUser().exec_() @staticmethod def setting_server(): ServerSetting().exec_() @staticmethod def setting_dimension(): DimensionSetting().exec_() @staticmethod def help_client_register(): ClientRegister().exec_()
class MyWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle( 'Graphical utility for destroying, zeroing, and deleting files') self.label_donate = QLabel( 'Copyright (c) 2021, Aleksandr Suvorov | Donate: 4048 0250 0089 5923' ) self.label_donate.setAlignment(Qt.AlignCenter) self.label_logo = QLabel(f'Smart Cleaner<sup> {VERSION}</sup>') self.label_logo.setAlignment(Qt.AlignCenter) self.label_logo.setStyleSheet('font-size: 48px;') self.label_files = QLabel('Files') self.label_files.setStyleSheet("color: rgb(84, 180, 40);") self.label_dirs = QLabel('Folders') self.label_dirs.setStyleSheet("color: rgb(177, 98, 42);") self.label_errors = QLabel('Errors') self.label_errors.setStyleSheet("color: rgb(255, 68, 44);") self.lcd_files = QLCDNumber() self.lcd_files.setSegmentStyle(QLCDNumber.Flat) self.lcd_files.setStyleSheet("color: rgb(84, 180, 40);") self.lcd_dirs = QLCDNumber() self.lcd_dirs.setSegmentStyle(QLCDNumber.Flat) self.lcd_dirs.setStyleSheet("color: rgb(177, 98, 42);") self.lcd_errors = QLCDNumber() self.lcd_errors.setSegmentStyle(QLCDNumber.Flat) self.lcd_errors.setMinimumHeight(30) self.lcd_errors.setStyleSheet("color: rgb(255, 68, 44);") self.lcd_files.setDigitCount(15) self.lcd_dirs.setDigitCount(15) self.lcd_errors.setDigitCount(15) self.h_box1 = QHBoxLayout() self.h_box1.addWidget(self.label_dirs) self.h_box1.addWidget(self.label_files) self.h_box1.addWidget(self.label_errors) self.h_box2 = QHBoxLayout() self.h_box2.addWidget(self.lcd_dirs) self.h_box2.addWidget(self.lcd_files) self.h_box2.addWidget(self.lcd_errors) self.label_cons = QLabel('Information console:') self.text_browser = QTextBrowser() self.text_browser.setText( f'Smart Cleaner v{VERSION} \nUtility for overwriting, zeroing, and deleting files\n' f'https://github.com/mysmarthub') self.btn_console_clear = QPushButton('Reset') self.btn_donate = QPushButton('Donate | Visa: 4048 0250 0089 5923') self.btn_donate.setToolTip( 'We will be grateful for any financial support.\nThis will help the program ' 'develop and remain free.\nThanks!') self.btn_exit = QPushButton('Exit') self.h_box3 = QHBoxLayout() self.h_box3.addWidget(self.btn_donate) self.h_box3.addStretch(1) self.h_box3.addWidget(self.btn_console_clear) self.chb_del_dirs = QCheckBox('Delete folders') self.chb_del_dirs.setChecked(True) self.label_shred = QLabel('Rewrite:') self.spin_box = QSpinBox() self.spin_box.setMinimum(1) self.spin_box.setMaximum(1000) self.spin_box.setValue(30) self.h_box4 = QHBoxLayout() self.h_box4.addWidget(self.chb_del_dirs) self.h_box4.addWidget(self.label_shred) self.h_box4.addWidget(self.spin_box) self.h_box4.addStretch(1) self.list_widget = QListWidget() self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.btn_add_folder = QPushButton('+ Folder') self.btn_add_files = QPushButton('+ Files') self.btn_remove_item = QPushButton('- Remove') self.btn_zero_files = QPushButton('Zeroing') self.btn_shred_files = QPushButton('Erasing') self.btn_del_files = QPushButton('Delete') self.h_box5 = QHBoxLayout() self.h_box5.addWidget(self.btn_add_folder) self.h_box5.addWidget(self.btn_add_files) self.h_box5.addWidget(self.btn_remove_item) self.h_box5.addStretch(1) self.h_box5.addWidget(self.btn_shred_files) self.h_box5.addWidget(self.btn_zero_files) self.h_box5.addWidget(self.btn_del_files) self.h_box5.addWidget(self.btn_exit) self.v_box = QVBoxLayout() self.v_box.addWidget(self.label_logo) self.v_box.addLayout(self.h_box1) self.v_box.addLayout(self.h_box2) self.v_box.addWidget(self.label_cons) self.v_box.addWidget(self.text_browser) self.v_box.addLayout(self.h_box3) self.v_box.addLayout(self.h_box4) self.v_box.addWidget(self.list_widget) self.v_box.addLayout(self.h_box5) self.v_box.addWidget(self.label_donate) self.setLayout(self.v_box) self.smart_cleaner = SmartCleaner() self.btn_donate.clicked.connect( lambda: webbrowser.open('https://yoomoney.ru/to/4100115206129186')) self.btn_console_clear.clicked.connect(self.clear_console) self.btn_add_folder.clicked.connect(self.add_dir) self.btn_add_files.clicked.connect(self.add_files) self.btn_remove_item.clicked.connect(self.remove_items) self.btn_shred_files.clicked.connect(self.shred_start) self.btn_zero_files.clicked.connect(self.zeroing_start) self.btn_del_files.clicked.connect(self.delete_start) self.btn_exit.clicked.connect(self.close) self.smart_cleaner.signal.connect(self.update_information) self.smart_cleaner.started.connect(self.at_start) self.smart_cleaner.finished.connect(self.at_finish) def clear_console(self): self.lcd_dirs.display(0) self.lcd_files.display(0) self.lcd_errors.display(0) self.text_browser.setText( f'Smart Cleaner v{VERSION} \nUtility for overwriting, zeroing, and deleting files\n' f'https://github.com/mysmarthub') def add_dir(self) -> None: path = QFileDialog.getExistingDirectory(self, 'Select the folder to add: ') self._add_path(path) def add_files(self) -> None: path_tuple = QFileDialog.getOpenFileNames(self, 'Select files to add: ') for path in path_tuple[0]: self._add_path(path) def add_item(self, item: str) -> None: self.list_widget.addItem(item) def remove_items(self) -> None: for SelectedItem in self.list_widget.selectedItems(): self.list_widget.takeItem(self.list_widget.row(SelectedItem)) self.smart_cleaner.path_data.del_path(SelectedItem.text()) self.text_browser.append( f'{SelectedItem.text()}\nThe path was successfully deleted!!!') def _add_path(self, path: str) -> None: if path: if self.smart_cleaner.path_data.add_path(path): self.add_item(path) self.text_browser.append( f'{path}\nThe path was added successfully!') else: self.text_browser.append( f'Error when adding or the path was added earlier!!!') def shred_start(self): self.start(method='shred') def zeroing_start(self): self.start(method='zero') def delete_start(self): self.start(method='del') def start(self, method='shred'): if not self.smart_cleaner.path_data.is_any_data: self.show_msg('Warning!', 'There is no data for mashing!!!') else: reply = QMessageBox.question( self, 'Warning!', 'The data will be destroyed, are you sure?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: if method == 'zero': self.text_browser.append('Files are reset to zero.') elif method == 'shred': self.text_browser.append('File mashing is started.') elif method == 'del': self.text_browser.append('File deletion started.') self.smart_cleaner.work_method = method self.smart_cleaner.shreds = self.spin_box.value() self.smart_cleaner.delete_a_folder = self.chb_del_dirs.isChecked( ) self.smart_cleaner.start() def update_information(self, s: str) -> None: self.text_browser.append(s) self.update_lcd() def update_lcd(self) -> None: self.lcd_dirs.display(str(self.smart_cleaner.cleaner.count_del_dirs)) self.lcd_files.display(str(self.smart_cleaner.cleaner.count_del_files)) self.lcd_errors.display(str(self.smart_cleaner.num_errors)) def at_start(self): self.from_disable(True) def at_finish(self) -> None: if self.smart_cleaner.work_method != 'zero': self.list_widget.clear() self.update_lcd() self.from_disable(False) self.finish_msg() def finish_msg(self) -> None: if self.smart_cleaner.work_method == 'zero': msg = ('Reset', 'Reset files: ') count = self.smart_cleaner.cleaner.count_zero_files elif self.smart_cleaner.work_method == 'shred': msg = ('Mashing', 'Passageways: ') count = self.smart_cleaner.cleaner.count_del_files else: msg = ('Delete', 'Deleted files: ') count = self.smart_cleaner.cleaner.count_del_files self.show_msg( 'Warning!', f'{msg[0]} completed successfully!!!\n' f' {msg[1]} {count}\n ' f'Deleted folders: {self.smart_cleaner.cleaner.count_del_dirs}\n ' f'Errors: {self.smart_cleaner.num_errors}') def from_disable(self, status: bool) -> None: self.btn_zero_files.setDisabled(status) self.btn_remove_item.setDisabled(status) self.btn_add_folder.setDisabled(status) self.btn_shred_files.setDisabled(status) self.btn_console_clear.setDisabled(status) self.btn_add_files.setDisabled(status) self.btn_del_files.setDisabled(status) self.chb_del_dirs.setDisabled(status) self.spin_box.setDisabled(status) self.list_widget.setDisabled(status) def show_msg(self, title: str = 'Warning!', msg: str = 'Message...') -> None: QMessageBox.about(self, title, msg) def closeEvent(self, event) -> None: reply = QMessageBox.question( self, 'Exit', 'Are you sure you want to terminate the program?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.hide() self.smart_cleaner.wait(3000) event.accept() else: event.ignore()
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.users = {} self.fps = 30 self.playing = False self.capturing = False self.capture_frame = None self.flag_recognize = False self.recognizing_frame = None self.recognized_faces = [] self.model = None self.setFixedSize(Config.width, Config.height) qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) self.setWindowIcon(QIcon('icons/icon.png')) self.setWindowTitle('人工智障人脸识别客户端') self.lbl_viewer = QLabel(self) self.lbl_viewer.setGeometry( QRect(10, 26, Config.width - 130, Config.height - 60)) self.lbl_viewer.setText('没有图像') font = QFont() font.setPointSize(20) self.lbl_viewer.setFont(font) self.lbl_viewer.setAlignment(Qt.AlignCenter) self.lbl_viewer.setFrameShape(QFrame.StyledPanel) self.btn_open_camera = QPushButton(self) self.btn_open_camera.setGeometry(QRect(Config.width - 110, 10, 100, 26)) self.btn_open_camera.setText('打开摄像头') self.btn_open_camera.clicked.connect(self.btn_click) self.btn_close_camera = QPushButton(self) self.btn_close_camera.setGeometry( QRect(Config.width - 110, 46, 100, 26)) self.btn_close_camera.setText('关闭摄像头') self.btn_close_camera.setDisabled(True) self.btn_close_camera.clicked.connect(self.btn_click) self.btn_open_video = QPushButton(self) self.btn_open_video.setGeometry(QRect(Config.width - 110, 82, 100, 26)) self.btn_open_video.setText('播放视频') self.btn_open_video.clicked.connect(self.btn_click) self.btn_close_video = QPushButton(self) self.btn_close_video.setGeometry( QRect(Config.width - 110, 118, 100, 26)) self.btn_close_video.setText('停止播放') self.btn_close_video.setDisabled(True) self.btn_close_video.clicked.connect(self.btn_click) self.cb_recognize = QCheckBox(self) self.cb_recognize.setText('启动识别') self.cb_recognize.setDisabled(True) self.cb_recognize.setGeometry(QRect(Config.width - 108, 154, 100, 26)) self.cb_recognize.clicked.connect(self.change_recognize) self.cb_show_match_result = QCheckBox(self) self.cb_show_match_result.setText('显示匹配度') self.cb_show_match_result.setDisabled(True) self.cb_show_match_result.setGeometry( QRect(Config.width - 108, 192, 100, 26)) if Config.show_match_result: self.cb_show_match_result.setChecked(True) self.cb_show_match_result.clicked.connect( self.change_show_match_result) lbl_threshold = QLabel(self) lbl_threshold.setText("识别精度") lbl_threshold.setGeometry(QRect(Config.width - 108, 228, 60, 26)) self.sb_threshold = QSpinBox(self) self.sb_threshold.setValue(Config.threshold) self.sb_threshold.setMinimum(30) self.sb_threshold.setMaximum(100) self.sb_threshold.valueChanged.connect(self.change_threshold) self.sb_threshold.setGeometry(QRect(Config.width - 45, 228, 40, 26)) self.btn_capture = QPushButton(self) self.btn_capture.setGeometry( QRect(Config.width - 110, Config.height - 200, 100, 26)) self.btn_capture.setText('截屏') self.btn_capture.setDisabled(True) self.btn_capture.clicked.connect(self.btn_click) self.lbl_capture_pic = QLabel(self) self.lbl_capture_pic.setGeometry( QRect(Config.width - 110, Config.height - 160, 100, 100)) self.lbl_capture_pic.setAlignment(Qt.AlignCenter) self.lbl_capture_pic.setFrameShape(QFrame.StyledPanel) self.btn_capture_save = QPushButton(self) self.btn_capture_save.setGeometry( QRect(Config.width - 110, Config.height - 60, 100, 26)) self.btn_capture_save.setText('保存截图') self.btn_capture_save.setDisabled(True) self.btn_capture_save.clicked.connect(self.btn_click) self.train_model() def btn_click(self): btn = self.sender() if btn == self.btn_open_camera: self.btn_open_camera.setDisabled(True) self.btn_close_camera.setDisabled(False) self.btn_capture.setDisabled(False) self.cb_recognize.setDisabled(False) self.start_play(0) elif btn == self.btn_close_camera: self.stop_play() self.lbl_viewer.clear() self.btn_open_camera.setDisabled(False) self.btn_close_camera.setDisabled(True) self.btn_capture.setDisabled(True) self.cb_recognize.setDisabled(True) elif btn == self.btn_open_video: file_name = QFileDialog.getOpenFileName( self, "Open Video", "/", "Video Files (*.avi *.mp4 *.mpeg *.mov)") if file_name[0] != '': self.start_play(file_name[0]) self.btn_close_video.setDisabled(False) elif btn == self.btn_close_video: self.stop_play() self.lbl_viewer.clear() self.btn_open_camera.setDisabled(False) self.btn_close_camera.setDisabled(True) self.btn_capture.setDisabled(True) self.cb_recognize.setDisabled(True) elif btn == self.btn_capture: self.capturing = True self.btn_capture_save.setDisabled(False) elif btn == self.btn_capture_save: AddUserFace(self.capture_frame).exec_() self.train_model() def change_recognize(self): if self.sender().isChecked(): self.flag_recognize = True Thread(target=self.recognize).start() self.cb_show_match_result.setDisabled(False) else: self.flag_recognize = False self.cb_show_match_result.setDisabled(True) def change_show_match_result(self): Config.config_parser.set( "recognition", 'show_match_result', str(True if self.sender().isChecked() else False)) Config.show_match_result = True if self.sender().isChecked() else False Config.save() @staticmethod def change_threshold(value): Config.config_parser.set("recognition", 'threshold', str(value)) Config.threshold = value Config.save() def start_play(self, path): self.playing = True Thread(target=self.play, args=(path, )).start() def stop_play(self): self.lbl_viewer.clear() self.playing = False def play(self, path): video_capture = cv2.VideoCapture(path) fps = video_capture.get(cv2.CAP_PROP_FPS) while self.playing: start_time = time.time() ret, frame = video_capture.read() if ret: if self.flag_recognize: # 存放当前帧给识别线程 if self.recognizing_frame is None: self.recognizing_frame = frame.copy() # 显示已识别的人脸 faces = self.recognized_faces.copy() for face in faces: x, y, w, h = face['position'] cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 1, cv2.LINE_AA) cv2.putText( frame, face['name'] + ('(' + str(face['degree']) + ')' if Config.show_match_result else ''), (x, y - 15), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 0), 2) img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) image = QImage(img, img.shape[1], img.shape[0], img.shape[1] * 3, QImage.Format_RGB888) pix_map = QPixmap.fromImage(image) pix_map = pix_map.scaled(Config.width - 130, Config.height - 60, Qt.KeepAspectRatio) self.lbl_viewer.setPixmap(pix_map) # 保存截图 if self.capturing: self.capture_frame = frame.copy() pix_map = pix_map.scaled(100, 100, Qt.KeepAspectRatio) self.lbl_capture_pic.setPixmap(pix_map) self.capturing = False # 根据FPS控制休眠 end_time = time.time() diff_time = end_time - start_time if diff_time < 1 / fps: time.sleep(1 / fps - diff_time) def recognize(self): while self.flag_recognize: try: if self.recognizing_frame is None: time.sleep(0.05) continue self.recognized_faces.clear() faces = HaarcascadeDetective.get_faces_position( self.recognizing_frame) for (x, y, w, h) in faces: recognized_face = {'position': (x, y, w, h)} face = self.recognizing_frame[y:y + h, x:x + w] if self.model is not None: gray = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY) params = self.model.predict(gray) if params[1] <= Config.threshold: recognized_face['name'] = self.users[params[0]] recognized_face['degree'] = int(params[1]) self.recognized_faces.append(recognized_face) self.recognizing_frame = None except Exception as e: print(e) def train_model(self): users = DbHelper.query_users() for user in users: self.users[user[0]] = user[1] y, x = [], [] if not os.path.exists("faces"): return faces_dir = os.listdir('faces') for user_dir in faces_dir: faces = os.listdir('faces{}{}'.format(os.sep, user_dir)) for face in faces: y.append(int(user_dir)) im = cv2.imread( 'faces{}{}{}{}'.format(os.sep, user_dir, os.sep, face), 0) x.append(np.asarray(im, dtype=np.uint8)) if len(x) != 0 and len(y) != 0: self.model = cv2.face.LBPHFaceRecognizer_create() self.model.train(np.asarray(x), np.asarray(y, dtype=np.int64)) def closeEvent(self, *args, **kwargs): self.playing = False
class TextExchangeDialog(QDialog): def __init__(self): super().__init__(GlobalAccess().get_main_window()) self.setWindowModality(QtCore.Qt.WindowModal) self.resize(319, 462) self.setSizeGripEnabled(False) self.setModal(True) self.layout = QVBoxLayout(self) self.grid_layout = QtWidgets.QGridLayout() widget = QWidget(self) widget.setLayout(self.grid_layout) self.value_group_box = QtWidgets.QGroupBox(self) self.grid_layout_child = QtWidgets.QGridLayout(self.value_group_box) self.id_label = QtWidgets.QLabel(self.value_group_box) self.grid_layout_child.addWidget(self.id_label, 0, 0, 1, 1) self.id_layout = QtWidgets.QVBoxLayout() self.bib_radio_button = QtWidgets.QRadioButton(self.value_group_box) self.bib_radio_button.setChecked(True) self.id_layout.addWidget(self.bib_radio_button) self.name_radio_button = QtWidgets.QRadioButton(self.value_group_box) self.id_layout.addWidget(self.name_radio_button) self.grid_layout_child.addLayout(self.id_layout, 0, 1, 1, 1) self.value_label = QtWidgets.QLabel(self.value_group_box) self.grid_layout_child.addWidget(self.value_label, 1, 0, 1, 1) self.value_combo_box = QtWidgets.QComboBox(self.value_group_box) self.value_combo_box.addItems(get_value_options()) self.grid_layout_child.addWidget(self.value_combo_box, 1, 1, 1, 1) self.id_label.raise_() self.bib_radio_button.raise_() self.value_label.raise_() self.value_combo_box.raise_() self.grid_layout.addWidget(self.value_group_box, 0, 0, 1, 1) self.separator_group_box = QtWidgets.QGroupBox(self) self.separator_grid_layout = QtWidgets.QGridLayout( self.separator_group_box) self.space_radio_button = QtWidgets.QRadioButton( self.separator_group_box) self.separator_grid_layout.addWidget(self.space_radio_button, 0, 0, 1, 1) self.tab_radio_button = QtWidgets.QRadioButton( self.separator_group_box) self.tab_radio_button.setChecked(True) self.separator_grid_layout.addWidget(self.tab_radio_button, 1, 0, 1, 1) self.semicolon_radio_button = QtWidgets.QRadioButton( self.separator_group_box) self.separator_grid_layout.addWidget(self.semicolon_radio_button, 2, 0, 1, 1) self.custom_layout = QtWidgets.QHBoxLayout() self.custom_radio_button = QtWidgets.QRadioButton( self.separator_group_box) self.custom_layout.addWidget(self.custom_radio_button) self.custom_edit = QtWidgets.QLineEdit(self.separator_group_box) self.custom_layout.addWidget(self.custom_edit) self.separator_grid_layout.addLayout(self.custom_layout, 3, 0, 1, 1) self.grid_layout.addWidget(self.separator_group_box, 0, 1, 1, 1) self.options_group_box = QtWidgets.QGroupBox(self) self.options_grid_layout = QtWidgets.QGridLayout( self.options_group_box) self.option_creating_new_result_checkbox = QCheckBox( _("Create new result, if doesn't exist")) self.options_grid_layout.addWidget( self.option_creating_new_result_checkbox, 0, 0, 1, 1) self.grid_layout.addWidget(self.options_group_box, 1, 0, 1, 2) self.text_edit = QtWidgets.QPlainTextEdit(self) self.grid_layout.addWidget(self.text_edit, 2, 0, 1, 2) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = button_box.button(QDialogButtonBox.Ok) self.button_ok.setText(_('OK')) self.button_ok.clicked.connect(self.accept) self.button_cancel = button_box.button(QDialogButtonBox.Cancel) self.button_cancel.setText(_('Cancel')) self.button_cancel.clicked.connect(self.reject) stf_button = button_box.addButton(_('Save to file'), QDialogButtonBox.ActionRole) stf_button.clicked.connect(self.save_to_file) stf_button.setDisabled(True) lff_button = button_box.addButton(_('Load from file'), QDialogButtonBox.ActionRole) lff_button.clicked.connect(self.load_from_file) lff_button.setDisabled(True) self.layout.addWidget(widget) self.layout.addWidget(button_box) self.retranslate_ui(self) def save_to_file(self): pass def load_from_file(self): pass def retranslate_ui(self, text_io): text_io.setWindowTitle(_("Dialog")) self.value_group_box.setTitle(_("Values")) self.id_label.setText(_("Identifier")) self.bib_radio_button.setText(_("Bib")) self.name_radio_button.setText(_("Person name")) self.value_label.setText(_("Value")) self.separator_group_box.setTitle(_("Separator")) self.space_radio_button.setText(_("space")) self.tab_radio_button.setText(_("tab")) self.semicolon_radio_button.setText(_("semicolon")) self.custom_radio_button.setText(_("custom")) self.options_group_box.setTitle(_("Options")) self.text_edit.setPlainText('') self.get_text_wrapper() self.value_combo_box.currentIndexChanged.connect(self.get_text_wrapper) self.bib_radio_button.clicked.connect(self.get_text_wrapper) self.name_radio_button.clicked.connect(self.get_text_wrapper) self.space_radio_button.clicked.connect(self.get_text_wrapper) self.semicolon_radio_button.clicked.connect(self.get_text_wrapper) self.tab_radio_button.clicked.connect(self.get_text_wrapper) self.custom_radio_button.clicked.connect(self.get_text_wrapper) self.custom_edit.textChanged.connect(self.get_text_wrapper) def get_text_wrapper(self): try: index = 'bib' if self.name_radio_button.isChecked(): index = 'person name' key = self.value_combo_box.currentText() readonly = key in get_readonly_options() if readonly: self.button_ok.setDisabled(True) else: self.button_ok.setDisabled(False) if key == _('Finish'): self.option_creating_new_result_checkbox.setDisabled(False) else: self.option_creating_new_result_checkbox.setDisabled(True) separator = ' ' if self.tab_radio_button.isChecked(): separator = '\t' elif self.semicolon_radio_button.isChecked(): separator = ';' elif self.custom_radio_button.isChecked(): separator = self.custom_edit.text() self.text_edit.setPlainText(get_text(index, key, separator)) except Exception as e: logging.error(e) def accept(self, *args, **kwargs): try: index_type = 'bib' if self.name_radio_button.isChecked(): index_type = 'person name' key = self.value_combo_box.currentText() separator = ' ' if self.tab_radio_button.isChecked(): separator = '\t' elif self.semicolon_radio_button.isChecked(): separator = ';' elif self.custom_radio_button.isChecked(): separator = self.custom_edit.text() text = self.text_edit.toPlainText() lines = text.split('\n') success_count = 0 for i in lines: arr = i.split(separator) if len(arr) > 1: value = arr[-1] index = arr[0] if separator == ' ' and len(arr) > 2: if index_type == 'person name': index += separator + arr[1] value = ' '.join(arr[1:]) if value: person = get_person_by_id(index_type, index) if person: set_property(person, key, value, creating_new_result=self. option_creating_new_result_checkbox. isChecked()) success_count += 1 else: logging.debug( 'text_io: no person found for line ' + i) else: logging.debug('text_io: empty value for line ' + i) logging.debug('text_io: processed ' + str(success_count) + ' from ' + str(len(lines)) + ' lines') except Exception as e: logging.error(e) super().accept(*args, **kwargs)
class SettingsWindow(QDialog): def __init__(self, parent: Optional[QWidget] = None, firstStart: bool = False) -> None: super().__init__(parent, ) if parent: self.setWindowTitle('Settings') else: self.setWindowTitle(getTitleString('Settings')) self.setAttribute(Qt.WA_DeleteOnClose) settings = QSettings() mainLayout = QVBoxLayout(self) # First Start info if firstStart: firstStartInfo = QLabel( ''' <p><strong>Hello! It looks like this is your first time using w3modmanager, or the game installation path recently changed.</strong></p> <p> Please review the settings below. </p> ''', self) firstStartInfo.setWordWrap(True) firstStartInfo.setContentsMargins(10, 10, 10, 10) firstStartInfo.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) mainLayout.addWidget(firstStartInfo) # Game gbGame = QGroupBox('Game Path', self) mainLayout.addWidget(gbGame) gbGameLayout = QVBoxLayout(gbGame) gamePathLayout = QHBoxLayout() self.gamePath = QLineEdit(self) self.gamePath.setPlaceholderText('Path to witcher3.exe...') if settings.value('gamePath'): self.gamePath.setText(str(settings.value('gamePath'))) self.gamePath.textChanged.connect( lambda: self.validateGamePath(self.gamePath.text())) gamePathLayout.addWidget(self.gamePath) self.locateGame = QPushButton('Detect', self) self.locateGame.clicked.connect(self.locateGameEvent) self.locateGame.setToolTip( 'Automatically detect the game path if possible') gamePathLayout.addWidget(self.locateGame) selectGame = QPushButton('Browse', self) selectGame.clicked.connect(self.selectGameEvent) gamePathLayout.addWidget(selectGame) gbGameLayout.addLayout(gamePathLayout) gamePathInfoLayout = QHBoxLayout() self.gamePathInfo = QLabel('', self) self.gamePathInfo.setContentsMargins(4, 4, 4, 4) self.gamePathInfo.setMinimumHeight(36) self.gamePathInfo.setWordWrap(True) gamePathInfoLayout.addWidget(self.gamePathInfo) gbGameLayout.addLayout(gamePathInfoLayout) # Config gbConfig = QGroupBox('Game Config', self) mainLayout.addWidget(gbConfig) gbConfigLayout = QVBoxLayout(gbConfig) configPathLayout = QHBoxLayout() self.configPath = QLineEdit(self) self.configPath.setPlaceholderText('Path to config folder...') if settings.value('configPath'): self.configPath.setText(str(settings.value('configPath'))) self.configPath.textChanged.connect( lambda: self.validateConfigPath(self.configPath.text())) configPathLayout.addWidget(self.configPath) self.locateConfig = QPushButton('Detect', self) self.locateConfig.clicked.connect(self.locateConfigEvent) self.locateConfig.setToolTip( 'Automatically detect the config folder if possible') configPathLayout.addWidget(self.locateConfig) selectConfig = QPushButton('Browse', self) selectConfig.clicked.connect(self.selectConfigEvent) configPathLayout.addWidget(selectConfig) gbConfigLayout.addLayout(configPathLayout) configPathInfoLayout = QHBoxLayout() self.configPathInfo = QLabel('', self) self.configPathInfo.setContentsMargins(4, 4, 4, 4) self.configPathInfo.setMinimumHeight(36) self.configPathInfo.setWordWrap(True) configPathInfoLayout.addWidget(self.configPathInfo) gbConfigLayout.addLayout(configPathInfoLayout) # Nexus Mods API gbNexusModsAPI = QGroupBox('Nexus Mods API', self) mainLayout.addWidget(gbNexusModsAPI) gbNexusModsAPILayout = QVBoxLayout(gbNexusModsAPI) self.nexusAPIKey = QLineEdit(self) self.nexusAPIKey.setPlaceholderText('Personal API Key...') if settings.value('nexusAPIKey'): self.nexusAPIKey.setText(str(settings.value('nexusAPIKey'))) self.nexusAPIKey.textChanged.connect( lambda: self.validateApiKey(self.nexusAPIKey.text())) gbNexusModsAPILayout.addWidget(self.nexusAPIKey) self.nexusAPIKeyInfo = QLabel('🌐', self) self.nexusAPIKeyInfo.setOpenExternalLinks(True) self.nexusAPIKeyInfo.setWordWrap(True) self.nexusAPIKeyInfo.setContentsMargins(4, 4, 4, 4) self.nexusAPIKeyInfo.setMinimumHeight(48) gbNexusModsAPILayout.addWidget(self.nexusAPIKeyInfo) self.nexusGetInfo = QCheckBox('Get Mod details after adding a new mod', self) self.nexusGetInfo.setChecked( settings.value('nexusGetInfo', 'True') == 'True') self.nexusGetInfo.setDisabled(True) gbNexusModsAPILayout.addWidget(self.nexusGetInfo) self.nexusCheckUpdates = QCheckBox('Check for Mod updates on startup', self) self.nexusCheckUpdates.setChecked( settings.value('nexusCheckUpdates', 'False') == 'True') self.nexusCheckUpdates.setDisabled(True) gbNexusModsAPILayout.addWidget(self.nexusCheckUpdates) self.nexusCheckClipboard = QCheckBox( 'Monitor the Clipboard for Nexus Mods URLs', self) self.nexusCheckClipboard.setChecked( settings.value('nexusCheckClipboard', 'False') == 'True') self.nexusCheckClipboard.setDisabled(True) gbNexusModsAPILayout.addWidget(self.nexusCheckClipboard) # Output gbOutput = QGroupBox('Output Preferences', self) mainLayout.addWidget(gbOutput) gbOutputLayout = QVBoxLayout(gbOutput) self.unhideOutput = QCheckBox('Auto-show output panel', self) self.unhideOutput.setChecked( settings.value('unhideOutput', 'True') == 'True') gbOutputLayout.addWidget(self.unhideOutput) self.debugOutput = QCheckBox('Show debug output', self) self.debugOutput.setChecked( settings.value('debugOutput', 'False') == 'True') gbOutputLayout.addWidget(self.debugOutput) # Actions actionsLayout = QHBoxLayout() actionsLayout.setAlignment(Qt.AlignRight) self.save = QPushButton('Save', self) self.save.clicked.connect(self.saveEvent) self.save.setAutoDefault(True) self.save.setDefault(True) actionsLayout.addWidget(self.save) cancel = QPushButton('Cancel', self) cancel.clicked.connect(self.cancelEvent) actionsLayout.addWidget(cancel) mainLayout.addLayout(actionsLayout) # Setup if not settings.value('gamePath'): self.locateGameEvent() self.setMinimumSize(QSize(420, 420)) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.validGamePath = False self.validConfigPath = False self.validNexusAPIKey = False self.validateGamePath(self.gamePath.text()) self.validateConfigPath(self.configPath.text()) self.validateApiKey(self.nexusAPIKey.text()) self.updateSaveButton() self.finished.connect( lambda: self.validateApiKey.cancel()) # type: ignore def saveEvent(self) -> None: settings = QSettings() settings.setValue('settingsWindowGeometry', self.saveGeometry()) settings.setValue('gamePath', self.gamePath.text()) settings.setValue('configPath', self.configPath.text()) settings.setValue('nexusAPIKey', self.nexusAPIKey.text()) settings.setValue('nexusGetInfo', str(self.nexusGetInfo.isChecked())) settings.setValue('nexusCheckUpdates', str(self.nexusCheckUpdates.isChecked())) settings.setValue('nexusCheckClipboard', str(self.nexusCheckClipboard.isChecked())) settings.setValue('debugOutput', str(self.debugOutput.isChecked())) settings.setValue('unhideOutput', str(self.unhideOutput.isChecked())) self.close() def cancelEvent(self) -> None: self.close() def selectGameEvent(self) -> None: dialog: QFileDialog = QFileDialog(self, 'Select witcher3.exe', '', 'The Witcher 3 (witcher3.exe)') dialog.setOptions(QFileDialog.ReadOnly) dialog.setFileMode(QFileDialog.ExistingFile) if (dialog.exec_()): if dialog.selectedFiles(): self.gamePath.setText(dialog.selectedFiles()[0]) def selectConfigEvent(self) -> None: dialog: QFileDialog = QFileDialog(self, 'Select config folder', '', 'The Witcher 3') dialog.setOptions(QFileDialog.ReadOnly) dialog.setFileMode(QFileDialog.Directory) if (dialog.exec_()): if dialog.selectedFiles(): self.configPath.setText(dialog.selectedFiles()[0]) def locateGameEvent(self) -> None: game = fetcher.findGamePath() if game: self.gamePath.setText(str(game)) else: self.gamePathInfo.setText(''' <font color="#888"> Could not detect The Witcher 3!<br> Please make sure the game is installed, or set the path manually. </font>''') def locateConfigEvent(self) -> None: config = fetcher.findConfigPath() if config: self.configPath.setText(str(config)) else: self.configPathInfo.setText(''' <font color="#888"> Could not detect a valid config path! Please make sure the The Witcher 3 was started at least once, or set the path manually. </font>''') def validateGamePath(self, text: str) -> bool: # validate game installation path if not verifyGamePath(Path(text)): self.gamePath.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.gamePathInfo.setText( '<font color="#888">Please enter a valid game path.</font>') self.validGamePath = False self.locateGame.setDisabled(False) self.updateSaveButton() return False else: self.gamePath.setStyleSheet('') self.gamePathInfo.setText( '<font color="#888">Everything looks good!</font>') self.validGamePath = True self.locateGame.setDisabled(True) self.updateSaveButton() return True def validateConfigPath(self, text: str) -> bool: # validate game config path if not verifyConfigPath(Path(text)): self.configPath.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.configPathInfo.setText('''<font color="#888"> Please enter a valid config path. You need to start the The Witcher 3 at least once to generate the necessary user.settings and input.settings files.</font> ''') self.validConfigPath = False self.locateConfig.setDisabled(False) self.updateSaveButton() return False else: self.configPath.setStyleSheet('') self.configPathInfo.setText( '<font color="#888">Everything looks good!</font>') self.validConfigPath = True self.locateConfig.setDisabled(True) self.updateSaveButton() return True @debounce(200, cancel_running=True) async def validateApiKey(self, text: str) -> bool: # validate neus mods api key self.nexusGetInfo.setDisabled(True) self.nexusCheckUpdates.setDisabled(True) self.nexusCheckClipboard.setDisabled(True) self.nexusAPIKey.setStyleSheet('') if not text: self.nexusAPIKeyInfo.setText(''' <font color="#888">The API Key is used to check for mod updates, \ to get mod details and to download mods. \ Get your Personal API Key <a href="https://www.nexusmods.com/users/myaccount?tab=api">here</a>.</font> ''') self.validNexusAPIKey = True self.updateSaveButton() return True self.nexusAPIKeyInfo.setText('🌐') try: apiUser = await getUserInformation(text) except UnauthorizedError: self.nexusAPIKey.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.nexusAPIKeyInfo.setText(''' <font color="#888">Not a valid API Key. \ Get your Personal API Key <a href="https://www.nexusmods.com/users/myaccount?tab=api">here</a>.</font> ''') self.validNexusAPIKey = False self.updateSaveButton() return False except (RequestError, ResponseError, Exception) as e: self.nexusAPIKey.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.nexusAPIKeyInfo.setText(f''' <font color="#888">Could not validate API Key: {e}.</font> ''') self.validNexusAPIKey = False self.updateSaveButton() return False self.nexusAPIKeyInfo.setText( f'<font color="#888">Valid API Key for {apiUser["name"]}!</font>') self.validNexusAPIKey = True self.nexusGetInfo.setDisabled(False) self.nexusCheckUpdates.setDisabled(False) self.nexusCheckClipboard.setDisabled(False) self.updateSaveButton() return True def updateSaveButton(self) -> None: # TODO: release: disable saving invalid settings # self.save.setDisabled(not all(( # self.validConfigPath, # self.validGamePath, # self.validNexusAPIKey, # ))) # noqa self.save.setDisabled(False)
class AudioInfoDialog(QDialog): def __init__(self, audios_name, audios_delay, audios_language, audios_track_name, audios_set_default, audios_set_forced, audios_default_value_delay, audios_default_value_language, audios_default_value_track_name, audios_default_value_set_default, audios_default_value_set_forced, audio_set_default_disabled=False, audio_set_forced_disabled=False, disable_edit=False, parent=None): super().__init__(parent) self.window_title = "Audio Info" self.state = "no" self.audios_count = len(audios_delay) self.messageIcon = QLabel() self.audio_tab_comboBox = InfoCellDialogTabComboBox( hint="Audios Groups") for i in range(self.audios_count): self.audio_tab_comboBox.addItem("Audio #" + str(i + 1)) self.audio_tab_comboBox.setCurrentIndex(0) self.audio_tab_comboBox.currentIndexChanged.connect( self.update_current_audio_index) self.current_audio_index = 0 self.disable_edit = disable_edit self.current_audio_name = audios_name self.current_audio_language = audios_language self.current_audio_delay = audios_delay self.current_audio_track_name = audios_track_name self.current_audio_set_default = audios_set_default self.current_audio_set_forced = audios_set_forced self.default_audio_language = audios_default_value_language self.default_audio_delay = audios_default_value_delay self.default_audio_track_name = audios_default_value_track_name self.default_audio_set_default = audios_default_value_set_default self.default_audio_set_forced = audios_default_value_set_forced self.audio_set_default_disabled = audio_set_default_disabled self.audio_set_forced_disabled = audio_set_forced_disabled self.audio_name_label = QLabel("Audio Name:") self.audio_name_value = QLabel( str(self.current_audio_name[self.current_audio_index])) width_to_be_fixed = 0 for i in range(len(self.current_audio_name)): width_to_be_fixed = max( width_to_be_fixed, self.audio_name_value.fontMetrics().boundingRect( self.current_audio_name[i]).width()) self.audio_name_value.setFixedWidth(width_to_be_fixed + 10) self.audio_delay_label = QLabel("Audio Delay:") self.audio_delay_spin = QDoubleSpinBox() self.setup_audio_delay_spin() self.audio_language_label = QLabel("Audio Language:") self.audio_language_comboBox = QComboBox() self.setup_audio_language_comboBox() self.audio_track_name_label = QLabel("Audio Track Name:") self.audio_track_name_lineEdit = QLineEdit() self.setup_audio_track_name_lineEdit() self.audio_set_forced_label = QLabel("Audio Forced State:") self.audio_set_forced_checkBox = QCheckBox() self.setup_audio_set_forced_checkBox() self.audio_set_default_label = QLabel("Audio Default State:") self.audio_set_default_checkBox = QCheckBox() self.setup_audio_set_default_checkBox() self.yes_button = QPushButton("OK") self.no_button = QPushButton("Cancel") self.reset_button = QPushButton("Reset To Default") self.buttons_layout = QHBoxLayout() self.audio_delay_layout = QHBoxLayout() self.audio_language_layout = QHBoxLayout() self.audio_track_name_layout = QHBoxLayout() self.audio_set_default_layout = QHBoxLayout() self.audio_set_forced_layout = QHBoxLayout() self.buttons_layout.addWidget(QLabel(""), stretch=3) self.buttons_layout.addWidget(self.reset_button, stretch=2) self.buttons_layout.addWidget(self.yes_button, stretch=2) self.buttons_layout.addWidget(self.no_button, stretch=2) self.buttons_layout.addWidget(QLabel(""), stretch=3) self.audio_setting_layout = QGridLayout() self.audio_editable_setting_layout = QFormLayout() self.audio_editable_setting_layout.addRow(self.audio_name_label, self.audio_name_value) self.audio_editable_setting_layout.addRow( self.audio_track_name_label, self.audio_track_name_lineEdit) self.audio_editable_setting_layout.addRow(self.audio_language_label, self.audio_language_comboBox) self.audio_editable_setting_layout.addRow(self.audio_delay_label, self.audio_delay_spin) self.audio_editable_setting_layout.addRow( self.audio_set_default_label, self.audio_set_default_checkBox) self.audio_editable_setting_layout.addRow( self.audio_set_forced_label, self.audio_set_forced_checkBox) self.audio_setting_layout.addWidget(self.audio_tab_comboBox, 0, 0) self.audio_setting_layout.addLayout(self.audio_editable_setting_layout, 1, 0, 5, 2) self.audio_setting_layout.addWidget(self.messageIcon, 1, 3, 5, -1) self.main_layout = QGridLayout() self.main_layout.addLayout(self.audio_setting_layout, 0, 0, 2, 3) self.main_layout.addLayout(self.buttons_layout, 2, 0, 1, -1) self.main_layout.setContentsMargins(20, 20, 20, 20) self.setLayout(self.main_layout) self.setup_ui() self.signal_connect() def setup_ui(self): self.disable_question_mark_window() self.messageIcon.setPixmap( QtGui.QPixmap(GlobalFiles.AudioIconPath).scaledToHeight(100)) self.set_dialog_values() self.set_default_buttons() if self.audio_set_default_disabled: self.audio_set_default_disable() if self.audio_set_forced_disabled: self.audio_set_forced_disable() if self.disable_edit: self.audio_track_name_lineEdit.setEnabled(False) self.audio_language_comboBox.setEnabled(False) self.audio_delay_spin.setEnabled(False) self.audio_set_default_checkBox.setEnabled(False) self.audio_set_forced_checkBox.setEnabled(False) self.reset_button.setEnabled(False) self.setup_tool_tip_hint_audio_set_default() self.setup_tool_tip_hint_audio_set_forced() def signal_connect(self): self.audio_track_name_lineEdit.textEdited.connect( self.update_current_audio_track_name) self.audio_delay_spin.editingFinished.connect( self.update_current_audio_delay) self.audio_language_comboBox.currentTextChanged.connect( self.update_current_audio_language) self.audio_set_default_checkBox.stateChanged.connect( self.update_current_audio_set_default) self.audio_set_forced_checkBox.stateChanged.connect( self.update_current_audio_set_forced) self.yes_button.clicked.connect(self.click_yes) self.no_button.clicked.connect(self.click_no) self.reset_button.clicked.connect(self.reset_audio_setting) def click_yes(self): self.state = "yes" self.close() def click_no(self): self.state = "no" self.close() def set_dialog_values(self): self.setWindowTitle(self.window_title) self.setWindowIcon(GlobalFiles.InfoSettingIcon) def disable_question_mark_window(self): self.setWindowFlag(Qt.WindowContextHelpButtonHint, on=False) def increase_message_font_size(self, value): message_font = self.message.font() message_font.setPointSize(self.message.fontInfo().pointSize() + value) self.message.setFont(message_font) def set_default_buttons(self): self.yes_button.setDefault(True) self.yes_button.setFocus() def showEvent(self, a0: QtGui.QShowEvent) -> None: super().showEvent(a0) self.setFixedSize(self.size()) def setup_audio_track_name_lineEdit(self): self.audio_track_name_lineEdit.setClearButtonEnabled(True) self.audio_track_name_lineEdit.setText( self.current_audio_track_name[self.current_audio_index]) def setup_audio_language_comboBox(self): self.audio_language_comboBox.addItems(AllAudiosLanguages) self.audio_language_comboBox.setCurrentIndex( AllAudiosLanguages.index( self.current_audio_language[self.current_audio_index])) self.audio_language_comboBox.setMaxVisibleItems(8) self.audio_language_comboBox.setStyleSheet( "QComboBox { combobox-popup: 0; }") def setup_audio_delay_spin(self): # self.audio_delay_spin.setMaximumWidth(screen_size.width() // 16) self.audio_delay_spin.setDecimals(3) self.audio_delay_spin.setMinimum(-9999.0) self.audio_delay_spin.setMaximum(9999.0) self.audio_delay_spin.setSingleStep(0.5) self.audio_delay_spin.setValue( float(self.current_audio_delay[self.current_audio_index])) def setup_audio_set_default_checkBox(self): self.audio_set_default_checkBox.setText("Set Default") self.audio_set_default_checkBox.setChecked( bool(self.current_audio_set_default[self.current_audio_index])) def setup_audio_set_forced_checkBox(self): self.audio_set_forced_checkBox.setText("Set Forced") self.audio_set_forced_checkBox.setChecked( bool(self.current_audio_set_forced[self.current_audio_index])) def update_current_audio_track_name(self): self.current_audio_track_name[self.current_audio_index] = str( self.audio_track_name_lineEdit.text()) def update_current_audio_delay(self): self.current_audio_delay[self.current_audio_index] = round( self.audio_delay_spin.value(), 5) def update_current_audio_language(self): self.current_audio_language[self.current_audio_index] = str( self.audio_language_comboBox.currentText()) def update_current_audio_set_default(self): new_state = self.audio_set_default_checkBox.checkState() == Qt.Checked self.current_audio_set_default[self.current_audio_index] = new_state if new_state: for i in range(len(self.current_audio_set_default)): if i != self.current_audio_index: self.current_audio_set_default[i] = False def update_current_audio_set_forced(self): new_state = self.audio_set_forced_checkBox.checkState() == Qt.Checked self.current_audio_set_forced[self.current_audio_index] = new_state if new_state: for i in range(len(self.current_audio_set_forced)): if i != self.current_audio_index: self.current_audio_set_forced[i] = False def reset_audio_setting(self): self.current_audio_language[ self.current_audio_index] = self.default_audio_language[ self.current_audio_index] self.current_audio_delay[ self.current_audio_index] = self.default_audio_delay[ self.current_audio_index] self.current_audio_track_name[ self.current_audio_index] = self.default_audio_track_name[ self.current_audio_index] self.current_audio_set_default[ self.current_audio_index] = self.default_audio_set_default[ self.current_audio_index] self.current_audio_set_forced[ self.current_audio_index] = self.default_audio_set_forced[ self.current_audio_index] self.audio_language_comboBox.setCurrentIndex( AllAudiosLanguages.index( self.current_audio_language[self.current_audio_index])) self.audio_delay_spin.setValue( float(self.current_audio_delay[self.current_audio_index])) self.audio_track_name_lineEdit.setText( self.current_audio_track_name[self.current_audio_index]) self.audio_set_default_checkBox.setChecked( bool(self.current_audio_set_default[self.current_audio_index])) self.audio_set_forced_checkBox.setChecked( bool(self.current_audio_set_forced[self.current_audio_index])) def audio_set_default_disable(self): self.audio_set_default_checkBox.setDisabled(True) def audio_set_forced_disable(self): self.audio_set_forced_checkBox.setDisabled(True) def setup_tool_tip_hint_audio_set_default(self): if self.audio_set_default_checkBox.isEnabled(): self.audio_set_default_checkBox.setToolTip( "<nobr>set this audio to be the default audio track " "when play") self.audio_set_default_checkBox.setToolTipDuration(12000) else: self.audio_set_default_checkBox.setToolTip( "<nobr>set this audio to be the default audio track when play<br><b>Disabled</b> because " "option " "<b>make this audio default</b> is enabled on mux setting tab " ) self.audio_set_default_checkBox.setToolTipDuration(12000) def setup_tool_tip_hint_audio_set_forced(self): if self.audio_set_forced_checkBox.isEnabled(): self.audio_set_forced_checkBox.setToolTip( "<nobr>set this audio to be the forced audio track when " "play") self.audio_set_forced_checkBox.setToolTipDuration(12000) else: self.audio_set_forced_checkBox.setToolTip( "<nobr>set this audio to be the forced audio track when play<br><b>Disabled</b> because " "option " "<b>make this audio default and forced</b> is enabled on mux setting tab " ) self.audio_set_forced_checkBox.setToolTipDuration(12000) def update_current_audio_index(self, new_index): self.current_audio_index = new_index self.audio_delay_spin.setValue( float(self.current_audio_delay[self.current_audio_index])) self.audio_set_default_checkBox.setChecked( bool(self.current_audio_set_default[self.current_audio_index])) self.audio_set_forced_checkBox.setChecked( bool(self.current_audio_set_forced[self.current_audio_index])) self.audio_language_comboBox.setCurrentIndex( AllAudiosLanguages.index( self.current_audio_language[self.current_audio_index])) self.audio_track_name_lineEdit.setText( self.current_audio_track_name[self.current_audio_index]) self.audio_name_value.setText( str(self.current_audio_name[self.current_audio_index])) def execute(self): self.exec_()
class RenameOptionsView(QWidget): """View responsible for holding renaming options. Attributes: layout (QVBoxLayout): Main layout of view. frame_layout (QVBoxLayout: Layout of frame which holds options. frame (QFrame): Frame surrounding options. prefix_h_layout (QHBoxLayout): Layout holding prefix options. complete_rename_h_layout (QHBoxLayout): Layout holding complete rename options. search_and_replace_h_layout (QHBoxLayout): Layout holding search and replace options. renumber_h_layout (QHBoxLayout): Layout holding renumber options. remove_ext_h_layout (QHBoxLayout): Layout holding remove options. change_ext_h_layout (QHBoxLayout): Layout holding change extension options. create_backup_h_layout (QHBoxLayout): Layout holding backup options. preview_h_layout (QHBoxLayout): Layout holding preview options. start_lbl (QLabel): Label for renumbering start. padding_lbl (QLabel): Label for renumbering padding. add_prefix_cb (QCheckBox): Used to signify the user wants to add a prefix to the renaming. prefix (QLineEdit): prefix to add. complete_rename_cb (QCheckBox): Used to signify the user wants to completely rename the file. new_name (QLineEdit): New name used when renaming. search_and_replace_cb (QCheckBox): Used to signify the user wants to partially rename files. find (QLineEdit): When searching and replacing this is what the user wants to search for. replace (QLineEdit): When searching and replacing this is what the user wants to replace with. renumber_cb (QCheckBox): Used to signify the user wants to renumber while renaming. start_num (QSpinBox): Number to start with when renumbering files. padding (QComboBox): Padding to apply to renaming when renumbering files. dot_cb (QCheckBox): When checked a dot will be used to separate the renumber from the name. remove_ext_cb (QCheckBox): Used to signify the user wants to remove extensions when renaming. backup_files_cb (QCheckBox): Used to signify the user wants to backup old files before renaming. change_ext_cb (QCheckBox): Used to signify the user wants to change the extension while renaming. change_ext (QLineEdit): New extension to add to the renamed file. preview_cb (QCheckBox): Used to signify the user wants to preview the rename before renaming. """ def __init__(self): super(RenameOptionsView, self).__init__() self.layout = QVBoxLayout() self.frame_layout = QVBoxLayout() self.options_lbl = QLabel(prefs.OPTIONS) self.frame = QFrame() self.prefix_h_layout = QHBoxLayout() self.complete_rename_h_layout = QHBoxLayout() self.search_and_replace_h_layout = QHBoxLayout() self.renumber_h_layout = QHBoxLayout() self.remove_ext_h_layout = QHBoxLayout() self.change_ext_h_layout = QHBoxLayout() self.create_backup_h_layout = QHBoxLayout() self.preview_h_layout = QHBoxLayout() self.start_lbl = QLabel(prefs.START_NUM) self.padding_lbl = QLabel(prefs.PADDING) self.add_prefix_cb = QCheckBox(prefs.PREFIX) self.prefix = QLineEdit(prefs.PREFIX_DEFAULT) self.complete_rename_cb = QCheckBox(prefs.COMPLETE_RENAME) self.new_name = QLineEdit(prefs.COMPLETE_RENAME_DEFAULT) self.search_and_replace_cb = QCheckBox(prefs.SEARCH_AND_REPLACE) self.find = QLineEdit(prefs.SEARCH_AND_REPLACE_DEFAULT) self.replace = QLineEdit(prefs.REPLACE_WITH_DEFAULT) self.renumber_cb = QCheckBox(prefs.RENUMBER) self.start_num = QSpinBox() self.padding = QComboBox() self.dot_cb = QCheckBox(prefs.USE_DOT) self.remove_ext_cb = QCheckBox(prefs.REMOVE_EXT) self.backup_files_cb = QCheckBox(prefs.BACKUP) self.change_ext_cb = QCheckBox(prefs.CHANGE_EXT) self.change_ext = QLineEdit(prefs.CHANGE_EXT_DEFAULT) self.preview_cb = QCheckBox(prefs.PREVIEW) self._configure() def _configure(self) -> None: """Configure the RenameOptionsView.""" self.frame.setLayout(self.frame_layout) self.frame.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.layout.addWidget(self.options_lbl) self.layout.addWidget(self.frame) self.add_prefix_cb.setToolTip(prefs.PREFIX_TOOLTIP) self.prefix.setDisabled(True) self.prefix.setMaximumWidth(prefs.PREFIX_WIDTH) self.prefix.setMinimumWidth(prefs.PREFIX_WIDTH) self.complete_rename_cb.setToolTip(prefs.COMPLETE_RENAME_TOOLTIP) self.new_name.setDisabled(True) self.new_name.setMaximumWidth(prefs.NEW_NAME_WIDTH) self.new_name.setMinimumWidth(prefs.NEW_NAME_WIDTH) self.search_and_replace_cb.setToolTip(prefs.SEARCH_AND_REPLACE_TOOLTIP) self.find.setDisabled(True) self.find.setMinimumWidth(prefs.FIND_WIDTH) self.find.setMaximumWidth(prefs.FIND_WIDTH) self.replace.setDisabled(True) self.replace.setMaximumWidth(prefs.REPLACE_WIDTH) self.replace.setMinimumWidth(prefs.REPLACE_WIDTH) self.renumber_cb.setToolTip(prefs.RENUMBER_TOOLTIP) self.start_num.setToolTip(prefs.START_NUM_TOOLTIP) self.start_num.setDisabled(True) self.start_num.setValue(prefs.START_NUM_DEFAULT) self.start_num.setMinimumWidth(prefs.START_NUM_MIN_WIDTH) self.padding.setToolTip(prefs.PADDING_TOOLTIP) self.padding.setDisabled(True) self.padding.addItems([str(x) for x in range(10)]) self.padding.setCurrentIndex(4) self.padding.setMinimumWidth(prefs.PADDING_MIN_WIDTH) self.dot_cb.setToolTip(prefs.USE_DOT_TOOLTIP) self.dot_cb.setDisabled(True) self.dot_cb.setChecked(True) self.dot_cb.setMinimumWidth(prefs.DOT_WIDTH) self.dot_cb.setMaximumWidth(prefs.DOT_WIDTH) self.remove_ext_cb.setToolTip(prefs.REMOVE_EXT_TOOLTIP) self.change_ext.setToolTip(prefs.CHANGE_EXT_TOOLTIP) self.change_ext.setDisabled(True) self.backup_files_cb.setToolTip(prefs.BACKUP_TOOLTIP) self.backup_files_cb.setChecked(True) self.preview_cb.setToolTip(prefs.PREVIEW_TOOLTIP) self.preview_cb.setChecked(True) self.prefix_h_layout.addWidget(self.add_prefix_cb) self.prefix_h_layout.addWidget(self.prefix) self.frame_layout.addLayout(self.prefix_h_layout) self.complete_rename_h_layout.addWidget(self.complete_rename_cb) self.complete_rename_h_layout.addWidget(self.new_name) self.frame_layout.addLayout(self.complete_rename_h_layout) self.search_and_replace_h_layout.addWidget(self.search_and_replace_cb) self.search_and_replace_h_layout.addWidget(self.find) self.search_and_replace_h_layout.addWidget(self.replace) self.frame_layout.addLayout(self.search_and_replace_h_layout) self.renumber_h_layout.addWidget(self.renumber_cb) self.renumber_h_layout.addStretch(1) self.renumber_h_layout.addWidget(self.start_lbl) self.renumber_h_layout.addWidget(self.start_num) self.renumber_h_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE)) self.renumber_h_layout.addWidget(self.padding_lbl) self.renumber_h_layout.addWidget(self.padding) self.renumber_h_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE)) self.renumber_h_layout.addWidget(self.dot_cb) self.frame_layout.addLayout(self.renumber_h_layout) self.change_ext_h_layout.addWidget(self.change_ext_cb) self.change_ext_h_layout.addWidget(self.change_ext) self.frame_layout.addLayout(self.change_ext_h_layout) self.remove_ext_h_layout.addWidget(self.remove_ext_cb) self.frame_layout.addLayout(self.remove_ext_h_layout) self.create_backup_h_layout.addWidget(self.backup_files_cb) self.frame_layout.addLayout(self.create_backup_h_layout) self.preview_h_layout.addWidget(self.preview_cb) self.frame_layout.addLayout(self.preview_h_layout) self.frame_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE)) self.setLayout(self.layout) def disable_change_ext(self) -> None: """Disable change extension.""" self.change_ext.setDisabled(True) def disable_dot(self) -> None: """Disable dot checkbox.""" self.dot_cb.setDisabled(True) def disable_find(self) -> None: """Disable find.""" self.find.setDisabled(True) def disable_new_name(self) -> None: """Disable new name.""" print("disable new name") self.new_name.setDisabled(True) def disable_padding(self) -> None: """Disable padding.""" self.padding.setDisabled(True) def disable_prefix(self) -> None: """Disable prefix.""" self.prefix.setDisabled(True) def disable_start_num(self) -> None: """Disable start num.""" self.start_num.setDisabled(True) def disable_replace(self) -> None: """Disable replace.""" self.replace.setDisabled(True) def enable_change_ext(self) -> None: """Disable change extension.""" self.change_ext.setDisabled(False) def enable_dot(self) -> None: """Enable dot checkbox.""" self.dot_cb.setEnabled(True) def enable_find(self) -> None: """Enable find.""" self.find.setEnabled(True) def enable_new_name(self) -> None: """Enable new name.""" print("enable new name.") self.new_name.setEnabled(True) def enable_padding(self) -> None: """Enable padding.""" self.padding.setEnabled(True) def enable_prefix(self) -> None: """Enable prefix.""" self.prefix.setEnabled(True) def enable_replace(self) -> None: """Enable replace.""" self.replace.setEnabled(True) def enable_start_num(self) -> None: """Enable start num.""" self.start_num.setEnabled(True) def get_add_prefix(self) -> bool: """Return if end user wants to add a prefix and it is not the default value.""" result = self.get_prefix_checked() if result and self.get_prefix() == prefs.PREFIX_DEFAULT: result = False return result def get_do_backup(self) -> bool: """Return if end user wants to backup files.""" return self.backup_files_cb.isChecked() def get_change_ext(self) -> bool: """Return if the change extension checkbox is checked.""" return self.change_ext_cb.isChecked() def get_do_complete_rename(self) -> bool: """Get if end user wants to completely rename.""" return self.complete_rename_cb.isChecked() def get_dot(self) -> str: """Return dot string based on end users configuration. Note: If the end user has not enable using dot separators an empty string will be returned. """ return "." if self.get_do_dot() else "" def get_do_dot(self) -> bool: """Return if the end user wants to use dot separators when renaming.""" return self.dot_cb.isChecked() def get_do_change_ext(self) -> bool: """Return if the end user wants to change the extension.""" result = self.change_ext_cb.isChecked() if self.get_new_ext() == prefs.CHANGE_EXT_DEFAULT: return False return result def get_do_padding(self) -> bool: """Return if the end user wants to add padding.""" return False if self.get_padding() == 0 else True def get_do_preview(self) -> bool: """Return if the end user wants to preview changes.""" return self.preview_cb.isChecked() def get_do_rename(self) -> bool: """Return if end user wants to rename the full item and it is not the default value.""" result = self.complete_rename_cb.isChecked() if result and self.get_new_name() == prefs.COMPLETE_RENAME_DEFAULT: result = False return result def get_do_renumber(self) -> bool: """Return if the end user wants to renumber.""" return self.renumber_cb.isChecked() def get_do_search(self) -> bool: """Return if end user wants to perform a search and replace AND it is not the default values respectfully. Note: If you only want to know if search and replace is checked use get_search_and_replace. """ result = self.search_and_replace_cb.isChecked() if result and (self.get_find() == prefs.SEARCH_AND_REPLACE_DEFAULT or self.get_replace() == prefs.REPLACE_WITH_DEFAULT): result = False return result def get_do_search_and_replace(self) -> bool: """Return if end user wants to perform a search and replace.""" return self.search_and_replace_cb.isChecked() def get_find(self) -> str: """Return find value.""" return str(self.find.text()) def get_new_ext(self) -> str: """Return new ext.""" return str(self.change_ext.text()) def get_new_name(self) -> str: """Return new_name value.""" return str(self.new_name.text()) def get_padding(self) -> int: """Return the current padding value.""" return int(self.padding.currentText()) def get_prefix_checked(self) -> bool: """Return if the prefix checkbox is checked.""" return self.add_prefix_cb.isChecked() def get_prefix(self) -> str: """Return the current prefix value end user has entered.""" return str(self.prefix.text()) def get_remove_ext(self) -> bool: """Return if end user has checked the remove extension checkbox.""" return self.remove_ext_cb.isChecked() def get_replace(self) -> str: """Return the current replace value end user has entered.""" return str(self.replace.text()) def get_start_num(self) -> int: """Return start number from view.""" return int(self.start_num.value()) def set_change_ext_style(self, style: str) -> None: """Set style of change extension. Args: style: Style sheet applied to change extension. """ self.change_ext.setStyleSheet(style) def set_disabled(self) -> None: """Disable View.""" self.setDisabled(True) def set_enable(self) -> None: """Enable View.""" self.setEnabled(True) def set_find(self, value: str) -> None: """Set the value of find. Args: value: Value applied to find """ self.find.setText(value) def set_find_style(self, style: str) -> None: """Set style of find. Args: style: Style sheet applied to find. """ self.find.setStyleSheet(style) def set_new_name(self, value: str) -> None: """Set the value of new name. Args: value: Value applied to new_name """ self.new_name.setText(value) def set_new_name_style(self, style: str) -> None: """Set style of new_name. Args: style: Style sheet applied to new_name. """ self.new_name.setStyleSheet(style) def set_prefix(self, value: str) -> None: """Set the value of prefix. Args: value: Value applied to prefix """ self.prefix.setText(value) def set_prefix_style(self, style: str) -> None: """Set style of prefix. Args: style: Style sheet applied to prefix. """ self.prefix.setStyleSheet(style) def set_remove_ext(self, state: bool) -> None: """Set the remove_ext checkbox as checked or unchecked. Args: state: Check state of remove_ext. """ self.remove_ext_cb.setCheckState(Qt.Checked if state else Qt.Unchecked) def set_replace(self, value: str) -> None: """Set the value of replace. Args: value: Value applied to replace """ self.replace.setText(value) def set_replace_style(self, style: str) -> None: """Set style of replace. Args: style: Style sheet applied to replace. """ self.replace.setStyleSheet(style)
class extractPeaksDialog(QDialog): def __init__(self, *args, **kwargs): super(extractPeaksDialog, self).__init__(*args, **kwargs) self.peaksScraped = False self.small = 3 self.failures_nulled = False self.rundownThreshold = 0.5 # to assess whether responses are running down (by factor 2 or more) self.makeDialog() def makeDialog(self): """Create the controls for the dialog""" self.setWindowTitle("Extract peaks according to reference pattern") layout = QGridLayout() w = QWidget() w.setLayout(layout) self.resize(500, 400) vbox = QVBoxLayout() vbox.addWidget(w) self.setLayout(vbox) self.N_ROI_label = QLabel('Extracting peaks') #will be altered as soon as data loads self.skipRB = QCheckBox('Skip ROIs with SNR less than') self.skipRB.setChecked(False) self.skipRB.setLayoutDirection(QtCore.Qt.LeftToRight) self.skipRB.stateChanged.connect(self.maskLowSNR) self.skipSB = pg.SpinBox(value=3, step=.2, bounds=[1, 10], delay=0) self.skipSB.setFixedSize(60, 25) self.skipSB.valueChanged.connect(self.maskLowSNR) psr_label = QLabel('Search range around peak (data points)') self.psrSB = pg.SpinBox(value=3, step=2, bounds=[1, 7], delay=0, int=True) self.psrSB.setFixedSize(60, 25) #will be altered as soon as data loads self.noiseRB = QCheckBox('Treat peaks as failures when < SD x') self.noiseRB.setChecked(False) self.noiseRB.setLayoutDirection(QtCore.Qt.LeftToRight) self.noiseRB.stateChanged.connect(self.setFailures) self.noiseRB.setDisabled(True) self.noiseSB = pg.SpinBox(value=1.5, step=.1, bounds=[.2, 10], delay=0) self.noiseSB.setFixedSize(60, 25) self.noiseSB.valueChanged.connect(self.setFailures) self.noiseSB.setDisabled(True) self.peaksLabel = QLabel('No peaks set to be failures.') _doScrapeBtn = QPushButton('Extract responses') _doScrapeBtn.clicked.connect(self.scrapePeaks) self.getRundownBtn = QPushButton('Calculate rundown') self.getRundownBtn.clicked.connect(self.getRundown) self.getRundownBtn.setDisabled(True) _cancelBtn = QPushButton('Cancel') _cancelBtn.clicked.connect(self.reject) self.acceptBtn = QPushButton('Accept and Return') self.acceptBtn.clicked.connect(self.prepareAccept) self.acceptBtn.setDisabled(True) layout.addWidget(self.N_ROI_label, 0, 0, 1, 2) layout.addWidget(self.skipRB, 1, 0, 1, 3) layout.addWidget(self.skipSB, 1, 2, 1, 1) layout.addWidget(psr_label, 2, 0, 1, 2) layout.addWidget(self.psrSB, row=2, col=2) layout.addWidget(self.noiseRB, 3, 0, 1, 3) layout.addWidget(self.noiseSB, 3, 2, 1, 1) layout.addWidget(self.peaksLabel, 4, 0, 1, -1) layout.addWidget(_doScrapeBtn, 5, 0) layout.addWidget(self.getRundownBtn, 5, 1) layout.addWidget(_cancelBtn, 6, 1) layout.addWidget(self.acceptBtn, 6, 2) self.setLayout(layout) def setExternalParameters(self, extPa): """extPa is a dictionary of external parameters that can be passed""" if 'Max' in extPa: self.selecter.setMaximum(extPa['Max']) print("Changing spinbox max to : {}".format(extPa['Max'])) if 'Min' in extPa: self.selecter.setMinimum(extPa['Min']) print("Changing spinbox min to : {}".format(extPa['Min'])) if 'tPeaks' in extPa: self.tPeaks = extPa['tPeaks'] def prepGuiParameters(self): """Take parameters specified by GUI""" #True if box is checked, otherwise False self.ignore = self.skipRB.isChecked() self.psr = self.psrSB.value() // 2 #floor division to get ears def addDataset(self, data): """Bring in external dataset for analysis""" self.tracedata = data.traces # each dataframe in this dictionary could have a different set of ROI self.name = data.DSname + "_expk" tdk = self.tracedata.keys() tdk_display = ", ".join(str(k) for k in tdk) N_ROI = np.array([len(self.tracedata[d].columns) for d in tdk]) N_Peaks = len(self.tPeaks) self.total_peaks = (N_ROI * N_Peaks).sum() self.N_ROI_label.setText( "Extracting {} peaks from {} ROIs (total {})\n over the sets named {}" .format(N_Peaks, N_ROI, self.total_peaks, tdk_display)) _printable = "{}\n{}\n".format(tdk_display, [self.tracedata[d].head() for d in tdk]) print("Added data of type {}:\n{}\n".format(type(self.tracedata), _printable)) self.maskLowSNR() def getRundown(self, silent=False): rtext = "" self.rundownCount = 0 for _condi, _pkdf in self.pk_extracted_by_condi.items(): _Np = len(_pkdf.index) _NROI = len(_pkdf.columns) ten_percent = int(_Np / 10) rtext += "{} condition, 10% of peaks count is {} peaks\n".format( _condi, ten_percent) # look at first 5 peaks _firsttenpc = _pkdf.iloc[0:ten_percent].describe().loc["mean"] # look at last 5 peaks _lasttenpc = _pkdf.iloc[-1 - ten_percent:-1].describe().loc["mean"] _tdf = self.tracedata[_condi] _max = _tdf.max() _SD = _tdf.std() _bestSNR = _max / _SD _startSNR = _firsttenpc / _SD _endSNR = _lasttenpc / _SD #print ("ff, lf : {} {}".format(_firstfive, _lastfive)) _rundownRatio = _lasttenpc.div(_firsttenpc).sort_values() self.rundownCount += _rundownRatio[ _rundownRatio < self.rundownThreshold].count() _rd_SNR = pd.concat([_rundownRatio, _bestSNR, _startSNR, _endSNR], axis=1) _rd_SNR.columns = [ 'Rundown', 'Best SNR', 'Initial SNR', 'Final SNR' ] rtext += "Rundown (amplitude ratio: last 10% / first 10%) and signal to noise ratio (start, end)\nfor {} ROIs (ROIs with worst rundown first):\n{}\n\n".format( _NROI, _rd_SNR.round(2).to_string()) rtext += "Total number of traces with rundown worse than threshold ({}): {}\n".format( self.rundownThreshold, self.rundownCount) print(rtext) if not silent: ###Make a pop up window of these results qmb = QDialog() qmb.setWindowTitle('Rundown {}'.format(self.name)) qmb.setGeometry(800, 600, 600, 600) self.rundownText = QtGui.QTextEdit() font = QtGui.QFont() font.setFamily('Courier') font.setFixedPitch(True) font.setPointSize(12) self.rundownText.setCurrentFont(font) self.rundownText.setText(rtext) self.rundownText.setReadOnly(True) #add buttons, make it the right size qmb.layout = QVBoxLayout() qmb.layout.addWidget(self.rundownText) qmb.setLayout(qmb.layout) qmb.exec_() def scrapePeaks(self): """Some peak-finding function with output filtering based on SNR""" self.prepGuiParameters() self.pk_extracted_by_condi = {} for _condi in self.tracedata.keys(): maxVal = len(self.tPeaks) ROI_df = self.tracedata[_condi] #print (ROI_df) peaksList = [] progMsg = "Get {0} peaks, {1} set..".format(maxVal, _condi) with pg.ProgressDialog(progMsg, 0, maxVal) as dlg: dlg.setMinimumWidth(300) for t in self.tPeaks: dlg += 1 idx = np.searchsorted(ROI_df.index, t) # avoid falling off start or end of columns e = max(idx - self.psr, 0) # zero biased so add one. l = min(idx + self.psr + 1, len(ROI_df.index)) print(t, e, idx, l, ROI_df.iloc[e:l]) p = ROI_df.iloc[e:l].max().to_frame().transpose() peaksList.append(p) #stick rows together (all have same zero index...) peaksdf = pd.concat(peaksList) # Overwrite index with the original peak positions # (somewhat inexact because of the 'range') peaksdf.index = self.tPeaks self.pk_extracted_by_condi[_condi] = peaksdf # yes, output may be modified below self.peaksScraped = True self.acceptBtn.setEnabled(True) self.getRundownBtn.setEnabled(True) self.noiseRB.setEnabled(True) self.noiseSB.setEnabled(True) self.excludedListedByCondi = {} if self.ignore: # freshly excludedList peaks from traces with low SNR self.maskLowSNR() self.splitAllowedExcluded() def splitAllowedExcluded(self): # the cut-off value _cut = self.excludeSNRcut #split peak data into sets from high and low SNR for s in self.pk_extracted_by_condi.keys(): wls = self.allowedLists[s] bls = self.excludedLists[s] pk = self.pk_extracted_by_condi[s] allowedListed = pk[wls.sort_values(ascending=False).index] excludedListed = pk[bls.sort_values(ascending=False).index] self.pk_extracted_by_condi[s] = allowedListed self.excludedListedByCondi[s + "_SNR<" + str(_cut)] = excludedListed def prepareAccept(self): # substitute failures (destructively) if self.failures_nulled: self.pk_extracted_by_condi = self.pk_extracted_with_failures # divide peak results into Allowed list and Excluded list based on SNR self.splitAllowedExcluded() self.accept() def setFailures(self): self.failures_nulled = True # setting failures modifies the output destructively and must retain original!!! self.pk_extracted_with_failures = self.pk_extracted_by_condi.copy( ) #is that enough? if self.noiseRB.isChecked == False: self.noiseSB.setDisabled(True) return else: self.noiseSB.setEnabled(True) # in allowedList traces self.noiseCut = self.noiseSB.value() print("Self.noisecut {}".format(self.noiseCut)) _numberCut = 0 for _condi in self.tracedata: _peaksDF = self.pk_extracted_with_failures[_condi] _df = self.tracedata[_condi] #print (_df) _noise = _df.std() #print ("NOISE: ", _noise) _peaksDF = _peaksDF.where(_peaksDF > _noise * self.noiseCut, 0) #print ("peaksdf",_peaksDF ) _bycol = _peaksDF.isin([0.0]).sum() #print ("bycol {} sum {}".format(_bycol, _bycol.sum())) _numberCut += _bycol.sum() self.pk_extracted_with_failures[_condi] = _peaksDF # Provide some indication of total peaks altered interactively self.peaksLabel.setText( "{} peaks set as failures ({: .1f}% of total).".format( _numberCut, 100 * _numberCut / self.total_peaks)) def maskLowSNR(self): """split the peak output according to SNR of parent traces""" """moving the spinbox for SNR Cutoff also comes here""" print('maskLowSNR') if self.skipRB.isChecked == False: self.skipSB.setDisabled(True) return else: self.skipSB.setEnabled(True) self.excludeSNRcut = self.skipSB.value() # use selective region (LR?) # or just the whole trace? #store allowedLists and excludedLists as values with the set as key. self.allowedLists = {} self.excludedLists = {} self.allowedCount = 0 self.excludedCount = 0 for _condi, _tdf in self.tracedata.items(): #_df = self.tracedata[_condi] # find SNR from column-wise Max / SD _max = _tdf.max() _SD = _tdf.std() snr = _max / _SD #print ("max {}, sd {}, snr {}".format(_max, _SD, snr)) # add histogram of SNR values with 'SNRcut'-off drawn? self.allowedLists[_condi] = snr.where( snr >= self.excludeSNRcut).dropna() self.excludedLists[_condi] = snr.where( snr < self.excludeSNRcut).dropna() self.allowedCount += len(self.allowedLists[_condi]) self.excludedCount += len(self.excludedLists[_condi]) #print ("allowedList: "+_condi, self.allowedLists[_condi]) #print ("excludedList: "+_condi, self.excludedLists[_condi]) #update dialog skipLabelText = "Skipping {0} traces out of {1} for low SNR.".format( self.excludedCount, self.allowedCount + self.excludedCount) self.skipRB.setText(skipLabelText)
class TornaSettingsDialog(QDialog): def __init__(self, parent=None, torna_id=None): super(TornaSettingsDialog, self).__init__(parent) self.parent = parent self.setModal(True) self.setWindowTitle("Verseny beállítások") self.torna_id = torna_id self.main_layout = QVBoxLayout() self.setLayout(self.main_layout) if self.torna_id is not None: self.create_torna_selection() self.set_layouts() self.add_variables() self.alapertekek() self.add_buttonbox() def set_layouts(self): self.tartalom_layout = QHBoxLayout() self.main_layout.addLayout(self.tartalom_layout) self.layout = QVBoxLayout() self.gomb_layout = QVBoxLayout() self.tartalom_layout.addLayout(self.layout) self.tartalom_layout.addLayout(self.gomb_layout) def add_variables(self): self.layout.addWidget(QLabel("A verseny megnevezése:")) self.torna_name = QLineEdit() self.torna_name.setPlaceholderText("A verseny megnevezése") self.layout.addWidget(self.torna_name) self.layout.addWidget(QLabel("Legyen csoportkör?")) self.is_roundrobin = QCheckBox() self.is_roundrobin.stateChanged.connect(self.roundrobin_changed) self.layout.addWidget(self.is_roundrobin) self.layout.addWidget(QLabel("Csoportok száma:")) self.csoport_number = CustomSpinBox(1, 16) self.layout.addWidget(self.csoport_number) self.layout.addWidget(QLabel("Játékosok száma csoportonként:")) self.jatekos_per_csoport = CustomSpinBox(3, 8) self.layout.addWidget(self.jatekos_per_csoport) self.layout.addWidget(QLabel("Játéknem:")) self.variant = CustomSpinBox(301, 1001) self.layout.addWidget(self.variant) self.layout.addWidget(QLabel("Set-ek?:")) self.is_sets = QCheckBox() self.is_sets.stateChanged.connect(self.is_sets_changed) self.layout.addWidget(self.is_sets) self.layout.addWidget(QLabel("Set-ek száma:")) self.sets_number = CustomSpinBox(1, 8) self.sets_number.setDisabled(True) self.layout.addWidget(self.sets_number) self.layout.addWidget(QLabel("Leg-ek száma:")) self.legs_number = CustomSpinBox(2, 30) self.layout.addWidget(self.legs_number) self.layout.addWidget(QLabel("Best of...")) self.is_best = QCheckBox() self.layout.addWidget(self.is_best) self.layout.addWidget(QLabel("Döntetlen")) self.is_draw = QCheckBox() self.is_draw.stateChanged.connect(self.is_draw_changed) self.layout.addWidget(self.is_draw) self.layout.addWidget(QLabel("Pont(Győzelem):")) self.pont_win = CustomSpinBox(2, 5) self.layout.addWidget(self.pont_win) self.layout.addWidget(QLabel("Pont(Döntetlen):")) self.pont_draw = CustomSpinBox(1, 3) self.pont_draw.setDisabled(True) self.layout.addWidget(self.pont_draw) self.layout.addWidget(QLabel("Pont(Vereség):")) self.pont_lost = CustomSpinBox(0, 2) self.layout.addWidget(self.pont_lost) self.layout.addWidget(QLabel("Főág")) self.is_single_elim = QCheckBox() self.is_single_elim.stateChanged.connect(self.is_single_changed) self.layout.addWidget(self.is_single_elim) self.layout.addWidget(QLabel("Főág száma:")) self.num_single = CustomSpinBox(4, 128) self.num_single.setDisabled(True) self.layout.addWidget(self.num_single) self.layout.addWidget(QLabel("Leg-ek száma a főágon:")) self.leg_num_single = CustomSpinBox(3, 20) self.leg_num_single.setDisabled(True) self.layout.addWidget(self.leg_num_single) self.layout.addWidget(QLabel("Leg-ek száma az elődöntőben:")) self.leg_num_semifinal = CustomSpinBox(4, 20) self.leg_num_semifinal.setDisabled(True) self.layout.addWidget(self.leg_num_semifinal) self.layout.addWidget(QLabel("Leg-ek száma a döntőben:")) self.leg_num_final = CustomSpinBox(5, 20) self.leg_num_final.setDisabled(True) self.layout.addWidget(self.leg_num_final) self.layout.addWidget(QLabel("3. hely kijátszva")) self.is_3place = QCheckBox() self.is_3place.stateChanged.connect(self.is_3place_changed) self.is_3place.setDisabled(True) self.layout.addWidget(self.is_3place) self.layout.addWidget(QLabel("Leg-ek száma a 3. helyért:")) self.leg_num_3place = CustomSpinBox(4, 20) self.leg_num_3place.setDisabled(True) self.layout.addWidget(self.leg_num_3place) def create_torna_selection(self): self.tournaments = QComboBox() self.tournaments.setModelColumn(0) self.tournaments.currentIndexChanged.connect(self.torna_valasztas) self.main_layout.addWidget(self.tournaments) self.load_torna() def load_torna(self): torna = QSqlQueryModel() query = QSqlQuery("select * from torna_settings where aktiv=2") torna.setQuery(query) if torna.record(0).value(0): for i in range(torna.rowCount()): self.tournaments.addItem( torna.record(i).value(1), torna.record(i).value(0)) # a value(0) a torna_id else: print("Nincs aktív torna") def torna_valasztas(self, i): self.torna_id = self.tournaments.itemData(i) self.alapertekek() def alapertekek(self): if not self.torna_id: self.torna_name.clear() self.is_roundrobin.setChecked(True) self.csoport_number.setValue(1) self.jatekos_per_csoport.setValue(4) self.variant.setValue(501) self.is_sets.setChecked(False) self.sets_number.setValue(1) self.legs_number.setValue(2) self.is_best.setChecked(False) self.is_draw.setChecked(False) self.pont_win.setValue(2) self.pont_draw.setValue(1) self.pont_lost.setValue(0) self.is_single_elim.setChecked(False) self.num_single.setValue(8) self.leg_num_single.setValue(3) self.leg_num_semifinal.setValue(4) self.leg_num_final.setValue(5) self.is_3place.setChecked(False) self.leg_num_3place.setValue(4) else: model = QSqlTableModel(db=db) model.setTable("torna_settings") model.setFilter(f"torna_id={self.torna_id}") model.select() # print(model.record(0)) self.torna_name.setText(model.record(0).value(1)) self.is_roundrobin.setChecked(model.record(0).value(2)) self.csoport_number.setValue(model.record(0).value(3)) self.jatekos_per_csoport.setValue(model.record(0).value(4)) self.variant.setValue(int(model.record(0).value(5))) self.is_sets.setChecked(model.record(0).value(6)) self.sets_number.setValue(model.record(0).value(7)) self.legs_number.setValue(model.record(0).value(8)) self.is_best.setChecked(model.record(0).value(9)) self.is_draw.setChecked(model.record(0).value(10)) self.pont_win.setValue(model.record(0).value(11)) self.pont_draw.setValue(model.record(0).value(12)) self.pont_lost.setValue(model.record(0).value(13)) self.is_single_elim.setChecked(model.record(0).value(14)) self.num_single.setValue(model.record(0).value(15)) self.leg_num_single.setValue(model.record(0).value(17)) self.leg_num_semifinal.setValue(model.record(0).value(18)) self.leg_num_final.setValue(model.record(0).value(20)) self.is_3place.setChecked(model.record(0).value(16)) self.leg_num_3place.setValue(model.record(0).value(19)) def add_buttonbox(self): self.buttonbox = QDialogButtonBox() self.buttonbox.setOrientation(Qt.Vertical) self.buttonbox.addButton("Mentés", QDialogButtonBox.ActionRole) self.buttonbox.addButton("Alaphelyzet", QDialogButtonBox.ActionRole) # self.gomb_members = QPushButton("Résztvevők") # self.gomb_members.setDisabled(True) # self.buttonbox.addButton(self.gomb_members, QDialogButtonBox.ActionRole) # self.gomb_tabella = QPushButton("Tabella") # self.gomb_tabella.setDisabled(True) # self.buttonbox.addButton(self.gomb_tabella, QDialogButtonBox.ActionRole) self.buttonbox.addButton("Mégsem", QDialogButtonBox.ActionRole) self.buttonbox.clicked.connect(self.buttonbox_click) self.gomb_layout.addWidget(self.buttonbox) def roundrobin_changed(self, state): if state == Qt.Checked: self.csoport_number.setDisabled(False) self.jatekos_per_csoport.setDisabled(False) else: self.csoport_number.setDisabled(True) self.jatekos_per_csoport.setDisabled(True) def is_sets_changed(self, state): if state == Qt.Checked: self.sets_number.setDisabled(False) else: self.sets_number.setDisabled(True) def is_draw_changed(self, state): if state == Qt.Checked: self.pont_draw.setDisabled(False) else: self.pont_draw.setDisabled(True) def is_single_changed(self, state): # a főághoz kapcsolódó paraméterek tiltása/engedélyezése if state == Qt.Checked: self.num_single.setDisabled(False) self.is_3place.setDisabled(False) self.leg_num_single.setDisabled(False) self.leg_num_semifinal.setDisabled(False) if self.is_3place.isChecked(): self.leg_num_3place.setDisabled(False) else: self.leg_num_3place.setDisabled(True) self.leg_num_final.setDisabled(False) else: self.num_single.setDisabled(True) self.is_3place.setDisabled(True) self.leg_num_single.setDisabled(True) self.leg_num_semifinal.setDisabled(True) self.leg_num_3place.setDisabled(True) self.leg_num_final.setDisabled(True) def is_3place_changed(self, state): if state == Qt.Checked: self.leg_num_3place.setDisabled(False) else: self.leg_num_3place.setDisabled(True) def buttonbox_click(self, b): if b.text() == "Mentés": self.save() elif b.text() == "Alaphelyzet": self.alapertekek() # elif b.text() == "Résztvevők": # self.members() # elif b.text() == "Tabella": # self.tabella() elif b.text() == "Mégsem": self.reject() else: pass def save(self): if not self.torna_id: self.insert_torna_settings() else: self.update_torna_settings() self.close() def insert_torna_settings(self): van_ilyen_nev = False if len(self.torna_name.text()) != 0: torna_id_model = QSqlQueryModel() query = QSqlQuery( "select torna_id, torna_name from torna_settings", db=db) torna_id_model.setQuery(query) for i in range(torna_id_model.rowCount()): if torna_id_model.record(i).value(1) == self.torna_name.text(): msg = QMessageBox(self) msg.setStyleSheet("fonz-size: 20px") msg.setWindowTitle("Név ütközés!") msg.setText( '<html style="font-size: 14px; color: red">Már van ilyen nevű verseny!<br></html>' + '<html style="font-size: 16px">Kérem adjon a versenynek egyedi nevet!</html>' ) msg.exec_() van_ilyen_nev = True if not van_ilyen_nev: torna_settings_model = QSqlTableModel( db=db ) # !!!!!!! Ha több db van, akkor itt konkrétan meg kell adni torna_settings_model.setTable("torna_settings") record = torna_settings_model.record() record.setValue(1, self.torna_name.text()) if self.is_roundrobin.isChecked(): record.setValue(2, 1) else: record.setValue(2, 0) record.setValue(3, self.csoport_number.value()) record.setValue(4, self.jatekos_per_csoport.value()) record.setValue(5, self.variant.value()) if self.is_sets.isChecked(): record.setValue(6, 1) else: record.setValue(6, 0) record.setValue(7, self.sets_number.value()) record.setValue(8, self.legs_number.value()) # print(record.value(2)) if self.is_best.isChecked(): record.setValue(9, 1) else: record.setValue(9, 0) if self.is_draw.isChecked(): record.setValue(10, 1) else: record.setValue(10, 0) record.setValue(11, self.pont_win.value()) record.setValue(12, self.pont_draw.value()) record.setValue(13, self.pont_lost.value()) if self.is_single_elim.isChecked(): record.setValue(14, 1) else: record.setValue(14, 0) record.setValue(15, self.num_single.value()) if self.is_3place.isChecked(): record.setValue(16, 1) else: record.setValue(16, 0) record.setValue(17, self.leg_num_single.value()) record.setValue(18, self.leg_num_semifinal.value()) record.setValue(19, self.leg_num_3place.value()) record.setValue(20, self.leg_num_final.value()) record.setValue(21, 2) # aktiv flag: 0: vége, 1: folyamatban, 2: szerkesztés alatt # print(record) if torna_settings_model.insertRecord(-1, record): torna_settings_model.submitAll() else: db.rollback() torna_id_model2 = QSqlQueryModel() query2 = QSqlQuery( f"select torna_id from torna_settings where torna_name='{self.torna_name.text()}'", db=db) torna_id_model2.setQuery(query2) self.torna_id = int(torna_id_model2.record(0).value(0)) self.gomb_members.setDisabled(False) else: msg = QMessageBox(self) msg.setStyleSheet("fonz-size: 20px") msg.setWindowTitle("Hiányzik a verseny neve!") msg.setText( '<html style="font-size: 14px; color: red">A létrehozott versenynek kell egy elnevezés!<br></html>' + '<html style="font-size: 16px">Kérem adja meg a verseny nevét!</html>' ) msg.exec_() def update_torna_settings(self): torna_settings_model = QSqlTableModel(db=db) torna_settings_model.setTable("torna_settings") record = torna_settings_model.record() torna_settings_model.select() # for x in range(torna_settings_model.rowCount()): # record.setGenerated(x, False) record.setValue(0, self.torna_id) record.setValue(1, self.torna_name.text()) if self.is_roundrobin.isChecked(): record.setValue(2, 1) else: record.setValue(2, 0) record.setValue(3, self.csoport_number.value()) record.setValue(4, self.jatekos_per_csoport.value()) record.setValue(5, self.variant.value()) if self.is_sets.isChecked(): record.setValue(6, 1) else: record.setValue(6, 0) record.setValue(7, self.sets_number.value()) record.setValue(8, self.legs_number.value()) if self.is_best.isChecked(): record.setValue(9, 1) else: record.setValue(9, 0) if self.is_draw.isChecked(): record.setValue(10, 1) else: record.setValue(10, 0) record.setValue(11, self.pont_win.value()) record.setValue(12, self.pont_draw.value()) record.setValue(13, self.pont_lost.value()) if self.is_single_elim.isChecked(): record.setValue(14, 1) else: record.setValue(14, 0) record.setValue(15, self.num_single.value()) if self.is_3place.isChecked(): record.setValue(16, 1) else: record.setValue(16, 0) record.setValue(17, self.leg_num_single.value()) record.setValue(18, self.leg_num_semifinal.value()) record.setValue(19, self.leg_num_3place.value()) record.setValue(20, self.leg_num_final.value()) record.setValue(21, 2) for i in range(torna_settings_model.rowCount()): if torna_settings_model.record(i).value(0) == self.torna_id: # print(torna_settings_model.record(i).value(0), ":", i) record_number = i # print(record) if torna_settings_model.setRecord(record_number, record): torna_settings_model.submitAll() else: db.rollback() # def members(self): # # todo Itt kell a verseny résztvevőit öszerakni # pass # # def tabella(self): # # todo Itt kell a sorsolást, tabella összeállítást megcsinálni # pass def accept(self): # todo Ez majd csak a bezáráshoz kell super().accept() def reject(self): print("CANCEL") super().reject()
class TimekeepingPropertiesDialog(QDialog): def __init__(self): super().__init__(GlobalAccess().get_main_window()) self.time_format = 'hh:mm:ss' def exec_(self): self.init_ui() return super().exec_() def init_ui(self): # self.setFixedWidth(500) self.setWindowTitle(_('Timekeeping settings')) # self.setWindowIcon(QIcon(icon_dir('sportident.png'))) self.setSizeGripEnabled(False) self.setModal(True) self.tab_widget = QTabWidget() # timekeeping tab self.timekeeping_tab = QWidget() self.tk_layout = QFormLayout() self.label_zero_time = QLabel(_('Zero time')) self.item_zero_time = QTimeEdit() self.item_zero_time.setDisplayFormat("HH:mm") self.item_zero_time.setMaximumSize(60, 20) self.item_zero_time.setDisabled(True) self.tk_layout.addRow(self.label_zero_time, self.item_zero_time) self.label_si_port = QLabel(_('Available Ports')) self.item_si_port = AdvComboBox() self.item_si_port.addItems(SIReaderClient().get_ports()) self.tk_layout.addRow(self.label_si_port, self.item_si_port) self.start_group_box = QGroupBox(_('Start time')) self.start_layout = QFormLayout() self.item_start_protocol = QRadioButton(_('From protocol')) self.start_layout.addRow(self.item_start_protocol) self.item_start_station = QRadioButton(_('Start station')) self.start_layout.addRow(self.item_start_station) self.item_start_cp = QRadioButton(_('Control point')) self.item_start_cp_value = QSpinBox() self.item_start_cp_value.setMaximumSize(60, 20) self.start_layout.addRow(self.item_start_cp, self.item_start_cp_value) self.item_start_gate = QRadioButton(_('Start gate')) self.item_start_gate.setDisabled(True) self.start_layout.addRow(self.item_start_gate) self.start_group_box.setLayout(self.start_layout) self.tk_layout.addRow(self.start_group_box) self.finish_group_box = QGroupBox(_('Finish time')) self.finish_layout = QFormLayout() self.item_finish_station = QRadioButton(_('Finish station')) self.finish_layout.addRow(self.item_finish_station) self.item_finish_cp = QRadioButton(_('Control point')) self.item_finish_cp_value = QSpinBox() self.item_finish_cp_value.setMinimum(-1) self.item_finish_cp_value.setMaximumSize(60, 20) self.finish_layout.addRow(self.item_finish_cp, self.item_finish_cp_value) self.item_finish_beam = QRadioButton(_('Light beam')) self.item_finish_beam.setDisabled(True) self.finish_layout.addRow(self.item_finish_beam) self.finish_group_box.setLayout(self.finish_layout) self.tk_layout.addRow(self.finish_group_box) self.chip_reading_box = QGroupBox(_('Assigning a chip when reading')) self.chip_reading_layout = QFormLayout() self.chip_reading_off = QRadioButton(_('Off')) self.chip_reading_layout.addRow(self.chip_reading_off) self.chip_reading_unknown = QRadioButton(_('Only unknown members')) self.chip_reading_layout.addRow(self.chip_reading_unknown) self.chip_reading_always = QRadioButton(_('Always')) self.chip_reading_layout.addRow(self.chip_reading_always) self.chip_reading_autocreate = QRadioButton(_('Athlete auto create')) self.chip_reading_layout.addRow(self.chip_reading_autocreate) self.chip_reading_box.setLayout(self.chip_reading_layout) self.tk_layout.addRow(self.chip_reading_box) self.chip_duplicate_box = QGroupBox(_('Several readout of chip')) self.chip_duplicate_layout = QFormLayout() self.chip_duplicate_serveral_results = QRadioButton(_('Several results')) self.chip_duplicate_layout.addRow(self.chip_duplicate_serveral_results) self.chip_duplicate_bib_request = QRadioButton(_('Ask for a bib when re-reading the card')) self.chip_duplicate_layout.addRow(self.chip_duplicate_bib_request) self.chip_duplicate_relay_find_leg = QRadioButton(_('Find next relay leg')) self.chip_duplicate_layout.addRow(self.chip_duplicate_relay_find_leg) self.chip_duplicate_merge = QRadioButton(_('Merge punches')) self.chip_duplicate_layout.addRow(self.chip_duplicate_merge) self.chip_duplicate_box.setLayout(self.chip_duplicate_layout) self.tk_layout.addRow(self.chip_duplicate_box) self.assignment_mode = QCheckBox(_('Assignment mode')) self.assignment_mode.stateChanged.connect(self.on_assignment_mode) self.tk_layout.addRow(self.assignment_mode) self.timekeeping_tab.setLayout(self.tk_layout) # result processing tab self.result_proc_tab = QWidget() self.result_proc_layout = QFormLayout() self.rp_time_radio = QRadioButton(_('by time')) self.result_proc_layout.addRow(self.rp_time_radio) self.rp_scores_radio = QRadioButton(_('by scores')) self.result_proc_layout.addRow(self.rp_scores_radio) self.rp_scores_group = QGroupBox() self.rp_scores_layout = QFormLayout(self.rp_scores_group) self.rp_rogain_scores_radio = QRadioButton(_('rogain scores')) self.rp_scores_layout.addRow(self.rp_rogain_scores_radio) self.rp_fixed_scores_radio = QRadioButton(_('fixed scores')) self.rp_fixed_scores_edit = QSpinBox() self.rp_fixed_scores_edit.setMaximumWidth(50) self.rp_scores_layout.addRow(self.rp_fixed_scores_radio, self.rp_fixed_scores_edit) self.rp_scores_minute_penalty_label = QLabel(_('minute penalty')) self.rp_scores_minute_penalty_edit = QSpinBox() self.rp_scores_minute_penalty_edit.setMaximumWidth(50) self.rp_scores_layout.addRow(self.rp_scores_minute_penalty_label, self.rp_scores_minute_penalty_edit) self.result_proc_layout.addRow(self.rp_scores_group) self.result_proc_tab.setLayout(self.result_proc_layout) # marked route settings self.marked_route_tab = QWidget() self.mr_layout = QFormLayout() self.mr_off_radio = QRadioButton(_('no penalty')) self.mr_layout.addRow(self.mr_off_radio) self.mr_time_radio = QRadioButton(_('penalty time')) self.mr_time_edit = QTimeEdit() self.mr_time_edit.setDisplayFormat(self.time_format) self.mr_layout.addRow(self.mr_time_radio, self.mr_time_edit) self.mr_laps_radio = QRadioButton(_('penalty laps')) self.mr_layout.addRow(self.mr_laps_radio) self.mr_counting_lap_check = QCheckBox(_('counting lap')) self.mr_counting_lap_check.setDisabled(True) # TODO self.mr_layout.addRow(self.mr_counting_lap_check) self.mr_lap_station_check = QCheckBox(_('lap station')) self.mr_lap_station_check.setDisabled(True) # TODO self.mr_lap_station_edit = QSpinBox() self.mr_lap_station_edit.setMaximumWidth(50) self.mr_layout.addRow(self.mr_lap_station_check, self.mr_lap_station_edit) self.mr_dont_dqs_check = QCheckBox(_("Don't disqualify")) self.mr_layout.addRow(self.mr_dont_dqs_check) self.mr_max_penalty_by_cp = QCheckBox(_("Max penalty = quantity of cp")) self.mr_layout.addRow(self.mr_max_penalty_by_cp) self.marked_route_tab.setLayout(self.mr_layout) # scores """ Scores [ x ] scores array 40, 37, 35, 33, ... 2, 1 [ Edit ] [ ] scores formula 1000 - 1000 * result / leader [ Edit ] """ self.scores_tab = QWidget() self.scores_layout = QFormLayout() self.scores_off = QRadioButton(_('scores off')) self.scores_array = QRadioButton(_('scores array')) self.scores_array_edit = QLineEdit() self.scores_formula = QRadioButton(_('scores formula')) self.scores_formula_edit = QLineEdit() self.scores_formula_hint = QLabel(_('scores formula hint')) self.scores_formula_hint.setWordWrap(True) self.scores_layout.addRow(self.scores_off) self.scores_layout.addRow(self.scores_array) self.scores_layout.addRow(self.scores_array_edit) self.scores_layout.addRow(self.scores_formula) self.scores_layout.addRow(self.scores_formula_edit) self.scores_layout.addRow(self.scores_formula_hint) self.scores_tab.setLayout(self.scores_layout) # time settings self.time_settings_tab = QWidget() self.time_settings_layout = QFormLayout() self.time_settings_accuracy_label = QLabel(_('Accuracy')) self.time_settings_accuracy_edit = QSpinBox() self.time_settings_accuracy_edit.setMaximumWidth(50) self.time_settings_accuracy_edit.setMaximum(3) self.time_settings_layout.addRow(self.time_settings_accuracy_label, self.time_settings_accuracy_edit) self.time_settings_format = QGroupBox() self.time_settings_format.setTitle(_('Format of competitions')) self.time_settings_format_less = QRadioButton(_('< 24')) self.time_settings_format_more = QRadioButton(_('> 24')) self.time_settings_format_layout = QFormLayout() self.time_settings_format_layout.addRow(self.time_settings_format_less) self.time_settings_format_layout.addRow(self.time_settings_format_more) self.time_settings_format.setLayout(self.time_settings_format_layout) self.time_settings_layout.addRow(self.time_settings_format) self.time_settings_tab.setLayout(self.time_settings_layout) self.tab_widget.addTab(self.timekeeping_tab, _('SPORTident (Sportiduino, ...) settings')) self.tab_widget.addTab(self.result_proc_tab, _('Result processing')) self.tab_widget.addTab(self.scores_tab, _('Scores')) self.tab_widget.addTab(self.marked_route_tab, _('Penalty calculation')) self.tab_widget.addTab(self.time_settings_tab, _('Time settings')) def cancel_changes(): self.close() def apply_changes(): try: self.apply_changes_impl() except Exception as e: logging.error(str(e)) self.close() button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = button_box.button(QDialogButtonBox.Ok) self.button_ok.setText(_('OK')) self.button_ok.clicked.connect(apply_changes) self.button_cancel = button_box.button(QDialogButtonBox.Cancel) self.button_cancel.setText(_('Cancel')) self.button_cancel.clicked.connect(cancel_changes) self.layout = QFormLayout(self) self.layout.addRow(self.tab_widget) self.layout.addRow(button_box) self.set_values_from_model() self.show() def on_assignment_mode(self): mode = False if self.assignment_mode.isChecked(): mode = True self.start_group_box.setDisabled(mode) self.finish_group_box.setDisabled(mode) self.chip_reading_box.setDisabled(mode) self.chip_duplicate_box.setDisabled(mode) def set_values_from_model(self): cur_race = race() zero_time = cur_race.get_setting('system_zero_time', (8, 0, 0)) start_source = cur_race.get_setting('system_start_source', 'protocol') start_cp_number = cur_race.get_setting('system_start_cp_number', 31) finish_source = cur_race.get_setting('system_finish_source', 'station') finish_cp_number = cur_race.get_setting('system_finish_cp_number', 90) assign_chip_reading = cur_race.get_setting('system_assign_chip_reading', 'off') duplicate_chip_processing = cur_race.get_setting('system_duplicate_chip_processing', 'several_results') assignment_mode = cur_race.get_setting('system_assignment_mode', False) si_port = cur_race.get_setting('system_port', '') self.item_zero_time.setTime(QTime(zero_time[0], zero_time[1])) self.item_si_port.setCurrentText(si_port) if start_source == 'protocol': self.item_start_protocol.setChecked(True) elif start_source == 'station': self.item_start_station.setChecked(True) elif start_source == 'cp': self.item_start_cp.setChecked(True) elif start_source == 'gate': self.item_start_gate.setChecked(True) self.item_start_cp_value.setValue(start_cp_number) if finish_source == 'station': self.item_finish_station.setChecked(True) elif finish_source == 'cp': self.item_finish_cp.setChecked(True) elif finish_source == 'beam': self.item_finish_beam.setChecked(True) self.item_finish_cp_value.setValue(finish_cp_number) if assign_chip_reading == 'off': self.chip_reading_off.setChecked(True) elif assign_chip_reading == 'only_unknown_members': self.chip_reading_unknown.setChecked(True) elif assign_chip_reading == 'always': self.chip_reading_always.setChecked(True) elif assign_chip_reading == 'autocreate': self.chip_reading_autocreate.setChecked(True) if duplicate_chip_processing == 'several_results': self.chip_duplicate_serveral_results.setChecked(True) elif duplicate_chip_processing == 'bib_request': self.chip_duplicate_bib_request.setChecked(True) elif duplicate_chip_processing == 'relay_find_leg': self.chip_duplicate_relay_find_leg.setChecked(True) elif duplicate_chip_processing == 'merge': self.chip_duplicate_merge.setChecked(True) self.assignment_mode.setChecked(assignment_mode) # result processing obj = cur_race rp_mode = obj.get_setting('result_processing_mode', 'time') rp_score_mode = obj.get_setting('result_processing_score_mode', 'rogain') rp_fixed_scores_value = obj.get_setting('result_processing_fixed_score_value', 1) rp_scores_minute_penalty = obj.get_setting('result_processing_scores_minute_penalty', 1) if rp_mode == 'time': self.rp_time_radio.setChecked(True) else: self.rp_scores_radio.setChecked(True) if rp_score_mode == 'rogain': self.rp_rogain_scores_radio.setChecked(True) else: self.rp_fixed_scores_radio.setChecked(True) self.rp_fixed_scores_edit.setValue(rp_fixed_scores_value) self.rp_scores_minute_penalty_edit.setValue(rp_scores_minute_penalty) # penalty calculation mr_mode = obj.get_setting('marked_route_mode', 'off') mr_penalty_time = OTime(msec=obj.get_setting('marked_route_penalty_time', 60000)) mr_if_counting_lap = obj.get_setting('marked_route_if_counting_lap', True) mr_if_station_check = obj.get_setting('marked_route_if_station_check', False) mr_station_code = obj.get_setting('marked_route_station_code', 80) mr_if_dont_dsq_check = obj.get_setting('marked_route_dont_dsq', False) mr_if_max_penalty_by_cp = obj.get_setting('marked_route_max_penalty_by_cp', False) if mr_mode == 'off': self.mr_off_radio.setChecked(True) elif mr_mode == 'time': self.mr_time_radio.setChecked(True) else: self.mr_laps_radio.setChecked(True) self.mr_time_edit.setTime(mr_penalty_time.to_time()) self.mr_counting_lap_check.setChecked(mr_if_counting_lap) self.mr_lap_station_check.setChecked(mr_if_station_check) self.mr_lap_station_edit.setValue(mr_station_code) self.mr_dont_dqs_check.setChecked(mr_if_dont_dsq_check) self.mr_max_penalty_by_cp.setChecked(mr_if_max_penalty_by_cp) # score settings scores_mode = obj.get_setting('scores_mode', 'off') scores_array = obj.get_setting('scores_array', '40,37,35,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,' '16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1') scores_formula = obj.get_setting('scores_formula', '200 - 100 * time / leader') if scores_mode == 'off': self.scores_off.setChecked(True) elif scores_mode == 'array': self.scores_array.setChecked(True) elif scores_mode == 'formula': self.scores_formula.setChecked(True) self.scores_array_edit.setText(scores_array) self.scores_formula_edit.setText(scores_formula) # time settings time_accuracy = obj.get_setting('time_accuracy', 0) time_format_24 = obj.get_setting('time_format_24', 'less24') self.time_settings_accuracy_edit.setValue(time_accuracy) if time_format_24 == 'less24': self.time_settings_format_less.setChecked(True) elif time_format_24 == 'more24': self.time_settings_format_more.setChecked(True) def apply_changes_impl(self): obj = race() start_source = 'protocol' if self.item_start_station.isChecked(): start_source = 'station' elif self.item_start_cp.isChecked(): start_source = 'cp' elif self.item_start_gate.isChecked(): start_source = 'gate' finish_source = 'station' if self.item_finish_cp.isChecked(): finish_source = 'cp' elif self.item_finish_beam.isChecked(): finish_source = 'beam' assign_chip_reading = 'off' if self.chip_reading_unknown.isChecked(): assign_chip_reading = 'only_unknown_members' elif self.chip_reading_always.isChecked(): assign_chip_reading = 'always' elif self.chip_reading_autocreate.isChecked(): assign_chip_reading = 'autocreate' duplicate_chip_processing = 'several_results' if self.chip_duplicate_bib_request.isChecked(): duplicate_chip_processing = 'bib_request' elif self.chip_duplicate_relay_find_leg.isChecked(): duplicate_chip_processing = 'relay_find_leg' elif self.chip_duplicate_merge.isChecked(): duplicate_chip_processing = 'merge' start_cp_number = self.item_start_cp_value.value() finish_cp_number = self.item_finish_cp_value.value() old_start_cp_number = obj.get_setting('system_start_cp_number', 31) old_finish_cp_number = obj.get_setting('system_finish_cp_number', 90) if old_start_cp_number != start_cp_number or old_finish_cp_number != finish_cp_number: race().clear_results() obj.set_setting('system_port', self.item_si_port.currentText()) obj.set_setting('system_start_source', start_source) obj.set_setting('system_finish_source', finish_source) obj.set_setting('system_start_cp_number', start_cp_number) obj.set_setting('system_finish_cp_number', finish_cp_number) obj.set_setting('system_assign_chip_reading', assign_chip_reading) obj.set_setting('system_duplicate_chip_processing', duplicate_chip_processing) obj.set_setting('system_assignment_mode', self.assignment_mode.isChecked()) # result processing rp_mode = 'time' if self.rp_scores_radio.isChecked(): rp_mode = 'scores' rp_score_mode = 'rogain' if self.rp_fixed_scores_radio.isChecked(): rp_score_mode = 'fixed' rp_fixed_scores_value = self.rp_fixed_scores_edit.value() rp_scores_minute_penalty = self.rp_scores_minute_penalty_edit.value() obj.set_setting('result_processing_mode', rp_mode) obj.set_setting('result_processing_score_mode', rp_score_mode) obj.set_setting('result_processing_fixed_score_value', rp_fixed_scores_value) obj.set_setting('result_processing_scores_minute_penalty', rp_scores_minute_penalty) # marked route mr_mode = 'off' if self.mr_laps_radio.isChecked(): mr_mode = 'laps' if self.mr_time_radio.isChecked(): mr_mode = 'time' obj.set_setting('marked_route_mode', mr_mode) mr_penalty_time = time_to_otime(self.mr_time_edit.time()).to_msec() mr_if_counting_lap = self.mr_counting_lap_check.isChecked() mr_if_station_check = self.mr_lap_station_check.isChecked() mr_station_code = self.mr_lap_station_edit.value() mr_if_dont_dsq = self.mr_dont_dqs_check.isChecked() mr_if_max_penalty_by_cp = self.mr_max_penalty_by_cp.isChecked() obj.set_setting('marked_route_mode', mr_mode) obj.set_setting('marked_route_penalty_time', mr_penalty_time) obj.set_setting('marked_route_if_counting_lap', mr_if_counting_lap) obj.set_setting('marked_route_if_station_check', mr_if_station_check) obj.set_setting('marked_route_station_code', mr_station_code) obj.set_setting('marked_route_dont_dsq', mr_if_dont_dsq) obj.set_setting('marked_route_max_penalty_by_cp', mr_if_max_penalty_by_cp) # score settings scores_mode = 'off' if self.scores_array.isChecked(): scores_mode = 'array' elif self.scores_formula.isChecked(): scores_mode = 'formula' scores_array = self.scores_array_edit.text() scores_formula = self.scores_formula_edit.text() obj.set_setting('scores_mode', scores_mode) obj.set_setting('scores_array', scores_array) obj.set_setting('scores_formula', scores_formula) # time settings time_accuracy = self.time_settings_accuracy_edit.value() time_format_24 = 'less24' if self.time_settings_format_more.isChecked(): time_format_24 = 'more24' obj.set_setting('time_accuracy', time_accuracy) obj.set_setting('time_format_24', time_format_24) ResultCalculation(race()).process_results()
class NGL_HKLViewer(QWidget): def __init__(self, parent=None): super(NGL_HKLViewer, self).__init__(parent) self.verbose = 0 self.UseOSbrowser = False self.jscriptfname = "" self.devmode = False for e in sys.argv: if "verbose" in e: self.verbose = e.split("verbose=")[1] if "UseOSbrowser" in e: self.UseOSbrowser = e.split("UseOSbrowser=")[1] if "jscriptfname" in e: self.jscriptfname = e.split("jscriptfname=")[1] if "devmode" in e: self.devmode = True self.zmq_context = None self.bufsize = 20000 self.originalPalette = QApplication.palette() self.openFileNameButton = QPushButton("Load reflection file") self.openFileNameButton.setDefault(True) self.openFileNameButton.clicked.connect(self.OpenReflectionsFile) self.debugbutton = QPushButton("Debug") self.debugbutton.clicked.connect(self.DebugInteractively) self.settingsbtn = QPushButton("Settings") self.settingsbtn.clicked.connect(self.SettingsDialog) self.mousemoveslider = QSlider(Qt.Horizontal) self.mousemoveslider.setMinimum(0) self.mousemoveslider.setMaximum(300) self.mousemoveslider.setValue(0) self.mousemoveslider.sliderReleased.connect( self.onFinalMouseSensitivity) self.mousemoveslider.valueChanged.connect(self.onMouseSensitivity) self.mousesensitxtbox = QLineEdit('') self.mousesensitxtbox.setReadOnly(True) self.fontspinBox = QDoubleSpinBox() self.fontspinBox.setSingleStep(1) self.fontspinBox.setRange(4, 50) self.font = QFont() self.font.setFamily(self.font.defaultFamily()) self.fontspinBox.setValue(self.font.pointSize()) #self.fontspinBox.setValue(self.font.pixelSize()) self.fontspinBox.valueChanged.connect(self.onFontsizeChanged) self.Fontsize_labeltxt = QLabel() self.Fontsize_labeltxt.setText("Font size:") self.cameraPerspectCheckBox = QCheckBox() self.cameraPerspectCheckBox.setText("Perspective camera") self.cameraPerspectCheckBox.clicked.connect(self.onCameraPerspect) self.cameraPerspectCheckBox.setCheckState(Qt.Unchecked) self.settingsform = SettingsForm(self) self.MillerComboBox = QComboBox() self.MillerComboBox.activated.connect(self.onMillerComboSelchange) #self.MillerComboBox.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.MillerLabel = QLabel() self.MillerLabel.setText("Selected HKL Scene") self.HKLnameedit = QLineEdit('') self.HKLnameedit.setReadOnly(True) self.textInfo = QTextEdit() self.textInfo.setLineWrapMode(QTextEdit.NoWrap) self.textInfo.setReadOnly(True) labels = [ "Label", "Type", "no. of HKLs", "Span of HKLs", "Min Max data", "Min Max sigmas", "d_min, d_max", "Symmetry unique", "Anomalous" ] self.millertable = QTableWidget(0, len(labels)) self.millertable.setHorizontalHeaderLabels(labels) self.millertable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft) # don't allow editing this table self.millertable.setEditTriggers(QTableWidget.NoEditTriggers) self.createExpansionBox() self.createFileInfoBox() self.CreateSliceTabs() self.createRadiiScaleGroupBox() self.createBinsBox() self.CreateFunctionTabs() mainLayout = QGridLayout() mainLayout.addWidget(self.FileInfoBox, 0, 0) mainLayout.addWidget(self.MillerLabel, 1, 0) mainLayout.addWidget(self.MillerComboBox, 2, 0) mainLayout.addWidget(self.functionTabWidget, 3, 0) mainLayout.addWidget(self.settingsbtn, 4, 0, 1, 1) #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) if self.UseOSbrowser == False: self.BrowserBox = QWebEngineView() mainLayout.addWidget(self.BrowserBox, 0, 1, 5, 3) self.BrowserBox.setUrl("https://cctbx.github.io/") #self.BrowserBox.setUrl("https://webglreport.com/") #self.BrowserBox.loadFinished.connect(self.onLoadFinished) mainLayout.setColumnStretch(2, 1) mainLayout.setRowStretch(0, 1) mainLayout.setRowStretch(1, 0) mainLayout.setRowStretch(2, 1) mainLayout.setRowStretch(3, 1) mainLayout.setColumnStretch(4, 0) self.setLayout(mainLayout) self.setWindowTitle("HKL-Viewer") self.cctbxproc = None self.LaunchCCTBXPython() self.out = None self.err = None self.comboviewwidth = 0 self.hklscenes_arrays = [] self.array_infotpls = [] self.matching_arrays = [] self.bin_infotpls = None self.bin_opacities = None self.html_url = "" self.spacegroups = [] self.info = [] self.infostr = "" self.fileisvalid = False self.NewFileLoaded = False self.NewHKLscenes = False self.updatingNbins = False self.binstableitemchanges = False self.show() def SettingsDialog(self): self.settingsform.show() def update(self): if self.cctbxproc: if self.cctbxproc.stdout: print(self.cctbxproc.stdout.read().decode("utf-8")) if self.cctbxproc.stderr: print(self.cctbxproc.stderr.read().decode("utf-8")) if self.out: print(self.out.decode("utf-8")) if self.err: print(self.err.decode("utf-8")) if self.zmq_context: try: msg = self.socket.recv( flags=zmq.NOBLOCK ) #To empty the socket from previous messages msgstr = msg.decode() self.infodict = eval(msgstr) #print("received from cctbx: " + str(self.infodict)) if self.infodict: if self.infodict.get("hklscenes_arrays"): self.hklscenes_arrays = self.infodict.get( "hklscenes_arrays", []) if self.infodict.get("array_infotpls"): self.array_infotpls = self.infodict.get( "array_infotpls", []) if self.infodict.get("bin_data_label"): self.BinDataComboBox.setCurrentText( self.infodict["bin_data_label"]) if self.infodict.get("bin_infotpls"): self.bin_infotpls = self.infodict["bin_infotpls"] self.nbins = len(self.bin_infotpls) self.updatingNbins = True self.Nbins_spinBox.setValue(self.nbins) self.updatingNbins = False self.binstable.clearContents() self.binstable.setRowCount(self.nbins) for row, bin_infotpl in enumerate(self.bin_infotpls): for col, elm in enumerate(bin_infotpl): # only allow changing the last column with opacity values if col != 3: item = QTableWidgetItem(str(elm)) else: item = QTableWidgetItem() item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setCheckState(Qt.Checked) item.setFlags(item.flags() ^ Qt.ItemIsEditable) self.binstable.setItem(row, col, item) if self.bin_opacities: self.update_table_opacities() if self.infodict.get("bin_opacities"): self.bin_opacities = self.infodict["bin_opacities"] if self.binstable.rowCount() > 0: self.update_table_opacities() if self.infodict.get("html_url"): self.html_url = self.infodict["html_url"] if self.UseOSbrowser == False: self.BrowserBox.setUrl(self.html_url) # workaround for background colour bug in chromium # https://bugreports.qt.io/browse/QTBUG-41960 self.BrowserBox.page().setBackgroundColor( QColor(100, 100, 100, 1.0)) if self.infodict.get("spacegroups"): self.spacegroups = self.infodict.get("spacegroups", []) self.SpaceGroupComboBox.clear() self.SpaceGroupComboBox.addItems(self.spacegroups) if self.infodict.get("merge_data"): self.mergedata = self.infodict["merge_data"] currentinfostr = "" if self.infodict.get("info"): currentinfostr = self.infodict.get("info", []) if self.infodict.get("NewFileLoaded"): self.NewFileLoaded = self.infodict.get( "NewFileLoaded", False) if self.infodict.get("NewHKLscenes"): self.NewHKLscenes = self.infodict.get( "NewHKLscenes", False) self.fileisvalid = True #print("ngl_hkl_infodict: " + str(ngl_hkl_infodict)) if currentinfostr: #print(currentinfostr) self.infostr += currentinfostr + "\n" # display no more than self.bufsize bytes of text self.infostr = self.infostr[-self.bufsize:] self.textInfo.setPlainText(self.infostr) self.textInfo.verticalScrollBar().setValue( self.textInfo.verticalScrollBar().maximum()) if self.NewFileLoaded and self.NewHKLscenes: #if self.mergedata == True : val = Qt.CheckState.Checked #if self.mergedata == None : val = Qt.CheckState.PartiallyChecked #if self.mergedata == False : val = Qt.CheckState.Unchecked #self.mergecheckbox.setCheckState(val ) #print("got hklscenes: " + str(self.hklscenes_arrays)) self.MillerComboBox.clear() self.MillerComboBox.addItems( [e[3] for e in self.hklscenes_arrays]) self.MillerComboBox.setCurrentIndex( -1) # unselect the first item in the list self.comboviewwidth = 0 for e in self.hklscenes_arrays: self.comboviewwidth = max( self.comboviewwidth, self.MillerComboBox.fontMetrics().width(e[3])) self.MillerComboBox.view().setMinimumWidth( self.comboviewwidth) self.millertable.clearContents() self.millertable.setRowCount(len( self.hklscenes_arrays)) for n, millarr in enumerate(self.array_infotpls): for m, elm in enumerate(millarr): self.millertable.setItem( n, m, QTableWidgetItem(str(elm))) self.functionTabWidget.setDisabled(True) self.NewFileLoaded = False if self.NewHKLscenes: self.BinDataComboBox.clear() self.BinDataComboBox.addItems( ["Resolution"] + [e[3] for e in self.hklscenes_arrays]) self.BinDataComboBox.view().setMinimumWidth( self.comboviewwidth) #self.BinDataComboBox.setCurrentIndex(-1) # unselect the first item in the list self.NewHKLscenes = False except Exception as e: errmsg = str(e) if "Resource temporarily unavailable" not in errmsg: print(errmsg + traceback.format_exc(limit=10)) pass def onFinalMouseSensitivity(self): val = self.mousemoveslider.value() / 100.0 self.NGL_HKL_command( 'NGL_HKLviewer.viewer.NGL.mouse_sensitivity = %f' % val) def onMouseSensitivity(self): val = self.mousemoveslider.value() / 100.0 self.mousesensitxtbox.setText("%2.2f" % val) def onFontsizeChanged(self, val): font = app.font() font.setPointSize(val) app.setFont(font) self.settingsform.setFixedSize(self.settingsform.sizeHint()) def onCameraPerspect(self, val): if self.cameraPerspectCheckBox.isChecked(): self.NGL_HKL_command("NGL_HKLviewer.camera_type = perspective") else: self.NGL_HKL_command("NGL_HKLviewer.camera_type = orthographic") def MergeData(self): if self.mergecheckbox.checkState() == Qt.CheckState.Checked: self.NGL_HKL_command('NGL_HKLviewer.mergedata = True') if self.mergecheckbox.checkState() == Qt.CheckState.PartiallyChecked: self.NGL_HKL_command('NGL_HKLviewer.mergedata = None') if self.mergecheckbox.checkState() == Qt.CheckState.Unchecked: self.NGL_HKL_command('NGL_HKLviewer.mergedata = False') def ExpandToP1(self): if self.expandP1checkbox.isChecked(): self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = True') else: self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = False') def ExpandAnomalous(self): if self.expandAnomalouscheckbox.isChecked(): self.NGL_HKL_command( 'NGL_HKLviewer.viewer.expand_anomalous = True') else: self.NGL_HKL_command( 'NGL_HKLviewer.viewer.expand_anomalous = False') def showSysAbsent(self): if self.sysabsentcheckbox.isChecked(): self.NGL_HKL_command( 'NGL_HKLviewer.viewer.show_systematic_absences = True') else: self.NGL_HKL_command( 'NGL_HKLviewer.viewer.show_systematic_absences = False') def showMissing(self): if self.missingcheckbox.isChecked(): self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = True') else: self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = False') def showOnlyMissing(self): if self.onlymissingcheckbox.isChecked(): self.NGL_HKL_command( 'NGL_HKLviewer.viewer.show_only_missing = True') else: self.NGL_HKL_command( 'NGL_HKLviewer.viewer.show_only_missing = False') def showSlice(self): if self.showslicecheckbox.isChecked(): self.NGL_HKL_command('NGL_HKLviewer.viewer.slice_mode = True') if self.expandP1checkbox.isChecked(): self.NGL_HKL_command("""NGL_HKLviewer.viewer { expand_to_p1 = True inbrowser = False } """) if self.expandAnomalouscheckbox.isChecked(): self.NGL_HKL_command("""NGL_HKLviewer.viewer { expand_anomalous = True inbrowser = False } """) else: self.NGL_HKL_command("""NGL_HKLviewer.viewer { slice_mode = False inbrowser = True } """) def onSliceComboSelchange(self, i): rmin = self.array_infotpls[self.MillerComboBox.currentIndex()][3][0][i] rmax = self.array_infotpls[self.MillerComboBox.currentIndex()][3][1][i] self.sliceindexspinBox.setRange(rmin, rmax) self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_axis = %s" % self.sliceaxis[i]) def onSliceIndexChanged(self, val): self.sliceindex = val self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_index = %d" % self.sliceindex) def onBindataComboSelchange(self, i): if self.BinDataComboBox.currentText(): if self.BinDataComboBox.currentIndex() > 0: bin_scene_label = str(self.BinDataComboBox.currentIndex() - 1) else: bin_scene_label = "Resolution" self.NGL_HKL_command("NGL_HKLviewer.bin_scene_label = %s" % bin_scene_label) def update_table_opacities(self, allalpha=None): bin_opacitieslst = eval(self.bin_opacities) self.binstable_isready = False for binopacity in bin_opacitieslst: if not allalpha: alpha = float(binopacity.split(",")[0]) else: alpha = allalpha bin = int(binopacity.split(",")[1]) item = QTableWidgetItem() item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) if alpha < 0.5: item.setCheckState(Qt.Unchecked) else: item.setCheckState(Qt.Checked) item.setFlags(item.flags() ^ Qt.ItemIsEditable) self.binstable.setItem(bin, 3, item) self.binstable_isready = True def SetOpaqueAll(self): if self.binstableitemchanges: return bin_opacitieslst = eval(self.bin_opacities) nbins = len(bin_opacitieslst) sum = 0 for binopacity in bin_opacitieslst: sum += float(binopacity.split(",")[0]) if sum >= nbins: self.OpaqueAllCheckbox.setCheckState(Qt.Checked) if sum == 0: self.OpaqueAllCheckbox.setCheckState(Qt.Unchecked) if sum > 0.0 and sum < nbins: self.OpaqueAllCheckbox.setCheckState(Qt.PartiallyChecked) def onBinsTableItemChanged(self, item): row = item.row() column = item.column() try: if item.checkState() == Qt.Unchecked: newval = 0 else: newval = 1.0 if column == 3 and self.binstable_isready: # changing opacity assert (newval <= 1.0 and newval >= 0.0) bin_opacitieslst = eval(self.bin_opacities) bin_opacitieslst[row] = str(newval) + ', ' + str(row) self.bin_opacities = str(bin_opacitieslst) self.SetOpaqueAll() self.NGL_HKL_command( 'NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' % self.bin_opacities) except Exception as e: print(str(e)) #self.binstable.currentItem().setText( self.currentSelectedBinsTableVal) def onBinsTableItemSelectionChanged(self): row = self.binstable.currentItem().row() column = self.binstable.currentItem().column() self.currentSelectedBinsTableVal = self.binstable.currentItem().text() #print( "in itemSelectionChanged " + self.currentSelectedBinsTableVal) def onOpaqueAll(self): self.binstableitemchanges = True bin_opacitieslst = eval(self.bin_opacities) nbins = len(bin_opacitieslst) bin_opacitieslst = [] self.binstable_isready = False if self.OpaqueAllCheckbox.isChecked(): for i in range(nbins): bin_opacitieslst.append("1.0, %d" % i) else: for i in range(nbins): bin_opacitieslst.append("0.0, %d" % i) self.bin_opacities = str(bin_opacitieslst) self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' % self.bin_opacities) self.binstableitemchanges = False self.binstable_isready = True """ def onLoadFinished(self, val): pass #print("web page finished loading now") def onBinsTableitemActivated(self, item): row = item.row() column = item.column() currentval = item.text() #print( "in itemActivated " + currentval) def onBinsTableCellentered(self, row, col): pass #print( "in Cellentered " + self.binstable.currentItem().text() ) def onBinsTableCellPressed(self, row, col): pass #print( "in CellPressed " + self.binstable.currentItem().text() ) """ def onNbinsChanged(self, val): self.nbins = val if not self.updatingNbins: # avoid possible endless loop to cctbx self.NGL_HKL_command("NGL_HKLviewer.nbins = %d" % self.nbins) def onRadiiScaleChanged(self, val): self.radii_scale = val self.NGL_HKL_command(""" NGL_HKLviewer.viewer { nth_power_scale_radii = %f scale = %f } """ % (self.nth_power_scale, self.radii_scale)) def onPowerScaleChanged(self, val): self.nth_power_scale = val self.NGL_HKL_command(""" NGL_HKLviewer.viewer { nth_power_scale_radii = %f scale = %f } """ % (self.nth_power_scale, self.radii_scale)) def onManualPowerScale(self): if self.ManualPowerScalecheckbox.isChecked(): self.NGL_HKL_command( 'NGL_HKLviewer.viewer.nth_power_scale_radii = %f' % self.nth_power_scale) self.power_scale_spinBox.setEnabled(True) else: self.NGL_HKL_command( 'NGL_HKLviewer.viewer.nth_power_scale_radii = -1.0') self.power_scale_spinBox.setEnabled(False) self.nth_power_scale = -1.0 def OpenReflectionsFile(self): options = QFileDialog.Options() fileName, filtr = QFileDialog.getOpenFileName( self, "Load reflections file", "", "All Files (*);;MTZ Files (*.mtz);;CIF (*.cif)", "", options) if fileName: self.HKLnameedit.setText(fileName) #self.infostr = "" self.textInfo.setPlainText("") self.fileisvalid = False self.NGL_HKL_command('NGL_HKLviewer.filename = "%s"' % fileName) self.MillerComboBox.clear() self.BinDataComboBox.clear() def createExpansionBox(self): self.SpaceGroupComboBox = QComboBox() self.SpaceGroupComboBox.activated.connect(self.SpacegroupSelchange) self.SpacegroupLabel = QLabel() self.SpacegroupLabel.setText("Space Subgroups") self.mergecheckbox = QCheckBox() self.mergecheckbox.setText("Merge data") #self.mergecheckbox.setTristate (True) self.mergecheckbox.clicked.connect(self.MergeData) self.expandP1checkbox = QCheckBox() self.expandP1checkbox.setText("Expand to P1") self.expandP1checkbox.clicked.connect(self.ExpandToP1) self.expandAnomalouscheckbox = QCheckBox() self.expandAnomalouscheckbox.setText("Show Friedel pairs") self.expandAnomalouscheckbox.clicked.connect(self.ExpandAnomalous) self.sysabsentcheckbox = QCheckBox() self.sysabsentcheckbox.setText("Show Systematic Absences") self.sysabsentcheckbox.clicked.connect(self.showSysAbsent) self.missingcheckbox = QCheckBox() self.missingcheckbox.setText("Show Missing") self.missingcheckbox.clicked.connect(self.showMissing) self.onlymissingcheckbox = QCheckBox() self.onlymissingcheckbox.setText("Only Show Missing") self.onlymissingcheckbox.clicked.connect(self.showOnlyMissing) self.ExpansionBox = QGroupBox("Expansions") layout = QGridLayout() layout.addWidget(self.SpacegroupLabel, 0, 0) layout.addWidget(self.SpaceGroupComboBox, 0, 1) #layout.addWidget(self.mergecheckbox, 1, 0) layout.addWidget(self.expandP1checkbox, 1, 0) layout.addWidget(self.expandAnomalouscheckbox, 1, 1) layout.addWidget(self.sysabsentcheckbox, 2, 0) layout.addWidget(self.missingcheckbox, 3, 0) layout.addWidget(self.onlymissingcheckbox, 3, 1) layout.setRowStretch(0, 0) layout.setRowStretch(1, 0) layout.setRowStretch(2, 0) layout.setRowStretch(3, 1) self.ExpansionBox.setLayout(layout) def CreateSliceTabs(self): self.showslicecheckbox = QCheckBox() self.showslicecheckbox.setText("Show Slice") self.showslicecheckbox.clicked.connect(self.showSlice) self.sliceindexspinBox = QDoubleSpinBox() self.sliceindex = 0 self.sliceindexspinBox.setValue(self.sliceindex) self.sliceindexspinBox.setDecimals(0) self.sliceindexspinBox.setSingleStep(1) self.sliceindexspinBox.setRange(0, 20) self.sliceindexspinBox.valueChanged.connect(self.onSliceIndexChanged) self.SliceLabelComboBox = QComboBox() self.SliceLabelComboBox.activated.connect(self.onSliceComboSelchange) self.sliceaxis = ["h", "k", "l"] self.SliceLabelComboBox.addItems(self.sliceaxis) self.sliceTabWidget = QTabWidget() tab1 = QWidget() layout1 = QGridLayout() layout1.addWidget(self.showslicecheckbox, 0, 0, 1, 1) layout1.addWidget(self.SliceLabelComboBox, 0, 1, 1, 1) layout1.addWidget(self.sliceindexspinBox, 0, 2, 1, 1) tab1.setLayout(layout1) tab2 = QWidget() layout2 = QGridLayout() self.hvec_spinBox = QDoubleSpinBox(self.sliceTabWidget) self.hvecval = 2.0 self.hvec_spinBox.setValue(self.hvecval) self.hvec_spinBox.setDecimals(2) self.hvec_spinBox.setSingleStep(0.5) self.hvec_spinBox.setRange(-100.0, 10.0) self.hvec_spinBox.valueChanged.connect(self.onHvecChanged) self.hvec_Label = QLabel() self.hvec_Label.setText("H") layout2.addWidget(self.hvec_Label, 0, 0, 1, 1) layout2.addWidget(self.hvec_spinBox, 0, 1, 1, 1) self.kvec_spinBox = QDoubleSpinBox(self.sliceTabWidget) self.kvecval = 0.0 self.kvec_spinBox.setValue(self.kvecval) self.kvec_spinBox.setDecimals(2) self.kvec_spinBox.setSingleStep(0.5) self.kvec_spinBox.setRange(-100.0, 100.0) self.kvec_spinBox.valueChanged.connect(self.onKvecChanged) self.kvec_Label = QLabel() self.kvec_Label.setText("K") layout2.addWidget(self.kvec_Label, 1, 0, 1, 1) layout2.addWidget(self.kvec_spinBox, 1, 1, 1, 1) self.lvec_spinBox = QDoubleSpinBox(self.sliceTabWidget) self.lvecval = 0.0 self.lvec_spinBox.setValue(self.lvecval) self.lvec_spinBox.setDecimals(2) self.lvec_spinBox.setSingleStep(0.5) self.lvec_spinBox.setRange(-100.0, 100.0) self.lvec_spinBox.valueChanged.connect(self.onLvecChanged) self.lvec_Label = QLabel() self.lvec_Label.setText("L") layout2.addWidget(self.lvec_Label, 2, 0, 1, 1) layout2.addWidget(self.lvec_spinBox, 2, 1, 1, 1) self.hkldist_spinBox = QDoubleSpinBox(self.sliceTabWidget) self.hkldistval = 0.0 self.hkldist_spinBox.setValue(self.hkldistval) self.hkldist_spinBox.setDecimals(2) self.hkldist_spinBox.setSingleStep(0.5) self.hkldist_spinBox.setRange(-100.0, 100.0) self.hkldist_spinBox.valueChanged.connect(self.onHKLdistChanged) self.hkldist_Label = QLabel() self.hkldist_Label.setText("Distance from Origin") layout2.addWidget(self.hkldist_Label, 3, 0, 1, 1) layout2.addWidget(self.hkldist_spinBox, 3, 1, 1, 1) self.clipwidth_spinBox = QDoubleSpinBox(self.sliceTabWidget) self.clipwidthval = 0.5 self.clipwidth_spinBox.setValue(self.clipwidthval) self.clipwidth_spinBox.setDecimals(2) self.clipwidth_spinBox.setSingleStep(0.05) self.clipwidth_spinBox.setRange(0.0, 100.0) self.clipwidth_spinBox.valueChanged.connect(self.onClipwidthChanged) self.clipwidth_Label = QLabel() self.clipwidth_Label.setText("Clip Plane Width") layout2.addWidget(self.clipwidth_Label, 4, 0, 1, 1) layout2.addWidget(self.clipwidth_spinBox, 4, 1, 1, 1) self.ClipBox = QGroupBox("Normal Vector to Clip Plane") self.ClipBox.setLayout(layout2) layout3 = QGridLayout() self.ClipPlaneChkBox = QCheckBox(self.sliceTabWidget) self.ClipPlaneChkBox.setText( "Use clip plane normal to HKL vector pointing out") self.ClipPlaneChkBox.clicked.connect(self.onClipPlaneChkBox) layout3.addWidget(self.ClipPlaneChkBox, 0, 0) layout3.addWidget(self.ClipBox, 1, 0) tab2.setLayout(layout3) self.sliceTabWidget.addTab(tab1, "Explicit Slicing") self.sliceTabWidget.addTab(tab2, "Clip Plane Slicing") self.ClipBox.setDisabled(True) def onClipPlaneChkBox(self): if self.ClipPlaneChkBox.isChecked(): self.ClipBox.setDisabled(False) philstr = """NGL_HKLviewer.normal_clip_plane { h = %s k = %s l = %s hkldist = %s clipwidth = %s } NGL_HKLviewer.viewer.NGL.fixorientation = %s """ %(self.hvecval, self.kvecval, self.lvecval, self.hkldistval, self.clipwidthval, \ str(self.fixedorientcheckbox.isChecked()) ) self.NGL_HKL_command(philstr) else: self.ClipBox.setDisabled(True) self.NGL_HKL_command( "NGL_HKLviewer.normal_clip_plane.clipwidth = None") def onClipwidthChanged(self, val): self.clipwidthval = val self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.clipwidth = %f" % self.clipwidthval) def onHKLdistChanged(self, val): self.hkldistval = val self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.hkldist = %f" % self.hkldistval) def onHvecChanged(self, val): self.hvecval = val self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.h = %f" % self.hvecval) def onKvecChanged(self, val): self.kvecval = val self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.k = %f" % self.kvecval) def onLvecChanged(self, val): self.lvecval = val self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.l = %f" % self.lvecval) def onFixedorient(self): self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.fixorientation = %s' \ %str(self.fixedorientcheckbox.isChecked())) def onMillerComboSelchange(self, i): self.NGL_HKL_command("NGL_HKLviewer.scene_id = %d" % i) #self.MillerComboBox.setCurrentIndex(i) if self.MillerComboBox.currentText(): self.functionTabWidget.setEnabled(True) self.expandAnomalouscheckbox.setEnabled(True) # don' allow anomalous expansion for data that's already anomalous for arrayinfo in self.array_infotpls: isanomalous = arrayinfo[-1] label = arrayinfo[0] if isanomalous and label == self.MillerComboBox.currentText( )[:len(label)]: self.expandAnomalouscheckbox.setDisabled(True) else: self.functionTabWidget.setDisabled(True) self.SpaceGroupComboBox.clear() self.SpaceGroupComboBox.addItems(self.spacegroups) # need to supply issymunique flag in infotuple #if self.hklscenes_arrays[ i ][6] == 0: # self.mergecheckbox.setEnabled(True) #else: # self.mergecheckbox.setEnabled(False) def createFileInfoBox(self): self.FileInfoBox = QGroupBox("Reflection File Information") layout = QGridLayout() layout.addWidget(self.openFileNameButton, 0, 0, 1, 2) if self.devmode: layout.addWidget(self.debugbutton, 0, 2, 1, 1) layout.addWidget(self.HKLnameedit, 1, 0, 1, 3) layout.addWidget(self.millertable, 2, 0, 1, 3) layout.addWidget(self.textInfo, 3, 0, 1, 3) #layout.setColumnStretch(1, 2) self.FileInfoBox.setLayout(layout) def createRadiiScaleGroupBox(self): self.RadiiScaleGroupBox = QGroupBox("Radii Size of HKL Spheres") self.ManualPowerScalecheckbox = QCheckBox() self.ManualPowerScalecheckbox.setText( "Manual Power Scaling of Sphere Radii") self.ManualPowerScalecheckbox.clicked.connect(self.onManualPowerScale) self.power_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox) self.nth_power_scale = 0.5 self.power_scale_spinBox.setValue(self.nth_power_scale) self.power_scale_spinBox.setDecimals(2) self.power_scale_spinBox.setSingleStep(0.05) self.power_scale_spinBox.setRange(0.0, 1.0) self.power_scale_spinBox.valueChanged.connect(self.onPowerScaleChanged) self.power_scale_spinBox.setEnabled(False) self.powerscaleLabel = QLabel() self.powerscaleLabel.setText("Power scale Factor") self.radii_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox) self.radii_scale = 1.0 self.radii_scale_spinBox.setValue(self.radii_scale) self.radii_scale_spinBox.setDecimals(1) self.radii_scale_spinBox.setSingleStep(0.1) self.radii_scale_spinBox.setRange(0.2, 2.0) self.radii_scale_spinBox.valueChanged.connect(self.onRadiiScaleChanged) self.radiiscaleLabel = QLabel() self.radiiscaleLabel.setText("Linear Scale Factor") layout = QGridLayout() layout.addWidget(self.ManualPowerScalecheckbox, 1, 0, 1, 2) layout.addWidget(self.powerscaleLabel, 2, 0, 1, 2) layout.addWidget(self.power_scale_spinBox, 2, 1, 1, 2) layout.addWidget(self.radiiscaleLabel, 3, 0, 1, 2) layout.addWidget(self.radii_scale_spinBox, 3, 1, 1, 2) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 0) self.RadiiScaleGroupBox.setLayout(layout) def createBinsBox(self): self.binstable = QTableWidget(0, 4) self.binstable_isready = False labels = [ "no. of HKLs", "lower bin value", "upper bin value", "opacity" ] self.binstable.setHorizontalHeaderLabels(labels) self.binstable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft) self.bindata_labeltxt = QLabel() self.bindata_labeltxt.setText("Data binned:") self.Nbins_spinBox = QSpinBox() self.Nbins_spinBox.setSingleStep(1) self.Nbins_spinBox.setRange(1, 40) self.Nbins_spinBox.valueChanged.connect(self.onNbinsChanged) self.Nbins_labeltxt = QLabel() self.Nbins_labeltxt.setText("Number of bins:") self.OpaqueAllCheckbox = QCheckBox() #self.OpaqueAllCheckbox.setTristate() self.OpaqueAllCheckbox.setText("Show all data in bins") self.OpaqueAllCheckbox.clicked.connect(self.onOpaqueAll) self.binstable.itemChanged.connect(self.onBinsTableItemChanged) self.binstable.itemSelectionChanged.connect( self.onBinsTableItemSelectionChanged) self.BinDataComboBox = QComboBox() self.BinDataComboBox.activated.connect(self.onBindataComboSelchange) self.BinsGroupBox = QGroupBox("Bins") layout = QGridLayout() layout.addWidget(self.bindata_labeltxt, 0, 0) layout.addWidget(self.BinDataComboBox, 0, 1) layout.addWidget(self.Nbins_labeltxt, 0, 2) layout.addWidget(self.Nbins_spinBox, 0, 3) layout.addWidget(self.OpaqueAllCheckbox, 1, 2) layout.addWidget(self.binstable, 2, 0, 1, 4) layout.setColumnStretch(0, 0) layout.setColumnStretch(1, 2) layout.setColumnStretch(3, 1) self.BinsGroupBox.setLayout(layout) def DebugInteractively(self): import code, traceback code.interact(local=locals(), banner="".join(traceback.format_stack(limit=10))) def CreateFunctionTabs(self): self.functionTabWidget = QTabWidget() tab1 = QWidget() layout1 = QGridLayout() layout1.addWidget(self.ExpansionBox, 0, 0) layout1.setRowStretch(0, 0) tab1.setLayout(layout1) tab2 = QWidget() layout2 = QGridLayout() self.fixedorientcheckbox = QCheckBox(self.sliceTabWidget) self.fixedorientcheckbox.setText( "Fix orientation but allow zoom and translation") self.fixedorientcheckbox.clicked.connect(self.onFixedorient) layout2.addWidget(self.fixedorientcheckbox, 0, 0) layout2.addWidget(self.sliceTabWidget, 1, 0) tab2.setLayout(layout2) tab3 = QWidget() layout3 = QGridLayout() layout3.addWidget(self.RadiiScaleGroupBox, 0, 0) tab3.setLayout(layout3) tab4 = QWidget() layout4 = QGridLayout() layout4.addWidget(self.BinsGroupBox, 0, 0) tab4.setLayout(layout4) self.functionTabWidget.addTab(tab1, "Expand") self.functionTabWidget.addTab(tab2, "Slice") self.functionTabWidget.addTab(tab3, "Size") self.functionTabWidget.addTab(tab4, "Bins") self.functionTabWidget.setDisabled(True) def SpacegroupSelchange(self, i): self.NGL_HKL_command("NGL_HKLviewer.spacegroup_choice = %d" % i) def find_free_port(self): import socket s = socket.socket() s.bind(('', 0)) # Bind to a free port provided by the host. port = s.getsockname()[1] s.close() return port def LaunchCCTBXPython(self): self.sockport = self.find_free_port() self.zmq_context = zmq.Context() self.socket = self.zmq_context.socket(zmq.PAIR) self.socket.bind("tcp://127.0.0.1:%s" % self.sockport) try: msg = self.socket.recv( flags=zmq.NOBLOCK) #To empty the socket from previous messages except Exception as e: pass cmdargs = 'cctbx.python.bat -i -c "from crys3d.hklview import cmdlineframes;' \ + ' myHKLview = cmdlineframes.HKLViewFrame(useGuiSocket=%s, high_quality=True,' %self.sockport \ + ' jscriptfname = \'%s\', ' %self.jscriptfname \ + ' verbose=%s, UseOSBrowser= %s )"\n' %(self.verbose, str(self.UseOSbrowser)) self.cctbxproc = subprocess.Popen(cmdargs, shell=True, stdin=subprocess.PIPE, stdout=sys.stdout, stderr=sys.stderr) #time.sleep(1) def NGL_HKL_command(self, cmdstr): #print("sending:\n" + cmdstr) self.socket.send(bytes(cmdstr, "utf-8"))
class ReportDialog(QDialog): def __init__(self): super().__init__(GlobalAccess().get_main_window()) def exec_(self): self.init_ui() return super().exec_() def init_ui(self): self.setWindowTitle(_('Report creating')) self.setWindowIcon(QIcon(config.ICON)) self.setSizeGripEnabled(False) self.setModal(True) self.layout = QFormLayout(self) self.label_template = QLabel(_('Template')) self.item_template = AdvComboBox() self.item_template.addItems(get_templates(config.template_dir('reports'))) self.layout.addRow(self.label_template, self.item_template) if _settings['last_template'] is not None: self.item_template.setCurrentText(_settings['last_template']) self.item_custom_path = QPushButton(_('Choose template')) def select_custom_path(): file_name = get_open_file_name(_('Open HTML template'), _("HTML file (*.html)")) self.item_template.setCurrentText(file_name) self.item_custom_path.clicked.connect(select_custom_path) self.layout.addRow(self.item_custom_path) self.item_open_in_browser = QCheckBox(_('Open in browser')) self.item_open_in_browser.setChecked(_settings['open_in_browser']) self.layout.addRow(self.item_open_in_browser) self.item_save_to_last_file = QCheckBox(_('Save to last file')) self.item_save_to_last_file.setChecked(_settings['save_to_last_file']) self.layout.addRow(self.item_save_to_last_file) if _settings['last_file'] is None: self.item_save_to_last_file.setDisabled(True) self.item_selected = QCheckBox(_('Send selected')) self.item_selected.setChecked(_settings['selected']) self.layout.addRow(self.item_selected) def cancel_changes(): self.close() def apply_changes(): try: self.apply_changes_impl() except FileNotFoundError as e: logging.error(str(e)) except Exception as e: logging.error(str(e)) logging.exception(e) self.close() button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = button_box.button(QDialogButtonBox.Ok) self.button_ok.setText(_('OK')) self.button_ok.clicked.connect(apply_changes) self.button_cancel = button_box.button(QDialogButtonBox.Cancel) self.button_cancel.setText(_('Cancel')) self.button_cancel.clicked.connect(cancel_changes) self.layout.addRow(button_box) self.show() self.button_ok.setFocus() def apply_changes_impl(self): obj = race() mw = GlobalAccess().get_main_window() map_items = [obj.persons, obj.results, obj.groups, obj.courses, obj.organizations] map_names = ['persons', 'results', 'groups', 'courses', 'organizations'] selected_items = { 'persons': [], 'results': [], 'groups': [], 'courses': [], 'organizations': [], } template_path = self.item_template.currentText() _settings['last_template'] = template_path _settings['open_in_browser'] = self.item_open_in_browser.isChecked() _settings['save_to_last_file'] = self.item_save_to_last_file.isChecked() _settings['selected'] = self.item_selected.isChecked() if _settings['selected']: cur_items = map_items[mw.current_tab] for i in mw.get_selected_rows(): selected_items[map_names[mw.current_tab]].append(cur_items[i].to_dict()) ResultCalculation(obj).process_results() RaceSplits(obj).generate() ScoreCalculation(obj).calculate_scores() races_dict = [r.to_dict() for r in races()] if template_path.endswith('.docx'): # DOCX template processing full_path = config.template_dir() + template_path doc = DocxTemplate(full_path) context = {} context['race'] = races_dict[get_current_race_index()] context['name'] = config.NAME context['version'] = str(config.VERSION) doc.render(context) if _settings['save_to_last_file']: file_name = _settings['last_file'] else: file_name = get_save_file_name(_('Save As MS Word file'), _("MS Word file (*.docx)"), '{}_official'.format(obj.data.get_start_datetime().strftime("%Y%m%d"))) if file_name: doc.save(file_name) os.startfile(file_name) else: template = get_text_from_file( template_path, race=races_dict[get_current_race_index()], races=races_dict, rent_cards=list(RentCards().get()), current_race=get_current_race_index(), selected=selected_items ) if _settings['save_to_last_file']: file_name = _settings['last_file'] else: file_name = get_save_file_name(_('Save As HTML file'), _("HTML file (*.html)"), '{}_report'.format(obj.data.get_start_datetime().strftime("%Y%m%d"))) if len(file_name): _settings['last_file'] = file_name with codecs.open(file_name, 'w', 'utf-8') as file: file.write(template) file.close() # Open file in your browser if _settings['open_in_browser']: webbrowser.open('file://' + file_name, new=2)
class SubtitleInfoDialog(QDialog): def __init__(self, subtitle_name="Test", subtitle_delay=0.0, subtitle_language=Default_Subtitle_Language, subtitle_track_name="Test", subtitle_set_default=False, subtitle_set_forced=False, subtitle_default_value_delay=0.0, subtitle_default_value_language=Default_Subtitle_Language, subtitle_default_value_track_name="Test", subtitle_default_value_set_default=False, subtitle_default_value_set_forced=False, subtitle_set_default_disabled=False, subtitle_set_forced_disabled=False, disable_edit=False, parent=None): super().__init__(parent) self.window_title = "Subtitle Info" self.state = "no" self.messageIcon = QLabel() self.disable_edit = disable_edit self.current_subtitle_language = str(subtitle_language) self.current_subtitle_delay = str(subtitle_delay) self.current_subtitle_track_name = str(subtitle_track_name) self.current_subtitle_set_default = subtitle_set_default self.current_subtitle_set_forced = subtitle_set_forced self.default_subtitle_language = str(subtitle_default_value_language) self.default_subtitle_delay = str(subtitle_default_value_delay) self.default_subtitle_track_name = str( subtitle_default_value_track_name) self.default_subtitle_set_default = subtitle_default_value_set_default self.default_subtitle_set_forced = subtitle_default_value_set_forced self.subtitle_set_default_disabled = subtitle_set_default_disabled self.subtitle_set_forced_disabled = subtitle_set_forced_disabled self.subtitle_name_label = QLabel("Subtitle Name:") self.subtitle_name_value = QLabel(str(subtitle_name)) self.subtitle_delay_label = QLabel("Subtitle Delay:") self.subtitle_delay_spin = QDoubleSpinBox() self.setup_subtitle_delay_spin() self.subtitle_language_label = QLabel("Subtitle Language:") self.subtitle_language_comboBox = QComboBox() self.setup_subtitle_language_comboBox() self.subtitle_track_name_label = QLabel("Subtitle Track Name:") self.subtitle_track_name_lineEdit = QLineEdit() self.setup_subtitle_track_name_lineEdit() self.subtitle_set_forced_label = QLabel("Subtitle Forced State:") self.subtitle_set_forced_checkBox = QCheckBox() self.setup_subtitle_set_forced_checkBox() self.subtitle_set_default_label = QLabel("Subtitle Default State:") self.subtitle_set_default_checkBox = QCheckBox() self.setup_subtitle_set_default_checkBox() self.yes_button = QPushButton("OK") self.no_button = QPushButton("Cancel") self.reset_button = QPushButton("Reset To Default") self.buttons_layout = QHBoxLayout() self.subtitle_delay_layout = QHBoxLayout() self.subtitle_language_layout = QHBoxLayout() self.subtitle_track_name_layout = QHBoxLayout() self.subtitle_set_default_layout = QHBoxLayout() self.subtitle_set_forced_layout = QHBoxLayout() self.buttons_layout.addWidget(QLabel(""), stretch=3) self.buttons_layout.addWidget(self.reset_button, stretch=2) self.buttons_layout.addWidget(self.yes_button, stretch=2) self.buttons_layout.addWidget(self.no_button, stretch=2) self.buttons_layout.addWidget(QLabel(""), stretch=3) self.subtitle_setting_layout = QGridLayout() self.subtitle_changeble_setting_layout = QFormLayout() self.subtitle_changeble_setting_layout.addRow(self.subtitle_name_label, self.subtitle_name_value) self.subtitle_changeble_setting_layout.addRow( self.subtitle_track_name_label, self.subtitle_track_name_lineEdit) self.subtitle_changeble_setting_layout.addRow( self.subtitle_language_label, self.subtitle_language_comboBox) self.subtitle_changeble_setting_layout.addRow( self.subtitle_delay_label, self.subtitle_delay_spin) self.subtitle_changeble_setting_layout.addRow( self.subtitle_set_default_label, self.subtitle_set_default_checkBox) self.subtitle_changeble_setting_layout.addRow( self.subtitle_set_forced_label, self.subtitle_set_forced_checkBox) self.subtitle_setting_layout.addLayout( self.subtitle_changeble_setting_layout, 0, 0, 5, 2) self.subtitle_setting_layout.addWidget(self.messageIcon, 0, 3, 5, -1) self.main_layout = QGridLayout() self.main_layout.addLayout(self.subtitle_setting_layout, 0, 0, 2, 3) self.main_layout.addLayout(self.buttons_layout, 2, 0, 1, -1) self.main_layout.setContentsMargins(20, 20, 20, 20) self.setLayout(self.main_layout) self.setup_ui() self.signal_connect() def setup_ui(self): self.disable_question_mark_window() self.messageIcon.setPixmap( QtGui.QPixmap(GlobalFiles.SubtitleIconPath).scaledToHeight(100)) self.set_dialog_values() self.set_default_buttons() if self.subtitle_set_default_disabled: self.subtitle_set_default_disable() if self.subtitle_set_forced_disabled: self.subtitle_set_forced_disable() if self.disable_edit: self.subtitle_track_name_lineEdit.setEnabled(False) self.subtitle_language_comboBox.setEnabled(False) self.subtitle_delay_spin.setEnabled(False) self.subtitle_set_default_checkBox.setEnabled(False) self.subtitle_set_forced_checkBox.setEnabled(False) self.reset_button.setEnabled(False) self.setup_tool_tip_hint_subtitle_set_default() self.setup_tool_tip_hint_subtitle_set_forced() def signal_connect(self): self.subtitle_track_name_lineEdit.textEdited.connect( self.update_current_subtitle_track_name) self.subtitle_delay_spin.editingFinished.connect( self.update_current_subtitle_delay) self.subtitle_language_comboBox.currentTextChanged.connect( self.update_current_subtitle_language) self.subtitle_set_default_checkBox.stateChanged.connect( self.update_current_subtitle_set_default) self.subtitle_set_forced_checkBox.stateChanged.connect( self.update_current_subtitle_set_forced) self.yes_button.clicked.connect(self.click_yes) self.no_button.clicked.connect(self.click_no) self.reset_button.clicked.connect(self.reset_subtitle_setting) def click_yes(self): self.state = "yes" self.close() def click_no(self): self.close() def set_dialog_values(self): self.setWindowTitle(self.window_title) self.setWindowIcon(GlobalFiles.InfoSettingIcon) def disable_question_mark_window(self): self.setWindowFlag(Qt.WindowContextHelpButtonHint, on=False) def increase_message_font_size(self, value): message_font = self.message.font() message_font.setPointSize(self.message.fontInfo().pointSize() + value) self.message.setFont(message_font) def set_default_buttons(self): self.yes_button.setDefault(True) self.yes_button.setFocus() def showEvent(self, a0: QtGui.QShowEvent) -> None: super().showEvent(a0) self.setFixedSize(self.size()) def setup_subtitle_track_name_lineEdit(self): self.subtitle_track_name_lineEdit.setClearButtonEnabled(True) self.subtitle_track_name_lineEdit.setText( self.current_subtitle_track_name) def setup_subtitle_language_comboBox(self): self.subtitle_language_comboBox.addItems(AllSubtitlesLanguages) self.subtitle_language_comboBox.setCurrentIndex( AllSubtitlesLanguages.index(self.current_subtitle_language)) self.subtitle_language_comboBox.setMaxVisibleItems(8) self.subtitle_language_comboBox.setStyleSheet( "QComboBox { combobox-popup: 0; }") def setup_subtitle_delay_spin(self): # self.subtitle_delay_spin.setMaximumWidth(screen_size.width() // 16) self.subtitle_delay_spin.setDecimals(3) self.subtitle_delay_spin.setMinimum(-9999.0) self.subtitle_delay_spin.setMaximum(9999.0) self.subtitle_delay_spin.setSingleStep(0.5) self.subtitle_delay_spin.setValue(float(self.current_subtitle_delay)) def setup_subtitle_set_default_checkBox(self): self.subtitle_set_default_checkBox.setText("Set Default") self.subtitle_set_default_checkBox.setChecked( bool(self.current_subtitle_set_default)) def setup_subtitle_set_forced_checkBox(self): self.subtitle_set_forced_checkBox.setText("Set Forced") self.subtitle_set_forced_checkBox.setChecked( bool(self.current_subtitle_set_forced)) def update_current_subtitle_track_name(self): self.current_subtitle_track_name = str( self.subtitle_track_name_lineEdit.text()) def update_current_subtitle_delay(self): self.current_subtitle_delay = round(self.subtitle_delay_spin.value(), 5) def update_current_subtitle_language(self): self.current_subtitle_language = str( self.subtitle_language_comboBox.currentText()) def update_current_subtitle_set_default(self): self.current_subtitle_set_default = ( self.subtitle_set_default_checkBox.checkState() == Qt.Checked) def update_current_subtitle_set_forced(self): self.current_subtitle_set_forced = ( self.subtitle_set_forced_checkBox.checkState() == Qt.Checked) def reset_subtitle_setting(self): self.current_subtitle_language = self.default_subtitle_language self.current_subtitle_delay = self.default_subtitle_delay self.current_subtitle_track_name = self.default_subtitle_track_name self.current_subtitle_set_default = self.default_subtitle_set_default self.current_subtitle_set_forced = self.default_subtitle_set_forced self.subtitle_language_comboBox.setCurrentIndex( AllSubtitlesLanguages.index(self.current_subtitle_language)) self.subtitle_delay_spin.setValue(float(self.current_subtitle_delay)) self.subtitle_track_name_lineEdit.setText( self.current_subtitle_track_name) self.subtitle_set_default_checkBox.setChecked( bool(self.current_subtitle_set_default)) self.subtitle_set_forced_checkBox.setChecked( bool(self.current_subtitle_set_forced)) def subtitle_set_default_disable(self): self.subtitle_set_default_checkBox.setDisabled(True) def subtitle_set_forced_disable(self): self.subtitle_set_forced_checkBox.setDisabled(True) def setup_tool_tip_hint_subtitle_set_default(self): if self.subtitle_set_default_checkBox.isEnabled(): self.subtitle_set_default_checkBox.setToolTip( "<nobr>set this subtitle to be the default subtitle track " "when play") self.subtitle_set_default_checkBox.setToolTipDuration(12000) else: self.subtitle_set_default_checkBox.setToolTip( "<nobr>set this subtitle to be the default subtitle track when play<br><b>Disabled</b> because " "option " "<b>make this subtitle default</b> is enabled on mux setting tab " ) self.subtitle_set_default_checkBox.setToolTipDuration(12000) def setup_tool_tip_hint_subtitle_set_forced(self): if self.subtitle_set_forced_checkBox.isEnabled(): self.subtitle_set_forced_checkBox.setToolTip( "<nobr>set this subtitle to be the forced subtitle track when " "play") self.subtitle_set_forced_checkBox.setToolTipDuration(12000) else: self.subtitle_set_forced_checkBox.setToolTip( "<nobr>set this subtitle to be the forced subtitle track when play<br><b>Disabled</b> because " "option " "<b>make this subtitle default and forced</b> is enabled on mux setting tab " ) self.subtitle_set_forced_checkBox.setToolTipDuration(12000) def execute(self): self.exec_()
class guiMain(QMainWindow): def __init__(self, bk, prefs): super(guiMain, self).__init__() self.taglist = taglist # Edit Plugin container object self.bk = bk # Handy prefs groupings self.gui_prefs = prefs['gui_selections'] self.misc_prefs = prefs['miscellaneous_settings'] self.update_prefs = prefs['update_settings'] self.combobox_values = prefs['combobox_values'] self._ok_to_close = False # Check online github files for newer version self.update, self.newversion = self.check_for_update() self.setup_ui() def setup_ui(self): app = QApplication.instance() p = app.palette() link_color = p.color(p.Active, p.Link).name() DELETE_STR = _t('guiMain', 'Delete') MODIFY_STR = _t('guiMain', 'Modify') self.NO_ATTRIB_STR = _t('guiMain', 'No attributes (naked tag)') self.NO_CHANGE_STR = _t('guiMain', 'No change') self.setWindowTitle(_t('guiMain', 'Tag Mechanic')) configAct = QAction(_t('guiMain', '&Config'), self) configAct.triggered.connect(self.showConfig) menubar = self.menuBar() fileMenu = menubar.addMenu(_t('guiMain', '&Edit')) fileMenu.addAction(configAct) layout = QVBoxLayout() widget = QWidget() widget.setLayout(layout) self.setCentralWidget(widget) if self.update: update_layout = QHBoxLayout() layout.addLayout(update_layout) self.label = QLabel() self.label.setText( _t('guiMain', 'Plugin Update Available') + ' ' + str(self.newversion)) self.label.setStyleSheet( 'QLabel {{color: {};}}'.format(link_color)) update_layout.addWidget(self.label) action_layout = QHBoxLayout() layout.addLayout(action_layout) label = QLabel(_t('guiMain', 'Action type:'), self) action_layout.addWidget(label) self.action_combo = QComboBox() action_layout.addWidget(self.action_combo) self.action_combo.addItems([DELETE_STR, MODIFY_STR]) self.action_combo.setCurrentIndex(self.gui_prefs['action']) self.action_combo.currentIndexChanged.connect(self.update_gui) tag_layout = QHBoxLayout() layout.addLayout(tag_layout) label = QLabel(_t('guiMain', 'Tag name:'), self) tag_layout.addWidget(label) self.tag_combo = QComboBox() tag_layout.addWidget(self.tag_combo) self.tag_combo.addItems(self.taglist) self.tag_combo.setCurrentIndex(self.gui_prefs['tag']) self.tag_combo.currentIndexChanged.connect(self.update_gui) attr_layout = QHBoxLayout() layout.addLayout(attr_layout) label = QLabel(_t('guiMain', 'Having the attribute:'), self) attr_layout.addWidget(label) self.attr_combo = QComboBox() attr_layout.addWidget(self.attr_combo) self.attr_combo.addItems(self.combobox_values['attrs']) self.attr_combo.addItem(self.NO_ATTRIB_STR) self.attr_combo.setCurrentIndex(self.gui_prefs['attrs']) self.attr_combo.currentIndexChanged.connect(self.update_gui) srch_layout = QHBoxLayout() layout.addLayout(srch_layout) label = QLabel(_t('guiMain', 'Whose value is (no quotes):'), self) srch_layout.addWidget(label) self.srch_txt = QLineEdit('', self) srch_layout.addWidget(self.srch_txt) self.srch_method = QCheckBox(_t('guiMain', 'Regex'), self) srch_layout.addWidget(self.srch_method) newtag_layout = QHBoxLayout() layout.addLayout(newtag_layout) label = QLabel(_t('guiMain', 'Change tag to:'), self) newtag_layout.addWidget(label) self.newtag_combo = QComboBox() newtag_layout.addWidget(self.newtag_combo) self.newtag_combo.addItem(self.NO_CHANGE_STR) self.newtag_combo.addItems(self.combobox_values['{}_changes'.format( str(self.tag_combo.currentText()))]) if self.action_combo.currentIndex() == 0: self.newtag_combo.setDisabled(True) newattr_layout = QVBoxLayout() layout.addLayout(newattr_layout) label = QLabel( _t('guiMain', 'New attribute string to insert (entire):'), self) newattr_layout.addWidget(label) self.newattr_txt = QLineEdit('', self) newattr_layout.addWidget(self.newattr_txt) self.copy_attr = QCheckBox( _t('guiMain', 'Copy existing attribute string'), self) self.copy_attr.stateChanged.connect(self.update_txt_box) newattr_layout.addWidget(self.copy_attr) if self.action_combo.currentIndex() == 0: self.copy_attr.setDisabled(True) self.newattr_txt.setDisabled(True) layout.addSpacing(10) self.text_panel = QTextEdit() self.text_panel.setReadOnly(True) layout.addWidget(self.text_panel) layout.addSpacing(10) button_layout = QHBoxLayout() layout.addLayout(button_layout) self.process_button = QPushButton(_t('guiMain', 'Process'), self) self.process_button.setToolTip('<p>{}'.format( _t('guiMain', 'Process selected files with current criteria'))) self.process_button.clicked.connect(self._process_clicked) button_layout.addWidget(self.process_button) self.abort_button = QPushButton(_t('guiMain', 'Abort Changes'), self) self.abort_button.setToolTip('<p>{}'.format( _t('guiMain', 'Make no changes and exit'))) self.abort_button.clicked.connect(self._abort_clicked) self.abort_button.setDisabled(True) button_layout.addWidget(self.abort_button) self.quit_button = QPushButton(_t('guiMain', 'Quit'), self) self.quit_button.setToolTip('<p>{}'.format( _t('guiMain', 'Quit with no changes'))) self.quit_button.clicked.connect(self._quit_clicked) button_layout.addWidget(self.quit_button) if self.misc_prefs['windowGeometry'] is not None: try: self.restoreGeometry( QByteArray.fromHex( self.misc_prefs['windowGeometry'].encode('ascii'))) except Exception: pass self.show() def update_gui(self): if self.attr_combo.currentIndex() == self.attr_combo.count() - 1: self.srch_txt.clear() self.srch_txt.setDisabled(True) self.srch_method.setChecked(False) self.srch_method.setDisabled(True) else: self.srch_txt.setDisabled(False) self.srch_method.setDisabled(False) self.newtag_combo.clear() self.newtag_combo.addItem(self.NO_CHANGE_STR) self.newtag_combo.addItems(self.combobox_values['{}_changes'.format( str(self.tag_combo.currentText()))]) if self.action_combo.currentIndex() == 0: self.newtag_combo.setCurrentIndex(0) self.newtag_combo.setDisabled(True) self.newattr_txt.clear() self.newattr_txt.setDisabled(True) self.copy_attr.setChecked(False) self.copy_attr.setDisabled(True) else: self.newtag_combo.setDisabled(False) self.newattr_txt.setDisabled(False) self.copy_attr.setDisabled(False) self.update_txt_box() def update_txt_box(self): if self.copy_attr.isChecked() or not self.copy_attr.isEnabled(): self.newattr_txt.clear() self.newattr_txt.setDisabled(True) else: self.newattr_txt.setDisabled(False) def refresh_attr_values(self): self.attr_combo.clear() self.attr_combo.addItems(self.combobox_values['attrs']) self.attr_combo.addItem(self.NO_ATTRIB_STR) def _process_clicked(self): criteria = {} global PROCESSED criteria['tag'] = str(self.tag_combo.currentText()) if self.action_combo.currentIndex() == 0: criteria['action'] = 'delete' else: criteria['action'] = 'modify' if self.attr_combo.currentIndex() == self.attr_combo.count() - 1: criteria['attrib'] = None else: criteria['attrib'] = str(self.attr_combo.currentText()) srch_str = str(self.srch_txt.displayText()) if not len(srch_str): srch_str = None if srch_str is None and criteria['attrib'] is not None: title = _t('guiMain', 'Error') msg = '<p>{0}'.format( _t('guiMain', 'Must enter a value for the attribute selected')) return QMessageBox.warning(self, title, msg, QMessageBox.Ok) criteria['srch_str'] = srch_str criteria['srch_method'] = 'normal' if self.srch_method.isChecked(): criteria['srch_method'] = 'regex' if self.newtag_combo.currentIndex() == 0: criteria['new_tag'] = None else: criteria['new_tag'] = str(self.newtag_combo.currentText()) if criteria['action'] == 'modify' and criteria[ 'new_tag'] is None and self.copy_attr.isChecked(): title = _t('guiMain', 'Error') msg = '<p>{0}'.format( _t('guiMain', 'What--exactly--would that achieve?')) return QMessageBox.question(self, title, msg, QMessageBox.Ok) criteria['new_str'] = str(self.newattr_txt.displayText()) criteria['copy'] = False if self.copy_attr.isChecked(): criteria['copy'] = True if not len(criteria['new_str']): criteria['new_str'] = '' # Disable the 'Process' button, disable the context customization menu self.process_button.setDisabled(True) PROCESSED = True totals = 0 self.text_panel.clear() self.text_panel.insertHtml('<h4>{}...</h4><br>'.format( _t('guiMain', 'Starting'))) # Loop through the files selected in Sigil's Book View for (typ, ident) in self.bk.selected_iter(): # Skip the ones that aren't the "Text" mimetype. if self.bk.id_to_mime(ident) != 'application/xhtml+xml': continue href = self.bk.id_to_href(ident) # Param 1 - the contents of the (x)html file. criteria['html'] = self.bk.readfile(ident) if not isinstance(criteria['html'], str): criteria['html'] = str(criteria['html'], 'utf-8') # Hand off the "criteria" parameters dictionary to the parsing engine parser = MarkupParser(criteria) # Retrieve the new markup and the number of occurrences changed try: html, occurrences = parser.processml() except Exception: self.text_panel.insertHtml('<p>{} {}! {}.</p>\n'.format( _t('guiMain', 'Error parsing'), href, _t('guiMain', 'File skipped'))) continue # Report whether or not changes were made (and how many) totals += occurrences if occurrences: # write changed markup back to file self.bk.writefile(ident, html) self.text_panel.insertHtml( '<p>{} {}:   {}</p>\n'.format( _t('guiMain', 'Occurrences found/changed in'), href, int(occurrences))) else: self.text_panel.insertHtml('<p>{} {}</p>\n'.format( _t('guiMain', 'Criteria not found in'), href)) # report totals if totals: self.quit_button.setText(_t('guiMain', 'Commit and Exit')) self.quit_button.setToolTip('<p>{}'.format( _t('guiMain', 'Commit all changes and exit'))) self.abort_button.setDisabled(False) self.text_panel.insertHtml( '<br><h4>{}:   {}</h4>'.format( _t('guiMain', 'Total occurrences found/changed'), int(totals))) else: self.text_panel.insertHtml('<br><h4>{}</h4>'.format( _t('guiMain', 'No changes made to book'))) self.text_panel.insertHtml('<br><h4>{}</h4>'.format( _t('guiMain', 'Finished'))) def _quit_clicked(self): self.misc_prefs['windowGeometry'] = self.saveGeometry().toHex().data( ).decode('ascii') if PROCESSED: self.gui_prefs['action'] = self.action_combo.currentIndex() self.gui_prefs['tag'] = self.tag_combo.currentIndex() self.gui_prefs['attrs'] = self.attr_combo.currentIndex() self._ok_to_close = True self.close() def _abort_clicked(self): global BAIL_OUT BAIL_OUT = True self._ok_to_close = True self.close() def getAbort(self): return BAIL_OUT def showConfig(self): ''' Launch Customization Dialog ''' dlg = ConfigDialog(self, self.combobox_values) if dlg.exec_() == QDialog.Accepted: self.refresh_attr_values() self.update_gui() def check_for_update(self): '''Use updatecheck.py to check for newer versions of the plugin''' last_time_checked = self.update_prefs['last_time_checked'] last_online_version = self.update_prefs['last_online_version'] chk = UpdateChecker(last_time_checked, last_online_version, self.bk._w) update_available, online_version, time = chk.update_info() # update preferences with latest date/time/version self.update_prefs['last_time_checked'] = time if online_version is not None: self.update_prefs['last_online_version'] = online_version if update_available: return (True, online_version) return (False, online_version) def closeEvent(self, event): if self._ok_to_close: event.accept() # let the window close else: self._abort_clicked()