1# 2# configuration_wdgt_card_appearance.py <Peter.Bienstman@UGent.be> 3# 4 5from copy import deepcopy 6 7from PyQt5 import QtCore, QtGui, QtWidgets 8 9from mnemosyne.libmnemosyne.fact import Fact 10from mnemosyne.libmnemosyne.gui_translator import _ 11from mnemosyne.libmnemosyne.component import Component 12from mnemosyne.pyqt_ui.preview_cards_dlg import PreviewCardsDlg 13from mnemosyne.libmnemosyne.ui_components.configuration_widget import \ 14 ConfigurationWidget 15from mnemosyne.pyqt_ui.ui_configuration_wdgt_card_appearance import \ 16 Ui_ConfigurationWdgtCardAppearance 17 18 19class ConfigurationWdgtCardAppearance(QtWidgets.QWidget, ConfigurationWidget, 20 Ui_ConfigurationWdgtCardAppearance): 21 22 name = _("Card appearance") 23 24 def __init__(self, **kwds): 25 super().__init__(**kwds) 26 self.setupUi(self) 27 self.dynamic_widgets = [] 28 self.affected_card_types = [] 29 self.fact_key_names = [] 30 self.non_latin_font_size_increase.setValue\ 31 (self.config()['non_latin_font_size_increase']) 32 # We calculate card_type_by_name here because these names can change 33 # if the user chooses another translation. 34 self.card_types_widget.addItem(_("<all card types>")) 35 self.card_type_by_name = {} 36 for card_type in self.database().sorted_card_types(): 37 if card_type.hidden_from_UI: 38 continue 39 self.card_type_by_name[_(card_type.name)] = card_type 40 self.card_types_widget.addItem(_(card_type.name)) 41 # Store backups in order to be able to revert our changes. 42 self.old_font = deepcopy(self.config()["font"]) 43 self.old_background_colour = \ 44 deepcopy(self.config()["background_colour"]) 45 self.old_font_colour = deepcopy(self.config()["font_colour"]) 46 self.old_alignment = deepcopy(self.config()["alignment"]) 47 48 def card_type_changed(self, new_card_type_name): 49 non_latin_widgets = [self.label_non_latin_1, self.label_non_latin_2, 50 self.label_non_latin_3, self.line_non_latin, 51 self.non_latin_font_size_increase] 52 background_align_widgets = [self.background_label, 53 self.background_button, self.align_label, self.alignment] 54 if new_card_type_name == _("<all card types>"): 55 self.affected_card_types = self.card_types() 56 self.fact_key_names = [_("Text")] 57 for widget in non_latin_widgets + background_align_widgets: 58 widget.show() 59 else: 60 new_card_type_name = new_card_type_name 61 new_card_type = self.card_type_by_name[new_card_type_name] 62 self.affected_card_types = [new_card_type] 63 self.fact_key_names = new_card_type.fact_key_names() 64 for widget in background_align_widgets: 65 if new_card_type.id.startswith("7::"): 66 widget.hide() 67 else: 68 widget.show() 69 for widget in non_latin_widgets: 70 widget.hide() 71 for widget in self.dynamic_widgets: 72 self.gridLayout.removeWidget(widget) 73 widget.close() 74 self.dynamic_widgets = [] 75 76 row = 0 77 self.font_buttons = QtWidgets.QButtonGroup() 78 self.colour_buttons = QtWidgets.QButtonGroup() 79 self.align_buttons = QtWidgets.QButtonGroup() 80 self.align_buttons.setExclusive(False) 81 for key_name in self.fact_key_names: 82 label = QtWidgets.QLabel(_(key_name) + ":", self) 83 self.gridLayout.addWidget(label, row, 0, 1, 1) 84 self.dynamic_widgets.append(label) 85 86 font = QtWidgets.QPushButton(_("Select font"), self) 87 self.font_buttons.addButton(font, row) 88 self.gridLayout.addWidget(font, row, 1, 1, 1) 89 self.dynamic_widgets.append(font) 90 91 colour = QtWidgets.QPushButton(_("Select colour"),self) 92 self.colour_buttons.addButton(colour, row) 93 self.gridLayout.addWidget(colour, row, 2, 1, 1) 94 self.dynamic_widgets.append(colour) 95 96 row += 1 97 self.gridLayout.setColumnStretch(1, 10) 98 self.gridLayout.setColumnStretch(2, 10) 99 self.font_buttons.buttonClicked[int].connect(self.update_font) 100 self.colour_buttons.buttonClicked[int].\ 101 connect(self.update_font_colour) 102 103 current_alignment = self.config().card_type_property(\ 104 "alignment", self.affected_card_types[0], default="center") 105 if current_alignment == "left": 106 self.alignment.setCurrentIndex(0) 107 elif current_alignment == "center": 108 self.alignment.setCurrentIndex(1) 109 elif current_alignment == "right": 110 self.alignment.setCurrentIndex(2) 111 # Make font light if different alignments are active. 112 self.alignment.setFont(self.font()) 113 values = set() 114 for card_type in self.affected_card_types: 115 if not card_type.id in self.config()["alignment"]: 116 values.add("center") 117 else: 118 values.add(self.config()["alignment"][card_type.id]) 119 if len(values) > 1: 120 self.alignment.font().setWeight(25) 121 else: 122 self.alignment.font().setWeight(50) 123 self.adjustSize() 124 125 def update_background_colour(self): 126 # Determine current colour. 127 current_rgb = self.config().card_type_property("background_colour", 128 self.affected_card_types[0]) 129 if current_rgb: 130 current_colour = QtGui.QColor(current_rgb) 131 else: 132 current_colour = self.palette().color(QtGui.QPalette.Base) 133 # Set new colour. 134 colour = QtWidgets.QColorDialog.getColor(current_colour, self) 135 if colour.isValid(): 136 for card_type in self.affected_card_types: 137 self.config().set_card_type_property("background_colour", 138 colour.rgb(), card_type) 139 140 def update_font(self, index): 141 # Determine keys affected. 142 if len(self.affected_card_types) > 1: 143 affected_fact_key = None # Actually means all the keys. 144 else: 145 affected_fact_key = \ 146 self.affected_card_types[0].fact_keys_and_names[index][0] 147 # Determine current font. 148 if len(self.affected_card_types) > 1: 149 font_strings = set() 150 for card_type in self.affected_card_types: 151 if card_type.hidden_from_UI: 152 continue 153 font_strings.add(self.config().card_type_property(\ 154 "font", card_type, card_type.fact_keys_and_names[0][0])) 155 if len(font_strings) > 1: 156 font_string = None 157 else: 158 font_string = font_strings.pop() 159 else: 160 font_string = self.config().card_type_property(\ 161 "font", self.affected_card_types[0], affected_fact_key) 162 current_font = QtGui.QFont(self.font()) 163 if font_string: 164 current_font.fromString(font_string) 165 # Set new font. 166 font, ok = QtWidgets.QFontDialog.getFont(current_font, self) 167 if ok: 168 font_string = font.toString() 169 for card_type in self.affected_card_types: 170 self.config().set_card_type_property("font", font_string, 171 card_type, affected_fact_key) 172 173 def update_font_colour(self, index): 174 # Determine keys affected. 175 if len(self.affected_card_types) > 1: 176 affected_fact_key = None # Actually means all the keys. 177 else: 178 affected_fact_key = \ 179 self.affected_card_types[0].fact_keys_and_names[index][0] 180 # Determine current colour. 181 if len(self.affected_card_types) > 1: 182 current_rgb = self.config().card_type_property(\ 183 "font_colour", self.card_type_with_id("1"), "f") 184 else: 185 current_rgb = self.config().card_type_property(\ 186 "font_colour", self.affected_card_types[0], affected_fact_key) 187 if current_rgb: 188 current_colour = QtGui.QColor(current_rgb) 189 else: 190 current_colour = QtGui.QColor(QtCore.Qt.black) 191 # Set new colour. 192 colour = QtWidgets.QColorDialog.getColor(current_colour, self) 193 if colour.isValid(): 194 for card_type in self.affected_card_types: 195 self.config().set_card_type_property("font_colour", 196 colour.rgb(), card_type, affected_fact_key) 197 198 def update_alignment(self, index): 199 if index == 0: 200 new_alignment = "left" 201 elif index == 1: 202 new_alignment = "center" 203 elif index == 2: 204 new_alignment = "right" 205 for card_type in self.affected_card_types: 206 self.config().set_card_type_property("alignment", new_alignment, 207 card_type) 208 self.alignment.font().setWeight(50) 209 210 def apply(self): 211 self.config()["non_latin_font_size_increase"] = \ 212 self.non_latin_font_size_increase.value() 213 for card_type in self.card_types(): 214 for render_chain in self.component_manager.all("render_chain"): 215 render_chain.renderer_for_card_type(card_type).\ 216 update(card_type) 217 218 def preview(self): 219 card_type = self.affected_card_types[0] 220 for render_chain in self.component_manager.all("render_chain"): 221 render_chain.renderer_for_card_type(card_type).update(card_type) 222 fact_data = {} 223 for fact_key, fact_key_name in card_type.fact_keys_and_names: 224 fact_data[fact_key] = _(fact_key_name) 225 # Tmp hack for cloze. 226 if fact_key == "text": 227 fact_data[fact_key] = "[" + _(fact_key_name) + "]" 228 fact = Fact(fact_data) 229 cards = card_type.create_sister_cards(fact) 230 # Tmp hack for Anki 231 for card in cards: 232 card.extra_data["ord"] = 1 233 tag_text = "" 234 dlg = PreviewCardsDlg(cards, tag_text, 235 component_manager=self.component_manager, parent=self) 236 dlg.exec_() 237 238 def reset_to_defaults(self): 239 if len(self.affected_card_types) > 1: 240 message = _("Reset all card types to default system font?") 241 else: 242 message = _("Reset '%s' to default system font?") \ 243 % (_(self.affected_card_types[0].name)) 244 result = self.main_widget().show_question(\ 245 message, _("&Yes"), _("&No"), "") 246 if result == 1: 247 return 248 self.non_latin_font_size_increase.setValue(0) 249 if len(self.affected_card_types) > 1: 250 self.config()["font"] = {} 251 self.config()["background_colour"] = {} 252 self.config()["font_colour"] = {} 253 self.config()["alignment"] = {} 254 else: 255 card_type_id = self.affected_card_types[0].id 256 self.config()["font"].pop(card_type_id, None) 257 self.config()["background_colour"].pop(card_type_id, None) 258 self.config()["font_colour"].pop(card_type_id, None) 259 self.config()["alignment"].pop(card_type_id, None) 260 self.alignment.setCurrentIndex(1) 261 262 def reject(self): 263 self.config()["font"] = self.old_font 264 self.config()["background_colour"] = self.old_background_colour 265 self.config()["font_colour"] = self.old_font_colour 266 self.config()["alignment"] = self.old_alignment 267 for card_type in self.card_types(): 268 for render_chain in self.component_manager.all("render_chain"): 269 render_chain.renderer_for_card_type(card_type).\ 270 update(card_type) 271 272