new 'new' and 'save' behaviour, document dir per platform

- 'new' now creates or opens mydeck on new install
- if not on a new install, open an in-memory database instead
- saveas refactored to require saving of an in-memory db
- autosave disabled until deck has an associated file
- openonline uses a tmp file as it depends on a file at the moment. this can
  go away if the sync code is refactored in the future
This commit is contained in:
Damien Elmes 2009-01-04 09:16:53 +09:00
parent a698f95b97
commit 75af04b383
2 changed files with 78 additions and 67 deletions

View file

@ -154,4 +154,4 @@ question or answer on all cards."""), parent=self)
if not self.parent.config['saveAfterAdding']: if not self.parent.config['saveAfterAdding']:
return return
if (self.addedItems % self.parent.config['saveAfterAddingNum']) == 0: if (self.addedItems % self.parent.config['saveAfterAddingNum']) == 0:
self.parent.saveDeck() self.parent.onSave()

View file

@ -7,7 +7,7 @@ from PyQt4.QtCore import *
from PyQt4.QtWebKit import QWebPage from PyQt4.QtWebKit import QWebPage
import os, sys, re, types, gettext, stat, traceback import os, sys, re, types, gettext, stat, traceback
import shutil, time, glob import shutil, time, glob, tempfile
from PyQt4.QtCore import * from PyQt4.QtCore import *
from PyQt4.QtGui import * from PyQt4.QtGui import *
@ -39,6 +39,7 @@ class AnkiQt(QMainWindow):
self.hideWelcome = False self.hideWelcome = False
self.views = [] self.views = []
self.setLang() self.setLang()
self.setupDocumentDir()
self.setupFonts() self.setupFonts()
self.setupBackupDir() self.setupBackupDir()
self.setupMainWindow() self.setupMainWindow()
@ -313,7 +314,7 @@ Please do not file a bug report with Anki.\n\n""")
num = self.config['saveAfterAnswerNum'] num = self.config['saveAfterAnswerNum']
stats = self.deck.getStats() stats = self.deck.getStats()
if stats['gTotal'] % num == 0: if stats['gTotal'] % num == 0:
self.saveDeck() self.onSave()
self.moveToState("getQuestion") self.moveToState("getQuestion")
def startRefreshTimer(self): def startRefreshTimer(self):
@ -464,7 +465,7 @@ new:
anki.deck.backupDir = os.path.join( anki.deck.backupDir = os.path.join(
self.config.configPath, "backups") self.config.configPath, "backups")
def loadDeck(self, deckPath, sync=True, interactive=True): def loadDeck(self, deckPath, sync=True, interactive=True, uprecent=True):
"Load a deck and update the user interface. Maybe sync." "Load a deck and update the user interface. Maybe sync."
# return True on success # return True on success
try: try:
@ -500,6 +501,7 @@ To upgrade an old deck, download Anki 0.9.8.7.
Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2}) Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
self.moveToState("noDeck") self.moveToState("noDeck")
return return
if uprecent:
self.updateRecentFiles(self.deck.path) self.updateRecentFiles(self.deck.path)
if sync and self.config['syncOnLoad']: if sync and self.config['syncOnLoad']:
if self.syncDeck(interactive=False): if self.syncDeck(interactive=False):
@ -538,7 +540,7 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
r = self.loadDeck(path, interactive=False) r = self.loadDeck(path, interactive=False)
if r: if r:
return r return r
self.onNew(True) self.onNew(initial=True)
def getDefaultDir(self, save=False): def getDefaultDir(self, save=False):
"Try and get default dir from most recently opened file." "Try and get default dir from most recently opened file."
@ -642,28 +644,30 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
"(Auto)save and close. Prompt if necessary. True if okay to proceed." "(Auto)save and close. Prompt if necessary. True if okay to proceed."
self.hideWelcome = hideWelcome self.hideWelcome = hideWelcome
if self.deck is not None: if self.deck is not None:
count = self.deck.cardCount if self.deck.modifiedSinceSave():
path = self.deck.path if (self.deck.path is None or
name = self.deck.name() (not self.config['saveOnClose'] and
# sync (saving automatically) not self.config['syncOnClose'])):
# backed in memory or autosave/sync off, must confirm
while 1:
res = ui.unsaved.ask(self)
if res == ui.unsaved.save:
if self.onSave(required=True):
break
elif res == ui.unsaved.cancel:
return False
else:
break
# auto sync (saving automatically)
if self.config['syncOnClose'] and self.deck.syncName: if self.config['syncOnClose'] and self.deck.syncName:
self.syncDeck(False, reload=False) self.syncDeck(False, reload=False)
while self.deckPath: while self.deckPath:
self.app.processEvents() self.app.processEvents()
time.sleep(0.1) time.sleep(0.1)
return True return True
# save # auto save
if self.deck.modifiedSinceSave():
if self.config['saveOnClose'] or self.config['syncOnClose']: if self.config['saveOnClose'] or self.config['syncOnClose']:
self.saveDeck() self.onSave()
else:
res = ui.unsaved.ask(self)
if res == ui.unsaved.save:
self.saveDeck()
elif res == ui.unsaved.cancel:
return False
elif res == ui.unsaved.discard:
pass
# close # close
self.deck.rollback() self.deck.rollback()
self.deck.close() self.deck.close()
@ -674,21 +678,17 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
ui.dialogs.closeAll() ui.dialogs.closeAll()
return True return True
def onNew(self, auto=False): def onNew(self, initial=False, path=None):
if not self.saveAndClose(hideWelcome=True): return if not self.saveAndClose(hideWelcome=True): return
if auto: if initial:
self.deck = DeckStorage.Deck() path = os.path.join(self.documentDir, "mydeck.anki")
else: if os.path.exists(path):
file = self.onSaveAsOrNew(new=True) # load mydeck instead
if not file: return self.loadDeck(path)
return self.deck = DeckStorage.Deck(path)
if os.path.exists(file):
os.unlink(file)
self.deck = DeckStorage.Deck(file)
self.deck.initUndo() self.deck.initUndo()
self.deck.addModel(BasicModel()) self.deck.addModel(BasicModel())
self.saveDeck() self.deck.save()
self.updateRecentFiles(self.deck.path)
self.moveToState("initial") self.moveToState("initial")
def ensureSyncParams(self): def ensureSyncParams(self):
@ -723,16 +723,17 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
def onOpenOnline(self): def onOpenOnline(self):
self.ensureSyncParams() self.ensureSyncParams()
if not self.saveAndClose(hideWelcome=True): return if not self.saveAndClose(hideWelcome=True): return
self.onNew() # we need a disk-backed file for syncing
if self.deck is None: dir = tempfile.mkdtemp()
return path = os.path.join(dir, u"untitled.anki")
self.onNew(path=path)
# ensure all changes come to us # ensure all changes come to us
self.deck.modified = 0 self.deck.modified = 0
self.deck.s.commit() self.deck.s.commit()
self.deck.syncName = "something" self.deck.syncName = "something"
self.deck.lastLoaded = self.deck.modified self.deck.lastLoaded = self.deck.modified
if self.config['syncUsername'] and self.config['syncPassword']: if self.config['syncUsername'] and self.config['syncPassword']:
if self.syncDeck(onlyMerge=True): if self.syncDeck(onlyMerge=True, reload=2):
return return
self.deck = None self.deck = None
self.moveToState("initial") self.moveToState("initial")
@ -764,22 +765,24 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
def onOpenSamples(self): def onOpenSamples(self):
self.onOpen(samples=True) self.onOpen(samples=True)
def onSave(self): def onSave(self, required=False):
if self.deck.modifiedSinceSave(): if not self.deck.path:
self.saveDeck() if required:
else: # backed in memory, make sure it's saved
self.setStatus(_("Deck is not modified.")) return self.onSaveAs()
return
if not self.deck.modifiedSinceSave():
return
self.deck.save()
self.updateTitleBar() self.updateTitleBar()
def onSaveAsOrNew(self, new=False): def onSaveAs(self):
"Prompt for a file name, then save." "Prompt for a file name, then save."
if new:
title = "Name Deck"
dir = anki.deck.ankiDir
else:
title = _("Save Deck As") title = _("Save Deck As")
if self.deck.path:
dir = os.path.dirname(self.deck.path) dir = os.path.dirname(self.deck.path)
else:
dir = self.documentDir
file = QFileDialog.getSaveFileName(self, title, file = QFileDialog.getSaveFileName(self, title,
dir, dir,
_("Deck files (*.anki)"), _("Deck files (*.anki)"),
@ -795,19 +798,12 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
if not ui.utils.askUser( if not ui.utils.askUser(
"This file exists. Are you sure you want to overwrite it?"): "This file exists. Are you sure you want to overwrite it?"):
return return
if new:
return file
self.deck = self.deck.saveAs(file) self.deck = self.deck.saveAs(file)
self.deck.initUndo() self.deck.initUndo()
self.updateTitleBar() self.updateTitleBar()
self.updateRecentFiles(self.deck.path) self.updateRecentFiles(self.deck.path)
self.moveToState("initial") self.moveToState("initial")
return file
def saveDeck(self):
self.setStatus(_("Saving..."))
self.deck.save()
self.updateTitleBar()
self.setStatus(_("Saving...done"))
# Opening and closing the app # Opening and closing the app
########################################################################## ##########################################################################
@ -1124,7 +1120,6 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
def onImport(self): def onImport(self):
if self.deck is None: if self.deck is None:
self.onNew() self.onNew()
if self.deck is not None:
ui.importing.ImportDialog(self) ui.importing.ImportDialog(self)
def onExport(self): def onExport(self):
@ -1219,7 +1214,6 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
if self.deck: if self.deck:
# save first, so we can rollback on failure # save first, so we can rollback on failure
self.deck.save() self.deck.save()
self.deck.close()
# store data we need before closing the deck # store data we need before closing the deck
self.deckPath = self.deck.path self.deckPath = self.deck.path
self.syncName = self.deck.syncName or self.deck.name() self.syncName = self.deck.syncName or self.deck.name()
@ -1231,6 +1225,7 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
t=time.time()) t=time.time())
else: else:
self.sourcesToCheck = [] self.sourcesToCheck = []
self.deck.close()
self.deck = None self.deck = None
self.loadAfterSync = reload self.loadAfterSync = reload
# hide all deck-associated dialogs # hide all deck-associated dialogs
@ -1265,10 +1260,15 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
"Reopen after sync finished." "Reopen after sync finished."
self.mainWin.buttonStack.show() self.mainWin.buttonStack.show()
if self.loadAfterSync: if self.loadAfterSync:
self.loadDeck(self.deckPath, sync=False) uprecent = self.loadAfterSync != 2
self.loadDeck(self.deckPath, sync=False, uprecent=uprecent)
self.deck.syncName = self.syncName self.deck.syncName = self.syncName
self.deck.s.flush() self.deck.s.flush()
self.deck.s.commit() self.deck.s.commit()
if self.loadAfterSync == 2:
# special case for open online: mark temp deck as in-memory
self.deck.path = None
self.deck.flushMod()
elif not self.hideWelcome: elif not self.hideWelcome:
self.moveToState("noDeck") self.moveToState("noDeck")
self.deckPath = None self.deckPath = None
@ -1367,7 +1367,7 @@ Error was:\n%(f1)s\n...\n%(f2)s""") % {'f1': fmt1, 'f2': fmt2})
self.connect(m.actionOpen, s, self.onOpen) self.connect(m.actionOpen, s, self.onOpen)
self.connect(m.actionOpenSamples, s, self.onOpenSamples) self.connect(m.actionOpenSamples, s, self.onOpenSamples)
self.connect(m.actionSave, s, self.onSave) self.connect(m.actionSave, s, self.onSave)
self.connect(m.actionSaveAs, s, self.onSaveAsOrNew) self.connect(m.actionSaveAs, s, self.onSaveAs)
self.connect(m.actionClose, s, self.onClose) self.connect(m.actionClose, s, self.onClose)
self.connect(m.actionExit, s, self, SLOT("close()")) self.connect(m.actionExit, s, self, SLOT("close()"))
self.connect(m.actionSyncdeck, s, self.syncDeck) self.connect(m.actionSyncdeck, s, self.syncDeck)
@ -1743,3 +1743,14 @@ tag or delete references to missing files?"""))
def onUncacheLatex(self): def onUncacheLatex(self):
anki.latex.deleteAllLatexImages(self.deck) anki.latex.deleteAllLatexImages(self.deck)
# System specific misc
##########################################################################
def setupDocumentDir(self):
if sys.platform.startswith("win32"):
raise "nyi"
elif sys.platform.startswith("darwin"):
self.documentDir = os.path.expanduser("~/Documents")
else:
self.documentDir = os.path.expanduser("~/.anki")