finish fields dialog

This commit is contained in:
Damien Elmes 2011-11-30 12:36:12 +09:00
parent 4eba9eb913
commit b9522487ad
8 changed files with 152 additions and 602 deletions

View file

@ -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."))

View file

@ -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

View file

@ -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

View file

@ -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("}}<br>", "}}\n")
return fmt
def screenToFormat(self, fmt):
fmt = fmt.replace("}}\n", "}}<br>")
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(
('<html><head>%s</head><body class="%s">' %
(getBase(self.col), c.cssClass())) +
"<style>" + styles + "</style>" +
mungeQA(c.q(reload=True)) +
self.maybeTextInput() +
"<hr>" +
mungeQA(c.a())
+ "</body></html>")
clearAudioQueue()
if c.id not in self.playedAudio:
playFromText(c.q())
playFromText(c.a())
self.playedAudio[c.id] = True
def maybeTextInput(self):
if self.card.template()['typeAns'] is not None:
return "<center><input type=text></center>"
return ""
def reject(self):
self.saveField()
self.mm.save(self.model)
self.mw.reset()
QDialog.reject(self)
def accept(self):
self.reject()
def reject(self):
return QDialog.reject(self)
self.mm.save(self.model)
saveGeom(self, "CardLayout")
saveSplitter(self.form.splitter, "clayout")
self.mw.reset()
return QDialog.reject(self)
modified = False
self.mw.startProgress()
self.col.updateProgress(_("Applying changes..."))
reset=True
if len(self.fieldOrdinalUpdatedIds) > 0:
self.col.rebuildFieldOrdinals(self.model.id, self.fieldOrdinalUpdatedIds)
modified = True
if self.needFieldRebuild:
modified = True
if modified:
self.note.model.setModified()
self.col.flushMod()
if self.noteedit and self.noteedit.onChange:
self.noteedit.onChange("all")
reset=False
if reset:
self.mw.reset()
self.col.finishProgress()
QDialog.reject(self)
def onHelp(self):
openHelp("CardLayout")
# Fields
##########################################################################
def setupFields(self):
self.fieldOrdinalUpdatedIds = []
self.updatingFields = False
self.needFieldRebuild = False
c = self.connect; f = self.form
sc = SIGNAL("stateChanged(int)")
cl = SIGNAL("clicked()")
c(f.fieldAdd, cl, self.addField)
c(f.fieldDelete, cl, self.deleteField)
c(f.fieldUp, cl, self.moveFieldUp)
c(f.fieldDown, cl, self.moveFieldDown)
c(f.preserveWhitespace, sc, self.saveField)
c(f.fieldUnique, sc, self.saveField)
c(f.fieldRequired, sc, self.saveField)
c(f.sticky, sc, self.saveField)
c(f.fieldList, SIGNAL("currentRowChanged(int)"),
self.fieldChanged)
c(f.fieldName, SIGNAL("lostFocus()"),
self.saveField)
c(f.fontFamily, SIGNAL("currentFontChanged(QFont)"),
self.saveField)
c(f.fontSize, SIGNAL("valueChanged(int)"),
self.saveField)
c(f.fontSizeEdit, SIGNAL("valueChanged(int)"),
self.saveField)
w = self.form.fontColour
c(w, SIGNAL("clicked()"),
lambda w=w: self.chooseColour(w))
c(self.form.rtl,
SIGNAL("stateChanged(int)"),
self.saveField)
def fieldChanged(self):
row = self.form.fieldList.currentRow()
if row == -1:
row = 0
self.field = self.model['flds'][row]
self.readField()
self.enableFieldMoveButtons()
def readField(self):
fld = self.field
f = self.form
self.updatingFields = True
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'])
f.sticky.setChecked(fld['sticky'])
self.updatingFields = False
def saveField(self, *args):
self.needFieldRebuild = True
if self.updatingFields:
return
self.updatingFields = True
fld = self.field
# get name; we'll handle it last
name = unicode(self.form.fieldName.text())
if not name:
return
fld['uniq'] = self.form.fieldUnique.isChecked()
fld['req'] = self.form.fieldRequired.isChecked()
fld['font'] = unicode(
self.form.fontFamily.currentFont().family())
fld['qsize'] = self.form.fontSize.value()
fld['esize'] = self.form.fontSizeEdit.value()
fld['qcol'] = str(
self.form.fontColour.palette().window().color().name())
fld['rtl'] = self.form.rtl.isChecked()
fld['pre'] = self.form.preserveWhitespace.isChecked()
fld['sticky'] = self.form.sticky.isChecked()
self.updatingFields = False
if fld['name'] != name:
self.mm.renameField(self.model, fld, name)
# as the field name has changed, we have to regenerate cards
self.cards = self.col.previewCards(self.note, self.type)
self.cardChanged(0)
self.renderPreview()
self.fillFieldList()
def fillFieldList(self, row = None):
oldRow = self.form.fieldList.currentRow()
if oldRow == -1:
oldRow = 0
self.form.fieldList.clear()
n = 1
for field in self.model['flds']:
label = field['name']
item = QListWidgetItem(label)
self.form.fieldList.addItem(item)
n += 1
count = self.form.fieldList.count()
if row != None:
self.form.fieldList.setCurrentRow(row)
else:
while (count > 0 and oldRow > (count - 1)):
oldRow -= 1
self.form.fieldList.setCurrentRow(oldRow)
self.enableFieldMoveButtons()
def enableFieldMoveButtons(self):
row = self.form.fieldList.currentRow()
if row < 1:
self.form.fieldUp.setEnabled(False)
else:
self.form.fieldUp.setEnabled(True)
if row == -1 or row >= (self.form.fieldList.count() - 1):
self.form.fieldDown.setEnabled(False)
else:
self.form.fieldDown.setEnabled(True)
def addField(self):
f = self.mm.newField(self.model)
l = len(self.model['flds'])
f['name'] = _("Field %d") % l
self.mw.progress.start()
self.mm.addField(self.model, f)
self.mw.progress.finish()
self.reload()
self.form.fieldList.setCurrentRow(l)
self.form.fieldName.setFocus()
self.form.fieldName.selectAll()
def deleteField(self):
row = self.form.fieldList.currentRow()
if row == -1:
return
if len(self.model.fields) < 2:
showInfo(_("Please add a new field first."))
return
if askUser(_("Delete this field and its data from all notes?")):
self.mw.progress.start()
self.model.delField(self.field)
self.mw.progress.finish()
# need to update q/a format
self.reload()
def moveFieldUp(self):
row = self.form.fieldList.currentRow()
if row == -1:
return
if row == 0:
return
self.mw.progress.start()
self.model.moveField(self.field, row-1)
self.mw.progress.finish()
self.form.fieldList.setCurrentRow(row-1)
self.reload()
def moveFieldDown(self):
row = self.form.fieldList.currentRow()
if row == -1:
return
if row == len(self.model.fields) - 1:
return
self.mw.progress.start()
self.model.moveField(self.field, row+1)
self.mw.progress.finish()
self.form.fieldList.setCurrentRow(row+1)
self.reload()
openHelp("Fields")

