diff --git a/aqt/browser.py b/aqt/browser.py
index c9c8002ca..281668a9b 100644
--- a/aqt/browser.py
+++ b/aqt/browser.py
@@ -299,7 +299,7 @@ class StatusDelegate(QItemDelegate):
class Browser(QMainWindow):
def __init__(self, mw):
- QMainWindow.__init__(self, None)
+ QMainWindow.__init__(self, mw)
#applyStyles(self)
self.mw = mw
self.col = self.mw.col
@@ -491,8 +491,8 @@ class Browser(QMainWindow):
self.onRowChanged)
def setupEditor(self):
- self.editor = aqt.editor.Editor(self.mw,
- self.form.fieldsArea)
+ self.editor = aqt.editor.Editor(
+ self.mw, self.form.fieldsArea, self)
self.editor.stealFocus = False
def onRowChanged(self, current, previous):
@@ -534,7 +534,7 @@ class Browser(QMainWindow):
def onSortChanged(self, idx, ord):
type = self.model.activeCols[idx]
- noSort = ("question", "answer", "template", "cardGroup", "noteGroup")
+ noSort = ("question", "answer", "template", "deck", "ndeck")
if type in noSort:
showInfo(_("Sorting on this column is not supported. Please "
"choose another."))
diff --git a/aqt/clayout.py b/aqt/clayout.py
index b207eb662..af5e0a48e 100644
--- a/aqt/clayout.py
+++ b/aqt/clayout.py
@@ -191,7 +191,7 @@ Please create a new card first."""))
n = len(self.cards)
cur = self.card.template()['ord']+1
pos = getOnlyText(
- _("Enter new card position (1..%s):") % n,
+ _("Enter new card position (1...%s):") % n,
default=str(cur))
if not pos:
return
diff --git a/aqt/editor.py b/aqt/editor.py
index 4caf0f2be..8f9665952 100644
--- a/aqt/editor.py
+++ b/aqt/editor.py
@@ -192,9 +192,10 @@ $(function () {
# caller is responsible for resetting note on reset
class Editor(object):
- def __init__(self, mw, widget, addMode=False):
- self.widget = widget
+ def __init__(self, mw, widget, parentWindow, addMode=False):
self.mw = mw
+ self.widget = widget
+ self.parentWindow = parentWindow
self.note = None
self.stealFocus = True
self.addMode = addMode
@@ -233,7 +234,7 @@ class Editor(object):
######################################################################
def _addButton(self, name, func, key=None, tip=None, size=True, text="",
- check=False):
+ check=False, native=False):
b = QPushButton(text)
if check:
b.connect(b, SIGNAL("clicked(bool)"), func)
@@ -242,7 +243,8 @@ class Editor(object):
if size:
b.setFixedHeight(20)
b.setFixedWidth(20)
- b.setStyle(self.plastiqueStyle)
+ if not native:
+ b.setStyle(self.plastiqueStyle)
b.setFocusPolicy(Qt.NoFocus)
if not text:
b.setIcon(QIcon(":/icons/%s.png" % name))
@@ -266,13 +268,15 @@ class Editor(object):
self.iconsBox.setMargin(0)
self.iconsBox.setSpacing(0)
self.outerLayout.addLayout(self.iconsBox)
- # align to right
- self.iconsBox.addItem(QSpacerItem(20,1, QSizePolicy.Expanding))
b = self._addButton
b("fields", self.onFields, "Ctrl+f",
- shortcut(_("Layout (Ctrl+f)")), size=False, text=_("Fields"))
+ shortcut(_("Layout (Ctrl+f)")), size=False, text=_("Fields..."),
+ native=True)
b("layout", self.onCardLayout, "Ctrl+l",
- shortcut(_("Layout (Ctrl+l)")), size=False, text=_("Layout"))
+ shortcut(_("Layout (Ctrl+l)")), size=False, text=_("Layout..."),
+ native=True)
+ # align to right
+ self.iconsBox.addItem(QSpacerItem(20,1, QSizePolicy.Expanding))
b("text_bold", self.toggleBold, "Ctrl+b", _("Bold text (Ctrl+b)"),
check=True)
b("text_italic", self.toggleItalic, "Ctrl+i", _("Italic text (Ctrl+i)"),
@@ -311,7 +315,7 @@ class Editor(object):
def onFields(self):
from aqt.fields import FieldDialog
self.saveNow()
- FieldDialog(self.mw, self.note, parent=self.widget)
+ FieldDialog(self.mw, self.note, parent=self.parentWindow)
def onCardLayout(self):
from aqt.clayout import CardLayout
@@ -320,7 +324,7 @@ class Editor(object):
ord = self.card.ord
else:
ord = 0
- CardLayout(self.mw, self.note, ord=ord, parent=self.widget)
+ CardLayout(self.mw, self.note, ord=ord, parent=self.parentWindow)
self.loadNote()
# JS->Python bridge
diff --git a/aqt/fields.py b/aqt/fields.py
index 7a19858f1..064d840a7 100644
--- a/aqt/fields.py
+++ b/aqt/fields.py
@@ -5,29 +5,25 @@ from aqt.qt import *
import re
from anki.consts import *
import aqt
-from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA, \
- saveSplitter, restoreSplitter, showInfo, askUser, getText, \
- openHelp
-from anki.utils import isMac, isWin
-
-# raise Exception("Remember to disallow media&latex refs in edit.")
-
-# need to strip the field management code out of this
+from aqt.utils import showWarning, openHelp, getOnlyText
class FieldDialog(QDialog):
def __init__(self, mw, note, ord=0, parent=None):
- QDialog.__init__(self, parent or mw, Qt.Window)
+ QDialog.__init__(self, parent or mw) #, Qt.Window)
self.mw = aqt.mw
self.parent = parent or mw
self.note = note
self.col = self.mw.col
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)
self.form.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False)
+ self.currentIdx = None
self.fillFields()
self.setupSignals()
self.form.fieldList.setCurrentRow(0)
@@ -36,6 +32,7 @@ class FieldDialog(QDialog):
##########################################################################
def fillFields(self):
+ self.currentIdx = None
self.form.fieldList.clear()
for f in self.model['flds']:
self.form.fieldList.addItem(f['name'])
@@ -47,24 +44,80 @@ class FieldDialog(QDialog):
c(f.fieldList, s("currentRowChanged(int)"), self.onRowChange)
c(f.fieldAdd, s("clicked()"), self.onAdd)
c(f.fieldDelete, s("clicked()"), self.onDelete)
- c(f.fieldUp, s("clicked()"), self.onUp)
- c(f.fieldDown, s("clicked()"), self.onDown)
+ c(f.fieldRename, s("clicked()"), self.onRename)
+ c(f.fieldPosition, s("clicked()"), self.onPosition)
c(f.sortField, s("clicked()"), self.onSortField)
+ c(f.buttonBox, s("helpRequested()"), self.onHelp)
def onRowChange(self, idx):
+ if idx == -1:
+ return
+ self.saveField()
self.loadField(idx)
+ def _uniqueName(self, prompt, ignoreOrd=None):
+ txt = getOnlyText(prompt)
+ if not txt:
+ return
+ for f in self.model['flds']:
+ if ignoreOrd is not None and f['ord'] == ignoreOrd:
+ continue
+ if f['name'] == txt:
+ showWarning(_("That field name is already used."))
+ return
+ return txt
+
+ def onRename(self):
+ name = self._uniqueName(_("New name:"), self.currentIdx)
+ if not name:
+ return
+ idx = self.currentIdx
+ f = self.model['flds'][idx]
+ self.mm.renameField(self.model, f, name)
+ self.saveField()
+ self.fillFields()
+ self.form.fieldList.setCurrentRow(idx)
+
def onAdd(self):
- pass
+ name = self._uniqueName(_("Field name:"))
+ if not name:
+ return
+ self.saveField()
+ self.mw.progress.start()
+ f = self.mm.newField(name)
+ self.mm.addField(self.model, f)
+ self.mw.progress.finish()
+ self.fillFields()
+ self.form.fieldList.setCurrentRow(len(self.model['flds'])-1)
def onDelete(self):
- pass
+ if len(self.model['flds']) < 3:
+ return showWarning(_("Notes require at least two fields."))
+ f = self.model['flds'][self.form.fieldList.currentRow()]
+ self.mw.progress.start()
+ self.mm.remField(self.model, f)
+ self.mw.progress.finish()
+ self.fillFields()
+ self.form.fieldList.setCurrentRow(0)
- def onUp(self):
- pass
-
- def onDown(self):
- pass
+ def onPosition(self, delta=-1):
+ l = len(self.model['flds'])
+ txt = getOnlyText(_("New position (1...%d):") % l)
+ if not txt:
+ return
+ try:
+ pos = int(txt)
+ except ValueError:
+ return
+ if not 0 < pos <= l:
+ return
+ self.saveField()
+ f = self.model['flds'][self.currentIdx]
+ self.mw.progress.start()
+ self.mm.moveField(self.model, f, pos-1)
+ self.mw.progress.finish()
+ self.fillFields()
+ self.form.fieldList.setCurrentRow(pos-1)
def onSortField(self):
# don't allow user to disable; it makes no sense
@@ -72,389 +125,35 @@ class FieldDialog(QDialog):
self.model['sortf'] = self.form.fieldList.currentRow()
def loadField(self, idx):
+ self.currentIdx = idx
fld = self.model['flds'][idx]
f = self.form
- f.fieldName.setText(fld['name'])
f.fontFamily.setCurrentFont(QFont(fld['font']))
f.fontSize.setValue(fld['size'])
f.sticky.setChecked(fld['sticky'])
- print self.model['sortf'] == fld['ord']
f.sortField.setChecked(self.model['sortf'] == fld['ord'])
f.rtl.setChecked(fld['rtl'])
- # Cards & Preview
- ##########################################################################
-
- def setupCards(self):
- self.updatingCards = False
- self.playedAudio = {}
- f = self.form
- if self.type == 0:
- f.templateType.setText(
- _("Templates that will be created:"))
- elif self.type == 1:
- f.templateType.setText(
- _("Templates used by note:"))
- else:
- f.templateType.setText(
- _("All templates:"))
- # replace with more appropriate size hints
- for e in ("cardQuestion", "cardAnswer"):
- 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(f, e, w)
- f.templateLayout.addWidget(w, r[0], r[1])
- c = self.connect
- c(f.cardList, SIGNAL("activated(int)"), self.cardChanged)
- c(f.editTemplates, SIGNAL("clicked()"), self.onEdit)
- 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"))
- 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)
- c(f.clozectx, SIGNAL("clicked()"), self.saveCard)
- def linkClicked(url):
- QDesktopServices.openUrl(QUrl(url))
- f.preview.page().setLinkDelegationPolicy(
- QWebPage.DelegateExternalLinks)
- self.connect(f.preview,
- SIGNAL("linkClicked(QUrl)"),
- linkClicked)
- f.alignment.addItems(alignmentLabels().values())
- self.typeFieldNames = self.mm.fieldMap(self.model)
- 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, s)
-
- def formatToScreen(self, fmt):
- fmt = fmt.replace("}}
", "}}\n")
- return fmt
-
- def screenToFormat(self, fmt):
- fmt = fmt.replace("}}\n", "}}
")
- return fmt
-
- def onEdit(self):
- aqt.templates.Templates(self.mw, self.model, self)
- self.reload()
-
- def formatChanged(self):
- if self.updatingCards:
+ def saveField(self):
+ # not initialized yet?
+ if self.currentIdx is None:
return
- 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):
- 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):
- self.updatingCards = True
- t = self.card.template()
+ idx = self.currentIdx
+ fld = self.model['flds'][idx]
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)
- # model-level, but there's nowhere else to put this
- f.clozectx.setChecked(self.model['clozectx'])
- self.updatingCards = False
+ fld['font'] = f.fontFamily.currentFont().family()
+ fld['size'] = f.fontSize.value()
+ fld['sticky'] = f.sticky.isChecked()
+ fld['rtl'] = f.rtl.isChecked()
- def fillCardList(self):
- self.form.cardList.clear()
- cards = []
- idx = 0
- for n, c in enumerate(self.cards):
- if c.ord == self.ord:
- cards.append(_("%s (current)") % c.template()['name'])
- idx = n
- else:
- cards.append(c.template()['name'])
- self.form.cardList.addItems(cards)
- self.form.cardList.setCurrentIndex(idx)
- self.cardChanged(idx)
- self.form.cardList.setFocus()
-
- def cardChanged(self, idx):
- self.card = self.cards[idx]
- self.readCard()
- self.renderPreview()
-
- def saveCard(self):
- if self.updatingCards:
- return
- t = self.card.template()
- t['align'] = self.form.alignment.currentIndex()
- t['bg'] = unicode(
- self.form.background.palette().window().color().name())
- t['hideQ'] = self.form.questionInAnswer.isChecked()
- t['emptyAns'] = self.form.allowEmptyAnswer.isChecked()
- idx = self.form.typeAnswer.currentIndex()
- if not idx:
- t['typeAns'] = None
- else:
- t['typeAns'] = idx-1
- self.model['clozectx'] = self.form.clozectx.isChecked()
- self.renderPreview()
-
- def chooseColour(self, button, type="field"):
- new = QColorDialog.getColor(button.palette().window().color(), self,
- _("Choose Color"),
- QColorDialog.DontUseNativeDialog)
- if new.isValid():
- button.setPalette(QPalette(new))
- if type == "field":
- self.saveField()
- else:
- self.saveCard()
-
- def renderPreview(self):
- c = self.card
- styles = self.model['css']
- styles += "\n.cloze { font-weight: bold; color: blue; }"
- self.form.preview.setHtml(
- ('