From 60ba70b1b5a048b01ff5777d9a834319a33d1f04 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sat, 10 Dec 2011 21:11:19 +0900 Subject: [PATCH] add cards dialog & model chooser --- aqt/addcards.py | 11 ++-- aqt/editor.py | 9 ++- aqt/fields.py | 1 - aqt/main.py | 16 ------ aqt/modelchooser.py | 131 ++++-------------------------------------- aqt/models.py | 103 ++++++++++++++++++++++----------- aqt/utils.py | 2 +- designer/main.ui | 43 +------------- designer/modelopts.ui | 33 ++++++++++- designer/models.ui | 2 +- 10 files changed, 127 insertions(+), 224 deletions(-) diff --git a/aqt/addcards.py b/aqt/addcards.py index 079631667..0499ca23c 100644 --- a/aqt/addcards.py +++ b/aqt/addcards.py @@ -39,7 +39,8 @@ class AddCards(QDialog): self.setupNewNote() def setupEditor(self): - self.editor = aqt.editor.Editor(self.mw, self.form.fieldsArea, True) + self.editor = aqt.editor.Editor( + self.mw, self.form.fieldsArea, self, True) def setupChooser(self): self.modelChooser = aqt.modelchooser.ModelChooser( @@ -69,7 +70,7 @@ class AddCards(QDialog): self.connect(self.helpButton, SIGNAL("clicked()"), self.helpRequested) # history b = bb.addButton( - _("History")+ u'▼', ar) + _("History")+ u" ▾", ar) self.connect(b, SIGNAL("clicked()"), self.onHistory) b.setEnabled(False) self.historyButton = b @@ -126,10 +127,10 @@ class AddCards(QDialog): browser.onSearch() def addNote(self, note): - if any(note.problems()): + if note.dupeOrEmpty(): showWarning(_( - "Some fields are missing or not unique."), - help="AddItems#AddError") + "The first field is empty or not unique."), + help="AddItems#AddError") return cards = self.mw.col.addNote(note) if not cards: diff --git a/aqt/editor.py b/aqt/editor.py index ecfc810dc..81bd47792 100644 --- a/aqt/editor.py +++ b/aqt/editor.py @@ -275,7 +275,7 @@ class Editor(object): native=True, canDisable=False) b("layout", self.onCardLayout, "Ctrl+l", shortcut(_("Customize Card Layout (Ctrl+l)")), - size=False, text=_("Layout..."), native=True, canDisable=False) + size=False, text=_("Cards..."), native=True, canDisable=False) # align to right self.iconsBox.addItem(QSpacerItem(20,1, QSizePolicy.Expanding)) b("text_bold", self.toggleBold, "Ctrl+b", _("Bold text (Ctrl+b)"), @@ -298,7 +298,7 @@ class Editor(object): # fixme: better image names b("text-speak", self.onAddMedia, "F3", _("Add pictures/audio/video (F3)")) b("media-record", self.onRecSound, "F5", _("Record audio (F5)")) - b("adv", self.onAdvanced, text=u"▼") + b("adv", self.onAdvanced, text=u"▾") s = QShortcut(QKeySequence("Ctrl+t, t"), self.widget) s.connect(s, SIGNAL("activated()"), self.insertLatex) s = QShortcut(QKeySequence("Ctrl+t, e"), self.widget) @@ -442,7 +442,10 @@ class Editor(object): contents = self.note.fields[0] browser = aqt.dialogs.open("Browser", self.mw) browser.form.searchEdit.setText( - "'model:%s' '%s'" % (self.note.model()['name'], contents)) + "'model:%s' '%s:%s'" % ( + self.note.model()['name'], + self.note.model()['flds'][0]['name'], + contents)) browser.onSearch() def fieldsAreBlank(self): diff --git a/aqt/fields.py b/aqt/fields.py index 064d840a7..f663ea377 100644 --- a/aqt/fields.py +++ b/aqt/fields.py @@ -18,7 +18,6 @@ class FieldDialog(QDialog): self.mm = self.mw.col.models self.model = note.model() self.mw.checkpoint(_("Fields")) - self.setWindowModality(Qt.WindowModal) self.form = aqt.forms.fields.Ui_Dialog() self.form.setupUi(self) self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False) diff --git a/aqt/main.py b/aqt/main.py index 7084563d9..04f4785d6 100755 --- a/aqt/main.py +++ b/aqt/main.py @@ -671,28 +671,12 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors") self.col.reset() self.moveToState("overview") - def onGroups(self, parent=None): - from aqt.groups import Groups - g = Groups(self, parent) - def onCardStats(self): self.cardStats.show() def onStats(self): aqt.stats.DeckStats(self) - def onCardLayout(self): - from aqt.clayout import CardLayout - CardLayout(self, self.reviewer.card.note(), ord=self.reviewer.card.ord) - - def onDeckOpts(self): - import aqt.deckopts - aqt.deckopts.DeckOptions(self) - - def onModels(self): - import aqt.models - aqt.models.Models(self) - def onPrefs(self): import aqt.preferences aqt.preferences.Preferences(self) diff --git a/aqt/modelchooser.py b/aqt/modelchooser.py index a973d692e..54bd9f1ab 100644 --- a/aqt/modelchooser.py +++ b/aqt/modelchooser.py @@ -1,9 +1,9 @@ +# -*- coding: utf-8 -*- # Copyright: Damien Elmes # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html from aqt.qt import * from operator import itemgetter -from anki import stdmodels from anki.lang import ngettext from anki.hooks import addHook, remHook, runHook from aqt.utils import isMac @@ -11,24 +11,22 @@ import aqt class ModelChooser(QHBoxLayout): - def __init__(self, mw, widget, cards=True, label=True): + def __init__(self, mw, widget, label=True): QHBoxLayout.__init__(self) self.widget = widget self.mw = mw self.deck = mw.col - self.handleCards = cards self.label = label self._ignoreReset = False self.setMargin(0) - self.setSpacing(4) + self.setSpacing(8) self.setupModels() - self.setupTemplates() addHook('reset', self.onReset) self.widget.setLayout(self) def setupModels(self): if self.label: - self.modelLabel = QLabel(_("Model:")) + self.modelLabel = QLabel(_("Note Type:")) self.addWidget(self.modelLabel) # models dropdown self.models = QComboBox() @@ -39,9 +37,12 @@ class ModelChooser(QHBoxLayout): self.connect(self.models, SIGNAL("activated(int)"), self.onModelChange) # edit button self.edit = QPushButton() - if not isMac: + if isMac: + self.edit.setFixedWidth(24) + self.edit.setFixedHeight(21) + else: self.edit.setFixedWidth(32) - self.edit.setIcon(QIcon(":/icons/configure.png")) + self.edit.setIcon(QIcon(":/icons/gears.png")) self.edit.setShortcut(_("Shift+Alt+e")) self.edit.setToolTip(_("Customize Models")) self.edit.setAutoDefault(False) @@ -54,22 +55,12 @@ class ModelChooser(QHBoxLayout): self.models.setSizePolicy(sizePolicy) self.updateModels() - def setupTemplates(self): - self.cardShortcuts = [] - if self.handleCards: - self.cards = QPushButton() - self.cards.setAutoDefault(False) - self.connect(self.cards, SIGNAL("clicked()"), self.onCardChange) - self.addWidget(self.cards) - self.updateTemplates() - def cleanup(self): remHook('reset', self.onReset) def onReset(self): if not self._ignoreReset: self.updateModels() - self.updateTemplates() def show(self): self.widget.show() @@ -83,8 +74,7 @@ class ModelChooser(QHBoxLayout): def onModelChange(self, idx): model = self._models[idx] - self.deck.conf['currentModelId'] = model.id - self.updateTemplates() + self.deck.conf['curModel'] = model.id self._ignoreReset = True runHook("currentModelChanged") self._ignoreReset = False @@ -95,105 +85,6 @@ class ModelChooser(QHBoxLayout): key=itemgetter("name")) self.models.addItems([m['name'] for m in self._models]) for c, m in enumerate(self._models): - if m['id'] == str(self.deck.conf['currentModelId']): + if m['id'] == str(self.deck.conf['curModel']): self.models.setCurrentIndex(c) break - - def updateTemplates(self): - if not self.handleCards: - return - # remove any shortcuts - for s in self.cardShortcuts: - s.setEnabled(False) - self.cardShortcuts = [] - m = self.deck.models.current() - ts = m['tmpls'] - active = [t['name'] for t in ts if t['actv']] - txt = ngettext("%d card", "%d cards", len(active)) % len(active) - self.cards.setText(txt) - n = 1 - for t in ts: - s = QShortcut(QKeySequence("Ctrl+%d" % n), self.widget) - self.widget.connect(s, SIGNAL("activated()"), - lambda t=t: self.toggleTemplate(t)) - self.cardShortcuts.append(s) - n += 1 - - def onCardChange(self): - m = QMenu(self.widget) - model = self.deck.models.current() - for template in model.templates: - action = QAction(self.widget) - action.setCheckable(True) - if template['actv']: - action.setChecked(True) - action.setText(template['name']) - self.connect(action, SIGNAL("triggered()"), - lambda t=template: \ - self.toggleTemplate(t)) - m.addAction(action) - m.exec_(self.cards.mapToGlobal(QPoint(0,0))) - - def canDisableTemplate(self): - return len([t for t in self.deck.models.current()['tmpls'] - if t['actv']]) > 1 - - def toggleTemplate(self, card): - if not card['actv']: - card['actv'] = True - elif self.canDisableTemplate(): - card['actv'] = False - self.deck.models.current().flush() - self.updateTemplates() - -class AddModel(QDialog): - - def __init__(self, mw, parent=None): - self.parent = parent or mw - self.mw = mw - self.deck = 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: - item = QListWidgetItem(_("Add: %s") % name) - self.dialog.models.addItem(item) - self.models.append((True, func)) - # add copies - mids = self.deck.db.list("select id from models order by name") - for m in [self.deck.getModel(mid, False) for mid in mids]: - m.id = None - item = QListWidgetItem(_("Copy: %s") % m['name']) - self.dialog.models.addItem(item) - m['name'] = _("%s copy") % m['name'] - self.models.append((False, m)) - self.dialog.models.setCurrentRow(0) - # the list widget will swallow the enter key - s = QShortcut(QKeySequence("Return"), self) - self.connect(s, SIGNAL("activated()"), self.accept) - # help - self.connect(self.dialog.buttonBox, SIGNAL("helpRequested()"), self.onHelp) - - def get(self): - self.exec_() - return self.model - - def reject(self): - self.accept() - - def accept(self): - (isStd, model) = self.models[self.dialog.models.currentRow()] - if isStd: - # create - self.model = model(self.deck) - else: - # add copy to deck - self.mw.col.addModel(model) - self.model = model - QDialog.accept(self) - - def onHelp(self): - openHelp("AddModel") diff --git a/aqt/models.py b/aqt/models.py index 5bf014726..901731dcb 100644 --- a/aqt/models.py +++ b/aqt/models.py @@ -3,8 +3,9 @@ from aqt.qt import * from operator import itemgetter -from aqt.utils import showInfo, askUser, getText, maybeHideClose +from aqt.utils import showInfo, askUser, getText, maybeHideClose, openHelp import aqt.modelchooser, aqt.clayout +from anki import stdmodels class Models(QDialog): def __init__(self, mw, parent=None): @@ -35,7 +36,7 @@ class Models(QDialog): c(b, s, self.onRename) b = box.addButton(_("Delete"), t) c(b, s, self.onDelete) - b = box.addButton(_("Advanced..."), t) + b = box.addButton(_("Options..."), t) c(b, s, self.onAdvanced) c(f.modelsList, SIGNAL("currentRowChanged(int)"), self.modelChanged) c(f.modelsList, SIGNAL("itemDoubleClicked(QListWidgetItem*)"), @@ -45,9 +46,10 @@ class Models(QDialog): maybeHideClose(box) def onRename(self): - txt = getText(_("New name?"), default=self.model.name) + txt = getText(_("New name:"), default=self.model.name) if txt[0]: - self.model.name = txt[0] + self.model['name'] = txt[0] + self.mm.save(self.model) self.updateModelsList() def updateModelsList(self): @@ -59,7 +61,7 @@ class Models(QDialog): self.form.modelsList.clear() for m in self.models: item = QListWidgetItem(_("%(name)s [%(notes)d notes]") % dict( - name=m.name, notes=m.useCount())) + name=m['name'], notes=self.mm.useCount(m))) self.form.modelsList.addItem(item) self.form.modelsList.setCurrentRow(row) @@ -70,31 +72,10 @@ class Models(QDialog): self.model = self.models[idx] def onAdd(self): - m = aqt.modelchooser.AddModel(self.mw, self).get() + m = AddModel(self.mw, self).get() if m: - self.col.addModel(m) self.updateModelsList() - def onLayout(self): - # set to current - # # see if there's an available note - dummy = False - id = self.col.db.scalar( - "select id from notes where mid = ?", self.model.id) - if id: - note = self.col.getNote(id) - else: - # generate a dummy one - self.col.conf['currentModelId'] = self.model.id - note = self.col.newNote() - for f in note.keys(): - note[f] = f - self.col.addNote(note) - dummy = True - aqt.clayout.CardLayout(self.mw, note, type=2, parent=self) - if dummy: - self.col._delNotes([note.id]) - def onDelete(self): if len(self.models) < 2: showInfo(_("Please add another model first."), @@ -104,7 +85,7 @@ class Models(QDialog): _("Delete this model and all its cards?"), parent=self): return - self.col.delModel(self.model.id) + self.mm.rem(self.model) self.model = None self.updateModelsList() @@ -112,14 +93,20 @@ class Models(QDialog): d = QDialog(self) frm = aqt.forms.modelopts.Ui_Dialog() frm.setupUi(d) - frm.latexHeader.setText(self.model.conf['latexPre']) - frm.latexFooter.setText(self.model.conf['latexPost']) + frm.clozeCtx.setChecked(self.model['clozectx']) + frm.latexHeader.setText(self.model['latexPre']) + frm.latexFooter.setText(self.model['latexPost']) + d.setWindowTitle(_("Options for %s") % self.model['name']) + self.connect( + frm.buttonBox, SIGNAL("helpRequested()"), + lambda: openHelp("NoteOptions")) d.exec_() - self.model.conf['latexPre'] = unicode(frm.latexHeader.toPlainText()) - self.model.conf['latexPost'] = unicode(frm.latexFooter.toPlainText()) + self.model['clozectx'] = frm.clozeCtx.isChecked() + self.model['latexPre'] = unicode(frm.latexHeader.toPlainText()) + self.model['latexPost'] = unicode(frm.latexFooter.toPlainText()) def saveModel(self): - self.model.flush() + self.mm.save(self.model) # Cleanup ########################################################################## @@ -130,3 +117,53 @@ class Models(QDialog): self.saveModel() self.mw.reset() 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: + item = QListWidgetItem(_("Add: %s") % name) + self.dialog.models.addItem(item) + self.models.append((True, func)) + # add copies + for m in self.col.models.all(): + 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) + self.connect(s, SIGNAL("activated()"), self.accept) + # help + self.connect(self.dialog.buttonBox, SIGNAL("helpRequested()"), self.onHelp) + + def get(self): + self.exec_() + return self.model + + def reject(self): + self.accept() + + 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("AddModel") diff --git a/aqt/utils.py b/aqt/utils.py index f11eef87b..12a7b1cf8 100644 --- a/aqt/utils.py +++ b/aqt/utils.py @@ -358,7 +358,7 @@ def tooltip(msg, period=3000, parent=None): evt.accept() self.hide() closeTooltip() - aw = parent or aqt.mw.app.activeWindow() + aw = parent or aqt.mw.app.activeWindow() or aqt.mw lab = CustomLabel("""\ diff --git a/designer/main.ui b/designer/main.ui index 9b2dcc1c3..bbc670dfa 100644 --- a/designer/main.ui +++ b/designer/main.ui @@ -104,6 +104,7 @@ + @@ -112,10 +113,6 @@ - - - :/icons/application-exit.png:/icons/application-exit.png - E&xit @@ -124,12 +121,8 @@ - - - :/icons/configure.png:/icons/configure.png - - &Preferences + &Preferences... Configure interface language and options @@ -142,10 +135,6 @@ - - - :/icons/anki.png:/icons/anki.png - &About... @@ -154,10 +143,6 @@ - - - :/icons/package_games_card.png:/icons/package_games_card.png - &Card Info @@ -172,10 +157,6 @@ false - - - :/icons/edit-undo.png:/icons/edit-undo.png - &Undo @@ -184,10 +165,6 @@ - - - :/icons/text-speak.png:/icons/text-speak.png - &Unused Media... @@ -211,10 +188,6 @@ - - - :/icons/emblem-favorite.png:/icons/emblem-favorite.png - &Support Anki... @@ -228,19 +201,11 @@ - - - :/icons/sqlitebrowser.png:/icons/sqlitebrowser.png - &Check DB... - - - :/icons/help-hint.png:/icons/help-hint.png - &Guide... @@ -249,10 +214,6 @@ - - - :/icons/user-identity.png:/icons/user-identity.png - &Switch Profile... diff --git a/designer/modelopts.ui b/designer/modelopts.ui index 4871dd783..6f5c30095 100644 --- a/designer/modelopts.ui +++ b/designer/modelopts.ui @@ -9,12 +9,12 @@ 0 0 - 353 - 363 + 276 + 323 - Model Options + @@ -22,6 +22,33 @@ 0 + + + Basic + + + + + + Show context in cloze answers + + + + + + + Qt::Vertical + + + + 20 + 184 + + + + + + LaTeX diff --git a/designer/models.ui b/designer/models.ui index 7d115f021..9e9158d61 100644 --- a/designer/models.ui +++ b/designer/models.ui @@ -14,7 +14,7 @@ - Models + Note Types