def __init__(self, parent): QDialog.__init__(self, parent) self.parent = parent self.fieldWidgets = {} self.controls = pinyin.forms.generated.builddb.Ui_BuildDB() self.controls.setupUi(self)
def accept(self): saveGeom(self, "TT/TIFP") row = self.list_box.currentRow() if len(self.fuzzy_items) > 0: row = self.list_box.currentRow() self.selkey = self.fuzzy_items[row] if self.selkey not in self.originalkeys: k = self.selkey.strip() if " " in k: tooltip('tags may not contain spaces. Aborting ...') return if self.dict: self.selvalue = self.dict[self.selkey] QDialog.accept(self) else: if not self.allownew: tooltip('nothing entered. Aborting ...') else: input = self.input_line.text().strip() if input: if " " in input: tooltip('tags may not contain spaces. Aborting ...') else: self.selkey = input QDialog.accept(self) else: tooltip('nothing entered. Aborting ...')
def __init__(self, parent=None, config=None): self.parent = parent self.config = config QDialog.__init__(self, parent, Qt.Window) self.dialog = settings_textwrapper.Ui_Dialog() self.dialog.setupUi(self) self.menuentry = "" if config: if config["Hotkey"]: self.dialog.hotkey.setKeySequence(config["Hotkey"]) if config["Target group in menu"]: self.dialog.le_menu_group.setText( config["Target group in menu"]) if config["Text_in_menu_styling"]: self.dialog.pte_before.insertPlainText( config["Text_in_menu_styling"]) if config["Text_in_menu_styling_nightmode"]: self.dialog.pte_after.insertPlainText( config["Text_in_menu_styling_nightmode"]) if config["Show_in_menu"]: self.dialog.cb_contextmenu_show.setChecked(True) if config["Text_in_menu"]: self.dialog.le_contextmenu_text.setText(config["Text_in_menu"]) if config["extrabutton_show"]: self.dialog.cb_extrabutton_show.setChecked(True) if config["extrabutton_text"]: self.dialog.le_extrabutton_text.setText( config["extrabutton_text"]) if config["extrabutton_tooltip"]: self.dialog.le_tooltip_text.setText( config["extrabutton_tooltip"])
def __init__(self, parent, thisconf, progs): if thisconf: self.thisconf = thisconf else: self.thisconf = {} self.progs = progs self.exts_used_when_opened = self.thisconf.get("extensions", []) self.parent = parent QDialog.__init__(self, parent, Qt.Window) self.dialog = config_dialog__add_edit_single_entry.Ui_Dialog() self.dialog.setupUi(self) self.adjustSize() self.fill_fields() self.dialog.pb_load_from_defaults.clicked.connect( self.load_from_defaults) self.dialog.pb_path_add.clicked.connect(self.add_default_path) self.dialog.pb_path_up.clicked.connect(self.path_up) self.dialog.pb_path_down.clicked.connect(self.path_down) self.dialog.pb_path_del.clicked.connect(self.del_default_path) self.dialog.pb_cmd_pickpath.clicked.connect(self.pickcmdpath) self.dialog.pb_cmd_guess.clicked.connect(self.cmdguess) self.dialog.pb_parameters_guess.clicked.connect(self.parameters_guess) self.dialog.buttonBox.accepted.disconnect(self.accept) self.dialog.buttonBox.accepted.connect(self.onAccept) self.dialog.buttonBox.rejected.disconnect(self.reject) self.dialog.buttonBox.rejected.connect(self.onReject) self.dialog.buttonBox.helpRequested.connect(self.onHelp) self.dialog.pb_parameters_guess.hide() self.dialog.pb_params_info.clicked.connect(self.onParamsInfo)
def accept(self): # originally "Setting" was used for the foreground or background color. The value for # "Setting" is used when clicking a menu/button or shortcut. So before/after must be # in "Setting" # But only set this when closing the dialog so that the unique string is not shown # to the user. That workaround is a consequence of reading the config from the # QTableWidget directly .... bef = self.dialog.pte_before.toPlainText() aft = self.dialog.pte_after.toPlainText() self.newsetting = { "Category": "text wrapper", "Hotkey": self.dialog.hotkey.keySequence().toString(), "Setting": "", # bef + unique_string + aft, "Show_in_menu": self.dialog.cb_contextmenu_show.isChecked(), "Target group in menu": self.dialog.le_menu_group.text(), "Text_in_menu": self.dialog.le_contextmenu_text.text(), "Text_in_menu_styling": bef, "Text_in_menu_styling_nightmode": aft, "extrabutton_show": self.dialog.cb_extrabutton_show.isChecked(), "extrabutton_text": self.dialog.le_extrabutton_text.text(), "extrabutton_tooltip": self.dialog.le_tooltip_text.text(), } if self.config: # new entries don't have this entry yet if "Category" in self.config: self.newsetting["Category"] = self.config["Category"] QDialog.accept(self)
def __init__(self, mw, deck): QDialog.__init__(self, mw) self.mw = mw self.deck = deck self.childDids = [ d[1] for d in self.mw.col.decks.children(self.deck['id']) ] self._origNewOrder = None self.form = aqt.forms.dconf.Ui_Dialog() self.form.setupUi(self) self.mw.checkpoint(_("Options")) self.setupCombos() self.setupConfs() self.setWindowModality(Qt.WindowModal) self.form.buttonBox.helpRequested.connect( lambda: openHelp("deckoptions")) self.form.confOpts.clicked.connect(self.confOpts) self.form.buttonBox.button( QDialogButtonBox.RestoreDefaults).clicked.connect(self.onRestore) self.setWindowTitle(_("Options for %s") % self.deck['name']) # qt doesn't size properly with altered fonts otherwise restoreGeom(self, "deckconf", adjustSize=True) self.show() self.exec_() saveGeom(self, "deckconf")
def __init__(self, parent=None): self.parent = parent QDialog.__init__(self, parent, Qt.Window) self.dialog = settings_select_category.Ui_Dialog() self.dialog.setupUi(self) self.dialog.list_categories.addItems(addable_options) self.dialog.list_categories.itemDoubleClicked.connect(self.accept)
def __init__(self, mw): QDialog.__init__(self, mw, Qt.Window) mw.setupDialogGC(self) self.mw = mw self.name = "deckStats" self.period = 0 self.form = aqt.forms.stats.Ui_Dialog() self.oldPos = None self.wholeCollection = False self.setMinimumWidth(700) f = self.form f.setupUi(self) restoreGeom(self, self.name) b = f.buttonBox.addButton(_("Save PDF"), QDialogButtonBox.ActionRole) b.clicked.connect(self.saveImage) b.setAutoDefault(False) f.groups.clicked.connect(lambda: self.changeScope("deck")) f.groups.setShortcut("g") f.all.clicked.connect(lambda: self.changeScope("collection")) f.month.clicked.connect(lambda: self.changePeriod(0)) f.year.clicked.connect(lambda: self.changePeriod(1)) f.life.clicked.connect(lambda: self.changePeriod(2)) maybeHideClose(self.form.buttonBox) addCloseShortcut(self) self.show() self.refresh() self.activateWindow()
def onAddField(self): diag = QDialog(self) form = aqt.forms.addfield.Ui_Dialog() form.setupUi(diag) fields = [f['name'] for f in self.model['flds']] form.fields.addItems(fields) form.font.setCurrentFont(QFont("Arial")) form.size.setValue(20) diag.show() # Work around a Qt bug, # https://bugreports.qt-project.org/browse/QTBUG-1894 if isMac or isWin: # No problems on Macs or Windows. form.fields.showPopup() else: # Delay showing the pop-up. self.mw.progress.timer(200, form.fields.showPopup, False) if not diag.exec_(): return if form.radioQ.isChecked(): obj = self.tform.front else: obj = self.tform.back self._addField(obj, fields[form.fields.currentIndex()], form.font.currentFont().family(), form.size.value())
def onTargetDeck(self): from aqt.tagedit import TagEdit t = self.card.template() d = QDialog(self) d.setWindowTitle("Anki") d.setMinimumWidth(400) l = QVBoxLayout() lab = QLabel(_("""\ Enter deck to place new %s cards in, or leave blank:""") % self.card.template()['name']) lab.setWordWrap(True) l.addWidget(lab) te = TagEdit(d, type=1) te.setCol(self.col) l.addWidget(te) if t['did']: te.setText(self.col.decks.get(t['did'])['name']) te.selectAll() bb = QDialogButtonBox(QDialogButtonBox.Close) bb.rejected.connect(d.close) l.addWidget(bb) d.setLayout(l) d.exec_() if not te.text().strip(): t['did'] = None else: t['did'] = self.col.decks.id(te.text())
def __init__(self, parent, question, help=None, edit=None, default="", \ title="Anki", minWidth=400): QDialog.__init__(self, parent) self.setWindowTitle(title) self.question = question self.help = help self.qlabel = QLabel(question) self.setMinimumWidth(minWidth) v = QVBoxLayout() v.addWidget(self.qlabel) if not edit: edit = QLineEdit() self.l = edit if default: self.l.setText(default) self.l.selectAll() v.addWidget(self.l) buts = QDialogButtonBox.Ok | QDialogButtonBox.Cancel if help: buts |= QDialogButtonBox.Help b = QDialogButtonBox(buts) v.addWidget(b) self.setLayout(v) b.button(QDialogButtonBox.Ok).clicked.connect(self.accept) b.button(QDialogButtonBox.Cancel).clicked.connect(self.reject) if help: b.button(QDialogButtonBox.Help).clicked.connect(self.helpRequested)
def onDelete(): saveGeom(diag, "emptyCards") QDialog.accept(diag) self.checkpoint(_("Delete Empty")) self.col.remCards(cids) tooltip(ngettext("%d card deleted.", "%d cards deleted.", len(cids)) % len(cids)) self.reset()
def __init__(self, parent=None, alternatives=[]): self.parent = parent QDialog.__init__(self, parent, Qt.Window) self.dialog = settings_select_group.Ui_Dialog() self.dialog.setupUi(self) self.dialog.list_categories.addItems(alternatives) self.dialog.list_categories.itemDoubleClicked.connect(self.accept)
def cleanup_and_close(self): gui_hooks.editor_did_load_note.remove(self.editor_did_load_note) gui_hooks.operation_did_execute.remove(self.on_operation_did_execute) self.editor.cleanup() saveGeom(self, self.dialog_geometry_tag) aqt.dialogs.markClosed(self.dialog_registry_tag) QDialog.reject(self)
def reject(self) -> None: if self._close_when_done and self._syncer.is_syncing(): # closing while syncing on close starts an abort self._on_abort() return aqt.dialogs.markClosed("sync_log") QDialog.reject(self)
def accept(self): # replace cursor with unique string s = """insertTextAtCursor('%s')""" % unique_string self.execJavaScript(s) mw.col.cmhelper_field_content = self.execJavaScript(self.js_save_cmd) saveGeom(self, "1043915942_CmDialog") self.web = None QDialog.accept(self)
def accept(self): row = self.frm.fields.currentRow() if row < len(self.model['flds']): self.field = self.model['flds'][row]['name'] elif row == self.frm.fields.count() - 2: self.field = "_tags" else: self.field = None QDialog.accept(self)
def closeEvent(self, event): ok = askUser("Close and discard changes?") if ok: event.ignore() saveGeom(self, "1043915942_CmDialog") self.web = None QDialog.reject(self) else: event.ignore()
def __init__(self, mw, did=None): QDialog.__init__(self, mw, Qt.Window) self.mw = mw self.col = mw.col self.frm = aqt.forms.exporting.Ui_ExportDialog() self.frm.setupUi(self) self.exporter = None self.setup(did) self.exec_()
def reject(self): self.saveField() if self.oldSortField != self.model['sortf']: self.mw.progress.start() self.mw.col.updateFieldCache(self.mm.nids(self.model)) self.mw.progress.finish() self.mm.save(self.model) self.mw.reset() QDialog.reject(self)
def accept(self): saveGeom(self, self.geomKey) remHook('reset', self.onReset) row = self.form.list.currentRow() if row < 0: showInfo(_("Please select something.")) return self.name = self.names[self.form.list.currentRow()] QDialog.accept(self)
def accept(self): self.tagstring = "" for t in self.line_list: if not self.basic_mode: t.hideCompleter() text = t.text() if text: self.tagstring += text + " " saveGeom(self, "TagDialogExtended") QDialog.accept(self)
def __init__(self, mw, names=None, accept=None, title=None, help="studydeck", current=None, cancel=True, parent=None, dyn=False, buttons=None, geomKey="default"): QDialog.__init__(self, parent or mw) if buttons is None: buttons = [] self.mw = mw self.form = aqt.forms.studydeck.Ui_Dialog() self.form.setupUi(self) self.form.filter.installEventFilter(self) self.cancel = cancel addHook('reset', self.onReset) self.geomKey = "studyDeck-" + geomKey restoreGeom(self, self.geomKey) if not cancel: self.form.buttonBox.removeButton( self.form.buttonBox.button(QDialogButtonBox.Cancel)) if buttons: for b in buttons: self.form.buttonBox.addButton(b, QDialogButtonBox.ActionRole) else: b = QPushButton(_("Add")) b.setShortcut(QKeySequence("Ctrl+N")) b.setToolTip(shortcut(_("Add New Deck (Ctrl+N)"))) self.form.buttonBox.addButton(b, QDialogButtonBox.ActionRole) b.clicked.connect(self.onAddDeck) if title: self.setWindowTitle(title) if not names: names = sorted(self.mw.col.decks.allNames(dyn=dyn)) self.nameFunc = None self.origNames = names else: self.nameFunc = names self.origNames = names() self.name = None self.ok = self.form.buttonBox.addButton(accept or _("Study"), QDialogButtonBox.AcceptRole) self.setWindowModality(Qt.WindowModal) self.form.buttonBox.helpRequested.connect(lambda: openHelp(help)) self.form.filter.textEdited.connect(self.redraw) self.form.list.itemDoubleClicked.connect(self.accept) self.show() # redraw after show so position at center correct self.redraw("", current) self.exec_()
def __init__(self, editor, parent_window, selected_text, selected_is_url=False): QDialog.__init__(self, parent_window, Qt.Window) self.editor_instance = editor self.parent_window = parent_window self.selected_text = selected_text self.selected_is_url = selected_is_url self.setWindowTitle("Anki: Create a hyperlink") self.resize(DIALOG_SIZE_X, DIALOG_SIZE_Y) restoreGeom(self, "318752047__add_hyperlink") self.pb_ok = QPushButton("&OK", self) self.pb_ok.setEnabled(False) self.pb_ok.clicked.connect( lambda: self.insert_anchor(url_edit.text(), urltext_edit.text())) self.pb_cancel = QPushButton("&Cancel", self) self.pb_cancel.clicked.connect(self.reject) url_label = QLabel("Link to:") url_edit = QLineEdit() url_edit.setPlaceholderText("URL") url_edit.textChanged.connect(lambda: self.enable_ok_button( self.pb_ok, url_edit.text(), urltext_edit.text())) urltext_label = QLabel("Text to display:") urltext_edit = QLineEdit() urltext_edit.setPlaceholderText("Text") urltext_edit.textChanged.connect(lambda: self.enable_ok_button( self.pb_ok, url_edit.text(), urltext_edit.text())) self.button_bar = QHBoxLayout() self.button_bar.addStretch(1) self.button_bar.addWidget(self.pb_cancel) self.button_bar.addWidget(self.pb_ok) self.dialog_vbox = QVBoxLayout() self.dialog_vbox.addWidget(url_label) self.dialog_vbox.addWidget(url_edit) self.dialog_vbox.addWidget(urltext_label) self.dialog_vbox.addWidget(urltext_edit) self.dialog_vbox.addLayout(self.button_bar) self.setLayout(self.dialog_vbox) # if user already selected text, put it in urltext_edit if self.selected_text: if self.selected_is_url: url_edit.setText(self.selected_text) urltext_edit.setFocus() else: urltext_edit.setText(self.selected_text) url_edit.setFocus()
def __init__(self, mw): QDialog.__init__(self, mw) self.mw = mw self.deck = self.mw.col.decks.current() self.conf = self.mw.col.decks.getConf(self.deck['conf']) self.form = f = aqt.forms.customstudy.Ui_Dialog() f.setupUi(self) self.setWindowModality(Qt.WindowModal) self.setupSignals() f.radio1.click() self.exec_()
def __init__(self, parent, tags, alltags): QDialog.__init__(self, parent, Qt.WindowType.Window) # super().__init__(parent) self.parent = parent self.all_tags = alltags self.setWindowTitle("Anki - Edit Tags") self.form = dialog_qlistwidget.Ui_Dialog() self.form.setupUi(self) sheet_to_use = stylesheet_dark if theme_manager.night_mode else stylesheet_light self.form.listWidget.setStyleSheet(sheet_to_use) # self.form.listWidget.currentRowChanged.connect(self.on_row_changed) self.form.buttonBox.accepted.connect(self.accept) self.form.buttonBox.rejected.connect(self.reject) self.form.pb_search.clicked.connect(lambda: self.do_browser_search(extra_search="")) self.form.pb_edit_tag.clicked.connect(self.tagselector) self.form.pb_add_empty.clicked.connect(lambda: self.maybe_add_line(force=True)) self.shortcut = QShortcut(QKeySequence("Ctrl+Return"), self) self.shortcut.activated.connect(self.accept) originalheight = self.height() restoreGeom(self, "TagDialogExtended") self.resize(self.width(), originalheight) if not tags: tags = ["",] else: tags.append("") for t in tags: self.maybe_add_line(t) self.cut = gc("in tag lines dialog: open filterdialog for single tag") if self.cut: self.form.pb_edit_tag.setToolTip('shortcut: {}'.format(self.cut)) self.selkey = QShortcut(QKeySequence(self.cut), self) self.selkey.activated.connect(self.tagselector) self.browser_scut = gc("in tag lines dialog: search browser for tag") if self.browser_scut: self.form.pb_search.setToolTip('shortcut: {}'.format(self.browser_scut)) self.browser_scut_key = QShortcut(QKeySequence(self.browser_scut), self) self.browser_scut_key.activated.connect(lambda: self.do_browser_search(extra_search="")) # don't also set Ctrl+t,a/gc("editor: show filterdialog to add single tag") for # self.tagselector: What if the user has already set them to the same etc. I'd have # to do a lot of checking self.addnl = gc("in tag lines dialog: insert additional line") if self.addnl: self.form.pb_add_empty.setToolTip('shortcut: {}'.format(self.addnl)) self.addnlscut = QShortcut(QKeySequence(self.addnl), self) self.addnlscut.activated.connect(lambda: self.maybe_add_line(force=True))
def accept(self): self.conf_text_to_dict() # updates self.current_config self.clean_settings[self.active_settings_group] = self.current_config wcs("clean_settings", self.clean_settings) cbr = self.form.bot_cb_recent_notes AllItems = [int(cbr.itemText(i)) for i in range(cbr.count())] wcs("config_window_loadable_nids", AllItems) saveGeom(self, "html_cleaner_conf_window") aqt.dialogs.markClosed("html_cleaner_config") QDialog.accept(self)
def __init__(self, browser, searchstring, quick_insert_addon_filter_func): self.searchstring = searchstring self.parent = browser self.browser = browser QDialog.__init__(self, self.parent, Qt.Window) self.form = search_box.Ui_Dialog() self.form.setupUi(self) self.setupUI() self.settext() if quick_insert_addon_filter_func: self.quick_insert_addon_filter_func = quick_insert_addon_filter_func self.form.pte.textChanged.connect(self.text_change_helper)
def __init__(self, mw) -> None: QDialog.__init__(self) self.form = import_dialog.Ui_Dialog() self.form.setupUi(self) self.conf = mw.addonManager.getConfig(__name__) self.mw = mw self.extract_thread: Optional[ImportThread] = None self.notes: Set[TwNote] = set() self.warnings: List[str] = [] self.wikis = list(self.conf['wikis'].items()) self.form.wikiProgressBar.setMaximum(len(self.wikis))
def _reject(self): remHook('reset', self.onReset) remHook('currentModelChanged', self.onModelChange) clearAudioQueue() self.removeTempNote(self.editor.note) self.editor.cleanup() self.modelChooser.cleanup() self.deckChooser.cleanup() self.mw.maybeReset() saveGeom(self, "add") aqt.dialogs.markClosed("AddCards") QDialog.reject(self)
def accept(self): # check maps field_map = self.get_field_map() templates_map = self.get_template_map() if any(True for template in list(templates_map.values()) if template is None) and \ not aqt.utils.askUser(_( "Any cards mapped to nothing will be deleted. " "If a note has no remaining cards, it will be lost. " "Are you sure you want to continue?")): return self.collection.models.change(self.old_model, self.note_id_list, self.targetModel, field_map, templates_map) self.cleanup() QDialog.accept(self)
def __init__(self, collection, note_id_list, old_model=None, parent=None): QDialog.__init__(self, parent) self.collection = collection self.note_id_list = note_id_list self.old_model = old_model if self.old_model is None: first_note = Note(collection, id=note_id_list[0]) self.old_model = first_note.model() # todo consider extracting UI file self.form = aqt.forms.changemodel.Ui_Dialog() self.form.setupUi(self) self.setWindowModality(Qt.WindowModal) self.setup() self.pauseUpdate = False self.model_changed(self.collection.models.current()) aqt.utils.restoreGeom(self, "changeModel") anki.hooks.addHook("reset", self.on_reset) anki.hooks.addHook("currentModelChanged", self.on_reset)
def displaygrid(self, config, units): self.generate(config, units) self.win = QDialog(mw) self.wv = KanjiGridWebView() vl = QVBoxLayout() vl.setContentsMargins(0, 0, 0, 0) vl.addWidget(self.wv) self.wv.stdHtml(self.html) hl = QHBoxLayout() vl.addLayout(hl) sh = QPushButton("Save HTML", clicked=lambda: self.savehtml(config)) hl.addWidget(sh) sp = QPushButton("Save Image", clicked=self.savepng) hl.addWidget(sp) bb = QPushButton("Close", clicked=self.win.reject) hl.addWidget(bb) self.win.setLayout(vl) self.win.resize(500, 400) self.timepoint("Window complete") return 0
class KanjiGrid: def __init__(self, mw): if mw: self.menuAction = QAction("Generate Kanji Grid", mw, triggered=self.setup) mw.form.menuTools.addSeparator() mw.form.menuTools.addAction(self.menuAction) def generate(self, config, units, saveMode=False): def kanjitile(char, index, count=0, avg_interval=0, missing=False): tile = "" score = "NaN" if avg_interval: score = round(scoreAdjust(avg_interval / config.interval), 2) if missing: colour = "#888" else: colour = "#000" if count != 0: bgcolour = hsvrgbstr(scoreAdjust(avg_interval / config.interval)/2) elif missing: bgcolour = "#EEE" else: bgcolour = "#FFF" if config.tooltips: tooltip = "Character: %s" % unicodedata.name(char) if count: tooltip += " | Count: %s | " % count tooltip += "Avg Interval: %s | Score: %s | " % (round(avg_interval, 2), score) tooltip += "Background: %s | Index: %s" % (bgcolour, index) tile += "\t<div style=\"background:%s;\" title=\"%s\">" % (bgcolour, tooltip) else: tile += "\t<div style=\"background:%s;\">" % (bgcolour) tile += "<a href=\"http://jisho.org/search/%s%%20%%23kanji\" style=\"color:%s;\">%s</a></div>\n" % (char, colour, char) return tile deckname = mw.col.decks.name(config.did).rsplit('::', 1)[-1] if saveMode: cols = config.wide else: cols = config.thin self.html = "<!doctype html><html><head><meta charset=\"UTF-8\" /><title>Anki Kanji Grid</title>" self.html += "<style type=\"text/css\">body{background-color:#FFF;}.maintable{width:85%%;}.maintable,.missingtable{margin-left:auto;margin-right:auto;display:grid;grid-template-columns:repeat(%s, 1fr);text-align:left;}.maintable > *,.missingtable > *{text-align:center;vertical-align:top;margin:1px;line-height:1.5em;}.key{display:inline-block;width:3em}a,a:visited{color:#000;text-decoration:none;}</style>" % cols if config.autothinwide: self.html += "<style type=\"text/css\">.maintable,.missingtable{display:block;font-size:0px}.maintable > *,.missingtable > *{display:inline-block;font-size:initial;width:1.5em;}</style>" self.html += "</head>\n" self.html += "<body>\n" self.html += "<span style=\"font-size: 3em;color: #888;\">Kanji Grid - %s</span><br>\n" % deckname self.html += "<div style=\"margin-bottom: 24pt;padding: 20pt;\"><p style=\"float: left\">Key:</p>" self.html += "<p style=\"float: right\">Weak " # keycolors = (hsvrgbstr(n/6.0) for n in range(6+1)) for c in [n/6.0 for n in range(6+1)]: self.html += "<span class=\"key\" style=\"background-color: %s;\"> </span>" % hsvrgbstr(c/2) self.html += " Strong</p></div>\n" self.html += "<div style=\"clear: both;\"><br><hr style=\"border-style: dashed;border-color: #666;width: 60%;\"><br></div>\n" self.html += "<div style=\"text-align: center;\">\n" if config.groupby >= len(SortOrder): groups = data.groups[config.groupby - len(SortOrder)] gc = 0 kanji = [u.value for u in units.values()] for i in range(1, len(groups.data)): self.html += "<h2 style=\"color:#888;\">%s Kanji</h2>\n" % groups.data[i][0] table = "<div class=\"maintable\">\n" count = -1 for unit in [units[c] for c in groups.data[i][1] if c in kanji]: if unit.count != 0 or config.unseen: count += 1 table += kanjitile(unit.value, count, unit.count, unit.avg_interval) table += "</div>\n" n = count+1 t = len(groups.data[i][1]) gc += n if config.unseen: table += "<details><summary>Missing kanji</summary><div class=\"missingtable\" style=\"max-width:75%;\">\n" count = -1 for char in [c for c in groups.data[i][1] if c not in kanji]: count += 1 table += kanjitile(char, count, missing=True) if count == -1: table += "<b style=\"color:#CCC\">None</b>" table += "</div></details>\n" self.html += "<h4 style=\"color:#888;\">%d of %d - %0.2f%%</h4>\n" % (n, t, n*100.0/t) self.html += table chars = reduce(lambda x, y: x+y, dict(groups.data).values()) self.html += "<h2 style=\"color:#888;\">%s Kanji</h2>" % groups.data[0][0] table = "<div class=\"maintable\">\n" count = -1 for unit in [u for u in units.values() if u.value not in chars]: if unit.count != 0 or config.unseen: count += 1 table += kanjitile(unit.value, count, unit.count, unit.avg_interval) table += "</div>\n" n = count+1 self.html += "<h4 style=\"color:#888;\">%d of %d - %0.2f%%</h4>\n" % (n, gc, n*100.0/gc) self.html += table self.html += "<style type=\"text/css\">.datasource{font-style:italic;font-size:0.75em;margin-top:1em;overflow-wrap:break-word;}.datasource a{color:#1034A6;}</style><span class=\"datasource\">Data source: " + ' '.join("<a href=\"{}\">{}</a>".format(w, urllib.parse.unquote(w)) if re.match("https?://", w) else w for w in groups.source.split(' ')) + "</span>" else: table = "<div class=\"maintable\">\n" unitsList = { SortOrder.NONE: sorted(units.values(), key=lambda unit: (unit.idx, unit.count)), SortOrder.UNICODE: sorted(units.values(), key=lambda unit: (unicodedata.name(unit.value), unit.count)), SortOrder.SCORE: sorted(units.values(), key=lambda unit: (scoreAdjust(unit.avg_interval / config.interval), unit.count), reverse=True), SortOrder.FREQUENCY: sorted(units.values(), key=lambda unit: (unit.count, scoreAdjust(unit.avg_interval / config.interval)), reverse=True), }[SortOrder(config.groupby)] count = -1 for unit in unitsList: if unit.count != 0 or config.unseen: count += 1 table += kanjitile(unit.value, count, unit.count, unit.avg_interval) table += "</div>\n" self.html += "<h4 style=\"color:#888;\">%d total unique kanji</h4>\n" % (count+1) self.html += table self.html += "</div></body></html>\n" self.timepoint("HTML generated") def displaygrid(self, config, units): self.generate(config, units) self.win = QDialog(mw) self.wv = KanjiGridWebView() vl = QVBoxLayout() vl.setContentsMargins(0, 0, 0, 0) vl.addWidget(self.wv) self.wv.stdHtml(self.html) hl = QHBoxLayout() vl.addLayout(hl) sh = QPushButton("Save HTML", clicked=lambda: self.savehtml(config)) hl.addWidget(sh) sp = QPushButton("Save Image", clicked=self.savepng) hl.addWidget(sp) bb = QPushButton("Close", clicked=self.win.reject) hl.addWidget(bb) self.win.setLayout(vl) self.win.resize(500, 400) self.timepoint("Window complete") return 0 def savehtml(self, config): fileName = QFileDialog.getSaveFileName(self.win, "Save Page", QStandardPaths.standardLocations(QStandardPaths.DesktopLocation)[0], "Web Page (*.html *.htm)")[0] if fileName != "": mw.progress.start(immediate=True) if ".htm" not in fileName: fileName += ".html" with open(fileName, 'w', encoding='utf-8') as fileOut: self.time = time.time() self.timepoint("HTML start") units = self.kanjigrid(config) self.generate(config, units, True) fileOut.write(self.html) mw.progress.finish() showInfo("Page saved to %s!" % os.path.abspath(fileOut.name)) def savepng(self): fileName = QFileDialog.getSaveFileName(self.win, "Save Page", QStandardPaths.standardLocations(QStandardPaths.DesktopLocation)[0], "Portable Network Graphics (*.png)")[0] if fileName != "": mw.progress.start(immediate=True) if ".png" not in fileName: fileName += ".png" oldsize = self.wv.size() self.wv.resize(self.wv.page().contentsSize().toSize()) # the file will be saved after the page gets redrawn (KanjiGridWebView.eventFilter) self.wv.save_png = (fileName, oldsize) def kanjigrid(self, config): dids = [config.did] for _, id_ in mw.col.decks.children(config.did): dids.append(id_) self.timepoint("Decks selected") cids = mw.col.db.list("select id from cards where did in %s or odid in %s" % (ids2str(dids), ids2str(dids))) self.timepoint("Cards selected") units = dict() notes = dict() for i in cids: card = mw.col.getCard(i) if card.nid not in notes.keys(): keys = card.note().keys() unitKey = set() matches = operator.eq if config.literal else operator.contains for keyword in config.pattern: for key in keys: if matches(key.lower(), keyword): unitKey.update(set(card.note()[key])) break notes[card.nid] = unitKey else: unitKey = notes[card.nid] if unitKey is not None: for ch in unitKey: addUnitData(units, ch, i, card, config.kanjionly) self.timepoint("Units created") return units def makegrid(self, config): self.time = time.time() self.timepoint("Start") units = self.kanjigrid(config) if units is not None: self.displaygrid(config, units) def setup(self): addonconfig = mw.addonManager.getConfig(__name__) config = types.SimpleNamespace(**addonconfig['defaults']) if addonconfig.get("_debug_time", False): self.timepoint = lambda c: print("%s: %0.3f" % (c, time.time()-self.time)) else: self.timepoint = lambda _: None config.did = mw.col.conf['curDeck'] swin = QDialog(mw) vl = QVBoxLayout() fl = QHBoxLayout() deckcb = QComboBox() deckcb.addItems(sorted(mw.col.decks.allNames())) deckcb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) fl.addWidget(QLabel("Deck: ")) deckcb.setCurrentText(mw.col.decks.get(config.did)['name']) def change_did(deckname): config.did = mw.col.decks.byName(deckname)['id'] deckcb.currentTextChanged.connect(change_did) fl.addWidget(deckcb) vl.addLayout(fl) frm = QGroupBox("Settings") vl.addWidget(frm) il = QVBoxLayout() fl = QHBoxLayout() field = QLineEdit() field.setPlaceholderText("e.g. \"kanji\" or \"sentence-kanji\" (default: \"%s\")" % config.pattern) il.addWidget(QLabel("Pattern or Field names to search for (case insensitive):")) fl.addWidget(field) liter = QCheckBox("Match exactly") liter.setChecked(config.literal) fl.addWidget(liter) il.addLayout(fl) stint = QSpinBox() stint.setRange(1, 65536) stint.setValue(config.interval) il.addWidget(QLabel("Card interval considered strong:")) il.addWidget(stint) ttcol = QSpinBox() ttcol.setRange(1, 99) ttcol.setValue(config.thin) il.addWidget(QLabel("Number of Columns:")) coll = QHBoxLayout() coll.addWidget(QLabel("In-app:")) coll.addWidget(ttcol) wtcol = QSpinBox() wtcol.setRange(1, 99) wtcol.setValue(config.wide) coll.addWidget(QLabel("Exported:")) coll.addWidget(wtcol) itcol = QCheckBox("Don't care") itcol.setChecked(addonconfig['defaults'].get("autothinwide", False)) def disableEnableColumnSettings(state): ttcol.setEnabled(state != Qt.Checked) wtcol.setEnabled(state != Qt.Checked) itcol.stateChanged.connect(disableEnableColumnSettings) disableEnableColumnSettings(itcol.checkState()) coll.addWidget(itcol) il.addLayout(coll) groupby = QComboBox() groupby.addItems([ *("None, sorted by " + x.pretty_value() for x in SortOrder), *(x.name for x in data.groups), ]) groupby.setCurrentIndex(config.groupby) il.addWidget(QLabel("Group by:")) il.addWidget(groupby) shnew = QCheckBox("Show units not yet seen") shnew.setChecked(config.unseen) il.addWidget(shnew) toolt = QCheckBox("Show informational tooltips") toolt.setChecked(config.tooltips) il.addWidget(toolt) frm.setLayout(il) hl = QHBoxLayout() vl.addLayout(hl) gen = QPushButton("Generate", clicked=swin.accept) hl.addWidget(gen) cls = QPushButton("Close", clicked=swin.reject) hl.addWidget(cls) swin.setLayout(vl) swin.setTabOrder(gen, cls) swin.setTabOrder(cls, field) swin.setTabOrder(field, liter) swin.setTabOrder(liter, stint) swin.setTabOrder(stint, ttcol) swin.setTabOrder(ttcol, wtcol) swin.setTabOrder(wtcol, groupby) swin.setTabOrder(groupby, shnew) swin.setTabOrder(shnew, toolt) swin.resize(500, 400) if swin.exec_(): mw.progress.start(immediate=True) if len(field.text().strip()) != 0: config.pattern = field.text().lower() config.pattern = config.pattern.split() config.literal = liter.isChecked() config.interval = stint.value() config.thin = ttcol.value() config.wide = wtcol.value() config.groupby = groupby.currentIndex() config.unseen = shnew.isChecked() config.tooltips = toolt.isChecked() config.autothinwide = itcol.isChecked() self.makegrid(config) mw.progress.finish() self.win.show()
def setup(self): addonconfig = mw.addonManager.getConfig(__name__) config = types.SimpleNamespace(**addonconfig['defaults']) if addonconfig.get("_debug_time", False): self.timepoint = lambda c: print("%s: %0.3f" % (c, time.time()-self.time)) else: self.timepoint = lambda _: None config.did = mw.col.conf['curDeck'] swin = QDialog(mw) vl = QVBoxLayout() fl = QHBoxLayout() deckcb = QComboBox() deckcb.addItems(sorted(mw.col.decks.allNames())) deckcb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) fl.addWidget(QLabel("Deck: ")) deckcb.setCurrentText(mw.col.decks.get(config.did)['name']) def change_did(deckname): config.did = mw.col.decks.byName(deckname)['id'] deckcb.currentTextChanged.connect(change_did) fl.addWidget(deckcb) vl.addLayout(fl) frm = QGroupBox("Settings") vl.addWidget(frm) il = QVBoxLayout() fl = QHBoxLayout() field = QLineEdit() field.setPlaceholderText("e.g. \"kanji\" or \"sentence-kanji\" (default: \"%s\")" % config.pattern) il.addWidget(QLabel("Pattern or Field names to search for (case insensitive):")) fl.addWidget(field) liter = QCheckBox("Match exactly") liter.setChecked(config.literal) fl.addWidget(liter) il.addLayout(fl) stint = QSpinBox() stint.setRange(1, 65536) stint.setValue(config.interval) il.addWidget(QLabel("Card interval considered strong:")) il.addWidget(stint) ttcol = QSpinBox() ttcol.setRange(1, 99) ttcol.setValue(config.thin) il.addWidget(QLabel("Number of Columns:")) coll = QHBoxLayout() coll.addWidget(QLabel("In-app:")) coll.addWidget(ttcol) wtcol = QSpinBox() wtcol.setRange(1, 99) wtcol.setValue(config.wide) coll.addWidget(QLabel("Exported:")) coll.addWidget(wtcol) itcol = QCheckBox("Don't care") itcol.setChecked(addonconfig['defaults'].get("autothinwide", False)) def disableEnableColumnSettings(state): ttcol.setEnabled(state != Qt.Checked) wtcol.setEnabled(state != Qt.Checked) itcol.stateChanged.connect(disableEnableColumnSettings) disableEnableColumnSettings(itcol.checkState()) coll.addWidget(itcol) il.addLayout(coll) groupby = QComboBox() groupby.addItems([ *("None, sorted by " + x.pretty_value() for x in SortOrder), *(x.name for x in data.groups), ]) groupby.setCurrentIndex(config.groupby) il.addWidget(QLabel("Group by:")) il.addWidget(groupby) shnew = QCheckBox("Show units not yet seen") shnew.setChecked(config.unseen) il.addWidget(shnew) toolt = QCheckBox("Show informational tooltips") toolt.setChecked(config.tooltips) il.addWidget(toolt) frm.setLayout(il) hl = QHBoxLayout() vl.addLayout(hl) gen = QPushButton("Generate", clicked=swin.accept) hl.addWidget(gen) cls = QPushButton("Close", clicked=swin.reject) hl.addWidget(cls) swin.setLayout(vl) swin.setTabOrder(gen, cls) swin.setTabOrder(cls, field) swin.setTabOrder(field, liter) swin.setTabOrder(liter, stint) swin.setTabOrder(stint, ttcol) swin.setTabOrder(ttcol, wtcol) swin.setTabOrder(wtcol, groupby) swin.setTabOrder(groupby, shnew) swin.setTabOrder(shnew, toolt) swin.resize(500, 400) if swin.exec_(): mw.progress.start(immediate=True) if len(field.text().strip()) != 0: config.pattern = field.text().lower() config.pattern = config.pattern.split() config.literal = liter.isChecked() config.interval = stint.value() config.thin = ttcol.value() config.wide = wtcol.value() config.groupby = groupby.currentIndex() config.unseen = shnew.isChecked() config.tooltips = toolt.isChecked() config.autothinwide = itcol.isChecked() self.makegrid(config) mw.progress.finish() self.win.show()