mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
Merge branch 'master' of github.com:dae/anki
This commit is contained in:
commit
1933779fa6
18 changed files with 125 additions and 41 deletions
|
@ -262,9 +262,14 @@ class DeckManager(object):
|
||||||
self.rename(draggedDeck, ontoDeckName + "::" + self._basename(draggedDeckName))
|
self.rename(draggedDeck, ontoDeckName + "::" + self._basename(draggedDeckName))
|
||||||
|
|
||||||
def _canDragAndDrop(self, draggedDeckName, ontoDeckName):
|
def _canDragAndDrop(self, draggedDeckName, ontoDeckName):
|
||||||
return draggedDeckName <> ontoDeckName \
|
if draggedDeckName == ontoDeckName \
|
||||||
and not self._isParent(ontoDeckName, draggedDeckName) \
|
or self._isParent(ontoDeckName, draggedDeckName) \
|
||||||
and not self._isAncestor(draggedDeckName, ontoDeckName)
|
or self._isAncestor(draggedDeckName, ontoDeckName):
|
||||||
|
return False
|
||||||
|
elif self.byName(ontoDeckName)['dyn']:
|
||||||
|
raise DeckRenameError(_("A filtered deck cannot have subdecks."))
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def _isParent(self, parentDeckName, childDeckName):
|
def _isParent(self, parentDeckName, childDeckName):
|
||||||
return self._path(childDeckName) == self._path(parentDeckName) + [ self._basename(childDeckName) ]
|
return self._path(childDeckName) == self._path(parentDeckName) + [ self._basename(childDeckName) ]
|
||||||
|
|
|
@ -132,6 +132,6 @@ class TextImporter(NoteImporter):
|
||||||
|
|
||||||
def noteFromFields(self, fields):
|
def noteFromFields(self, fields):
|
||||||
note = ForeignNote()
|
note = ForeignNote()
|
||||||
note.fields.extend([x.strip().replace("\n", "<br>") for x in fields])
|
note.fields.extend([x for x in fields])
|
||||||
note.tags.extend(self.tagsToAdd)
|
note.tags.extend(self.tagsToAdd)
|
||||||
return note
|
return note
|
||||||
|
|
|
@ -117,10 +117,13 @@ class NoteImporter(Importer):
|
||||||
self._ids = []
|
self._ids = []
|
||||||
self._cards = []
|
self._cards = []
|
||||||
self._emptyNotes = False
|
self._emptyNotes = False
|
||||||
|
dupeCount = 0
|
||||||
|
dupes = []
|
||||||
for n in notes:
|
for n in notes:
|
||||||
if not self.allowHTML:
|
for c in range(len(n.fields)):
|
||||||
for c in range(len(n.fields)):
|
if not self.allowHTML:
|
||||||
n.fields[c] = cgi.escape(n.fields[c])
|
n.fields[c] = cgi.escape(n.fields[c])
|
||||||
|
n.fields[c] = n.fields[c].strip().replace("\n", "<br>")
|
||||||
fld0 = n.fields[fld0idx]
|
fld0 = n.fields[fld0idx]
|
||||||
csum = fieldChecksum(fld0)
|
csum = fieldChecksum(fld0)
|
||||||
# first field must exist
|
# first field must exist
|
||||||
|
@ -151,11 +154,18 @@ class NoteImporter(Importer):
|
||||||
if data:
|
if data:
|
||||||
updates.append(data)
|
updates.append(data)
|
||||||
updateLog.append(updateLogTxt % fld0)
|
updateLog.append(updateLogTxt % fld0)
|
||||||
|
dupeCount += 1
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
|
elif self.importMode == 1:
|
||||||
|
dupeCount += 1
|
||||||
elif self.importMode == 2:
|
elif self.importMode == 2:
|
||||||
# allow duplicates in this case
|
# allow duplicates in this case
|
||||||
updateLog.append(dupeLogTxt % fld0)
|
if fld0 not in dupes:
|
||||||
|
# only show message once, no matter how many
|
||||||
|
# duplicates are in the collection already
|
||||||
|
updateLog.append(dupeLogTxt % fld0)
|
||||||
|
dupes.append(fld0)
|
||||||
found = False
|
found = False
|
||||||
# newly add
|
# newly add
|
||||||
if not found:
|
if not found:
|
||||||
|
@ -183,9 +193,19 @@ class NoteImporter(Importer):
|
||||||
self.col.sched.randomizeCards(did)
|
self.col.sched.randomizeCards(did)
|
||||||
else:
|
else:
|
||||||
self.col.sched.orderCards(did)
|
self.col.sched.orderCards(did)
|
||||||
|
|
||||||
part1 = ngettext("%d note added", "%d notes added", len(new)) % len(new)
|
part1 = ngettext("%d note added", "%d notes added", len(new)) % len(new)
|
||||||
part2 = ngettext("%d note updated", "%d notes updated", self.updateCount) % self.updateCount
|
part2 = ngettext("%d note updated", "%d notes updated",
|
||||||
self.log.append("%s, %s." % (part1, part2))
|
self.updateCount) % self.updateCount
|
||||||
|
if self.importMode == 0:
|
||||||
|
unchanged = dupeCount - self.updateCount
|
||||||
|
elif self.importMode == 1:
|
||||||
|
unchanged = dupeCount
|
||||||
|
else:
|
||||||
|
unchanged = 0
|
||||||
|
part3 = ngettext("%d note unchanged", "%d notes unchanged",
|
||||||
|
unchanged) % unchanged
|
||||||
|
self.log.append("%s, %s, %s." % (part1, part2, part3))
|
||||||
self.log.extend(updateLog)
|
self.log.extend(updateLog)
|
||||||
if self._emptyNotes:
|
if self._emptyNotes:
|
||||||
self.log.append(_("""\
|
self.log.append(_("""\
|
||||||
|
@ -213,7 +233,6 @@ content in the text file to the correct fields."""))
|
||||||
"insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)",
|
"insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)",
|
||||||
rows)
|
rows)
|
||||||
|
|
||||||
# need to document that deck is ignored in this case
|
|
||||||
def updateData(self, n, id, sflds):
|
def updateData(self, n, id, sflds):
|
||||||
self._ids.append(id)
|
self._ids.append(id)
|
||||||
if not self.processFields(n, sflds):
|
if not self.processFields(n, sflds):
|
||||||
|
|
|
@ -655,7 +655,7 @@ group by hour having count() > 30 order by hour""" % lim,
|
||||||
(_("Mature"), colMature),
|
(_("Mature"), colMature),
|
||||||
(_("Young+Learn"), colYoung),
|
(_("Young+Learn"), colYoung),
|
||||||
(_("Unseen"), colUnseen),
|
(_("Unseen"), colUnseen),
|
||||||
(_("Suspended"), colSusp))):
|
(_("Suspended+Buried"), colSusp))):
|
||||||
d.append(dict(data=div[c], label="%s: %s" % (t, div[c]), color=col))
|
d.append(dict(data=div[c], label="%s: %s" % (t, div[c]), color=col))
|
||||||
# text data
|
# text data
|
||||||
i = []
|
i = []
|
||||||
|
|
|
@ -6,7 +6,7 @@ import sys, os, traceback
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.utils import showInfo, openFolder, isWin, openLink, \
|
from aqt.utils import showInfo, openFolder, isWin, openLink, \
|
||||||
askUser
|
askUser, restoreGeom, saveGeom
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
import aqt
|
import aqt
|
||||||
|
@ -141,7 +141,9 @@ class GetAddons(QDialog):
|
||||||
b = self.form.buttonBox.addButton(
|
b = self.form.buttonBox.addButton(
|
||||||
_("Browse"), QDialogButtonBox.ActionRole)
|
_("Browse"), QDialogButtonBox.ActionRole)
|
||||||
self.connect(b, SIGNAL("clicked()"), self.onBrowse)
|
self.connect(b, SIGNAL("clicked()"), self.onBrowse)
|
||||||
|
restoreGeom(self, "getaddons", adjustSize=True)
|
||||||
self.exec_()
|
self.exec_()
|
||||||
|
saveGeom(self, "getaddons")
|
||||||
|
|
||||||
def onBrowse(self):
|
def onBrowse(self):
|
||||||
openLink(aqt.appShared + "addons/")
|
openLink(aqt.appShared + "addons/")
|
||||||
|
|
|
@ -1015,6 +1015,10 @@ where id in %s""" % ids2str(sf))
|
||||||
self._previewWeb = AnkiWebView(True)
|
self._previewWeb = AnkiWebView(True)
|
||||||
vbox.addWidget(self._previewWeb)
|
vbox.addWidget(self._previewWeb)
|
||||||
bbox = QDialogButtonBox()
|
bbox = QDialogButtonBox()
|
||||||
|
self._previewReplay = bbox.addButton(_("Replay Audio"), QDialogButtonBox.ActionRole)
|
||||||
|
self._previewReplay.setAutoDefault(False)
|
||||||
|
self._previewReplay.setShortcut(QKeySequence("R"))
|
||||||
|
self._previewReplay.setToolTip(_("Shortcut key: %s" % "R"))
|
||||||
self._previewPrev = bbox.addButton("<", QDialogButtonBox.ActionRole)
|
self._previewPrev = bbox.addButton("<", QDialogButtonBox.ActionRole)
|
||||||
self._previewPrev.setAutoDefault(False)
|
self._previewPrev.setAutoDefault(False)
|
||||||
self._previewPrev.setShortcut(QKeySequence("Left"))
|
self._previewPrev.setShortcut(QKeySequence("Left"))
|
||||||
|
@ -1023,6 +1027,7 @@ where id in %s""" % ids2str(sf))
|
||||||
self._previewNext.setShortcut(QKeySequence("Right"))
|
self._previewNext.setShortcut(QKeySequence("Right"))
|
||||||
c(self._previewPrev, SIGNAL("clicked()"), self._onPreviewPrev)
|
c(self._previewPrev, SIGNAL("clicked()"), self._onPreviewPrev)
|
||||||
c(self._previewNext, SIGNAL("clicked()"), self._onPreviewNext)
|
c(self._previewNext, SIGNAL("clicked()"), self._onPreviewNext)
|
||||||
|
c(self._previewReplay, SIGNAL("clicked()"), self._onReplayAudio)
|
||||||
vbox.addWidget(bbox)
|
vbox.addWidget(bbox)
|
||||||
self._previewWindow.setLayout(vbox)
|
self._previewWindow.setLayout(vbox)
|
||||||
restoreGeom(self._previewWindow, "preview")
|
restoreGeom(self._previewWindow, "preview")
|
||||||
|
@ -1050,6 +1055,9 @@ where id in %s""" % ids2str(sf))
|
||||||
self.onNextCard()
|
self.onNextCard()
|
||||||
self._updatePreviewButtons()
|
self._updatePreviewButtons()
|
||||||
|
|
||||||
|
def _onReplayAudio(self):
|
||||||
|
self.mw.reviewer.replayAudio(self)
|
||||||
|
|
||||||
def _updatePreviewButtons(self):
|
def _updatePreviewButtons(self):
|
||||||
if not self._previewWindow:
|
if not self._previewWindow:
|
||||||
return
|
return
|
||||||
|
@ -1321,7 +1329,10 @@ update cards set usn=?, mod=?, did=? where id in """ + scids,
|
||||||
frm.field.addItems([_("All Fields")] + fields)
|
frm.field.addItems([_("All Fields")] + fields)
|
||||||
self.connect(frm.buttonBox, SIGNAL("helpRequested()"),
|
self.connect(frm.buttonBox, SIGNAL("helpRequested()"),
|
||||||
self.onFindReplaceHelp)
|
self.onFindReplaceHelp)
|
||||||
if not d.exec_():
|
restoreGeom(d, "findreplace")
|
||||||
|
r = d.exec_()
|
||||||
|
saveGeom(d, "findreplace")
|
||||||
|
if not r:
|
||||||
return
|
return
|
||||||
if frm.field.currentIndex() == 0:
|
if frm.field.currentIndex() == 0:
|
||||||
field = None
|
field = None
|
||||||
|
|
|
@ -268,10 +268,15 @@ where id > ?""", (self.mw.col.sched.dayCutoff-86400)*1000)
|
||||||
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._rename(did))
|
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._rename(did))
|
||||||
a = m.addAction(_("Options"))
|
a = m.addAction(_("Options"))
|
||||||
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._options(did))
|
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._options(did))
|
||||||
|
a = m.addAction(_("Export"))
|
||||||
|
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._export(did))
|
||||||
a = m.addAction(_("Delete"))
|
a = m.addAction(_("Delete"))
|
||||||
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._delete(did))
|
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._delete(did))
|
||||||
m.exec_(QCursor.pos())
|
m.exec_(QCursor.pos())
|
||||||
|
|
||||||
|
def _export(self, did):
|
||||||
|
self.mw.onExport(did=did)
|
||||||
|
|
||||||
def _rename(self, did):
|
def _rename(self, did):
|
||||||
self.mw.checkpoint(_("Rename Deck"))
|
self.mw.checkpoint(_("Rename Deck"))
|
||||||
deck = self.mw.col.decks.get(did)
|
deck = self.mw.col.decks.get(did)
|
||||||
|
|
|
@ -7,7 +7,7 @@ from anki.consts import NEW_CARDS_RANDOM
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
import aqt
|
import aqt
|
||||||
from aqt.utils import showInfo, showWarning, openHelp, getOnlyText, askUser, \
|
from aqt.utils import showInfo, showWarning, openHelp, getOnlyText, askUser, \
|
||||||
tooltip
|
tooltip, saveGeom, restoreGeom
|
||||||
|
|
||||||
class DeckConf(QDialog):
|
class DeckConf(QDialog):
|
||||||
def __init__(self, mw, deck):
|
def __init__(self, mw, deck):
|
||||||
|
@ -33,9 +33,10 @@ class DeckConf(QDialog):
|
||||||
self.onRestore)
|
self.onRestore)
|
||||||
self.setWindowTitle(_("Options for %s") % self.deck['name'])
|
self.setWindowTitle(_("Options for %s") % self.deck['name'])
|
||||||
# qt doesn't size properly with altered fonts otherwise
|
# qt doesn't size properly with altered fonts otherwise
|
||||||
|
restoreGeom(self, "deckconf", adjustSize=True)
|
||||||
self.show()
|
self.show()
|
||||||
self.adjustSize()
|
|
||||||
self.exec_()
|
self.exec_()
|
||||||
|
saveGeom(self, "deckconf")
|
||||||
|
|
||||||
def setupCombos(self):
|
def setupCombos(self):
|
||||||
import anki.consts as cs
|
import anki.consts as cs
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
import aqt
|
import aqt
|
||||||
from aqt.utils import showWarning, openHelp, askUser
|
from aqt.utils import showWarning, openHelp, askUser, saveGeom, restoreGeom
|
||||||
|
|
||||||
class DeckConf(QDialog):
|
class DeckConf(QDialog):
|
||||||
def __init__(self, mw, first=False, search="", deck=None):
|
def __init__(self, mw, first=False, search="", deck=None):
|
||||||
|
@ -26,6 +26,7 @@ class DeckConf(QDialog):
|
||||||
SIGNAL("helpRequested()"),
|
SIGNAL("helpRequested()"),
|
||||||
lambda: openHelp("filtered"))
|
lambda: openHelp("filtered"))
|
||||||
self.setWindowTitle(_("Options for %s") % self.deck['name'])
|
self.setWindowTitle(_("Options for %s") % self.deck['name'])
|
||||||
|
restoreGeom(self, "dyndeckconf")
|
||||||
self.setupOrder()
|
self.setupOrder()
|
||||||
self.loadConf()
|
self.loadConf()
|
||||||
if search:
|
if search:
|
||||||
|
@ -33,6 +34,7 @@ class DeckConf(QDialog):
|
||||||
self.form.search.selectAll()
|
self.form.search.selectAll()
|
||||||
self.show()
|
self.show()
|
||||||
self.exec_()
|
self.exec_()
|
||||||
|
saveGeom(self, "dyndeckconf")
|
||||||
|
|
||||||
def setupOrder(self):
|
def setupOrder(self):
|
||||||
import anki.consts as cs
|
import anki.consts as cs
|
||||||
|
|
|
@ -12,17 +12,17 @@ from anki.exporting import exporters
|
||||||
|
|
||||||
class ExportDialog(QDialog):
|
class ExportDialog(QDialog):
|
||||||
|
|
||||||
def __init__(self, mw):
|
def __init__(self, mw, did=None):
|
||||||
QDialog.__init__(self, mw, Qt.Window)
|
QDialog.__init__(self, mw, Qt.Window)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.col = mw.col
|
self.col = mw.col
|
||||||
self.frm = aqt.forms.exporting.Ui_ExportDialog()
|
self.frm = aqt.forms.exporting.Ui_ExportDialog()
|
||||||
self.frm.setupUi(self)
|
self.frm.setupUi(self)
|
||||||
self.exporter = None
|
self.exporter = None
|
||||||
self.setup()
|
self.setup(did)
|
||||||
self.exec_()
|
self.exec_()
|
||||||
|
|
||||||
def setup(self):
|
def setup(self, did):
|
||||||
self.frm.format.insertItems(0, list(zip(*exporters())[0]))
|
self.frm.format.insertItems(0, list(zip(*exporters())[0]))
|
||||||
self.connect(self.frm.format, SIGNAL("activated(int)"),
|
self.connect(self.frm.format, SIGNAL("activated(int)"),
|
||||||
self.exporterChanged)
|
self.exporterChanged)
|
||||||
|
@ -32,6 +32,11 @@ class ExportDialog(QDialog):
|
||||||
# save button
|
# save button
|
||||||
b = QPushButton(_("Export..."))
|
b = QPushButton(_("Export..."))
|
||||||
self.frm.buttonBox.addButton(b, QDialogButtonBox.AcceptRole)
|
self.frm.buttonBox.addButton(b, QDialogButtonBox.AcceptRole)
|
||||||
|
# set default option if accessed through deck button
|
||||||
|
if did:
|
||||||
|
name = self.mw.col.decks.get(did)['name']
|
||||||
|
index = self.frm.deck.findText(name)
|
||||||
|
self.frm.deck.setCurrentIndex(index)
|
||||||
|
|
||||||
def exporterChanged(self, idx):
|
def exporterChanged(self, idx):
|
||||||
self.exporter = exporters()[idx][1](self.col)
|
self.exporter = exporters()[idx][1](self.col)
|
||||||
|
|
|
@ -295,7 +295,7 @@ def importFile(mw, file):
|
||||||
return
|
return
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
msg = repr(str(e))
|
msg = repr(str(e))
|
||||||
if msg == "unknownFormat":
|
if msg == "'unknownFormat'":
|
||||||
if file.endswith(".anki2"):
|
if file.endswith(".anki2"):
|
||||||
showWarning(_("""\
|
showWarning(_("""\
|
||||||
.anki2 files are not designed for importing. If you're trying to restore from a \
|
.anki2 files are not designed for importing. If you're trying to restore from a \
|
||||||
|
@ -379,7 +379,11 @@ def replaceWithApkg(mw, file, backup):
|
||||||
mw.unloadCollection()
|
mw.unloadCollection()
|
||||||
# overwrite collection
|
# overwrite collection
|
||||||
z = zipfile.ZipFile(file)
|
z = zipfile.ZipFile(file)
|
||||||
z.extract("collection.anki2", mw.pm.profileFolder())
|
try:
|
||||||
|
z.extract("collection.anki2", mw.pm.profileFolder())
|
||||||
|
except:
|
||||||
|
showWarning(_("The provided file is not a valid .apkg file."))
|
||||||
|
return
|
||||||
# because users don't have a backup of media, it's safer to import new
|
# because users don't have a backup of media, it's safer to import new
|
||||||
# data and rely on them running a media db check to get rid of any
|
# data and rely on them running a media db check to get rid of any
|
||||||
# unwanted media. in the future we might also want to deduplicate this
|
# unwanted media. in the future we might also want to deduplicate this
|
||||||
|
|
15
aqt/main.py
15
aqt/main.py
|
@ -16,7 +16,7 @@ import aqt.progress
|
||||||
import aqt.webview
|
import aqt.webview
|
||||||
import aqt.toolbar
|
import aqt.toolbar
|
||||||
import aqt.stats
|
import aqt.stats
|
||||||
from aqt.utils import restoreGeom, showInfo, showWarning,\
|
from aqt.utils import saveGeom, restoreGeom, showInfo, showWarning, \
|
||||||
restoreState, getOnlyText, askUser, applyStyles, showText, tooltip, \
|
restoreState, getOnlyText, askUser, applyStyles, showText, tooltip, \
|
||||||
openHelp, openLink, checkInvalidFilename
|
openHelp, openLink, checkInvalidFilename
|
||||||
import anki.db
|
import anki.db
|
||||||
|
@ -764,9 +764,9 @@ title="%s">%s</button>''' % (
|
||||||
import aqt.importing
|
import aqt.importing
|
||||||
aqt.importing.onImport(self)
|
aqt.importing.onImport(self)
|
||||||
|
|
||||||
def onExport(self):
|
def onExport(self, did=None):
|
||||||
import aqt.exporting
|
import aqt.exporting
|
||||||
aqt.exporting.ExportDialog(self)
|
aqt.exporting.ExportDialog(self, did=did)
|
||||||
|
|
||||||
# Cramming
|
# Cramming
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
@ -971,7 +971,9 @@ will be lost. Continue?"""))
|
||||||
diag.connect(box, SIGNAL("rejected()"), diag, SLOT("reject()"))
|
diag.connect(box, SIGNAL("rejected()"), diag, SLOT("reject()"))
|
||||||
diag.setMinimumHeight(400)
|
diag.setMinimumHeight(400)
|
||||||
diag.setMinimumWidth(500)
|
diag.setMinimumWidth(500)
|
||||||
|
restoreGeom(diag, "checkmediadb")
|
||||||
diag.exec_()
|
diag.exec_()
|
||||||
|
saveGeom(diag, "checkmediadb")
|
||||||
|
|
||||||
def deleteUnused(self, unused, diag):
|
def deleteUnused(self, unused, diag):
|
||||||
if not askUser(
|
if not askUser(
|
||||||
|
@ -980,7 +982,8 @@ will be lost. Continue?"""))
|
||||||
mdir = self.col.media.dir()
|
mdir = self.col.media.dir()
|
||||||
for f in unused:
|
for f in unused:
|
||||||
path = os.path.join(mdir, f)
|
path = os.path.join(mdir, f)
|
||||||
send2trash(path)
|
if os.path.exists(path):
|
||||||
|
send2trash(path)
|
||||||
tooltip(_("Deleted."))
|
tooltip(_("Deleted."))
|
||||||
diag.close()
|
diag.close()
|
||||||
|
|
||||||
|
@ -1003,10 +1006,12 @@ will be lost. Continue?"""))
|
||||||
self.progress.finish()
|
self.progress.finish()
|
||||||
part1 = ngettext("%d card", "%d cards", len(cids)) % len(cids)
|
part1 = ngettext("%d card", "%d cards", len(cids)) % len(cids)
|
||||||
part1 = _("%s to delete:") % part1
|
part1 = _("%s to delete:") % part1
|
||||||
diag, box = showText(part1 + "\n\n" + report, run=False)
|
diag, box = showText(part1 + "\n\n" + report, run=False,
|
||||||
|
geomKey="emptyCards")
|
||||||
box.addButton(_("Delete Cards"), QDialogButtonBox.AcceptRole)
|
box.addButton(_("Delete Cards"), QDialogButtonBox.AcceptRole)
|
||||||
box.button(QDialogButtonBox.Close).setDefault(True)
|
box.button(QDialogButtonBox.Close).setDefault(True)
|
||||||
def onDelete():
|
def onDelete():
|
||||||
|
saveGeom(diag, "emptyCards")
|
||||||
QDialog.accept(diag)
|
QDialog.accept(diag)
|
||||||
self.checkpoint(_("Delete Empty"))
|
self.checkpoint(_("Delete Empty"))
|
||||||
self.col.remCards(cids)
|
self.col.remCards(cids)
|
||||||
|
|
|
@ -115,7 +115,9 @@ class Models(QDialog):
|
||||||
self.connect(
|
self.connect(
|
||||||
frm.buttonBox, SIGNAL("helpRequested()"),
|
frm.buttonBox, SIGNAL("helpRequested()"),
|
||||||
lambda: openHelp("latex"))
|
lambda: openHelp("latex"))
|
||||||
|
restoreGeom(d, "modelopts")
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
saveGeom(d, "modelopts")
|
||||||
self.model['latexPre'] = unicode(frm.latexHeader.toPlainText())
|
self.model['latexPre'] = unicode(frm.latexHeader.toPlainText())
|
||||||
self.model['latexPost'] = unicode(frm.latexFooter.toPlainText())
|
self.model['latexPost'] = unicode(frm.latexFooter.toPlainText())
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,10 @@ class ProfileManager(object):
|
||||||
# can't translate, as lang not initialized
|
# can't translate, as lang not initialized
|
||||||
QMessageBox.critical(
|
QMessageBox.critical(
|
||||||
None, "Error", """\
|
None, "Error", """\
|
||||||
Anki can't write to the harddisk. Please see the \
|
Anki could not create the folder %s. Please ensure that location is not \
|
||||||
documentation for information on using a flash drive.""")
|
read-only and you have permission to write to it. If you cannot fix this \
|
||||||
|
issue, please see the documentation for information on running Anki from \
|
||||||
|
a flash drive.""" % self.base)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# Profile load/save
|
# Profile load/save
|
||||||
|
|
|
@ -106,14 +106,19 @@ class Reviewer(object):
|
||||||
# Audio
|
# Audio
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def replayAudio(self):
|
def replayAudio(self, previewer=None):
|
||||||
|
if previewer:
|
||||||
|
state = previewer._previewState
|
||||||
|
c = previewer.card
|
||||||
|
else:
|
||||||
|
state = self.state
|
||||||
|
c = self.card
|
||||||
clearAudioQueue()
|
clearAudioQueue()
|
||||||
c = self.card
|
if state == "question":
|
||||||
if self.state == "question":
|
|
||||||
playFromText(c.q())
|
playFromText(c.q())
|
||||||
elif self.state == "answer":
|
elif state == "answer":
|
||||||
txt = ""
|
txt = ""
|
||||||
if self._replayq(c):
|
if self._replayq(c, previewer):
|
||||||
txt = c.q()
|
txt = c.q()
|
||||||
txt += c.a()
|
txt += c.a()
|
||||||
playFromText(txt)
|
playFromText(txt)
|
||||||
|
@ -218,9 +223,10 @@ The front of this card is empty. Please run Tools>Empty Cards.""")
|
||||||
return self.mw.col.decks.confForDid(
|
return self.mw.col.decks.confForDid(
|
||||||
card.odid or card.did)['autoplay']
|
card.odid or card.did)['autoplay']
|
||||||
|
|
||||||
def _replayq(self, card):
|
def _replayq(self, card, previewer=None):
|
||||||
return self.mw.col.decks.confForDid(
|
s = previewer if previewer else self
|
||||||
self.card.odid or self.card.did).get('replayq', True)
|
return s.mw.col.decks.confForDid(
|
||||||
|
s.card.odid or s.card.did).get('replayq', True)
|
||||||
|
|
||||||
def _toggleStar(self):
|
def _toggleStar(self):
|
||||||
self.web.eval("_toggleStar(%s);" % json.dumps(
|
self.web.eval("_toggleStar(%s);" % json.dumps(
|
||||||
|
|
|
@ -61,9 +61,14 @@ class DeckStats(QDialog):
|
||||||
painter = QPainter(image)
|
painter = QPainter(image)
|
||||||
p.mainFrame().render(painter)
|
p.mainFrame().render(painter)
|
||||||
painter.end()
|
painter.end()
|
||||||
image.save(path, "png")
|
isOK = image.save(path, "png")
|
||||||
|
if isOK:
|
||||||
|
showInfo(_("An image was saved to your desktop."))
|
||||||
|
else:
|
||||||
|
showInfo(_("""\
|
||||||
|
Anki could not save the image. Please check that you have permission to write \
|
||||||
|
to your desktop."""))
|
||||||
p.setViewportSize(oldsize)
|
p.setViewportSize(oldsize)
|
||||||
showInfo(_("An image was saved to your desktop."))
|
|
||||||
|
|
||||||
def changePeriod(self, n):
|
def changePeriod(self, n):
|
||||||
self.period = n
|
self.period = n
|
||||||
|
|
|
@ -118,6 +118,7 @@ class StudyDeck(QDialog):
|
||||||
QDialog.accept(self)
|
QDialog.accept(self)
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
|
saveGeom(self, self.geomKey)
|
||||||
remHook('reset', self.onReset)
|
remHook('reset', self.onReset)
|
||||||
if not self.cancel:
|
if not self.cancel:
|
||||||
return self.accept()
|
return self.accept()
|
||||||
|
|
15
aqt/utils.py
15
aqt/utils.py
|
@ -47,7 +47,7 @@ def showInfo(text, parent=False, help="", type="info"):
|
||||||
b.setAutoDefault(False)
|
b.setAutoDefault(False)
|
||||||
return mb.exec_()
|
return mb.exec_()
|
||||||
|
|
||||||
def showText(txt, parent=None, type="text", run=True):
|
def showText(txt, parent=None, type="text", run=True, geomKey=None):
|
||||||
if not parent:
|
if not parent:
|
||||||
parent = aqt.mw.app.activeWindow() or aqt.mw
|
parent = aqt.mw.app.activeWindow() or aqt.mw
|
||||||
diag = QDialog(parent)
|
diag = QDialog(parent)
|
||||||
|
@ -63,9 +63,15 @@ def showText(txt, parent=None, type="text", run=True):
|
||||||
layout.addWidget(text)
|
layout.addWidget(text)
|
||||||
box = QDialogButtonBox(QDialogButtonBox.Close)
|
box = QDialogButtonBox(QDialogButtonBox.Close)
|
||||||
layout.addWidget(box)
|
layout.addWidget(box)
|
||||||
diag.connect(box, SIGNAL("rejected()"), diag, SLOT("reject()"))
|
def onReject():
|
||||||
|
if geomKey:
|
||||||
|
saveGeom(diag, geomKey)
|
||||||
|
QDialog.reject(diag)
|
||||||
|
diag.connect(box, SIGNAL("rejected()"), onReject)
|
||||||
diag.setMinimumHeight(400)
|
diag.setMinimumHeight(400)
|
||||||
diag.setMinimumWidth(500)
|
diag.setMinimumWidth(500)
|
||||||
|
if geomKey:
|
||||||
|
restoreGeom(diag, geomKey)
|
||||||
if run:
|
if run:
|
||||||
diag.exec_()
|
diag.exec_()
|
||||||
else:
|
else:
|
||||||
|
@ -280,7 +286,7 @@ def saveGeom(widget, key):
|
||||||
key += "Geom"
|
key += "Geom"
|
||||||
aqt.mw.pm.profile[key] = widget.saveGeometry()
|
aqt.mw.pm.profile[key] = widget.saveGeometry()
|
||||||
|
|
||||||
def restoreGeom(widget, key, offset=None):
|
def restoreGeom(widget, key, offset=None, adjustSize=False):
|
||||||
key += "Geom"
|
key += "Geom"
|
||||||
if aqt.mw.pm.profile.get(key):
|
if aqt.mw.pm.profile.get(key):
|
||||||
widget.restoreGeometry(aqt.mw.pm.profile[key])
|
widget.restoreGeometry(aqt.mw.pm.profile[key])
|
||||||
|
@ -289,6 +295,9 @@ def restoreGeom(widget, key, offset=None):
|
||||||
# bug in osx toolkit
|
# bug in osx toolkit
|
||||||
s = widget.size()
|
s = widget.size()
|
||||||
widget.resize(s.width(), s.height()+offset*2)
|
widget.resize(s.width(), s.height()+offset*2)
|
||||||
|
else:
|
||||||
|
if adjustSize:
|
||||||
|
widget.adjustSize()
|
||||||
|
|
||||||
def saveState(widget, key):
|
def saveState(widget, key):
|
||||||
key += "State"
|
key += "State"
|
||||||
|
|
Loading…
Reference in a new issue