示例#1
0
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
示例#2
0
文件: settings.py 项目: whs/runekit
    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)
示例#3
0
    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)
示例#4
0
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()
示例#5
0
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_()
示例#6
0
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()
示例#7
0
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
示例#8
0
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)
示例#9
0
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)
示例#10
0
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)
示例#12
0
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)
示例#13
0
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()
示例#14
0
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()
示例#15
0
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"))
示例#16
0
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)
示例#17
0
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>{} {}:&#160;&#160;&#160;{}</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>{}:&#160;&#160;&#160;{}</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()