implement deck browser

This commit is contained in:
Damien Elmes 2009-06-04 09:41:40 +09:00
parent 0d76d987ca
commit abdaf9e9df
6 changed files with 347 additions and 81 deletions

View file

@ -95,6 +95,7 @@ class Config(dict):
'proxyPort': 8080,
'proxyUser': '',
'proxyPass': '',
'loadLastDeck': False,
}
for (k,v) in fields.items():
if not self.has_key(k):

View file

@ -48,6 +48,7 @@ class AnkiQt(QMainWindow):
self.setupBackupDir()
self.setupProxy()
self.setupMainWindow()
self.setupDeckBrowser()
self.setupSystemHacks()
self.setupSound()
self.setupTray()
@ -66,9 +67,9 @@ class AnkiQt(QMainWindow):
self.restoreState(self.config['mainWindowState'])
# load deck
ui.splash.update()
if not self.maybeLoadLastDeck(args):
if self.config['loadLastDeck'] and not self.maybeLoadLastDeck(args):
self.setEnabled(True)
self.moveToState("auto")
self.moveToState("auto")
# check for updates
ui.splash.update()
self.setupErrorHandler()
@ -239,7 +240,6 @@ Please do not file a bug report with Anki.<br>""")
self.editor.deck = self.deck
if self.deck:
self.enableDeckMenuItems()
self.updateRecentFilesMenu()
self.updateViews(state)
if self.state == "studyScreen":
return self.moveToState("studyScreen")
@ -264,14 +264,13 @@ Please do not file a bug report with Anki.<br>""")
self.switchToReviewScreen()
if state == "noDeck":
self.deck = None
self.switchToWelcomeScreen()
self.help.hide()
self.currentCard = None
self.lastCard = None
self.disableDeckMenuItems()
self.updateRecentFilesMenu()
# hide all deck-associated dialogs
self.closeAllDeckWindows()
self.showDeckBrowser()
elif state == "getQuestion":
# stop anything playing
clearAudioQueue()
@ -494,7 +493,11 @@ new:
self.mainWin.mainStack.setCurrentIndex(4)
def switchToReviewScreen(self):
self.mainWin.mainStack.setCurrentIndex(6)
def switchToDecksScreen(self):
self.mainWin.mainStack.setCurrentIndex(5)
self.hideButtons()
# Buttons
##########################################################################
@ -700,32 +703,8 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
if path in self.config['recentDeckPaths']:
self.config['recentDeckPaths'].remove(path)
self.config['recentDeckPaths'].insert(0, path)
del self.config['recentDeckPaths'][8:]
del self.config['recentDeckPaths'][20:]
self.config.save()
self.updateRecentFilesMenu()
def updateRecentFilesMenu(self):
self.config['recentDeckPaths'] = [
p for p in self.config['recentDeckPaths']
if os.path.exists(p)]
if not self.config['recentDeckPaths']:
self.mainWin.menuOpenRecent.setEnabled(False)
return
self.mainWin.menuOpenRecent.setEnabled(True)
self.mainWin.menuOpenRecent.clear()
n = 1
for file in self.config['recentDeckPaths']:
a = QAction(self)
if sys.platform.startswith("darwin"):
a.setShortcut(_("Ctrl+Alt+%d" % n))
else:
a.setShortcut(_("Alt+%d" % n))
a.setText(os.path.basename(file))
a.setStatusTip(os.path.abspath(file))
self.connect(a, SIGNAL("triggered()"),
lambda n=n: self.loadRecent(n-1))
self.mainWin.menuOpenRecent.addAction(a)
n += 1
def loadRecent(self, n):
self.loadDeck(self.config['recentDeckPaths'][n])
@ -951,6 +930,132 @@ your deck."""))
self.moveToState("initial")
return file
# Deck browser
##########################################################################
def setupDeckBrowser(self):
self.connect(self.mainWin.downloadDeckButton,
SIGNAL("clicked()"),
self.onGetSharedDeck)
self.connect(self.mainWin.newDeckButton,
SIGNAL("clicked()"),
self.onNew)
self.connect(self.mainWin.importDeckButton,
SIGNAL("clicked()"),
self.onImport)
def showDeckBrowser(self):
import sip
focusButton = None
self.switchToDecksScreen()
if self.mainWin.decksFrame.layout():
while 1:
obj = self.mainWin.decksFrame.layout().takeAt(0)
if not obj:
break
if "QLabel" in repr(obj.widget()):
sip.delete(obj.widget())
else:
obj.widget().deleteLater()
sip.delete(obj)
sip.delete(self.mainWin.decksFrame.layout())
layout = QGridLayout()
self.deckBrowserDecks = []
if self.config['recentDeckPaths']:
layout.addWidget(QLabel(_("<b>Deck</b>")), 0, 0)
l = QLabel(_("<b>Due</b>"))
l.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
layout.addWidget(l, 0, 1)
l = QLabel(_("<b>New</b>"))
l.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
layout.addWidget(l, 0, 2)
toRemove = []
self.startProgress(max=len(self.config['recentDeckPaths']))
for c, d in enumerate(self.config['recentDeckPaths']):
self.updateProgress(_("Checking deck %(x)d of %(y)d...") % {
'x': c, 'y': len(self.config['recentDeckPaths'])})
if not os.path.exists(d):
toRemove.append(d)
continue
try:
deck = DeckStorage.Deck(d, backup=False)
except:
toRemove.append(d)
continue
self.deckBrowserDecks.append(d)
# name & stats
n = deck.name()
if len(n) > 30:
n = n[:30] + "..."
layout.addWidget(QLabel(n), c+1, 0)
l = QLabel("<b>" + str(deck.failedSoonCount + deck.revCount) +
"</b>")
l.setMinimumWidth(50)
l.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
layout.addWidget(l, c+1, 1)
l = QLabel(str(deck.newCount))
l.setMinimumWidth(50)
l.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
layout.addWidget(l, c+1, 2)
# open
openButton = QPushButton(_("Open"))
extra = ""
if c < 9:
extra = " (Alt+%d)" % (c+1)
openButton.setToolTip(_("Open this deck%s") % extra)
if c < 9:
if sys.platform.startswith("darwin"):
openButton.setShortcut(_("Ctrl+Alt+%d" % (c+1)))
else:
openButton.setShortcut(_("Alt+%d" % (c+1)))
self.connect(openButton, SIGNAL("clicked()"),
lambda d=d: self.loadDeck(d))
layout.addWidget(openButton, c+1, 3)
if c == 0:
focusButton = openButton
# more
moreButton = QComboBox()
moreButton.addItems(QStringList([
_("More"),
_("Forget"),
_("Delete")]))
moreButton.setToolTip(
_("Forget removes the deck from the list without deleting."))
self.connect(moreButton, SIGNAL("currentIndexChanged(int)"),
lambda idx, c=c: self.onDeckBrowserMore(idx, c))
layout.addWidget(moreButton, c+1, 4)
deck.close()
refresh = QPushButton(_("Refresh"))
self.connect(refresh, SIGNAL("clicked()"),
self.showDeckBrowser)
layout.addWidget(refresh, c+2, 3)
for d in toRemove:
self.config['recentDeckPaths'].remove(d)
self.finishProgress()
else:
layout.addWidget(QLabel(_(
"Welcome to Anki! Click 'Download Deck' to get started.")), 0, 0)
self.mainWin.decksFrame.setLayout(layout)
self.app.processEvents()
if focusButton:
focusButton.setFocus()
def onDeckBrowserMore(self, idx, c):
if idx == 0:
return
elif idx == 1:
# forget
self.config['recentDeckPaths'].remove(self.deckBrowserDecks[c])
self.showDeckBrowser()
elif idx == 2:
# delete
deck = self.deckBrowserDecks[c]
if ui.utils.askUser(_("Delete %s?") % os.path.basename(deck)):
print "deleting", deck
os.unlink(deck)
self.config['recentDeckPaths'].remove(deck)
self.showDeckBrowser()
# Opening and closing the app
##########################################################################
@ -983,17 +1088,9 @@ your deck."""))
##########################################################################
def onWelcomeAnchor(self, str):
if str == "new":
self.onNew()
elif str == "open":
self.onOpen()
elif str == "sample":
self.onGetSharedDeck()
elif str == "openrem":
self.onOpenOnline()
if str == "back":
self.saveAndClose()
if str == "addfacts":
if not self.deck:
self.onNew()
if self.deck:
self.onAddCard()
@ -1295,6 +1392,7 @@ learnt today")
mw.toolBar.addAction(mw.actionGraphs)
mw.toolBar.addAction(mw.actionMarkCard)
mw.toolBar.addAction(mw.actionRepeatAudio)
mw.toolBar.addAction(mw.actionClose)
self.addToolBar(Qt.TopToolBarArea, mw.toolBar)
mw.toolBar.setIconSize(QSize(self.config['iconSize'],
self.config['iconSize']))