View file

@ -193,6 +193,7 @@ Are you sure?"""):
# then load collection and launch into the deck browser
print "fixme: safeguard against multiple instances"
self.col = Collection(self.pm.collectionPath())
self.progress.setupDB(self.col.db)
# skip the reset step; open overview directly
self.moveToState("review")
@ -212,8 +213,6 @@ Are you sure?"""):
getattr(self, "_"+state+"State")(oldState, *args)
def _deckBrowserState(self, oldState):
self.disableDeckMenuItems()
self.closeAllWindows()
self.deckBrowser.show()
def _colLoadingState(self, oldState):
@ -429,27 +428,33 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
else:
aw.close()
def close(self, showBrowser=True):
"Close current deck."
def close(self):
"Close and backup collection."
if not self.col:
return
# if we were cramming, restore the standard scheduler
if self.col.stdSched():
self.col.reset()
runHook("deckClosing")
print "focusOut() should be handled with deckClosing now"
#self.col.close()
self.backup()
self.closeAllWindows()
self.col.close()
self.col = None
if showBrowser:
self.moveToState("deckBrowser")
# Syncing
##########################################################################
def backup(self):
print "backup"
# Syncing
##########################################################################
def onSync(self):
return
return showInfo("sync not yet implemented")
from aqt.sync import Syncer
# close collection if loaded
if self.col:
self.col.close()
#
Syncer()
# Tools
##########################################################################
@ -484,11 +489,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
def closeEvent(self, event):
"User hit the X button, etc."
print "fixme: exit from edit current, review, etc"
if self.state == "editCurrentNote":
event.ignore()
return self.moveToState("saveEdit")
self.close(showBrowser=False)
self.close()
# if self.pm.profile['syncOnProgramOpen']:
# self.showBrowser = False
# self.syncDeck(interactive=False)
@ -857,118 +858,9 @@ Please choose a new deck name:"""))
def onSchemaMod(self, arg):
return askUser(_("""\
This operation can't be merged when syncing, so the next \
sync will overwrite any changes made on other devices that \
haven't been synced here yet. Continue?"""))
# Media locations
##########################################################################
# def setupMedia(self, deck):
# print "setup media"
# return
# prefix = self.pm.profile['mediaLocation']
# prev = deck.getVar("mediaLocation") or ""
# # set the media prefix
# if not prefix:
# next = ""
# elif prefix == "dropbox":
# p = self.dropboxFolder()
# next = os.path.join(p, "Public", "Anki")
# else:
# next = prefix
# # check if the media has moved
# migrateFrom = None
# if prev != next:
# # check if they were using plugin
# if not prev:
# p = self.dropboxFolder()
# p = os.path.join(p, "Public")
# deck.mediaPrefix = p
# migrateFrom = deck.mediaDir()
# if not migrateFrom:
# # find the old location
# deck.mediaPrefix = prev
# dir = deck.mediaDir()
# if dir and os.listdir(dir):
# # it contains files; we'll need to migrate
# migrateFrom = dir
# # setup new folder
# deck.mediaPrefix = next
# if migrateFrom:
# # force creation of new folder
# dir = deck.mediaDir(create=True)
# # migrate old files
# self.migrateMedia(migrateFrom, dir)
# else:
# # chdir if dir exists
# dir = deck.mediaDir()
# # update location
# deck.setVar("mediaLocation", next, mod=False)
# if dir and prefix == "dropbox":
# self.setupDropbox(deck)
# def migrateMedia(self, from_, to):
# if from_ == to:
# return
# files = os.listdir(from_)
# skipped = False
# for f in files:
# src = os.path.join(from_, f)
# dst = os.path.join(to, f)
# if not os.path.isfile(src):
# skipped = True
# continue
# if not os.path.exists(dst):
# shutil.copy2(src, dst)
# if not skipped:
# # everything copied, we can remove old folder
# shutil.rmtree(from_, ignore_errors=True)
# def dropboxFolder(self):
# try:
# import aqt.dropbox as db
# p = db.getPath()
# except:
# if isWin:
# s = QSettings(QSettings.UserScope, "Microsoft", "Windows")
# s.beginGroup("CurrentVersion/Explorer/Shell Folders")
# p = os.path.join(s.value("Personal"), "My Dropbox")
# else:
# p = os.path.expanduser("~/Dropbox")
# return p
# def setupDropbox(self, deck):
# if not self.pm.profile['dropboxPublicFolder']:
# # put a file in the folder
# open(os.path.join(
# deck.mediaPrefix, "right-click-me.txt"), "w").write("")
# # tell user what to do
# showInfo(_("""\
# A file called right-click-me.txt has been placed in DropBox's public folder. \
# After clicking OK, this folder will appear. Please right click on the file (\
# command+click on a Mac), choose DropBox>Copy Public Link, and paste the \
# link into Anki."""))
# # open folder and text prompt
# self.onOpenPluginFolder(deck.mediaPrefix)
# txt = getText(_("Paste path here:"), parent=self)
# if txt[0]:
# fail = False
# if not txt[0].lower().startswith("http"):
# fail = True
# if not txt[0].lower().endswith("right-click-me.txt"):
# fail = True
# if fail:
# showInfo(_("""\
# That doesn't appear to be a public link. You'll be asked again when the deck \
# is next loaded."""))
# else:
# self.pm.profile['dropboxPublicFolder'] = os.path.dirname(txt[0])
# if self.pm.profile['dropboxPublicFolder']:
# # update media url
# deck.setVar(
# "mediaURL", self.pm.profile['dropboxPublicFolder'] + "/" +
# os.path.basename(deck.mediaDir()) + "/")
This operation can't be merged when syncing, so if you have made \
changes on other devices that haven't been synced to this device yet, \
they will be lost. Are you sure you want to continue?"""))
# Advanced features
##########################################################################

View file

@ -25,10 +25,10 @@ class ProgressManager(object):
##########################################################################
def setupDB(self, db):
"Install a handler in the current deck."
"Install a handler in the current DB."
self.lastDbProgress = 0
self.inDB = False
db.set_progress_handler(self._dbProgress, 100000)
db.set_progress_handler(self._dbProgress, 10000)
def _dbProgress(self):
"Called from SQLite."

View file

@ -5,15 +5,14 @@ from aqt.qt import *
import os, types, socket, time, traceback
import aqt
import anki
from anki.sync import SyncClient, HttpSyncServerProxy, copyLocalMedia
from anki.sync import SYNC_HOST, SYNC_PORT
#from anki.sync import SyncClient, HttpSyncServerProxy, copyLocalMedia from
#anki.sync import SYNC_HOST, SYNC_PORT
from anki.errors import *
from anki import Deck
from anki.db import sqlite
import aqt.forms
from anki.hooks import addHook, removeHook
class SyncManager(object):
class Syncer(object):
# Syncing
##########################################################################

View file

@ -6,13 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<width>412</width>
<height>352</height>
</rect>
</property>
<property name="windowTitle">
<string>Fields</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
@ -37,62 +40,28 @@
<item>
<widget class="QPushButton" name="fieldAdd">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
<property name="autoDefault">
<bool>false</bool>
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="fieldDelete">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/editdelete.png</normaloff>:/icons/editdelete.png</iconset>
</property>
<property name="autoDefault">
<bool>false</bool>
<string>Delete</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="fieldUp">
<property name="toolTip">
<string>Move selected field up</string>
</property>
<widget class="QPushButton" name="fieldRename">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/arrow-up.png</normaloff>:/icons/arrow-up.png</iconset>
</property>
<property name="autoDefault">
<bool>false</bool>
<string>Rename</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="fieldDown">
<property name="toolTip">
<string>Move selected field down</string>
</property>
<widget class="QPushButton" name="fieldPosition">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/arrow-down.png</normaloff>:/icons/arrow-down.png</iconset>
</property>
<property name="autoDefault">
<bool>false</bool>
<string>Reposition</string>
</property>
</widget>
</item>
@ -115,27 +84,14 @@
</item>
<item>
<layout class="QGridLayout" name="_2">
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="fieldName"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Name</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Editing Font</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="0" column="1">
<widget class="QFontComboBox" name="fontFamily">
<property name="minimumSize">
<size>
@ -145,14 +101,14 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="3" column="1">
<widget class="QCheckBox" name="rtl">
<property name="text">
<string>Reverse text direction (RTL)</string>
</property>
</widget>
</item>
<item row="1" column="2">
<item row="0" column="2">
<widget class="QSpinBox" name="fontSize">
<property name="minimum">
<number>5</number>
@ -162,21 +118,21 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1">
<widget class="QCheckBox" name="sticky">
<property name="text">
<string>Remember last input</string>
<string>Remember last input when adding</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="1" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>Options</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="1" column="1">
<widget class="QRadioButton" name="sortField">
<property name="text">
<string>Sort by this field in the browser</string>
@ -201,11 +157,11 @@
<tabstop>fieldList</tabstop>
<tabstop>fieldAdd</tabstop>
<tabstop>fieldDelete</tabstop>
<tabstop>fieldUp</tabstop>
<tabstop>fieldDown</tabstop>
<tabstop>fieldName</tabstop>
<tabstop>fieldRename</tabstop>
<tabstop>fieldPosition</tabstop>
<tabstop>fontFamily</tabstop>
<tabstop>fontSize</tabstop>
<tabstop>sortField</tabstop>
<tabstop>sticky</tabstop>
<tabstop>rtl</tabstop>
<tabstop>buttonBox</tabstop>