more deck browser work

- add a separate toolbar for the deck browser
- add a message when there are no decks
- change the progress handler not to lock the UI immediately, which causes
  flicker
- ensure the webview is focused after stdHtml()
This commit is contained in:
Damien Elmes 2011-03-16 04:52:21 +09:00
parent 87f5fe8769
commit f96e03875a
5 changed files with 104 additions and 44 deletions

View file

@ -27,14 +27,11 @@ a.opts { font-size: 80%; padding: 2; background-color: #ccc; border-radius: 2px;
_body = """
<center>
<div id="outer">
<h1>%s</h1>
<h1>%(title)s</h1>
<table cellspacing=0 cellpadding=0 width=90%%>
%s
%(rows)s
</table>
<br><br>
%s
<p>
Click a deck to open it, or press the number/letter next to it.
%(extra)s
</div>
"""
@ -45,11 +42,16 @@ class DeckBrowser(object):
self.web = mw.web
self._browserLastRefreshed = 0
self._decks = []
mw.connect(mw.form.actionRefreshDeckBrowser, SIGNAL("activated()"),
self.refresh)
addHook("deckClosing", self.onClose)
def show(self):
def show(self, _init=True):
if _init:
self.web.setLinkHandler(self._linkHandler)
self.mw.setKeyHandler(self._keyHandler)
self._setupToolbar()
# refresh or reorder
if (time.time() - self._browserLastRefreshed >
self.mw.config['deckBrowserRefreshPeriod']):
t = time.time()
@ -57,23 +59,8 @@ class DeckBrowser(object):
print "check decks", time.time() - t
else:
self._reorderDecks()
if self._decks:
buf = ""
max=len(self._decks)-1
for c, deck in enumerate(self._decks):
buf += self._deckRow(c, max, deck)
self.web.stdHtml(_body%(_("Decks"), buf, self._summary()), _css)
else:
buf = ("""\
<br>
<font size=+1>
Welcome to Anki! Click <b>'Download'</b> to get started. You can return here
later by using File>Close.
</font>
<br>
""")
# FIXME: ensure deck open button is focused
# show
self._renderPage()
def onClose(self, deck):
print "onClose"
@ -90,6 +77,24 @@ later by using File>Close.
d['time'] = self.deck._dailyStats.reviewTime
d['reps'] = self.deck._dailyStats.reps
# Toolbar
##########################################################################
def _setupToolbar(self):
frm = self.mw.form
tb = frm.toolBar
tb.clear()
tb.addAction(frm.actionDownloadSharedDeck)
tb.addAction(frm.actionNew)
tb.addAction(frm.actionOpen)
tb.addAction(frm.actionImport)
tb.addAction(frm.actionOpenOnline)
tb.addAction(frm.actionRefreshDeckBrowser)
tb.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
# reshow so osx recalculates sizes
tb.hide()
tb.show()
# Event handlers
##########################################################################
@ -117,6 +122,27 @@ later by using File>Close.
# HTML generation
##########################################################################
def _renderPage(self):
if self._decks:
buf = ""
max=len(self._decks)-1
for c, deck in enumerate(self._decks):
buf += self._deckRow(c, max, deck)
self.web.stdHtml(_body%dict(
title=_("Decks"),
rows=buf,
extra="<p>%s<p>%s" % (
self._summary(),
_("Click a deck to open, or type a number."))),
_css)
else:
self.web.stdHtml(_body%dict(
title=_("Welcome!"),
rows="<tr><td align=center>%s</td></tr>"%_(
"Click <b>Download</b> to get started."),
extra=""),
_css)
def _deckRow(self, c, max, deck):
buf = "<tr>"
ok = deck['state'] == 'ok'
@ -207,10 +233,6 @@ later by using File>Close.
a.connect(a, SIGNAL("activated()"), lambda n=n: self._deleteRow(n))
m.exec_(QCursor.pos())
def _buttons(self):
# refresh = QPushButton(_("Refresh"))
return ""
def _hideRow(self, c):
if aqt.utils.askUser(_("""\
Hide %s from the list? You can File>Open it again later.""") %
@ -303,4 +325,4 @@ not be touched.""") % self._decks[c]['name']):
def refresh(self):
self._browserLastRefreshed = 0
self.show()
self.show(_init=False)

View file

@ -95,8 +95,6 @@ class AnkiQt(QMainWindow):
self.deck = None
self.currentCard = None
self.lastCard = None
# perhaps we want a separate toolbar instead?
self.form.toolBar.hide()
self.disableDeckMenuItems()
self.closeAllDeckWindows()
self.deckBrowser.show()
@ -1406,8 +1404,7 @@ learnt today")
# Toolbar
##########################################################################
def setupToolbar(self):
mw = self.form
def setupReviewToolbar(self):
mw.toolBar.addAction(mw.actionAddcards)
mw.toolBar.addAction(mw.actionEditCurrent)
mw.toolBar.addAction(mw.actionEditLayout)
@ -1417,8 +1414,12 @@ learnt today")
mw.toolBar.addAction(mw.actionMarkCard)
mw.toolBar.addAction(mw.actionRepeatAudio)
mw.toolBar.addAction(mw.actionClose)
mw.toolBar.setIconSize(QSize(self.config['iconSize'],
self.config['iconSize']))
def setupToolbar(self):
mw = self.form
mw.toolBar.setIconSize(QSize(24, 24))
#mw.toolBar.setIconSize(QSize(self.config['iconSize'],
# self.config['iconSize']))
toggle = mw.toolBar.toggleViewAction()
toggle.setText(_("Toggle Toolbar"))
self.connect(toggle, SIGNAL("triggered()"),

View file

@ -71,9 +71,6 @@ class ProgressManager(object):
self._levels += 1
if self._levels > 1:
return
# disable UI
self.mw.app.setOverrideCursor(QCursor(Qt.WaitCursor))
self.mw.setEnabled(False)
# setup window
parent = parent or self.app.activeWindow() or self.mw
label = label or _("Processing...")
@ -96,6 +93,7 @@ class ProgressManager(object):
self._max = max
self._firstTime = time.time()
self._lastTime = time.time()
self._disabled = False
def update(self, label=None, value=None, process=True):
#print self._min, self._counter, self._max, label, time.time() - self._lastTime
@ -113,8 +111,7 @@ class ProgressManager(object):
self._levels -= 1
if self._levels == 0:
self._win.cancel()
self.app.restoreOverrideCursor()
self.mw.setEnabled(True)
self._enableUI()
def clear(self):
"Restore the interface after an error."
@ -123,7 +120,22 @@ class ProgressManager(object):
self.finishProgress()
def _maybeShow(self):
if not self._shown and (time.time() - self._firstTime) > 2:
print "show2"
delta = time.time() - self._firstTime
# if more than 500ms have passed, disable the UI so the user doesn't
# try to click again. We don't do it immediately to avoid flicker.
if not self._disabled and delta > 0.5:
self._disableUI()
# if more than 2 seconds have passed, show a progress dialog
if not self._shown and delta > 2:
self._shown = True
self._win.show()
def _disableUI(self):
self._disabled = True
self.mw.app.setOverrideCursor(QCursor(Qt.WaitCursor))
self.mw.setEnabled(False)
def _enableUI(self):
self._disabled = False
self.app.restoreOverrideCursor()
self.mw.setEnabled(True)

View file

@ -68,6 +68,8 @@ class AnkiWebView(QWebView):
self.setHtml("""
<html><head><style>%s</style><script src="qrc:/jquery.min.js"></script></head>
<body>%s</body></html>""" % (css, body), loadCB)
# ensure we're focused
self.setFocus()
def setBridge(self, bridge):
self._bridge.setBridge(bridge)
def eval(self, js):

View file

@ -664,17 +664,31 @@
</property>
</action>
<action name="actionOpenOnline">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/document-open-remote.png</normaloff>:/icons/document-open-remote.png</iconset>
</property>
<property name="text">
<string>Personal Deck...</string>
</property>
<property name="iconText">
<string>AnkiWeb</string>
</property>
<property name="statusTip">
<string>Download a deck that you synced from another computer</string>
</property>
</action>
<action name="actionDownloadSharedDeck">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/download.png</normaloff>:/icons/download.png</iconset>
</property>
<property name="text">
<string>Shared Deck...</string>
</property>
<property name="iconText">
<string>Download</string>
</property>
<property name="statusTip">
<string>Download a deck that people have shared publicly</string>
</property>
@ -749,6 +763,15 @@
<string>Localize Media</string>
</property>
</action>
<action name="actionRefreshDeckBrowser">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/edit-redo.png</normaloff>:/icons/edit-redo.png</iconset>
</property>
<property name="text">
<string>Refresh</string>
</property>
</action>
</widget>
<resources>
<include location="icons.qrc"/>