primarily work on browser

This commit is contained in:
Damien Elmes 2011-11-28 19:21:20 +09:00
parent 6f4e0d6ef9
commit 23411c2872
9 changed files with 67 additions and 172 deletions

View file

@ -201,9 +201,9 @@ class DataModel(QAbstractTableModel):
type = self.columnType(col) type = self.columnType(col)
c = self.getCard(index) c = self.getCard(index)
if type == "question": if type == "question":
return self.question() return self.question(c)
elif type == "answer": elif type == "answer":
return self.answer() return self.answer(c)
elif type == "noteFld": elif type == "noteFld":
f = c.note() f = c.note()
return self.formatQA(f.fields[self.col.models.sortIdx(f.model())]) return self.formatQA(f.fields[self.col.models.sortIdx(f.model())])
@ -234,10 +234,10 @@ class DataModel(QAbstractTableModel):
elif type == "noteGroup": elif type == "noteGroup":
return self.browser.mw.col.groups.name(c.note().gid) return self.browser.mw.col.groups.name(c.note().gid)
def question(self): def question(self, c):
return self.formatQA(c.a()) return self.formatQA(c.a())
def answer(self): def answer(self, c):
return self.formatQA(c.a()) return self.formatQA(c.a())
def formatQA(self, txt): def formatQA(self, txt):
@ -332,8 +332,7 @@ class Browser(QMainWindow):
self.onSearch() self.onSearch()
def setupToolbar(self): def setupToolbar(self):
self.form.toolBar.setIconSize(QSize(self.mw.pm.profile['iconSize'], self.form.toolBar.setIconSize(QSize(32, 32))
self.mw.pm.profile['iconSize']))
self.form.toolBar.toggleViewAction().setText(_("Toggle Toolbar")) self.form.toolBar.toggleViewAction().setText(_("Toggle Toolbar"))
def setupMenus(self): def setupMenus(self):
@ -341,13 +340,12 @@ class Browser(QMainWindow):
c = self.connect; f = self.form; s = SIGNAL("triggered()") c = self.connect; f = self.form; s = SIGNAL("triggered()")
c(f.actionAddItems, s, self.mw.onAddCard) c(f.actionAddItems, s, self.mw.onAddCard)
c(f.actionDelete, s, self.deleteCards) c(f.actionDelete, s, self.deleteCards)
c(f.actionSetGroup, s, self.setGroup) #c(f.actionSetGroup, s, self.setGroup)
c(f.actionAddTag, s, self.addTags) c(f.actionAddTag, s, self.addTags)
c(f.actionDeleteTag, s, self.deleteTags) c(f.actionDeleteTag, s, self.deleteTags)
c(f.actionReposition, s, self.reposition) c(f.actionReposition, s, self.reposition)
c(f.actionReschedule, s, self.reschedule) c(f.actionReschedule, s, self.reschedule)
c(f.actionCram, s, self.cram) c(f.actionCram, s, self.cram)
c(f.actionAddCards, s, self.genCards)
c(f.actionChangeModel, s, self.onChangeModel) c(f.actionChangeModel, s, self.onChangeModel)
c(f.actionToggleSuspend, SIGNAL("triggered(bool)"), self.onSuspend) c(f.actionToggleSuspend, SIGNAL("triggered(bool)"), self.onSuspend)
c(f.actionToggleMark, SIGNAL("triggered(bool)"), self.onMark) c(f.actionToggleMark, SIGNAL("triggered(bool)"), self.onMark)
@ -662,7 +660,7 @@ class Browser(QMainWindow):
mitem.addChild(titem) mitem.addChild(titem)
def _groupTree(self, root): def _groupTree(self, root):
grps = self.col.sched.groupTree() grps = self.col.sched.deckDueTree()
def fillGroups(root, grps, head=""): def fillGroups(root, grps, head=""):
for g in grps: for g in grps:
item = self.CallbackItem( item = self.CallbackItem(
@ -725,6 +723,8 @@ class Browser(QMainWindow):
extra += self.cardStats.makeLine( extra += self.cardStats.makeLine(
_("Reviews"), "<a href=revlog>%d</a>" % self.card.reps) _("Reviews"), "<a href=revlog>%d</a>" % self.card.reps)
rep = rep.replace("</table>", extra) rep = rep.replace("</table>", extra)
self.form.cardLabel.setMaximumWidth(250)
self.form.cardLabel.setWordWrap(True)
self.form.cardLabel.setText(rep) self.form.cardLabel.setText(rep)
def onCardLink(self, url): def onCardLink(self, url):
@ -750,7 +750,7 @@ class Browser(QMainWindow):
d = QDialog(self) d = QDialog(self)
l = QVBoxLayout() l = QVBoxLayout()
l.setMargin(0) l.setMargin(0)
w = AnkiWebView(self.mw) w = AnkiWebView()
l.addWidget(w) l.addWidget(w)
w.stdHtml(data) w.stdHtml(data)
bb = QDialogButtonBox(QDialogButtonBox.Close) bb = QDialogButtonBox(QDialogButtonBox.Close)

View file

@ -10,7 +10,6 @@ from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA, \
saveSplitter, restoreSplitter, showInfo, askUser, getOnlyText, \ saveSplitter, restoreSplitter, showInfo, askUser, getOnlyText, \
showWarning, openHelp showWarning, openHelp
from anki.utils import isMac, isWin from anki.utils import isMac, isWin
import aqt.templates
# raise Exception("Remember to disallow media&latex refs in edit.") # raise Exception("Remember to disallow media&latex refs in edit.")
@ -106,21 +105,21 @@ Please create a new card first."""))
help = QPushButton(_("Help")) help = QPushButton(_("Help"))
help.setAutoDefault(False) help.setAutoDefault(False)
l.addWidget(help) l.addWidget(help)
c(l, SIGNAL("clicked()"), self.onHelp) c(help, SIGNAL("clicked()"), self.onHelp)
l.addStretch() l.addStretch()
rename = QPushButton(_("Rename")) rename = QPushButton(_("Rename"))
rename.setAutoDefault(False) rename.setAutoDefault(False)
l.addWidget(rename) l.addWidget(rename)
c(l, SIGNAL("clicked()"), self.onRename) c(rename, SIGNAL("clicked()"), self.onRename)
repos = QPushButton(_("Reposition")) repos = QPushButton(_("Reposition"))
repos.setAutoDefault(False) repos.setAutoDefault(False)
l.addWidget(repos) l.addWidget(repos)
c(l, SIGNAL("clicked()"), self.onReorder) c(repos, SIGNAL("clicked()"), self.onReorder)
l.addStretch() l.addStretch()
close = QPushButton(_("Close")) close = QPushButton(_("Close"))
close.setAutoDefault(False) close.setAutoDefault(False)
l.addWidget(close) l.addWidget(close)
c(l, SIGNAL("clicked()"), self.accept) c(close, SIGNAL("clicked()"), self.accept)
# Cards # Cards
########################################################################## ##########################################################################
@ -158,16 +157,19 @@ Please create a new card first."""))
c = self.card c = self.card
styles = "\n.cloze { font-weight: bold; color: blue; }" styles = "\n.cloze { font-weight: bold; color: blue; }"
html = '<html><body id=card><style>%s</style>%s</body></html>' html = '<html><body id=card><style>%s</style>%s</body></html>'
ti = self.maybeTextInput
self.tab['pform'].front.setHtml( self.tab['pform'].front.setHtml(
html % (styles, mungeQA(c.q(reload=True)))) html % (styles, ti(mungeQA(c.q(reload=True)))))
self.tab['pform'].back.setHtml( self.tab['pform'].back.setHtml(
html % (styles, mungeQA(c.a()))) html % (styles, ti(mungeQA(c.a()), 'a')))
def maybeTextInput(self): def maybeTextInput(self, txt, type='q'):
return "text input" if type == 'q':
if self.card.template()['typeAns'] is not None: repl = "<center><input type=text value='%s'></center>" % _(
return "<center><input type=text></center>" "(text is typed in here)")
return "" else:
repl = _("(typing comparison appears here)")
return re.sub("\[\[type:.+?\]\]", repl, txt)
# Card operations # Card operations
###################################################################### ######################################################################

