def rebuild_template_map(self, key=None, attr=None): if not key: key = "t" attr = "tmpls" map_widget = getattr(self, key + "widg") layout = getattr(self, key + "layout") src = self.old_model[attr] dst = self.targetModel[attr] if map_widget: layout.removeWidget(map_widget) map_widget.deleteLater() setattr(self, key + "MapWidget", None) map_widget = QWidget() map_widget_layout = QGridLayout() combos = [] targets = [entity['name'] for entity in dst] + [_("Nothing")] indices = {} for i, entity in enumerate(src): map_widget_layout.addWidget(QLabel(_("Change %s to:") % entity['name']), i, 0) combo_box = QComboBox() combo_box.addItems(targets) idx = min(i, len(targets) - 1) combo_box.setCurrentIndex(idx) indices[combo_box] = idx combo_box.currentIndexChanged.connect( lambda entry_id: self.on_combo_changed(entry_id, combo_box, key)) combos.append(combo_box) map_widget_layout.addWidget(combo_box, i, 1) map_widget.setLayout(map_widget_layout) layout.addWidget(map_widget) setattr(self, key + "widg", map_widget) setattr(self, key + "layout", layout) setattr(self, key + "combos", combos) setattr(self, key + "indices", indices)
def getDefinitionChoiceDialog(aw, entries): d = QDialog(aw) grid = QGridLayout() # adds found definitions to dialog window for x in range(len(entries)): button = QPushButton(entries[x].word) button.clicked.connect(partial(buttonPressed, entries[x],d)) label = QLabel() label.setText(entries[x].shortDef) label.setWordWrap(True) grid.addWidget(button,x,0) grid.addWidget(label,x,1,1,5) d.setLayout(grid) return d
def setupTags(self): import aqt.tagedit g = QGroupBox(self.widget) g.setFlat(True) tb = QGridLayout() tb.setSpacing(12) tb.setContentsMargins(6,6,6,6) # tags l = QLabel(_("Tags")) tb.addWidget(l, 1, 0) self.tags = aqt.tagedit.TagEdit(self.widget) self.tags.lostFocus.connect(self.saveTags) self.tags.setToolTip(shortcut(_("Jump to tags with Ctrl+Shift+T"))) tb.addWidget(self.tags, 1, 1) g.setLayout(tb) self.outerLayout.addWidget(g)
def _rebuildMap(self, key): """ key -- either "t" or "f", for template or fields. What to edit. """ map = getattr(self, key + "widg") lay = getattr(self, key + "layout") if map: lay.removeWidget(map) map.deleteLater() setattr(self, key + "MapWidget", None) map = QWidget() l = QGridLayout() combos = [] targets = [template['name'] for template in getattr(self, key + "dst")] indices = {} sources = getattr(self, key + "src") sourcesNames = [template["name"] for template in sources] if getUserOption("Associate to same name"): assoc = eltToPos(sourcesNames, targets) else: assoc = enumerate(sourcesNames) for indexSrc, (indexDst, templateName) in enumerate(assoc): l.addWidget(QLabel(_("Change %s to:") % templateName), indexSrc, 0) cb = QComboBox() cb.addItems(targets + [_("Nothing")]) idx = min(indexDst, len(targets)) cb.setCurrentIndex(idx) indices[cb] = idx cb.currentIndexChanged.connect( lambda i, cb=cb, key=key: self.onComboChanged(i, cb, key)) combos.append(cb) l.addWidget(cb, indexSrc, 1) map.setLayout(l) lay.addWidget(map) setattr(self, key + "widg", map) setattr(self, key + "layout", lay) setattr(self, key + "combos", combos) setattr(self, key + "indices", indices)
def rebuild_template_map(self, key=None, attr=None): if not key: key = "t" attr = "tmpls" map_widget = getattr(self, key + "widg") layout = getattr(self, key + "layout") src = self.old_model[attr] dst = self.targetModel[attr] if map_widget: layout.removeWidget(map_widget) map_widget.deleteLater() setattr(self, key + "MapWidget", None) map_widget = QWidget() map_widget_layout = QGridLayout() combos = [] targets = [entity['name'] for entity in dst] + [_("Nothing")] indices = {} for i, entity in enumerate(src): map_widget_layout.addWidget( QLabel(_("Change %s to:") % entity['name']), i, 0) combo_box = QComboBox() combo_box.addItems(targets) idx = min(i, len(targets) - 1) combo_box.setCurrentIndex(idx) indices[combo_box] = idx combo_box.currentIndexChanged.connect( lambda entry_id: self.on_combo_changed(entry_id, combo_box, key )) combos.append(combo_box) map_widget_layout.addWidget(combo_box, i, 1) map_widget.setLayout(map_widget_layout) layout.addWidget(map_widget) setattr(self, key + "widg", map_widget) setattr(self, key + "layout", layout) setattr(self, key + "combos", combos) setattr(self, key + "indices", indices)
def get_id_and_pass_from_user(mw: aqt.main.AnkiQt, username="", password="") -> Tuple[str, str]: diag = QDialog(mw) diag.setWindowTitle("Anki") diag.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) # type: ignore diag.setWindowModality(Qt.WindowModal) vbox = QVBoxLayout() info_label = QLabel( without_unicode_isolation( tr(TR.SYNC_ACCOUNT_REQUIRED, link="https://ankiweb.net/account/register"))) info_label.setOpenExternalLinks(True) info_label.setWordWrap(True) vbox.addWidget(info_label) vbox.addSpacing(20) g = QGridLayout() l1 = QLabel(tr(TR.SYNC_ANKIWEB_ID_LABEL)) g.addWidget(l1, 0, 0) user = QLineEdit() user.setText(username) g.addWidget(user, 0, 1) l2 = QLabel(tr(TR.SYNC_PASSWORD_LABEL)) g.addWidget(l2, 1, 0) passwd = QLineEdit() passwd.setText(password) passwd.setEchoMode(QLineEdit.Password) g.addWidget(passwd, 1, 1) vbox.addLayout(g) bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) # type: ignore bb.button(QDialogButtonBox.Ok).setAutoDefault(True) qconnect(bb.accepted, diag.accept) qconnect(bb.rejected, diag.reject) vbox.addWidget(bb) diag.setLayout(vbox) diag.show() accepted = diag.exec_() if not accepted: return ("", "") return (user.text().strip(), passwd.text())
def get_id_and_pass_from_user(mw: aqt.main.AnkiQt, username: str = "", password: str = "") -> tuple[str, str]: diag = QDialog(mw) diag.setWindowTitle("Anki") disable_help_button(diag) diag.setWindowModality(Qt.WindowModality.WindowModal) vbox = QVBoxLayout() info_label = QLabel( without_unicode_isolation( tr.sync_account_required( link="https://ankiweb.net/account/register"))) info_label.setOpenExternalLinks(True) info_label.setWordWrap(True) vbox.addWidget(info_label) vbox.addSpacing(20) g = QGridLayout() l1 = QLabel(tr.sync_ankiweb_id_label()) g.addWidget(l1, 0, 0) user = QLineEdit() user.setText(username) g.addWidget(user, 0, 1) l2 = QLabel(tr.sync_password_label()) g.addWidget(l2, 1, 0) passwd = QLineEdit() passwd.setText(password) passwd.setEchoMode(QLineEdit.EchoMode.Password) g.addWidget(passwd, 1, 1) vbox.addLayout(g) bb = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) # type: ignore bb.button(QDialogButtonBox.StandardButton.Ok).setAutoDefault(True) qconnect(bb.accepted, diag.accept) qconnect(bb.rejected, diag.reject) vbox.addWidget(bb) diag.setLayout(vbox) diag.show() accepted = diag.exec() if not accepted: return ("", "") return (user.text().strip(), passwd.text())
def _getUserPass(self): d = QDialog(self.mw) d.setWindowTitle("Anki") d.setWindowModality(Qt.WindowModal) vbox = QVBoxLayout() l = QLabel( _("""\ <h1>Account Required</h1> A free account is required to keep your collection synchronized. Please \ <a href="%s">sign up</a> for an account, then \ enter your details below.""") % "https://ankiweb.net/account/login") l.setOpenExternalLinks(True) l.setWordWrap(True) vbox.addWidget(l) vbox.addSpacing(20) g = QGridLayout() l1 = QLabel(_("AnkiWeb ID:")) g.addWidget(l1, 0, 0) user = QLineEdit() g.addWidget(user, 0, 1) l2 = QLabel(_("Password:")) g.addWidget(l2, 1, 0) passwd = QLineEdit() passwd.setEchoMode(QLineEdit.Password) g.addWidget(passwd, 1, 1) vbox.addLayout(g) bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.button(QDialogButtonBox.Ok).setAutoDefault(True) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) vbox.addWidget(bb) d.setLayout(vbox) d.show() accepted = d.exec_() u = user.text() p = passwd.text() if not accepted or not u or not p: return return (u, p)
class TagDialogExtended__BasicOrTagEdit(QDialog): def __init__(self, parent, tags, alltags): QDialog.__init__(self, parent, Qt.WindowType.Window) # super().__init__(parent) self.basic_mode = gc("dialog type: basic_but_quick") self.parent = parent self.alltags = alltags self.gridLayout = QGridLayout(self) self.gridLayout.setObjectName("gridLayout") self.label = QLabel("Edit tags:") self.gridLayout.addWidget(self.label, 0, 0, 1, 1) self.verticalLayout = QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.gridLayout.addLayout(self.verticalLayout, 1, 0, 1, 1) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Cancel | QDialogButtonBox.StandardButton.Ok) self.shortcut = QShortcut(QKeySequence("Ctrl+Return"), self) self.shortcut.activated.connect(self.accept) self.helpButton = QPushButton( "add empty line", clicked=lambda: self.maybe_add_line(force=True)) self.buttonBox.addButton(self.helpButton, QDialogButtonBox.ButtonRole.HelpRole) self.filterbutton = QPushButton("edit tag for current line", clicked=self.tagselector) self.buttonBox.addButton(self.filterbutton, QDialogButtonBox.ButtonRole.ResetRole) self.searchButton = QPushButton( "search", clicked=lambda: self.do_browser_search(extra_search="")) self.buttonBox.addButton(self.searchButton, QDialogButtonBox.ButtonRole.ResetRole) self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 1) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.setWindowTitle("Anki - Edit Tags") originalheight = self.height() restoreGeom(self, "TagDialogExtended") self.resize(self.width(), originalheight) if not tags: tags = [ "", ] else: tags.append("") self.line_list = [] 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.filterbutton.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.searchButton.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.helpButton.setToolTip('shortcut: {}'.format(self.addnl)) self.addnlscut = QShortcut(QKeySequence(self.addnl), self) self.addnlscut.activated.connect( lambda: self.maybe_add_line(force=True)) def current_tags_list(self): return [t.text() for t in self.line_list if t] def do_browser_search(self, extra_search=""): # Use the current line's text or the last line if the current one is an empty line note_tags = self.current_tags_list() searched_tag = shared_variables.focused_line.text() or ( note_tags[-1] if len(note_tags) > 0 else "") if searched_tag: browser = dialogs.open('Browser', mw) browser.setFilter('tag:"{}*" {}'.format(searched_tag, extra_search)) self.accept() else: tooltip("empty tag was selected for search") def tagselector(self): text = shared_variables.focused_line.text() d = FilterDialog(parent=self, values=self.alltags, allownew=True, prefill=text) if d.exec(): shared_variables.focused_line.setText(d.selkey) else: shared_variables.focused_line.setFocus() def change_focus_by_one(self, Down=True): for index, edit in enumerate(self.line_list): if edit == shared_variables.focused_line: if Down: if index == len( self.line_list) - 1: # if in last line go up self.line_list[0].setFocus() break else: newidx = index + 1 self.line_list[newidx].setFocus() break else: # go up if index == 0: # if in last line go up newidx = len(self.line_list) - 1 self.line_list[newidx].setFocus() break else: self.line_list[index - 1].setFocus() break def maybe_add_line(self, tag="", force=False): if self.line_list and not self.line_list[-1].text( ) and not force: # last lineedit is empty: self.line_list[-1].setFocus() self.line_list[-1].setText(tag) else: if self.basic_mode: te = MyBasicEdit(self) te.setText(tag) self.verticalLayout.addWidget(te) te.setFocus() self.line_list.append(te) else: te = MyTagEdit(self) te.setCol(mw.col) te.setText(tag) self.verticalLayout.addWidget(te) te.hideCompleter() te.setFocus() self.line_list.append(te) 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 reject(self): saveGeom(self, "TagDialogExtended") QDialog.reject(self)
class ImportDialog(QDialog): def __init__(self, mw, importer): QDialog.__init__(self, mw, Qt.Window) self.mw = mw self.importer = importer self.frm = aqt.forms.importing.Ui_ImportDialog() self.frm.setupUi(self) self.frm.buttonBox.button(QDialogButtonBox.Help).clicked.connect( self.helpRequested) self.setupMappingFrame() self.setupOptions() self.modelChanged() self.frm.autoDetect.setVisible(self.importer.needDelimiter) addHook("currentModelChanged", self.modelChanged) self.frm.autoDetect.clicked.connect(self.onDelimiter) self.updateDelimiterButtonText() self.frm.allowHTML.setChecked(self.mw.pm.profile.get( 'allowHTML', True)) self.frm.importMode.setCurrentIndex( self.mw.pm.profile.get('importMode', 1)) # import button b = QPushButton(_("Import")) self.frm.buttonBox.addButton(b, QDialogButtonBox.AcceptRole) self.exec_() def setupOptions(self): self.model = self.mw.col.models.current() self.modelChooser = aqt.modelchooser.ModelChooser(self.mw, self.frm.modelArea, label=False) self.deck = aqt.deckchooser.DeckChooser(self.mw, self.frm.deckArea, label=False) def modelChanged(self): self.importer.model = self.mw.col.models.current() self.importer.initMapping() self.showMapping() if self.mw.col.conf.get("addToCur", True): did = self.mw.col.conf['curDeck'] if self.mw.col.decks.isDyn(did): did = 1 else: did = self.importer.model['did'] #self.deck.setText(self.mw.col.decks.name(did)) def onDelimiter(self): str = getOnlyText(_("""\ By default, Anki will detect the character between fields, such as a tab, comma, and so on. If Anki is detecting the character incorrectly, you can enter it here. Use \\t to represent tab."""), self, help="importing") or "\t" str = str.replace("\\t", "\t") if len(str) > 1: showWarning( _("Multi-character separators are not supported. " "Please enter one character only.")) return self.hideMapping() def updateDelim(): self.importer.delimiter = str self.importer.updateDelimiter() self.showMapping(hook=updateDelim) self.updateDelimiterButtonText() def updateDelimiterButtonText(self): if not self.importer.needDelimiter: return if self.importer.delimiter: d = self.importer.delimiter else: d = self.importer.dialect.delimiter if d == "\t": d = _("Tab") elif d == ",": d = _("Comma") elif d == " ": d = _("Space") elif d == ";": d = _("Semicolon") elif d == ":": d = _("Colon") else: d = repr(d) txt = _("Fields separated by: %s") % d self.frm.autoDetect.setText(txt) def accept(self): self.importer.mapping = self.mapping if not self.importer.mappingOk(): showWarning(_("The first field of the note type must be mapped.")) return self.importer.importMode = self.frm.importMode.currentIndex() self.mw.pm.profile['importMode'] = self.importer.importMode self.importer.allowHTML = self.frm.allowHTML.isChecked() self.mw.pm.profile['allowHTML'] = self.importer.allowHTML did = self.deck.selectedId() if did != self.importer.model['did']: self.importer.model['did'] = did self.mw.col.models.save(self.importer.model) self.mw.col.decks.select(did) self.mw.progress.start(immediate=True) self.mw.checkpoint(_("Import")) try: self.importer.run() except UnicodeDecodeError: showUnicodeWarning() return except Exception as e: msg = _("Import failed.\n") err = repr(str(e)) if "1-character string" in err: msg += err elif "invalidTempFolder" in err: msg += self.mw.errorHandler.tempFolderMsg() else: msg += str(traceback.format_exc(), "ascii", "replace") showText(msg) return finally: self.mw.progress.finish() txt = _("Importing complete.") + "\n" if self.importer.log: txt += "\n".join(self.importer.log) self.close() showText(txt) self.mw.reset() def setupMappingFrame(self): # qt seems to have a bug with adding/removing from a grid, so we add # to a separate object and add/remove that instead self.frame = QFrame(self.frm.mappingArea) self.frm.mappingArea.setWidget(self.frame) self.mapbox = QVBoxLayout(self.frame) self.mapbox.setContentsMargins(0, 0, 0, 0) self.mapwidget = None def hideMapping(self): self.frm.mappingGroup.hide() def showMapping(self, keepMapping=False, hook=None): if hook: hook() if not keepMapping: self.mapping = self.importer.mapping self.frm.mappingGroup.show() assert self.importer.fields() # set up the mapping grid if self.mapwidget: self.mapbox.removeWidget(self.mapwidget) self.mapwidget.deleteLater() self.mapwidget = QWidget() self.mapbox.addWidget(self.mapwidget) self.grid = QGridLayout(self.mapwidget) self.mapwidget.setLayout(self.grid) self.grid.setContentsMargins(3, 3, 3, 3) self.grid.setSpacing(6) fields = self.importer.fields() for num in range(len(self.mapping)): text = _("Field <b>%d</b> of file is:") % (num + 1) self.grid.addWidget(QLabel(text), num, 0) if self.mapping[num] == "_tags": text = _("mapped to <b>Tags</b>") elif self.mapping[num]: text = _("mapped to <b>%s</b>") % self.mapping[num] else: text = _("<ignored>") self.grid.addWidget(QLabel(text), num, 1) button = QPushButton(_("Change")) self.grid.addWidget(button, num, 2) button.clicked.connect( lambda _, s=self, n=num: s.changeMappingNum(n)) def changeMappingNum(self, n): f = ChangeMap(self.mw, self.importer.model, self.mapping[n]).getField() try: # make sure we don't have it twice index = self.mapping.index(f) self.mapping[index] = None except ValueError: pass self.mapping[n] = f if getattr(self.importer, "delimiter", False): self.savedDelimiter = self.importer.delimiter def updateDelim(): self.importer.delimiter = self.savedDelimiter self.showMapping(hook=updateDelim, keepMapping=True) else: self.showMapping(keepMapping=True) def reject(self): self.modelChooser.cleanup() self.deck.cleanup() remHook("currentModelChanged", self.modelChanged) QDialog.reject(self) def helpRequested(self): openHelp("importing")
def _setupUi(self): layout = QGridLayout() # remove margins layout.setContentsMargins(QMargins()) self.setLayout(layout) row = 0 # 1st row label = QLabel(self, text='Lettering:') layout.addWidget(label, row, 0, alignment=Qt.AlignRight) widget = QLineEdit(self) layout.addWidget(widget, row, 1) label.setBuddy(widget) self.letteringEdit = widget row += 1 # 2nd row label = QLabel(self, text='Hint:') layout.addWidget(label, row, 0, alignment=Qt.AlignRight) widget = QLineEdit(self) layout.addWidget(widget, row, 1) label.setBuddy(widget) self.hintEdit = widget row += 1 # 3rd row label = QLabel(self, text='Part of speech:') layout.addWidget(label, row, 0, alignment=Qt.AlignRight) widget = QLineEdit(self) layout.addWidget(widget, row, 1) label.setBuddy(widget) self.partOfSpeechEdit = widget row += 1 #1-3 row second column widget = QTextEdit(self) layout.addWidget(widget, 0, 2, 3, 2) label.setBuddy(widget) self.definitionEdit = widget #4th row label = QLabel(self, text='Transcription:') layout.addWidget(label, row, 0, alignment=Qt.AlignRight | Qt.AlignTop) widget = TranscriptionsWidget(self) widget.setMaximumHeight(label.sizeHint().height() * 4) layout.addWidget(widget, row, 1, 1, 3) label.setBuddy(widget) self.transcriptionEdit = widget row += 2 #5th row label = QLabel(self, text='Examples:') layout.addWidget(label, row, 0, 1, 1, alignment=Qt.AlignRight | Qt.AlignTop) widget = ExamplesWidget(self) layout.addWidget(widget, row, 1, 2, 3) label.setBuddy(widget) self.examplesEdit = widget row += 2
def get_grid_layout(form) -> QWidget: w = QWidget() gridLayout = QGridLayout() gridLayout.setColumnStretch(1, 5) gridLayout.setContentsMargins(0, 0, 0, 5) ##### STRAIGHT LENGTH form.straightLengthLabel = make_label(w, "Begin at straight of length") gridLayout.addWidget(form.straightLengthLabel, 1, 0, 1, 1) form.straightLengthSpinBox = make_spin_box(w, 0, 100, "") gridLayout.addWidget(form.straightLengthSpinBox, 1, 1, 1, 2) ##### BASE EASE form.straightBaseEaseLabel = make_label(w, "Base ease reward") gridLayout.addWidget(form.straightBaseEaseLabel, 2, 0, 1, 1) form.straightBaseEaseSpinBox = make_spin_box(w) gridLayout.addWidget(form.straightBaseEaseSpinBox, 2, 1, 1, 2) ##### STEP EASE form.straightStepEaseLabel = make_label(w, "Step ease reward") gridLayout.addWidget(form.straightStepEaseLabel, 3, 0, 1, 1) form.straightStepEaseSpinBox = make_spin_box(w) gridLayout.addWidget(form.straightStepEaseSpinBox, 3, 1, 1, 2) ##### START EASE form.straightStartEaseLabel = make_label(w, "Start at ease") gridLayout.addWidget(form.straightStartEaseLabel, 4, 0, 1, 1) form.straightStartEaseSpinBox = make_spin_box(w, 130) gridLayout.addWidget(form.straightStartEaseSpinBox, 4, 1, 1, 2) ##### STOP EASE form.straightStopEaseLabel = make_label(w, "Stop at ease") gridLayout.addWidget(form.straightStopEaseLabel, 5, 0, 1, 1) form.straightStopEaseSpinBox = make_spin_box(w, 130) gridLayout.addWidget(form.straightStopEaseSpinBox, 5, 1, 1, 2) w.setLayout(gridLayout) return w