class StartMineSchedDialog(QDialog): # 定义选择信号 start_minesched_signal = Signal(str) # 初始化 def __init__(self, config: ConfigFactory, logger: LoggerFactory, title: str): super(StartMineSchedDialog, self).__init__() self.config = config self.logger = logger self.setWindowTitle(title) self.setModal(True) self.setWindowFlag(Qt.WindowContextHelpButtonHint, False) self.layout = QVBoxLayout() self.setLayout(self.layout) self.start_minesched_button_group = QButtonGroup() self.start_minesched_button_group.setExclusive(True) self.buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.minescheds = [] self.minesched_id = -1 # 设置MineSched不同版本列表 def set_minescheds(self, minescheds: list): self.minescheds = minescheds for _id, minesched in enumerate(self.minescheds): minesched_item = QRadioButton(minesched) self.start_minesched_button_group.addButton(minesched_item) self.start_minesched_button_group.setId(minesched_item, _id) if _id == 0: minesched_item.setChecked(True) self.minesched_id = 0 self.layout.addWidget(minesched_item) self.start_minesched_button_group.buttonClicked.connect( self.start_minesched_change) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) self.layout.addWidget(self.buttons) # 如果单击ok按钮 def accept(self): # 先关闭对话框,然后发送消息 super(StartMineSchedDialog, self).accept() self.config.set_config('minesched', 'minesched_location', self.minescheds[self.minesched_id]) # 发送surpac启动消息 self.start_minesched_signal.emit(self.minescheds[self.minesched_id]) def start_minesched_change(self): self.minesched_id = self.start_minesched_button_group.checkedId()
class ChoiceSurpacDialog(QDialog): # 定义选择信号 choices_surpac_signal = Signal(str) # 初始化 def __init__(self, config: ConfigFactory, logger: LoggerFactory, title: str, surpacs: list): super(ChoiceSurpacDialog, self).__init__() self.config = config self.logger = logger self.setWindowTitle(title) self.setModal(True) self.setWindowFlag(Qt.WindowContextHelpButtonHint, False) self.surpacs = surpacs self.choice_surpac_button_group = QButtonGroup() self.choice_surpac_button_group.setExclusive(True) layout = QVBoxLayout() for surpac_id, choice in enumerate(surpacs): surpac_item = QRadioButton(choice) self.choice_surpac_button_group.addButton(surpac_item) self.choice_surpac_button_group.setId(surpac_item, surpac_id) if surpac_id == 0: surpac_item.setChecked(True) self.surpac_id = 0 layout.addWidget(surpac_item) self.choice_surpac_button_group.buttonClicked.connect( self.choice_surpac_change) self.buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) layout.addWidget(self.buttons) self.setLayout(layout) def accept(self): # 先关闭对话框,然后发送消息 super(ChoiceSurpacDialog, self).accept() if self.config.get('master', 'surpac_location') == self.surpacs[self.surpac_id]: pass else: self.choices_surpac_signal.emit(self.surpacs[self.surpac_id]) self.config.set_config('master', 'surpac_location', self.surpacs[self.surpac_id]) def choice_surpac_change(self): self.surpac_id = self.choice_surpac_button_group.checkedId()
class ChoiceLanguageDialog(QDialog): # 定义选择信号 choices_language_dialog_signal = Signal(str) # 初始化 def __init__(self, config: ConfigFactory, logger: LoggerFactory, title: str, languages: list): super(ChoiceLanguageDialog, self).__init__() self.config = config self.logger = logger self.setWindowTitle(title) self.setModal(True) self.setWindowFlag(Qt.WindowContextHelpButtonHint, False) self.languages = languages self.choice_language_button_group = QButtonGroup() self.choice_language_button_group.setExclusive(True) layout = QVBoxLayout() for language_id, language in enumerate(languages): # 显示语言提示 language_item = QRadioButton(language.split(':')[0]) self.choice_language_button_group.addButton(language_item) self.choice_language_button_group.setId(language_item, language_id) if language_id == 0: language_item.setChecked(True) self.language_id = 0 layout.addWidget(language_item) self.choice_language_button_group.buttonClicked.connect(self.language_change) self.buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) layout.addWidget(self.buttons) self.setLayout(layout) def accept(self): # 先关闭对话框,然后发送消息 super(ChoiceLanguageDialog, self).accept() # 发送语言文件 language = self.languages[self.language_id].split(':')[1] self.choices_language_dialog_signal.emit(language) self.config.set_config('master', 'surpac_language_cfg', language) def language_change(self): self.language_id = self.choice_language_button_group.checkedId()
class SettingsWindow(QDialog): """Settings menu with two tabs for settings models and components""" def __init__(self, master, enigma_api): """ Submenu for setting Enigma model and component settings :param master: Qt parent object :param enigma_api: {EnigmaAPI} """ super().__init__(master) # QT WINDOW SETTINGS =================================================== main_layout = QVBoxLayout(self) self.__settings_frame = QFrame(self) self.__settings_layout = QHBoxLayout(self.__settings_frame) self.setWindowTitle("Settings") self.setLayout(main_layout) self.setFixedHeight(620) self.__reflector_group = [] self.__rotor_frames = [] # SAVE ATTRIBUTES ====================================================== self.__enigma_api = enigma_api self.__rotor_selectors = [] self.__ring_selectors = [] self.__ukwd_window = UKWDSettingsWindow(self, enigma_api) # ROTORS AND REFLECTOR SETTINGS ======================================== self.__ukwd_button = QPushButton("UKW-D pairs") self.__ukwd_button.clicked.connect(self.open_ukwd_window) # TAB WIDGET =========================================================== tab_widget = QTabWidget() self.__stacked_wikis = _ViewSwitcherWidget(self, self.regenerate_for_model) tab_widget.addTab(self.__stacked_wikis, "Enigma model") tab_widget.addTab(self.__settings_frame, "Component settings") # BUTTONS ============================================================== button_frame = QFrame(self) button_layout = QHBoxLayout(button_frame) button_layout.setAlignment(Qt.AlignRight) self.__apply_btn = QPushButton("Apply") self.__apply_btn.clicked.connect(self.collect) storno = QPushButton("Storno") storno.clicked.connect(self.close) button_layout.addWidget(storno) button_layout.addWidget(self.__apply_btn) # SHOW WIDGETS ========================================================= model_i = list(VIEW_DATA.keys()).index(self.__enigma_api.model()) self.__stacked_wikis.select_model(model_i) self.__stacked_wikis.highlight(model_i) main_layout.addWidget(tab_widget) main_layout.addWidget(button_frame) def open_ukwd_window(self): """Opens UKWD wiring menu""" logging.info("Opened UKW-D wiring menu...") self.__ukwd_window.exec_() self.refresh_ukwd() def refresh_ukwd(self): """Refreshes Apply button according to criteria (UKW-D rotor must be selected to edit its settings)""" if self.__reflector_group.checkedButton().text() == "UKW-D": logging.info("UKW-D reflector selected, enabling UKW-D button...") if len(self.__ukwd_window.pairs()) != 12: self.__apply_btn.setDisabled(True) self.__apply_btn.setToolTip( "Connect all 12 pairs in UKW-D wiring!") else: self.__apply_btn.setDisabled(False) self.__apply_btn.setToolTip(None) self.__ukwd_button.setDisabled(False) self.__ukwd_button.setToolTip( "Select the UKW-D rotor to edit settings") if len(self.__rotor_frames) == 4: # IF THIN ROTORS logging.info("Disabling thin rotor radiobuttons...") self.__rotor_frames[0].setDisabled(True) else: logging.info( "UKW-D reflector deselected, disabling UKW-D button...") self.__apply_btn.setDisabled(False) self.__apply_btn.setToolTip(None) self.__ukwd_button.setDisabled(True) self.__ukwd_button.setToolTip(None) if len(self.__rotor_frames) == 4: # IF THIN ROTORS logging.info("Enabling thin rotor radiobuttons...") self.__rotor_frames[0].setDisabled(False) def generate_components(self, reflectors, rotors, rotor_n, charset): """Generates currently displayed components based on Enigma model :param reflectors: {str} Reflector labels :param rotors: {[str, str, str]} Rotor labels :param rotor_n: {int} Number of rotors the Enigma model has """ # REFLECTOR SETTINGS =================================================== spacing = 15 style = "font-size: 18px; text-align: center;" reflector_frame = QFrame(self.__settings_frame) reflector_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Plain) reflector_layout = QVBoxLayout(reflector_frame) reflector_layout.setSpacing(spacing) reflector_layout.addWidget( QLabel("REFLECTOR", reflector_frame, styleSheet=style), alignment=Qt.AlignHCenter, ) self.__reflector_group = QButtonGroup(reflector_frame) reflector_layout.setAlignment(Qt.AlignTop) for i, model in enumerate(reflectors): radio = QRadioButton(model, reflector_frame) radio.setToolTip( "Reflector is an Enigma component that \nreflects " "letters from the rotors back to the lightboard") self.__reflector_group.addButton(radio) self.__reflector_group.setId(radio, i) reflector_layout.addWidget(radio, alignment=Qt.AlignTop) reflector_layout.addStretch() reflector_layout.addWidget(self.__ukwd_button) self.__reflector_group.button(0).setChecked(True) self.__reflector_group.buttonClicked.connect(self.refresh_ukwd) self.__settings_layout.addWidget(reflector_frame) # ROTOR SETTINGS ======================================================= self.__rotor_selectors = [] self.__ring_selectors = [] self.__rotor_frames = [] for rotor in range(rotor_n): rotor_frame = QFrame(self.__settings_frame) rotor_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Plain) rotor_layout = QVBoxLayout(rotor_frame) rotor_layout.setAlignment(Qt.AlignTop) rotor_layout.setSpacing(spacing) rotor_frame.setLayout(rotor_layout) # ROTOR RADIOS ===================================================== label = QLabel(SELECTOR_LABELS[-rotor_n:][rotor], rotor_frame, styleSheet=style) label.setToolTip(SELECTOR_TOOLTIPS[-rotor_n:][rotor]) rotor_layout.addWidget(label, alignment=Qt.AlignHCenter) button_group = QButtonGroup(rotor_frame) final_rotors = rotors if "Beta" in rotors: logging.info( "Enigma M4 rotors detected, adjusting radiobuttons...") if rotor == 0: final_rotors = ["Beta", "Gamma"] else: final_rotors.remove("Beta") final_rotors.remove("Gamma") for i, model in enumerate(final_rotors): radios = QRadioButton(model, rotor_frame) button_group.addButton(radios) button_group.setId(radios, i) rotor_layout.addWidget(radios, alignment=Qt.AlignTop) button_group.button(0).setChecked(True) # RINGSTELLUNG ===================================================== combobox = QComboBox(rotor_frame) for i, label in enumerate(LABELS[:len(charset)]): combobox.addItem(label, i) h_rule = QFrame(rotor_frame) h_rule.setFrameShape(QFrame.HLine) h_rule.setFrameShadow(QFrame.Sunken) self.__ring_selectors.append(combobox) self.__rotor_selectors.append(button_group) rotor_layout.addStretch() rotor_layout.addWidget(h_rule) rotor_layout.addWidget( QLabel("RING SETTING", rotor_frame, styleSheet=style), alignment=Qt.AlignHCenter, ) rotor_layout.addWidget(combobox) self.__settings_layout.addWidget(rotor_frame) self.__rotor_frames.append(rotor_frame) def clear_components(self): """Deletes all components settings widgets""" while True: child = self.__settings_layout.takeAt(0) if not child: break wgt = child.widget() wgt.deleteLater() del wgt def regenerate_for_model(self, new_model): """Regenerates component settings :param new_model: {str} Enigma model """ logging.info("Regenerating component settings...") self.clear_components() reflectors = self.__enigma_api.model_labels(new_model)["reflectors"] rotors = self.__enigma_api.model_labels(new_model)["rotors"] rotor_n = self.__enigma_api.rotor_n(new_model) charset = HISTORICAL[new_model]["charset"] self.generate_components(reflectors, rotors[::], rotor_n, charset) defaults = self.__enigma_api.default_cfg(new_model, rotor_n)[1] for selected, i in zip(defaults, range(rotor_n)): self.__rotor_selectors[i].button(selected).setChecked(True) self.__ukwd_window.clear_pairs() self.__ukwd_window._old_pairs = {} if new_model == self.__enigma_api.model(): self.load_from_api() self.__ukwd_window.refresh_pairs() self.refresh_ukwd() def load_from_api(self): """Loads displayed settings from shared EnigmaAPI instance""" logging.info("Loading component settings from EnigmaAPI...") model = self.__enigma_api.model() reflectors = self.__enigma_api.model_labels(model)["reflectors"] rotors = self.__enigma_api.model_labels(model)["rotors"] if "Beta" in rotors: rotors.remove("Beta") rotors.remove("Gamma") reflector_i = reflectors.index(self.__enigma_api.reflector()) self.__reflector_group.button(reflector_i).setChecked(True) for i, rotor in enumerate(self.__enigma_api.rotors()): if (model == "Enigma M4" and self.__enigma_api.reflector() != "UKW-D" and i == 0): rotor_i = ["Beta", "Gamma"].index(rotor) else: rotor_i = rotors.index(rotor) self.__rotor_selectors[i].button(rotor_i).setChecked(True) for i, ring in enumerate(self.__enigma_api.ring_settings()): self.__ring_selectors[i].setCurrentIndex(ring - 1) def collect(self): """Collects all selected settings for rotors and other components, applies them to the EnigmaAPI as new settings""" logging.info("Collecting new settings...") new_model = self.__stacked_wikis.currently_selected new_reflector = self.__reflector_group.checkedButton().text( ) # REFLECTOR CHOICES reflector_pairs = self.__ukwd_window.pairs() if new_reflector == "UKW-D" and new_model == "Enigma M4": new_rotors = [ group.checkedButton().text() for group in self.__rotor_selectors[1:] ] else: new_rotors = [ group.checkedButton().text() for group in self.__rotor_selectors ] ring_settings = [ ring.currentIndex() + 1 for ring in self.__ring_selectors ] logging.info("EnigmaAPI state before applying settings:\n%s", str(self.__enigma_api)) if new_model != self.__enigma_api.model(): self.__enigma_api.model(new_model) if new_reflector != self.__enigma_api.reflector(): self.__enigma_api.reflector(new_reflector) if new_reflector == "UKW-D": self.__enigma_api.reflector_pairs(reflector_pairs) if new_rotors != self.__enigma_api.rotors(): self.__enigma_api.rotors(new_rotors) if ring_settings != self.__enigma_api.ring_settings(): self.__enigma_api.ring_settings(ring_settings) logging.info("EnigmaAPI state when closing settings:\n%s", str(self.__enigma_api)) self.close() def pairs(self): """Returns current UKW-D pairs for collection""" return self._pairs
def generate_components(self, reflectors, rotors, rotor_n, charset): """Generates currently displayed components based on Enigma model :param reflectors: {str} Reflector labels :param rotors: {[str, str, str]} Rotor labels :param rotor_n: {int} Number of rotors the Enigma model has """ # REFLECTOR SETTINGS =================================================== spacing = 15 style = "font-size: 18px; text-align: center;" reflector_frame = QFrame(self.__settings_frame) reflector_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Plain) reflector_layout = QVBoxLayout(reflector_frame) reflector_layout.setSpacing(spacing) reflector_layout.addWidget( QLabel("REFLECTOR", reflector_frame, styleSheet=style), alignment=Qt.AlignHCenter, ) self.__reflector_group = QButtonGroup(reflector_frame) reflector_layout.setAlignment(Qt.AlignTop) for i, model in enumerate(reflectors): radio = QRadioButton(model, reflector_frame) radio.setToolTip( "Reflector is an Enigma component that \nreflects " "letters from the rotors back to the lightboard") self.__reflector_group.addButton(radio) self.__reflector_group.setId(radio, i) reflector_layout.addWidget(radio, alignment=Qt.AlignTop) reflector_layout.addStretch() reflector_layout.addWidget(self.__ukwd_button) self.__reflector_group.button(0).setChecked(True) self.__reflector_group.buttonClicked.connect(self.refresh_ukwd) self.__settings_layout.addWidget(reflector_frame) # ROTOR SETTINGS ======================================================= self.__rotor_selectors = [] self.__ring_selectors = [] self.__rotor_frames = [] for rotor in range(rotor_n): rotor_frame = QFrame(self.__settings_frame) rotor_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Plain) rotor_layout = QVBoxLayout(rotor_frame) rotor_layout.setAlignment(Qt.AlignTop) rotor_layout.setSpacing(spacing) rotor_frame.setLayout(rotor_layout) # ROTOR RADIOS ===================================================== label = QLabel(SELECTOR_LABELS[-rotor_n:][rotor], rotor_frame, styleSheet=style) label.setToolTip(SELECTOR_TOOLTIPS[-rotor_n:][rotor]) rotor_layout.addWidget(label, alignment=Qt.AlignHCenter) button_group = QButtonGroup(rotor_frame) final_rotors = rotors if "Beta" in rotors: logging.info( "Enigma M4 rotors detected, adjusting radiobuttons...") if rotor == 0: final_rotors = ["Beta", "Gamma"] else: final_rotors.remove("Beta") final_rotors.remove("Gamma") for i, model in enumerate(final_rotors): radios = QRadioButton(model, rotor_frame) button_group.addButton(radios) button_group.setId(radios, i) rotor_layout.addWidget(radios, alignment=Qt.AlignTop) button_group.button(0).setChecked(True) # RINGSTELLUNG ===================================================== combobox = QComboBox(rotor_frame) for i, label in enumerate(LABELS[:len(charset)]): combobox.addItem(label, i) h_rule = QFrame(rotor_frame) h_rule.setFrameShape(QFrame.HLine) h_rule.setFrameShadow(QFrame.Sunken) self.__ring_selectors.append(combobox) self.__rotor_selectors.append(button_group) rotor_layout.addStretch() rotor_layout.addWidget(h_rule) rotor_layout.addWidget( QLabel("RING SETTING", rotor_frame, styleSheet=style), alignment=Qt.AlignHCenter, ) rotor_layout.addWidget(combobox) self.__settings_layout.addWidget(rotor_frame) self.__rotor_frames.append(rotor_frame)
class AppearanceTab(QWidget): def __init__(self, parent): """Initialize the appearance tab """ super(AppearanceTab, self).__init__(parent) self.prefs = parent.prefs # Default column width code col_width_label = QLabel("Default Column Width:") self.col_width_edit = QLineEdit(str(self.prefs['default_column_width'])) self.col_width_edit.setMinimumWidth(40) self.col_width_edit.setMaximumWidth(100) validator = QIntValidator(10, 200, self) self.col_width_edit.setValidator(validator) # Visual style code style_label = QLabel("Visual Style of Application:") self.style_edit = QComboBox(self) self.style_edit.addItems(list(QStyleFactory.keys())) self.style_edit.setMaximumWidth(200) self.style_edit.setCurrentIndex(self.style_edit.findText(self.prefs['style'])) # Units display code units_header_label = QLabel("Units Display:") self.header_units_check = QCheckBox('Show Units in Table Headers', self) checked_header = Qt.Checked if self.prefs['show_units_in_headers'] == 1 else Qt.Unchecked self.header_units_check.setCheckState(checked_header) self.cells_units_check = QCheckBox('Show Units in Table Cells', self) checked_cells = Qt.Checked if self.prefs['show_units_in_cells'] == 1 else Qt.Unchecked self.cells_units_check.setCheckState(checked_cells) # Handling of file options code default_handling_text = QLabel("Select how options saved directly within an IDF " "file are treated. See \"Save Options\" tab " "for the options in question.") default_handling_text.setWordWrap(True) default_handling_text.setMaximumWidth(450) self.button_force = QRadioButton("Force Session Options:", self) force_text = QLabel("Options from the current session will be used for all " "files, ignoring any options saved in the IDF file.") force_text.setWordWrap(True) force_text.setMaximumWidth(450) force_text.setMinimumHeight(30) force_text.setIndent(25) self.button_obey = QRadioButton("Obey IDF Options if Present:", self) obey_text = QLabel("Obey options saved in the IDF file. If none are " "present, use the current session's options.") obey_text.setWordWrap(True) obey_text.setMaximumWidth(450) obey_text.setMinimumHeight(30) obey_text.setIndent(25) # Handling of file options group box self.behaviour_group_box = QGroupBox("Handling of File-based Options") self.behaviour_group_box.setMinimumHeight(220) self.behaviour_group_box.setMinimumWidth(450) behaviour_box = QVBoxLayout() behaviour_box.addWidget(default_handling_text) behaviour_box.addWidget(self.button_force) behaviour_box.addWidget(force_text) behaviour_box.addSpacing(5) behaviour_box.addWidget(self.button_obey) behaviour_box.addWidget(obey_text) behaviour_box.addStretch(1) self.behaviour_group_box.setLayout(behaviour_box) self.behaviour_button_group = QButtonGroup(self) self.behaviour_button_group.addButton(self.button_force) self.behaviour_button_group.addButton(self.button_obey) self.behaviour_button_group.setId(self.button_force, 0) self.behaviour_button_group.setId(self.button_obey, 1) self.behaviour_button_group.button(self.prefs['obey_idf_options']).setChecked(True) # Main layout code mainLayout = QVBoxLayout() mainLayout.addWidget(col_width_label) mainLayout.addWidget(self.col_width_edit) mainLayout.addSpacing(10) mainLayout.addWidget(style_label) mainLayout.addWidget(self.style_edit) mainLayout.addSpacing(10) mainLayout.addWidget(self.behaviour_group_box) mainLayout.addSpacing(10) mainLayout.addWidget(units_header_label) mainLayout.addWidget(self.header_units_check) mainLayout.addWidget(self.cells_units_check) mainLayout.addStretch(1) self.setLayout(mainLayout) # Update settings self.behaviour_button_group.buttonClicked.connect(self.update) self.col_width_edit.textChanged.connect(self.update) self.style_edit.currentIndexChanged.connect(self.update) self.header_units_check.stateChanged.connect(self.update) self.cells_units_check.stateChanged.connect(self.update) def update(self): self.prefs['default_column_width'] = self.col_width_edit.text() self.prefs['style'] = self.style_edit.currentText() self.prefs['obey_idf_options'] = self.behaviour_button_group.checkedId() self.prefs['show_units_in_headers'] = 1 if self.header_units_check.checkState() else 0 self.prefs['show_units_in_cells'] = 1 if self.cells_units_check.checkState() else 0