mirror of
https://github.com/ankitects/anki.git
synced 2025-11-14 16:47:12 -05:00
Earlier today I pushed a change that split this code up into multiple repos, but that has proved to complicate things too much. So we're back to a single repo, except the individual submodules are better separated than they were before. The README files need updating again; I will push them out soon. Aside from splitting out the different modules, the sound code has moved from from anki to aqt.
221 lines
7.1 KiB
Python
221 lines
7.1 KiB
Python
# Copyright: Ankitects Pty Ltd and contributors
|
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
import collections
|
|
from operator import itemgetter
|
|
|
|
import aqt.clayout
|
|
from anki import stdmodels
|
|
from anki.lang import _, ngettext
|
|
from aqt import AnkiQt
|
|
from aqt.qt import *
|
|
from aqt.utils import (
|
|
askUser,
|
|
getText,
|
|
maybeHideClose,
|
|
openHelp,
|
|
restoreGeom,
|
|
saveGeom,
|
|
showInfo,
|
|
)
|
|
|
|
|
|
class Models(QDialog):
|
|
def __init__(self, mw: AnkiQt, parent=None, fromMain=False):
|
|
self.mw = mw
|
|
parent = parent or mw
|
|
self.fromMain = fromMain
|
|
QDialog.__init__(self, parent, Qt.Window)
|
|
self.col = mw.col
|
|
assert self.col
|
|
self.mm = self.col.models
|
|
self.mw.checkpoint(_("Note Types"))
|
|
self.form = aqt.forms.models.Ui_Dialog()
|
|
self.form.setupUi(self)
|
|
self.form.buttonBox.helpRequested.connect(lambda: openHelp("notetypes"))
|
|
self.setupModels()
|
|
restoreGeom(self, "models")
|
|
self.exec_()
|
|
|
|
# Models
|
|
##########################################################################
|
|
|
|
def setupModels(self):
|
|
self.model = None
|
|
f = self.form
|
|
box = f.buttonBox
|
|
t = QDialogButtonBox.ActionRole
|
|
b = box.addButton(_("Add"), t)
|
|
b.clicked.connect(self.onAdd)
|
|
b = box.addButton(_("Rename"), t)
|
|
b.clicked.connect(self.onRename)
|
|
b = box.addButton(_("Delete"), t)
|
|
b.clicked.connect(self.onDelete)
|
|
if self.fromMain:
|
|
b = box.addButton(_("Fields..."), t)
|
|
b.clicked.connect(self.onFields)
|
|
b = box.addButton(_("Cards..."), t)
|
|
b.clicked.connect(self.onCards)
|
|
b = box.addButton(_("Options..."), t)
|
|
b.clicked.connect(self.onAdvanced)
|
|
f.modelsList.currentRowChanged.connect(self.modelChanged)
|
|
f.modelsList.itemDoubleClicked.connect(self.onRename)
|
|
self.updateModelsList()
|
|
f.modelsList.setCurrentRow(0)
|
|
maybeHideClose(box)
|
|
|
|
def onRename(self):
|
|
txt = getText(_("New name:"), default=self.model["name"])
|
|
if txt[1] and txt[0]:
|
|
self.model["name"] = txt[0]
|
|
self.mm.save(self.model, updateReqs=False)
|
|
self.updateModelsList()
|
|
|
|
def updateModelsList(self):
|
|
row = self.form.modelsList.currentRow()
|
|
if row == -1:
|
|
row = 0
|
|
self.models = self.col.models.all()
|
|
self.models.sort(key=itemgetter("name"))
|
|
self.form.modelsList.clear()
|
|
for m in self.models:
|
|
mUse = self.mm.useCount(m)
|
|
mUse = ngettext("%d note", "%d notes", mUse) % mUse
|
|
item = QListWidgetItem("%s [%s]" % (m["name"], mUse))
|
|
self.form.modelsList.addItem(item)
|
|
self.form.modelsList.setCurrentRow(row)
|
|
|
|
def modelChanged(self):
|
|
if self.model:
|
|
self.saveModel()
|
|
idx = self.form.modelsList.currentRow()
|
|
self.model = self.models[idx]
|
|
|
|
def onAdd(self):
|
|
m = AddModel(self.mw, self).get()
|
|
if m:
|
|
txt = getText(_("Name:"), default=m["name"])[0]
|
|
if txt:
|
|
m["name"] = txt
|
|
self.mm.ensureNameUnique(m)
|
|
self.mm.save(m)
|
|
self.updateModelsList()
|
|
|
|
def onDelete(self):
|
|
if len(self.models) < 2:
|
|
showInfo(_("Please add another note type first."), parent=self)
|
|
return
|
|
if self.mm.useCount(self.model):
|
|
msg = _("Delete this note type and all its cards?")
|
|
else:
|
|
msg = _("Delete this unused note type?")
|
|
if not askUser(msg, parent=self):
|
|
return
|
|
self.mm.rem(self.model)
|
|
self.model = None
|
|
self.updateModelsList()
|
|
|
|
def onAdvanced(self):
|
|
d = QDialog(self)
|
|
frm = aqt.forms.modelopts.Ui_Dialog()
|
|
frm.setupUi(d)
|
|
frm.latexsvg.setChecked(self.model.get("latexsvg", False))
|
|
frm.latexHeader.setText(self.model["latexPre"])
|
|
frm.latexFooter.setText(self.model["latexPost"])
|
|
d.setWindowTitle(_("Options for %s") % self.model["name"])
|
|
frm.buttonBox.helpRequested.connect(lambda: openHelp("latex"))
|
|
restoreGeom(d, "modelopts")
|
|
d.exec_()
|
|
saveGeom(d, "modelopts")
|
|
self.model["latexsvg"] = frm.latexsvg.isChecked()
|
|
self.model["latexPre"] = str(frm.latexHeader.toPlainText())
|
|
self.model["latexPost"] = str(frm.latexFooter.toPlainText())
|
|
|
|
def saveModel(self):
|
|
self.mm.save(self.model, updateReqs=False)
|
|
|
|
def _tmpNote(self):
|
|
self.mm.setCurrent(self.model)
|
|
n = self.col.newNote(forDeck=False)
|
|
for name in list(n.keys()):
|
|
n[name] = "(" + name + ")"
|
|
try:
|
|
if "{{cloze:Text}}" in self.model["tmpls"][0]["qfmt"]:
|
|
n["Text"] = _("This is a {{c1::sample}} cloze deletion.")
|
|
except:
|
|
# invalid cloze
|
|
pass
|
|
return n
|
|
|
|
def onFields(self):
|
|
from aqt.fields import FieldDialog
|
|
|
|
n = self._tmpNote()
|
|
FieldDialog(self.mw, n, parent=self)
|
|
|
|
def onCards(self):
|
|
from aqt.clayout import CardLayout
|
|
|
|
n = self._tmpNote()
|
|
CardLayout(self.mw, n, ord=0, parent=self, addMode=True)
|
|
|
|
# Cleanup
|
|
##########################################################################
|
|
|
|
# need to flush model on change or reject
|
|
|
|
def reject(self):
|
|
self.saveModel()
|
|
self.mw.reset()
|
|
saveGeom(self, "models")
|
|
QDialog.reject(self)
|
|
|
|
|
|
class AddModel(QDialog):
|
|
def __init__(self, mw, parent=None):
|
|
self.parent = parent or mw
|
|
self.mw = mw
|
|
self.col = mw.col
|
|
QDialog.__init__(self, self.parent, Qt.Window)
|
|
self.model = None
|
|
self.dialog = aqt.forms.addmodel.Ui_Dialog()
|
|
self.dialog.setupUi(self)
|
|
# standard models
|
|
self.models = []
|
|
for (name, func) in stdmodels.models:
|
|
if isinstance(name, collections.Callable):
|
|
name = name()
|
|
item = QListWidgetItem(_("Add: %s") % name)
|
|
self.dialog.models.addItem(item)
|
|
self.models.append((True, func))
|
|
# add copies
|
|
for m in sorted(self.col.models.all(), key=itemgetter("name")):
|
|
item = QListWidgetItem(_("Clone: %s") % m["name"])
|
|
self.dialog.models.addItem(item)
|
|
self.models.append((False, m))
|
|
self.dialog.models.setCurrentRow(0)
|
|
# the list widget will swallow the enter key
|
|
s = QShortcut(QKeySequence("Return"), self)
|
|
s.activated.connect(self.accept)
|
|
# help
|
|
self.dialog.buttonBox.helpRequested.connect(self.onHelp)
|
|
|
|
def get(self):
|
|
self.exec_()
|
|
return self.model
|
|
|
|
def reject(self):
|
|
QDialog.reject(self)
|
|
|
|
def accept(self):
|
|
(isStd, model) = self.models[self.dialog.models.currentRow()]
|
|
if isStd:
|
|
# create
|
|
self.model = model(self.col)
|
|
else:
|
|
# add copy to deck
|
|
self.model = self.mw.col.models.copy(model)
|
|
self.mw.col.models.setCurrent(self.model)
|
|
QDialog.accept(self)
|
|
|
|
def onHelp(self):
|
|
openHelp("notetypes")
|