From 2f6867c4cc1a5a88fe99ac0d838e69aa80cf5871 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 31 Mar 2011 16:29:42 +0900 Subject: [PATCH] start of clayout port --- aqt/clayout.py | 302 +++++++++++++++-------------------------- aqt/errors.py | 4 +- aqt/main.py | 5 +- aqt/modelproperties.py | 12 ++ aqt/reviewer.py | 1 - aqt/utils.py | 15 +- 6 files changed, 138 insertions(+), 201 deletions(-) diff --git a/aqt/clayout.py b/aqt/clayout.py index cec4b7eaf..e860eb76c 100644 --- a/aqt/clayout.py +++ b/aqt/clayout.py @@ -4,17 +4,15 @@ from PyQt4.QtGui import * from PyQt4.QtCore import * from PyQt4.QtWebKit import QWebPage, QWebView -import sys, re -import aqt.forms -import anki -from anki.models import * -from anki.facts import * -from anki.cards import Card +import re +from anki.consts import * +#from anki.models import * +#from anki.facts import * +import aqt from anki.sound import playFromText, clearAudioQueue -from aqt.ui.utils import saveGeom, restoreGeom, getBase, mungeQA, \ - saveSplitter, restoreSplitter +from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA, \ + saveSplitter, restoreSplitter, showInfo, isMac, isWin from anki.hooks import runFilter -from aqt import ui class ResizingTextEdit(QTextEdit): def sizeHint(self): @@ -22,137 +20,102 @@ class ResizingTextEdit(QTextEdit): class CardLayout(QDialog): - def __init__(self, parent, factedit, factOrModel, card=None): - self.parent = parent - QDialog.__init__(self, parent, Qt.Window) + # type is previewCards() type + def __init__(self, mw, fact, type=0, ord=0, parent=None): + QDialog.__init__(self, parent or mw, Qt.Window) self.mw = aqt.mw + self.fact = fact + self.type = type + self.ord = ord self.deck = self.mw.deck - self.factedit = factedit - self.card = card - if factedit is not None: - self.fact = factOrModel - self.model = self.fact.model - else: - self.model = factOrModel - # see if there's an available fact - id = self.deck.db.scalar( - "select id from facts where modelId = :id", id=self.model.id) - if id: - self.fact = self.deck.db.query(Fact).get(id) - else: - # generate a dummy one - self.fact = self.deck.newFact(self.model) - for f in self.fact.keys(): - self.fact[f] = f - self.plastiqueStyle = None - if (sys.platform.startswith("darwin") or - sys.platform.startswith("win32")): - self.plastiqueStyle = QStyleFactory.create("plastique") - if self.card: - # limited to an existing template - self.cards = [self.deck.db.query(Card).get(id) for id in - self.deck.db.column0( - "select id from cards where factId = :fid " - "order by ordinal", fid=self.fact.id)] - type = 0 - else: - if factedit: - # active & possible - self.cards = self.deck.previewFact(self.fact) - type = 1 - else: - # all - self.cards = self.deck.previewFact(self.fact, cms=self.model.cardModels) - type = 2 - if not self.cards: - ui.utils.showInfo(_( - "Please enter some text first."), - parent=self.parent) - return + self.model = fact.model() self.form = aqt.forms.clayout.Ui_Dialog() self.form.setupUi(self) - restoreSplitter(self.form.splitter, "clayout") - if type == 0: - self.form.templateType.setText( - _("Templates used by fact:")) - elif type == 1: - self.form.templateType.setText( - _("Templates that will be created:")) - else: - self.form.templateType.setText( - _("All templates:")) - # FIXME: add this + self.plastiqueStyle = None + if isMac or isWin: + self.plastiqueStyle = QStyleFactory.create("plastique") + # FIXME: add editing self.form.editTemplates.hide() self.connect(self.form.buttonBox, SIGNAL("helpRequested()"), self.onHelp) self.setupCards() self.setupFields() + restoreSplitter(self.form.splitter, "clayout") restoreGeom(self, "CardLayout") - # hack to ensure we're focused on the active template in the model - # properties - if type == 2 and factOrModel.currentCard.ordinal != 0: - idx = factOrModel.currentCard.ordinal - self.form.cardList.setCurrentIndex(idx) - self.cardChanged(idx) + self.reload() + if not self.cards: + showInfo(_("Please enter some text first."), + parent=parent or mw) + return self.exec_() + def reload(self): + self.cards = self.deck.previewCards(self.fact, self.type) + self.fillCardList() + self.fillFieldList() + self.fieldChanged(0) + self.readField() + # Cards & Preview ########################################################################## def setupCards(self): - self.needFormatRebuild = False self.updatingCards = False self.playedAudio = {} + f = self.form + if type == 0: + f.templateType.setText( + _("Templates used by fact:")) + elif type == 1: + f.templateType.setText( + _("Templates that will be created:")) + else: + f.templateType.setText( + _("All templates:")) # replace with more appropriate size hints for e in ("cardQuestion", "cardAnswer"): - w = getattr(self.form, e) - idx = self.form.templateLayout.indexOf(w) - r = self.form.templateLayout.getItemPosition(idx) - self.form.templateLayout.removeWidget(w) + w = getattr(f, e) + idx = f.templateLayout.indexOf(w) + r = f.templateLayout.getItemPosition(idx) + f.templateLayout.removeWidget(w) w.hide() w.deleteLater() w = ResizingTextEdit(self) - setattr(self.form, e, w) - self.form.templateLayout.addWidget(w, r[0], r[1]) - self.connect(self.form.cardList, SIGNAL("activated(int)"), + setattr(f, e, w) + f.templateLayout.addWidget(w, r[0], r[1]) + self.connect(f.cardList, SIGNAL("activated(int)"), self.cardChanged) - # self.connect(self.form.editTemplates, SIGNAL("clicked())"), + # self.connect(f.editTemplates, SIGNAL("clicked())"), # self.onEdit) - self.connect(self.form.cardQuestion, SIGNAL("textChanged()"), - lambda: self.formatChanged("question")) - self.connect(self.form.cardAnswer, SIGNAL("textChanged()"), - lambda: self.formatChanged("answer")) - self.connect(self.form.alignment, - SIGNAL("activated(int)"), - self.saveCard) - self.connect(self.form.background, - SIGNAL("clicked()"), - lambda w=self.form.background:\ + c = self.connect + c(f.cardQuestion, SIGNAL("textChanged()"), self.formatChanged) + c(f.cardAnswer, SIGNAL("textChanged()"), self.formatChanged) + c(f.alignment, SIGNAL("activated(int)"), self.saveCard) + c(f.background, SIGNAL("clicked()"), + lambda w=f.background:\ self.chooseColour(w, "card")) - self.connect(self.form.questionInAnswer, - SIGNAL("clicked()"), self.saveCard) - self.connect(self.form.allowEmptyAnswer, - SIGNAL("clicked()"), self.saveCard) - self.connect(self.form.typeAnswer, SIGNAL("activated(int)"), - self.saveCard) - self.connect(self.form.flipButton, SIGNAL("clicked()"), - self.onFlip) + c(f.questionInAnswer, SIGNAL("clicked()"), self.saveCard) + c(f.allowEmptyAnswer, SIGNAL("clicked()"), self.saveCard) + c(f.typeAnswer, SIGNAL("activated(int)"), self.saveCard) + c(f.flipButton, SIGNAL("clicked()"), self.onFlip) def linkClicked(url): QDesktopServices.openUrl(QUrl(url)) - self.form.preview.page().setLinkDelegationPolicy( + f.preview.page().setLinkDelegationPolicy( QWebPage.DelegateExternalLinks) - self.connect(self.form.preview, + self.connect(f.preview, SIGNAL("linkClicked(QUrl)"), linkClicked) if self.plastiqueStyle: - self.form.background.setStyle(self.plastiqueStyle) - self.form.alignment.clear() - self.form.alignment.addItems( + f.background.setStyle(self.plastiqueStyle) + f.alignment.addItems( QStringList(alignmentLabels().values())) - self.fillCardList() + self.typeFieldNames = self.model.fieldMap() + s = [_("Don't ask me to type in the answer")] + s += [_("Compare with field '%s'") % fi + for fi in self.typeFieldNames.keys()] + f.typeAnswer.insertItems(0, QStringList(s)) def formatToScreen(self, fmt): - fmt = re.sub("%\((.+?)\)s", "{{\\1}}", fmt) fmt = fmt.replace("}}
", "}}\n") return fmt @@ -165,31 +128,13 @@ class CardLayout(QDialog): # self, self.deck, self.model, self.mw, # onFinish=self.updateModelsList) - def formatChanged(self, type): + def formatChanged(self): if self.updatingCards: return - if type == "question": - text = unicode(self.form.cardQuestion.toPlainText()) - text = self.screenToFormat(text) - #self.realCardModel(self.card).qformat = text - self.card.cardModel.qformat = text - else: - text = unicode(self.form.cardAnswer.toPlainText()) - text = self.screenToFormat(text) - self.card.cardModel.aformat = text - self.fact.model.setModified() - self.deck.flushMod() - d = {} - for f in self.fact.model.fieldModels: - d[f.name] = (f.id, self.fact[f.name]) - for card in self.cards: - qa = formatQA(None, self.fact.modelId, d, card.splitTags(), - card.cardModel, self.deck) - card.question = qa['question'] - card.answer = qa['answer'] - card.setModified() - self.deck.setModified() - self.needFormatRebuild = True + text = unicode(self.form.cardQuestion.toPlainText()) + self.card.template()['qfmt'] = self.screenToFormat(text) + text = unicode(self.form.cardAnswer.toPlainText()) + self.card.template()['afmt'] = self.screenToFormat(text) self.renderPreview() def onFlip(self): @@ -199,29 +144,19 @@ class CardLayout(QDialog): self.form.cardQuestion.setPlainText(a) def readCard(self): - card = self.card.cardModel - self.form.background.setPalette(QPalette(QColor( - getattr(card, "lastFontColour")))) self.updatingCards = True - self.form.cardQuestion.setPlainText(self.formatToScreen(card.qformat)) - self.form.cardAnswer.setPlainText(self.formatToScreen(card.aformat)) - self.form.questionInAnswer.setChecked(card.questionInAnswer) - self.form.allowEmptyAnswer.setChecked(card.allowEmptyAnswer) - self.form.alignment.setCurrentIndex(card.questionAlign) - self.form.typeAnswer.clear() - self.typeFieldNames = self.deck.db.column0(""" -select fieldModels.name as n from fieldModels, cardModels -where cardModels.modelId = fieldModels.modelId -and cardModels.id = :id -order by n""", id=card.id) - s = [_("Don't ask me to type in the answer")] - s += [_("Compare with field '%s'") % f for f in self.typeFieldNames] - self.form.typeAnswer.insertItems(0, QStringList(s)) - try: - idx = self.typeFieldNames.index(card.typeAnswer) - except ValueError: - idx = -1 - self.form.typeAnswer.setCurrentIndex(idx + 1) + t = self.card.template() + f = self.form + f.background.setPalette(QPalette(QColor(t['bg']))) + f.cardQuestion.setPlainText(self.formatToScreen(t['qfmt'])) + f.cardAnswer.setPlainText(self.formatToScreen(t['afmt'])) + f.questionInAnswer.setChecked(t['hideQ']) + f.allowEmptyAnswer.setChecked(t['emptyAns']) + f.alignment.setCurrentIndex(t['align']) + if t['typeAns'] is None: + f.typeAnswer.setCurrentIndex(0) + else: + f.typeAnswer.setCurrentIndex(t['typeAns'] + 1) self.updatingCards = False def fillCardList(self): @@ -229,16 +164,15 @@ order by n""", id=card.id) cards = [] idx = 0 for n, c in enumerate(self.cards): - if c == self.card: - cards.append(_("%s (current)") % c.cardModel.name) + if c.ord == self.ord: + cards.append(_("%s (current)") % c.template()['name']) idx = n else: - cards.append(c.cardModel.name) + cards.append(c.template()['name']) self.form.cardList.addItems( QStringList(cards)) self.form.editTemplates.setEnabled(False) - if idx != 0: - self.form.cardList.setCurrentIndex(idx) + self.form.cardList.setCurrentIndex(idx) self.cardChanged(idx) self.form.cardList.setFocus() @@ -278,34 +212,28 @@ order by n""", id=card.id) def renderPreview(self): c = self.card - styles = (self.deck.rebuildCSS() + - ("\nhtml { background: %s }" % c.cardModel.lastFontColour)) - styles = runFilter("addStyles", styles, c) + styles = self.model.genCSS() self.form.preview.setHtml( ('%s' % getBase(self.deck, c)) + "" + - runFilter("drawQuestion", mungeQA(self.deck, c.htmlQuestion()), - c) + + mungeQA(c.q(reload=True)) + "
" + - runFilter("drawAnswer", mungeQA(self.deck, c.htmlAnswer()), - c) + mungeQA(c.a()) + "") clearAudioQueue() if c.id not in self.playedAudio: - playFromText(c.question) - playFromText(c.answer) + playFromText(c.q()) + playFromText(c.a()) self.playedAudio[c.id] = True def reject(self): + return + self.fact.model.setModified() + modified = False self.mw.startProgress() self.deck.updateProgress(_("Applying changes...")) reset=True - if self.needFormatRebuild: - # need to generate q/a templates - self.deck.updateCardsFromModel(self.fact.model) - self.deck.finishProgress() - modified = True if len(self.fieldOrdinalUpdatedIds) > 0: self.deck.rebuildFieldOrdinals(self.model.id, self.fieldOrdinalUpdatedIds) modified = True @@ -334,9 +262,6 @@ order by n""", id=card.id) self.fieldOrdinalUpdatedIds = [] self.updatingFields = False self.needFieldRebuild = False - self.fillFieldList() - self.fieldChanged(0) - self.readField() self.connect(self.form.fieldList, SIGNAL("currentRowChanged(int)"), self.fieldChanged) self.connect(self.form.fieldAdd, SIGNAL("clicked()"), @@ -377,28 +302,23 @@ order by n""", id=card.id) def fieldChanged(self, idx): if self.updatingFields: return - self.field = self.model.fieldModels[idx] + self.field = self.model.fields[idx] self.readField() self.enableFieldMoveButtons() def readField(self): - field = self.field + fld = self.field + f = self.form self.updatingFields = True - self.form.fieldName.setText(field.name) - self.form.fieldUnique.setChecked(field.unique) - self.form.fieldRequired.setChecked(field.required) - self.form.numeric.setChecked(field.numeric) - if not field.quizFontFamily: - # backwards compat - field.quizFontFamily = u"Arial" - self.form.fontFamily.setCurrentFont(QFont( - field.quizFontFamily)) - self.form.fontSize.setValue(field.quizFontSize or 20) - self.form.fontSizeEdit.setValue(field.editFontSize or 20) - self.form.fontColour.setPalette(QPalette(QColor( - field.quizFontColour or "#000000"))) - self.form.rtl.setChecked(not not field.features) - self.form.preserveWhitespace.setChecked(not not field.editFontFamily) + f.fieldName.setText(fld['name']) + f.fieldUnique.setChecked(fld['uniq']) + f.fieldRequired.setChecked(fld['req']) + f.fontFamily.setCurrentFont(QFont(fld['font'])) + f.fontSize.setValue(fld['qsize']) + f.fontSizeEdit.setValue(fld['esize']) + f.fontColour.setPalette(QPalette(QColor(fld['qcol']))) + f.rtl.setChecked(fld['rtl']) + f.preserveWhitespace.setChecked(fld['pre']) self.updatingFields = False def saveField(self, *args): @@ -445,8 +365,8 @@ order by n""", id=card.id) oldRow = 0 self.form.fieldList.clear() n = 1 - for field in self.model.fieldModels: - label = field.name + for field in self.model.fields: + label = field['name'] item = QListWidgetItem(label) self.form.fieldList.addItem(item) n += 1 diff --git a/aqt/errors.py b/aqt/errors.py index e34ac35d6..6969aecbe 100644 --- a/aqt/errors.py +++ b/aqt/errors.py @@ -9,6 +9,7 @@ from aqt.utils import showText class ErrorHandler(QObject): "Catch stderr and write into buffer." + ivl = 100 def __init__(self, mw): QObject.__init__(self, mw) @@ -35,11 +36,10 @@ class ErrorHandler(QObject): self.emit(SIGNAL("errorTimer")) def _setTimer(self): - ivl = 200 if not self.timer: self.timer = QTimer(self.mw) self.mw.connect(self.timer, SIGNAL("timeout()"), self.onTimeout) - self.timer.setInterval(200) + self.timer.setInterval(self.ivl) self.timer.setSingleShot(True) self.timer.start() diff --git a/aqt/main.py b/aqt/main.py index e2fec00bd..a964fc35c 100755 --- a/aqt/main.py +++ b/aqt/main.py @@ -655,8 +655,9 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors") aqt.stats.DeckStats(self) def onCardLayout(self): - aqt.clayout.CardLayout(self, 0, self.currentCard.fact, - card=self.currentCard) + from aqt.clayout import CardLayout + CardLayout(self, self.reviewer.card.fact(), type=1, + ord=self.reviewer.card.ord) def onDeckProperties(self): import aqt.deckopts diff --git a/aqt/modelproperties.py b/aqt/modelproperties.py index 6dc826571..d9bc6ba25 100644 --- a/aqt/modelproperties.py +++ b/aqt/modelproperties.py @@ -62,6 +62,18 @@ class ModelProperties(QDialog): self.cardLayout) def cardLayout(self): + # # see if there's an available fact + # id = self.deck.db.scalar( + # "select id from facts where modelId = :id", id=self.model.id) + # if id: + # self.fact = self.deck.db.query(Fact).get(id) + # else: + # # generate a dummy one + # self.fact = self.deck.newFact(self.model) + # for f in self.fact.keys(): + # self.fact[f] = f + + self.m.currentCard = self.currentCard ui.clayout.CardLayout(self, None, self.m) diff --git a/aqt/reviewer.py b/aqt/reviewer.py index f3f71b650..fb0ef4b1a 100644 --- a/aqt/reviewer.py +++ b/aqt/reviewer.py @@ -352,7 +352,6 @@ div#filler { css = self.mw.sharedCSS css += self.mw.deck.allCSS() css += self._css - css = runFilter("addStyles", css) return css # Type in the answer diff --git a/aqt/utils.py b/aqt/utils.py index a21aec569..84f685956 100644 --- a/aqt/utils.py +++ b/aqt/utils.py @@ -267,15 +267,17 @@ def applyStyles(widget): def getBase(deck, card): base = None if deck and card: - if deck.getBool("remoteImages") and card.fact.model.features: - base = card.fact.model.features - elif deck.mediaDir(): - if sys.platform.startswith("win32"): + print "fixme: remote images" + mdir = deck.media.dir() + if False: # deck.getBool("remoteImages") and card.fact.model.features: + pass #base = card.fact.model.features + elif mdir: + if isWin: prefix = u"file:///" else: prefix = u"file://" base = prefix + unicode( - urllib.quote(deck.mediaDir().encode("utf-8")), + urllib.quote(mdir.encode("utf-8")), "utf-8") + "/" if base: return '' % base @@ -294,3 +296,6 @@ def shortcut(key): if sys.platform == "darwin": return re.sub("(?i)ctrl", "Command", key) return key + +isMac = sys.platform.startswith("darwin") +isWin = sys.platform.startswith("win32")