View file

@ -28,7 +28,7 @@ _html = """
.field { .field {
border: 1px solid #aaa; background:#fff; color:#000; padding: 5px; border: 1px solid #aaa; background:#fff; color:#000; padding: 5px;
} }
.fname { font-size: 14px; vertical-align: middle; padding-right: 5px; } .fname { font-size: 12px; vertical-align: middle; padding-right: 5px; }
img { max-width: 150; max-height: 150; } img { max-width: 150; max-height: 150; }
body { margin: 5px; } body { margin: 5px; }
</style><script> </style><script>
@ -309,10 +309,10 @@ class Editor(object):
from aqt.clayout import CardLayout from aqt.clayout import CardLayout
self.saveNow() self.saveNow()
if self.card: if self.card:
type = 1; ord = self.card.ord ord = self.card.ord
else: else:
type = 0; ord = 0 ord = 0
CardLayout(self.mw, self.note, type=type, ord=ord, parent=self.widget) CardLayout(self.mw, self.note, ord=ord, parent=self.widget)
self.loadNote() self.loadNote()
# JS->Python bridge # JS->Python bridge
@ -397,7 +397,7 @@ class Editor(object):
self.web.setFocus() self.web.setFocus()
def fonts(self): def fonts(self):
return [(f['font'], f['esize']) return [(f['font'], f['size'])
for f in self.note.model()['flds']] for f in self.note.model()['flds']]
def saveNow(self): def saveNow(self):
@ -411,17 +411,14 @@ class Editor(object):
def checkValid(self): def checkValid(self):
cols = [] cols = []
self.dupe = None err = None
for c, p in enumerate(self.note.problems()): for f in self.note.fields:
if not p: cols.append("#fff")
cols.append("#fff") err = self.note.dupeOrEmpty()
elif p == "unique": if err:
cols.append("#fcc") cols[0] = "#fcc"
self.dupe = c
else:
cols.append("#ffc")
self.web.eval("setBackgrounds(%s);" % simplejson.dumps(cols)) self.web.eval("setBackgrounds(%s);" % simplejson.dumps(cols))
if self.dupe is not None: if err == 2:
self.web.eval("showDupes();") self.web.eval("showDupes();")
else: else:
self.web.eval("hideDupes();") self.web.eval("hideDupes();")
@ -496,11 +493,11 @@ class Editor(object):
if self.addMode: if self.addMode:
self.group.setCol(self.mw.col) self.group.setCol(self.mw.col)
self.tags.setText(self.note.stringTags().strip()) self.tags.setText(self.note.stringTags().strip())
if getattr(self.note, 'gid', None): if getattr(self.note, 'did', None):
gid = self.note.gid did = self.note.did
else: else:
gid = self.note.model().conf['gid'] did = self.note.model()['did']
self.group.setText(self.mw.col.groups.name(gid)) self.group.setText(self.mw.col.decks.name(did))
def saveTagsAndGroup(self): def saveTagsAndGroup(self):
if not self.note: if not self.note:
@ -508,9 +505,9 @@ class Editor(object):
self.note.tags = self.mw.col.tags.split(unicode(self.tags.text())) self.note.tags = self.mw.col.tags.split(unicode(self.tags.text()))
if self.addMode: if self.addMode:
# save group and tags to model # save group and tags to model
self.note.gid = self.mw.col.groups.id(unicode(self.group.text())) self.note.did = self.mw.col.decks.id(unicode(self.group.text()))
m = self.note.model() m = self.note.model()
m['gid'] = self.note.gid m['did'] = self.note.did
m['tags'] = self.note.tags m['tags'] = self.note.tags
self.mw.col.models.save(m) self.mw.col.models.save(m)
self.note.flush() self.note.flush()
@ -771,7 +768,7 @@ class Editor(object):
class EditorWebView(AnkiWebView): class EditorWebView(AnkiWebView):
def __init__(self, parent, editor): def __init__(self, parent, editor):
AnkiWebView.__init__(self, parent) AnkiWebView.__init__(self)
self.editor = editor self.editor = editor
self.errtxt = _("An error occured while opening %s") self.errtxt = _("An error occured while opening %s")
self.strip = self.editor.mw.pm.profile['stripHTML'] self.strip = self.editor.mw.pm.profile['stripHTML']

View file

@ -5,7 +5,6 @@ from aqt.qt import *
import re import re
from anki.consts import * from anki.consts import *
import aqt import aqt
from anki.sound import playFromText, clearAudioQueue
from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA, \ from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA, \
saveSplitter, restoreSplitter, showInfo, askUser, getText, \ saveSplitter, restoreSplitter, showInfo, askUser, getText, \
openHelp openHelp

View file

@ -2,6 +2,7 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from aqt.qt import * from aqt.qt import *
from operator import itemgetter
from aqt.utils import showInfo, askUser, getText, maybeHideClose from aqt.utils import showInfo, askUser, getText, maybeHideClose
import aqt.modelchooser, aqt.clayout import aqt.modelchooser, aqt.clayout
@ -10,7 +11,8 @@ class Models(QDialog):
self.mw = mw self.mw = mw
self.parent = parent or mw self.parent = parent or mw
QDialog.__init__(self, self.parent, Qt.Window) QDialog.__init__(self, self.parent, Qt.Window)
self.deck = mw.col self.col = mw.col
self.mm = self.col.models
self.mw.checkpoint(_("Models")) self.mw.checkpoint(_("Models"))
self.form = aqt.forms.models.Ui_Dialog() self.form = aqt.forms.models.Ui_Dialog()
self.form.setupUi(self) self.form.setupUi(self)
@ -27,9 +29,6 @@ class Models(QDialog):
c = self.connect; f = self.form; box = f.buttonBox c = self.connect; f = self.form; box = f.buttonBox
s = SIGNAL("clicked()") s = SIGNAL("clicked()")
t = QDialogButtonBox.ActionRole t = QDialogButtonBox.ActionRole
b = box.addButton(_("Layout..."), t)
c(b, s, self.onLayout)
b.setDefault(True)
b = box.addButton(_("Add"), t) b = box.addButton(_("Add"), t)
c(b, s, self.onAdd) c(b, s, self.onAdd)
b = box.addButton(_("Rename"), t) b = box.addButton(_("Rename"), t)
@ -55,8 +54,8 @@ class Models(QDialog):
row = self.form.modelsList.currentRow() row = self.form.modelsList.currentRow()
if row == -1: if row == -1:
row = 0 row = 0
mids = self.deck.db.list("select id from models order by name") self.models = self.col.models.all()
self.models = [self.deck.getModel(mid) for mid in mids] self.models.sort(key=itemgetter("name"))
self.form.modelsList.clear() self.form.modelsList.clear()
for m in self.models: for m in self.models:
item = QListWidgetItem(_("%(name)s [%(notes)d notes]") % dict( item = QListWidgetItem(_("%(name)s [%(notes)d notes]") % dict(
@ -73,28 +72,28 @@ class Models(QDialog):
def onAdd(self): def onAdd(self):
m = aqt.modelchooser.AddModel(self.mw, self).get() m = aqt.modelchooser.AddModel(self.mw, self).get()
if m: if m:
self.deck.addModel(m) self.col.addModel(m)
self.updateModelsList() self.updateModelsList()
def onLayout(self): def onLayout(self):
# set to current # set to current
# # see if there's an available note # # see if there's an available note
dummy = False dummy = False
id = self.deck.db.scalar( id = self.col.db.scalar(
"select id from notes where mid = ?", self.model.id) "select id from notes where mid = ?", self.model.id)
if id: if id:
note = self.deck.getNote(id) note = self.col.getNote(id)
else: else:
# generate a dummy one # generate a dummy one
self.deck.conf['currentModelId'] = self.model.id self.col.conf['currentModelId'] = self.model.id
note = self.deck.newNote() note = self.col.newNote()
for f in note.keys(): for f in note.keys():
note[f] = f note[f] = f
self.deck.addNote(note) self.col.addNote(note)
dummy = True dummy = True
aqt.clayout.CardLayout(self.mw, note, type=2, parent=self) aqt.clayout.CardLayout(self.mw, note, type=2, parent=self)
if dummy: if dummy:
self.deck._delNotes([note.id]) self.col._delNotes([note.id])
def onDelete(self): def onDelete(self):
if len(self.models) < 2: if len(self.models) < 2:
@ -105,7 +104,7 @@ class Models(QDialog):
_("Delete this model and all its cards?"), _("Delete this model and all its cards?"),
parent=self): parent=self):
return return
self.deck.delModel(self.model.id) self.col.delModel(self.model.id)
self.model = None self.model = None
self.updateModelsList() self.updateModelsList()

View file

@ -364,6 +364,8 @@ div#filler {
def typeAns(self): def typeAns(self):
"None if answer typing disabled." "None if answer typing disabled."
print "typeAns()"
return False
self.card.template()['typeAns'] self.card.template()['typeAns']
def typeAnsInput(self): def typeAnsInput(self):

View file

@ -9,7 +9,7 @@ class TagEdit(QLineEdit):
# 0 = tags, 1 = groups # 0 = tags, 1 = groups
def __init__(self, parent, type=0): def __init__(self, parent, type=0):
QLineEdit.__init__(self, parent) QLineEdit.__init__(self, parent)
self.deck = None self.col = None
self.model = QStringListModel() self.model = QStringListModel()
self.type = type self.type = type
if type == 0: if type == 0:
@ -20,13 +20,13 @@ class TagEdit(QLineEdit):
self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.setCompleter(self.completer) self.setCompleter(self.completer)
def setDeck(self, deck): def setCol(self, col):
"Set the current deck, updating list of available tags." "Set the current col, updating list of available tags."
self.deck = deck self.col = col
if self.type == 0: if self.type == 0:
l = sorted(self.deck.tags.all()) l = sorted(self.col.tags.all())
else: else:
l = self.deck.groups.all() l = self.col.groups.all()
self.model.setStringList(l) self.model.setStringList(l)
def addTags(self, tags): def addTags(self, tags):
@ -50,7 +50,7 @@ class TagCompleter(QCompleter):
def splitPath(self, str): def splitPath(self, str):
str = unicode(str).strip() str = unicode(str).strip()
str = re.sub(" +", " ", str) str = re.sub(" +", " ", str)
self.tags = self.parent.deck.tags.split(str) self.tags = self.parent.col.tags.split(str)
self.tags.append(u"") self.tags.append(u"")
p = self.edit.cursorPosition() p = self.edit.cursorPosition()
self.cursor = str.count(" ", 0, p) self.cursor = str.count(" ", 0, p)

View file

@ -1,105 +0,0 @@
# Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from aqt.qt import *
import aqt
from aqt.utils import saveGeom, restoreGeom, askUser, getText
class Templates(QDialog):
def __init__(self, mw, model, parent=None):
self.parent = parent or mw
QDialog.__init__(self, self.parent, Qt.Window)
self.mw = aqt.mw
self.model = model
self.form = aqt.forms.templates.Ui_Dialog()
self.form.setupUi(self)
self.setWindowTitle(_("%s Templates") % self.model.name)
self.setupTemplates()
self.updateTemplates()
self.exec_()
# Templates
##########################################################################
def setupTemplates(self):
f = self.form; c = self.connect; s = SIGNAL("clicked()")
c(f.templateList, SIGNAL("currentRowChanged(int)"),
self.templateRowChanged)
c(f.templateList, SIGNAL("itemDoubleClicked(QListWidgetItem*)"),
self.renameTemplate)
c(f.templateAdd, s, self.addTemplate)
c(f.templateDelete, s, self.deleteTemplate)
c(f.templateUp, s, self.moveTemplateUp)
c(f.templateDown, s, self.moveTemplateDown)
def renameTemplate(self, item):
txt = getText(_("New name?"), default=self.template['name'])
if txt[0]:
self.template['name'] = txt[0]
def updateTemplates(self, row = None):
row = self.form.templateList.currentRow() or 0
if row == -1:
row = 0
self.form.templateList.clear()
for template in self.model.templates:
item = QListWidgetItem(template['name'])
self.form.templateList.addItem(item)
count = self.form.templateList.count()
self.form.templateList.setCurrentRow(row)
def templateRowChanged(self):
self.template = self.model.templates[self.form.templateList.currentRow()]
self.enableTemplateMoveButtons()
def enableTemplateMoveButtons(self):
f = self.form
row = f.templateList.currentRow()
f.templateUp.setEnabled(row >= 1)
f.templateDown.setEnabled(row < (f.templateList.count() - 1))
def addTemplate(self):
templates = len(self.model.templates)
t = self.model.newTemplate()
t['name'] = _("Template %d") % (templates+1)
fields = self.model.fields
t['qfmt'] = "{{%s}}" % fields[0]['name']
if len(fields) > 1:
t['afmt'] = "{{%s}}" % fields[1]['name']
else:
t['afmt'] = ""
self.model.addTemplate(t)
self.updateTemplates()
def deleteTemplate(self):
if len (self.model.templates) < 2:
ui.utils.showWarning(
_("Please add a new template first."),
parent=self)
return
if not askUser(
_("Delete this template and all cards that use it?")):
return
self.model.delTemplate(self.template)
self.updateTemplates()
def moveTemplateUp(self):
row = self.form.templateList.currentRow()
if row == 0:
return
self.mw.progress.start()
self.model.moveTemplate(self.template, row-1)
self.mw.progress.finish()
self.updateTemplates()
self.form.templateList.setCurrentRow(row-1)
def moveTemplateDown(self):
row = self.form.templateList.currentRow()
if row == len(self.model.templates) - 1:
return
self.mw.progress.start()
self.model.moveTemplate(self.template, row+1)
self.mw.progress.finish()
self.updateTemplates()
self.form.templateList.setCurrentRow(row+1)

View file

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import os, cPickle, ctypes import os, cPickle, ctypes, shutil
from aqt.qt import * from aqt.qt import *
from anki.utils import isMac, isWin from anki.utils import isMac, isWin
from anki import Collection from anki import Collection
@ -132,6 +132,7 @@ carefully, as a lot has changed since the previous Anki version."""))
def isComplete(self): def isComplete(self):
return False return False
def initializePage(self): def initializePage(self):
self.setCommitPage(True)
self.setTitle(_("Upgrading")) self.setTitle(_("Upgrading"))
self.label = l = QLabel() self.label = l = QLabel()
l.setTextInteractionFlags(Qt.TextSelectableByMouse) l.setTextInteractionFlags(Qt.TextSelectableByMouse)