View file

@ -142,7 +142,7 @@ class Preferences(QDialog):
self.dialog.addZeroSpace.setChecked(self.config['addZeroSpace'])
self.dialog.alternativeTheme.setChecked(self.config['alternativeTheme'])
self.dialog.showProgress.setChecked(self.config['showProgress'])
self.dialog.preventEdits.setChecked(self.config['preventEditUntilAnswer'])
self.dialog.openLastDeck.setChecked(self.config['loadLastDeck'])
def updateAdvanced(self):
self.config['showTrayIcon'] = self.dialog.showTray.isChecked()
@ -155,6 +155,7 @@ class Preferences(QDialog):
self.config['alternativeTheme'] = self.dialog.alternativeTheme.isChecked()
self.config['showProgress'] = self.dialog.showProgress.isChecked()
self.config['preventEditUntilAnswer'] = self.dialog.preventEdits.isChecked()
self.config['loadLastDeck'] = self.dialog.openLastDeck.isChecked()
def codeToIndex(self, code):
n = 0

View file

@ -273,34 +273,19 @@ class View(object):
<br>
<table>
<tr>
<td>
<a href="welcome:open"><img src=":/icons/document-open.png"></a>
</td>
<td valign=middle><h2><a href="welcome:open">%(local)s</a></h2></td>
</tr>
<tr>
<td width=50>
<a href="welcome:sample"><img src=":/icons/anki.png"></a>
<a href="welcome:back"><img src=":/icons/go-previous.png"></a>
</td>
<td valign=middle><h2><a href="welcome:sample">%(dl_shared)s</a></h2></td>
</tr>
<tr>
<td>
<a href="welcome:openrem"><img src=":/icons/document-open-remote.png"></a>
</td>
<td valign=middle><h2><a href="welcome:openrem">%(dl_personal)s</a></h2></td>
<td valign=middle><h2><a href="welcome:back">%(back)s</a></h2></td>
</tr>
</table>""" % \
{"welcome":_("Welcome to Anki!"),
"add":_("Add material"),
"add":_("Add Material"),
"start":_("Start adding your own material."),
"local":_("Open Local Deck"),
"dl_shared":_("Download Shared Deck"),
"dl_personal":_("Download Personal Deck")})
"back":_("Back to Deck Browser"),
})
def drawDeckFinishedMessage(self):
"Tell the user the deck is finished."

View file

@ -5,8 +5,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>723</width>
<height>523</height>
<width>552</width>
<height>646</height>
</rect>
</property>
<property name="sizePolicy" >
@ -355,7 +355,7 @@
</sizepolicy>
</property>
<property name="currentIndex" >
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="blankPage" />
<widget class="QWidget" name="welcomePage" >
@ -912,6 +912,183 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page" >
<layout class="QVBoxLayout" name="verticalLayout_15" >
<item>
<spacer name="verticalSpacer_7" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>20</width>
<height>150</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5" >
<item>
<spacer name="horizontalSpacer" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frame_3" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13" >
<item>
<layout class="QVBoxLayout" name="verticalLayout_14" >
<property name="margin" >
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>&lt;h1>Decks&lt;/h1></string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="decksFrame" >
<property name="frameShape" >
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_4" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7" >
<item>
<spacer name="horizontalSpacer" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_16" >
<item>
<widget class="QPushButton" name="downloadDeckButton" >
<property name="text" >
<string>Download Deck</string>
</property>
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/download.png</normaloff>:/icons/download.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="newDeckButton" >
<property name="text" >
<string>Create Deck</string>
</property>
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/document-new.png</normaloff>:/icons/document-new.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="importDeckButton" >
<property name="text" >
<string>Import Text File</string>
</property>
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/document-import.png</normaloff>:/icons/document-import.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_8" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>20</width>
<height>150</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@ -1111,7 +1288,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>723</width>
<width>552</width>
<height>22</height>
</rect>
</property>
@ -1148,15 +1325,6 @@
<property name="title" >
<string>&amp;File</string>
</property>
<widget class="QMenu" name="menuOpenRecent" >
<property name="title" >
<string>Open &amp;Recent</string>
</property>
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/document-open-recent.png</normaloff>:/icons/document-open-recent.png</iconset>
</property>
</widget>
<widget class="QMenu" name="menuDownload" >
<property name="title" >
<string>&amp;Download...</string>
@ -1172,7 +1340,6 @@
</widget>
<addaction name="actionNew" />
<addaction name="actionOpen" />
<addaction name="menuOpenRecent" />
<addaction name="menuDownload" />
<addaction name="actionImport" />
<addaction name="separator" />
@ -1354,11 +1521,14 @@
<action name="actionClose" >
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/fileclose.png</normaloff>:/icons/fileclose.png</iconset>
<normaloff>:/icons/go-previous.png</normaloff>:/icons/go-previous.png</iconset>
</property>
<property name="text" >
<string>&amp;Close</string>
</property>
<property name="statusTip" >
<string>Close this deck and return to the deck browser</string>
</property>
<property name="shortcut" >
<string>Ctrl+W</string>
</property>
@ -1985,14 +2155,17 @@
<tabstop>optionsHelpButton</tabstop>
<tabstop>learnMoreButton</tabstop>
<tabstop>reviewEarlyButton</tabstop>
<tabstop>help</tabstop>
<tabstop>welcomeText</tabstop>
<tabstop>showAnswerButton</tabstop>
<tabstop>downloadDeckButton</tabstop>
<tabstop>newDeckButton</tabstop>
<tabstop>importDeckButton</tabstop>
<tabstop>easeButton1</tabstop>
<tabstop>easeButton2</tabstop>
<tabstop>easeButton3</tabstop>
<tabstop>easeButton4</tabstop>
<tabstop>saveEditorButton</tabstop>
<tabstop>welcomeText</tabstop>
<tabstop>showAnswerButton</tabstop>
<tabstop>help</tabstop>
</tabstops>
<resources>
<include location="../icons.qrc" />

View file

@ -556,13 +556,20 @@
</property>
</widget>
</item>
<item row="8" column="0" >
<item row="9" column="0" >
<widget class="QCheckBox" name="addZeroSpace" >
<property name="text" >
<string>Add hidden char to text (fixes Thai on OSX)</string>
</property>
</widget>
</item>
<item row="8" column="0" >
<widget class="QCheckBox" name="openLastDeck" >
<property name="text" >
<string>Open last deck instead of deck browser</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -605,6 +612,7 @@
</layout>
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>interfaceLang</tabstop>
<tabstop>label_2</tabstop>
<tabstop>showDivider</tabstop>
@ -630,9 +638,9 @@
<tabstop>showTimer</tabstop>
<tabstop>showTray</tabstop>
<tabstop>showStudyOptions</tabstop>
<tabstop>openLastDeck</tabstop>
<tabstop>addZeroSpace</tabstop>
<tabstop>buttonBox</tabstop>
<tabstop>tabWidget</tabstop>
</tabstops>
<resources/>
<connections>