diff --git a/ankiqt/ui/cardlist.py b/ankiqt/ui/cardlist.py
index 7c0069985..e726a86aa 100644
--- a/ankiqt/ui/cardlist.py
+++ b/ankiqt/ui/cardlist.py
@@ -613,11 +613,14 @@ class EditDeck(QMainWindow):
self.dialog.actionRedo.setEnabled(True)
else:
self.dialog.actionRedo.setEnabled(False)
- # update list
- if self.currentRow and self.model.cards:
- self.model.updateCard(self.currentRow)
- if type == "tag":
- self.drawTags()
+ if type=="all":
+ self.updateAfterCardChange()
+ else:
+ # update list
+ if self.currentRow and self.model.cards:
+ self.model.updateCard(self.currentRow)
+ if type == "tag":
+ self.drawTags()
def filterTextChanged(self):
interval = 300
@@ -763,6 +766,7 @@ class EditDeck(QMainWindow):
return
fact = self.currentCard.fact
self.editor.setFact(fact, True)
+ self.editor.card = self.currentCard
self.showCardInfo(self.currentCard)
self.onEvent()
self.updateToggles()
diff --git a/ankiqt/ui/clayout.py b/ankiqt/ui/clayout.py
index 4fe7e0bca..e28095b98 100644
--- a/ankiqt/ui/clayout.py
+++ b/ankiqt/ui/clayout.py
@@ -3,6 +3,7 @@
from PyQt4.QtGui import *
from PyQt4.QtCore import *
+from PyQt4.QtWebKit import QWebPage, QWebView
import sys, re
import ankiqt.forms
import anki
@@ -10,304 +11,250 @@ from anki.models import *
from anki.facts import *
from anki.fonts import toCanonicalFont
from anki.cards import Card
-from ankiqt.ui.utils import saveGeom, restoreGeom
+from anki.sound import playFromText, clearAudioQueue
+from ankiqt.ui.utils import saveGeom, restoreGeom, getBase, mungeQA
+from anki.hooks import runFilter
from ankiqt import ui
class CardLayout(QDialog):
- def __init__(self, parent, fact, card=None):
- QDialog.__init__(self, parent) #, Qt.Window)
- self.parent = parent
+ def __init__(self, factedit, fact, card=None):
+ self.parent = factedit.parent
+ QDialog.__init__(self, self.parent)
+ self.factedit = factedit
self.mw = ankiqt.mw
self.deck = self.mw.deck
self.fact = fact
self.model = fact.model
- self.card = card or self.model.cardModels[0]
+ self.card = card
self.ignoreUpdate = False
+ self.needFormatRebuild = False
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 card
+ self.cards = [self.card]
+ else:
+ # active & possible
+ self.cards = self.deck.previewFact(self.fact)
+ if not self.cards:
+ ui.utils.showInfo(_(
+ "Please enter some text first."),
+ parent=self.parent)
+ return
self.form = ankiqt.forms.clayout.Ui_Dialog()
self.form.setupUi(self)
# self.connect(self.form.helpButton, SIGNAL("clicked()"),
# self.onHelp)
- # self.setupChooser()
self.setupCards()
# self.setupFields()
- # self.setupButtons()
restoreGeom(self, "CardLayout")
self.exec_()
+ # Cards & Preview
+ ##########################################################################
+
def setupCards(self):
self.connect(self.form.cardList, SIGNAL("activated(int)"),
self.cardChanged)
+ 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:\
- self.chooseColour(w))
+ 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)
+ def linkClicked(self, url):
+ QDesktopServices.openUrl(QUrl(url))
+ self.form.preview.page().setLinkDelegationPolicy(
+ QWebPage.DelegateExternalLinks)
+ self.connect(self.form.preview,
+ SIGNAL("linkClicked(QUrl)"),
+ linkClicked)
if self.plastiqueStyle:
self.form.background.setStyle(self.plastiqueStyle)
- self.drawCards()
-
-
- def formatToScreen(self, fmt):
- fmt = fmt.replace("
", "
\n")
- fmt = re.sub("%\((.+?)\)s", "{{\\1}}", fmt)
- return fmt
-
- def screenToFormat(self, fmt):
- fmt = fmt.replace("
\n", "
")
- fmt = re.sub("{{(.+?)}}", "%(\\1)s", fmt)
- return fmt
-
- def saveCurrentCard(self):
- if not self.currentCard:
- return
- card = self.currentCard
- newname = unicode(self.form.cardName.text())
- if not newname:
- newname = _("Card-%d") % (self.model.cardModels.index(card) + 1)
- self.updateField(card, 'name', newname)
- s = unicode(self.form.cardQuestion.toPlainText())
- changed = self.updateField(card, 'qformat', self.screenToFormat(s))
- s = unicode(self.form.cardAnswer.toPlainText())
- changed2 = self.updateField(card, 'aformat', self.screenToFormat(s))
- self.needRebuild = self.needRebuild or changed or changed2
- self.updateField(card, 'questionInAnswer', self.form.questionInAnswer.isChecked())
- self.updateField(card, 'allowEmptyAnswer', self.form.allowEmptyAnswer.isChecked())
- idx = self.form.typeAnswer.currentIndex()
- if not idx:
- self.updateField(card, 'typeAnswer', u"")
- else:
- self.updateField(card, 'typeAnswer', self.fieldNames[idx-1])
- self.ignoreCardUpdate = True
- self.updateCards()
- self.ignoreCardUpdate = False
-
- def updateField(self, obj, field, value):
- if getattr(obj, field) != value:
- setattr(obj, field, value)
- self.model.setModified()
- self.deck.setModified()
- return True
- return False
-
-
-
- def drawCards(self):
- self.form.cardList.clear()
- self.form.cardList.addItems(
- QStringList([c.name for c in self.model.cardModels]))
self.form.alignment.clear()
self.form.alignment.addItems(
QStringList(alignmentLabels().values()))
- self.cardChanged(0)
+ self.fillCardList()
- def cardChanged(self, idx):
- self.card = self.model.cardModels[idx]
- self.readCard()
- self.drawQuestionAndAnswer()
+ def formatToScreen(self, fmt):
+ fmt = re.sub("%\((.+?)\)s", "{{\\1}}", fmt)
+ fmt = fmt.replace("}}
", "}}\n")
+ return fmt
+
+ def screenToFormat(self, fmt):
+ fmt = fmt.replace("}}\n", "}}
")
+ fmt = re.sub("{{(.+?)}}", "%(\\1)s", fmt)
+ return fmt
+
+ # def realCardModel(self, card):
+ # # get on disk representation from detached object
+ # for cm in self.fact.model.cardModels:
+ # if cm.id == card.cardModelId:
+ # return cm
+
+ def formatChanged(self, type):
+ 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)
+ card.question = qa['question']
+ card.answer = qa['answer']
+ card.setModified()
+ self.deck.setModified()
+ self.needFormatRebuild = True
+ self.renderPreview()
+
+ def onFlip(self):
+ q = unicode(self.form.cardQuestion.toPlainText())
+ a = unicode(self.form.cardAnswer.toPlainText())
+ self.form.cardAnswer.setPlainText(q)
+ self.form.cardQuestion.setPlainText(a)
def readCard(self):
- card = self.card
+ 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.typeAnswer.clear()
- self.fieldNames = self.deck.s.column0("""
+ self.typeFieldNames = self.deck.s.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.fieldNames]
+ s += [_("Compare with field '%s'") % f for f in self.typeFieldNames]
self.form.typeAnswer.insertItems(0, QStringList(s))
try:
- idx = self.fieldNames.index(card.typeAnswer)
+ idx = self.typeFieldNames.index(card.typeAnswer)
except ValueError:
idx = -1
self.form.typeAnswer.setCurrentIndex(idx + 1)
+ self.updatingCards = False
+
+ # def updateField(self, obj, field, value):
+ # if getattr(obj, field) != value:
+ # setattr(obj, field, value)
+ # self.model.setModified()
+ # self.deck.setModified()
+ # return True
+ # return False
+
+ def fillCardList(self):
+ self.form.cardList.clear()
+ self.form.cardList.addItems(
+ QStringList([c.cardModel.name for c in self.cards]))
+ if [self.card] == self.cards:
+ self.form.cardList.setEnabled(False)
+ self.form.editTemplates.setEnabled(False)
+ self.cardChanged(0)
+
+ def cardChanged(self, idx):
+ self.card = self.cards[idx]
+ self.readCard()
+ self.renderPreview()
def saveCard(self):
- if not self.card:
+ if self.updatingCards:
return
- self.card.questionAlign = self.form.align.currentIndex()
- setattr(self.card, "lastFontColour", unicode(
- self.form.backgroundColour.palette().window().color().name()))
- self.card.model.setModified()
- self.deck.setModified()
-
- self.drawQuestionAndAnswer()
-
- def cwidget(self, name, type):
- "Return a card widget."
- return getattr(self.form, type + name)
-
- def setupFields(self):
- self.connect(self.form.fieldList, SIGNAL("currentRowChanged(int)"),
- self.fieldChanged)
- for type in ("quiz", "edit"):
- self.connect(self.fwidget("fontFamily", type),
- SIGNAL("currentFontChanged(QFont)"),
- self.saveField)
- self.connect(self.fwidget("fontSize", type),
- SIGNAL("valueChanged(int)"),
- self.saveField)
- self.connect(self.fwidget("useFamily", type),
- SIGNAL("stateChanged(int)"),
- self.saveField)
- self.connect(self.fwidget("useSize", type),
- SIGNAL("stateChanged(int)"),
- self.saveField)
- if type == "quiz":
- self.connect(self.fwidget("useColour", type),
- SIGNAL("stateChanged(int)"),
- self.saveField)
- w = self.fwidget("fontColour", type)
- if self.plastiqueStyle:
- w.setStyle(self.plastiqueStyle)
- self.connect(w,
- SIGNAL("clicked()"),
- lambda w=w: self.chooseColour(w))
- elif type == "edit":
- self.connect(self.form.rtl,
- SIGNAL("stateChanged(int)"),
- self.saveField)
- self.currentField = None
- self.drawFields()
-
- def drawFields(self):
- self.form.fieldList.clear()
- n = 1
- self.ignoreUpdate = True
- for field in self.model.fieldModels:
- item = QListWidgetItem(
- _("Field %(num)d: %(name)s") % {
- 'num': n,
- 'name': field.name,
- })
- self.form.fieldList.addItem(item)
- n += 1
- self.form.fieldList.setCurrentRow(0)
- self.fieldChanged(0)
- self.ignoreUpdate = False
-
- def fwidget(self, name, type):
- "Return a field widget."
- if type == "edit":
- return getattr(self.form, name+"Edit")
+ card = self.card.cardModel
+ card.questionAlign = self.form.alignment.currentIndex()
+ card.lastFontColour = unicode(
+ self.form.background.palette().window().color().name())
+ card.questionInAnswer = self.form.questionInAnswer.isChecked()
+ card.allowEmptyAnswer = self.form.allowEmptyAnswer.isChecked()
+ idx = self.form.typeAnswer.currentIndex()
+ if not idx:
+ card.typeAnswer = u""
else:
- return getattr(self.form, name)
-
- def fieldChanged(self, idx):
- self.saveField()
- self.currentField = None
- field = self.model.fieldModels[idx]
- for type in ("quiz", "edit"):
- # family
- if getattr(field, type + 'FontFamily'):
- self.fwidget("useFamily", type).setCheckState(Qt.Checked)
- self.fwidget("fontFamily", type).setCurrentFont(QFont(
- getattr(field, type + 'FontFamily')))
- self.fwidget("fontFamily", type).setEnabled(True)
- else:
- self.fwidget("useFamily", type).setCheckState(Qt.Unchecked)
- self.fwidget("fontFamily", type).setEnabled(False)
- # size
- if getattr(field, type + 'FontSize'):
- self.fwidget("useSize", type).setCheckState(Qt.Checked)
- self.fwidget("fontSize", type).setValue(
- getattr(field, type + 'FontSize'))
- self.fwidget("fontSize", type).setEnabled(True)
- else:
- self.fwidget("useSize", type).setCheckState(Qt.Unchecked)
- self.fwidget("fontSize", type).setEnabled(False)
- if type == "quiz":
- # colour
- if getattr(field, type + 'FontColour'):
- self.fwidget("useColour", type).setCheckState(Qt.Checked)
- self.fwidget("fontColour", type).setPalette(QPalette(QColor(
- getattr(field, type + 'FontColour'))))
- self.fwidget("fontColour", type).setEnabled(True)
- else:
- self.fwidget("useColour", type).setCheckState(Qt.Unchecked)
- self.fwidget("fontColour", type).setEnabled(False)
- elif type == "edit":
- self.form.rtl.setChecked(not not field.features)
- self.currentField = field
-
- def saveField(self, *args):
- if self.ignoreUpdate:
- return
- field = self.currentField
- if not field:
- return
- for type in ("quiz", "edit"):
- # family
- if self.fwidget("useFamily", type).isChecked():
- setattr(field, type + 'FontFamily', toCanonicalFont(unicode(
- self.fwidget("fontFamily", type).currentFont().family())))
- else:
- setattr(field, type + 'FontFamily', None)
- # size
- if self.fwidget("useSize", type).isChecked():
- setattr(field, type + 'FontSize',
- int(self.fwidget("fontSize", type).value()))
- else:
- setattr(field, type + 'FontSize', None)
- # colour
- if type == "quiz":
- if self.fwidget("useColour", type).isChecked():
- w = self.fwidget("fontColour", type)
- c = w.palette().window().color()
- setattr(field, type + 'FontColour', str(c.name()))
- else:
- setattr(field, type + 'FontColour', None)
- elif type == "edit":
- if self.form.rtl.isChecked():
- field.features = u"rtl"
- else:
- field.features = u""
- field.model.setModified()
+ card.typeAnswer = self.typeFieldNames[idx-1]
+ card.model.setModified()
self.deck.flushMod()
- self.drawQuestionAndAnswer()
+ self.renderPreview()
- def chooseColour(self, button):
+ def chooseColour(self, button, type="field"):
new = QColorDialog.getColor(button.palette().window().color(), self)
if new.isValid():
button.setPalette(QPalette(new))
- self.saveField()
- self.saveCard()
-
- def drawQuestionAndAnswer(self):
- print "draw qa"
- return
- self.deck.flushMod()
- f = self.deck.newFact()
- f.tags = u""
- for field in f.fields:
- f[field.name] = field.name
- f.model = self.model
- c = Card(f, self.card)
- t = "