preliminary preview support
This commit is contained in:
parent
9875e26e06
commit
5951ccb09e
123
aqt/browser.py
123
aqt/browser.py
@ -2,19 +2,24 @@
|
|||||||
# Copyright: Damien Elmes <anki@ichi2.net>
|
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
import sre_constants, cgi
|
import sre_constants
|
||||||
from aqt.qt import *
|
import cgi
|
||||||
import time, re
|
import time
|
||||||
|
import re
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
import anki, aqt.forms
|
|
||||||
|
from aqt.qt import *
|
||||||
|
import anki
|
||||||
|
import aqt.forms
|
||||||
from anki.utils import fmtTimeSpan, ids2str, stripHTMLMedia, isWin, intTime, isMac
|
from anki.utils import fmtTimeSpan, ids2str, stripHTMLMedia, isWin, intTime, isMac
|
||||||
from aqt.utils import saveGeom, restoreGeom, saveSplitter, restoreSplitter, \
|
from aqt.utils import saveGeom, restoreGeom, saveSplitter, restoreSplitter, \
|
||||||
saveHeader, restoreHeader, saveState, restoreState, applyStyles, getTag, \
|
saveHeader, restoreHeader, saveState, restoreState, applyStyles, getTag, \
|
||||||
showInfo, askUser, tooltip, openHelp, showWarning, shortcut
|
showInfo, askUser, tooltip, openHelp, showWarning, shortcut, getBase, mungeQA
|
||||||
from anki.hooks import runHook, addHook, remHook
|
from anki.hooks import runHook, addHook, remHook
|
||||||
from aqt.webview import AnkiWebView
|
from aqt.webview import AnkiWebView
|
||||||
from aqt.toolbar import Toolbar
|
from aqt.toolbar import Toolbar
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
|
from anki.sound import playFromText, clearAudioQueue
|
||||||
|
|
||||||
COLOUR_SUSPENDED = "#FFFFB2"
|
COLOUR_SUSPENDED = "#FFFFB2"
|
||||||
COLOUR_MARKED = "#D9B2E9"
|
COLOUR_MARKED = "#D9B2E9"
|
||||||
@ -334,6 +339,7 @@ class Browser(QMainWindow):
|
|||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.col = self.mw.col
|
self.col = self.mw.col
|
||||||
self.lastFilter = ""
|
self.lastFilter = ""
|
||||||
|
self._previewWindow = None
|
||||||
self.form = aqt.forms.browser.Ui_Dialog()
|
self.form = aqt.forms.browser.Ui_Dialog()
|
||||||
self.form.setupUi(self)
|
self.form.setupUi(self)
|
||||||
restoreGeom(self, "editor", 0)
|
restoreGeom(self, "editor", 0)
|
||||||
@ -376,6 +382,7 @@ class Browser(QMainWindow):
|
|||||||
c(f.actionChangeModel, s, self.onChangeModel)
|
c(f.actionChangeModel, s, self.onChangeModel)
|
||||||
# edit
|
# edit
|
||||||
c(f.actionUndo, s, self.mw.onUndo)
|
c(f.actionUndo, s, self.mw.onUndo)
|
||||||
|
c(f.previewButton, SIGNAL("clicked()"), self.onTogglePreview)
|
||||||
c(f.actionInvertSelection, s, self.invertSelection)
|
c(f.actionInvertSelection, s, self.invertSelection)
|
||||||
c(f.actionSelectNotes, s, self.selectNotes)
|
c(f.actionSelectNotes, s, self.selectNotes)
|
||||||
c(f.actionFindReplace, s, self.onFindReplace)
|
c(f.actionFindReplace, s, self.onFindReplace)
|
||||||
@ -565,20 +572,27 @@ class Browser(QMainWindow):
|
|||||||
self.form.splitter.widget(1).setVisible(not not show)
|
self.form.splitter.widget(1).setVisible(not not show)
|
||||||
if not show:
|
if not show:
|
||||||
self.editor.setNote(None)
|
self.editor.setNote(None)
|
||||||
|
self.card = None
|
||||||
else:
|
else:
|
||||||
self.card = self.model.getCard(
|
self.card = self.model.getCard(
|
||||||
self.form.tableView.selectionModel().currentIndex())
|
self.form.tableView.selectionModel().currentIndex())
|
||||||
self.editor.setNote(self.card.note(reload=True))
|
self.editor.setNote(self.card.note(reload=True))
|
||||||
self.editor.card = self.card
|
self.editor.card = self.card
|
||||||
|
self._renderPreview(True)
|
||||||
self.toolbar.draw()
|
self.toolbar.draw()
|
||||||
|
|
||||||
def refreshCurrentCard(self, note):
|
def refreshCurrentCard(self, note):
|
||||||
self.model.refreshNote(note)
|
self.model.refreshNote(note)
|
||||||
|
self._renderPreview(False)
|
||||||
|
|
||||||
def refreshCurrentCardFilter(self, flag, note, fidx):
|
def refreshCurrentCardFilter(self, flag, note, fidx):
|
||||||
self.refreshCurrentCard(note)
|
self.refreshCurrentCard(note)
|
||||||
return flag
|
return flag
|
||||||
|
|
||||||
|
def currentRow(self):
|
||||||
|
idx = self.form.tableView.selectionModel().currentIndex()
|
||||||
|
return idx.row()
|
||||||
|
|
||||||
# Headers & sorting
|
# Headers & sorting
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
@ -942,6 +956,105 @@ where id in %s""" % ids2str(sf))
|
|||||||
self.close()
|
self.close()
|
||||||
self.mw.onCram(self.selectedCards())
|
self.mw.onCram(self.selectedCards())
|
||||||
|
|
||||||
|
# Preview
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
def onTogglePreview(self):
|
||||||
|
if self._previewWindow:
|
||||||
|
self._closePreview()
|
||||||
|
else:
|
||||||
|
self._openPreview()
|
||||||
|
|
||||||
|
def _openPreview(self):
|
||||||
|
c = self.connect
|
||||||
|
self._previewWindow = QDialog()
|
||||||
|
self._previewWindow.setWindowTitle(_("Preview"))
|
||||||
|
c(self._previewWindow, SIGNAL("finished(int)"), self._onPreviewFinished)
|
||||||
|
vbox = QVBoxLayout()
|
||||||
|
vbox.setMargin(0)
|
||||||
|
self._previewWeb = AnkiWebView()
|
||||||
|
vbox.addWidget(self._previewWeb)
|
||||||
|
bbox = QDialogButtonBox()
|
||||||
|
self._previewPrev = bbox.addButton("<", QDialogButtonBox.ActionRole)
|
||||||
|
self._previewPrev.setAutoDefault(False)
|
||||||
|
self._previewPrev.setShortcut(QKeySequence("Left"))
|
||||||
|
self._previewNext = bbox.addButton(">", QDialogButtonBox.ActionRole)
|
||||||
|
self._previewNext.setAutoDefault(False)
|
||||||
|
self._previewNext.setShortcut(QKeySequence("Right"))
|
||||||
|
c(self._previewPrev, SIGNAL("clicked()"), self._onPreviewPrev)
|
||||||
|
c(self._previewNext, SIGNAL("clicked()"), self._onPreviewNext)
|
||||||
|
vbox.addWidget(bbox)
|
||||||
|
self._previewWindow.setLayout(vbox)
|
||||||
|
restoreGeom(self._previewWindow, "preview")
|
||||||
|
self._previewWindow.show()
|
||||||
|
self._previewState = "question"
|
||||||
|
self._renderPreview(True)
|
||||||
|
|
||||||
|
def _onPreviewFinished(self, ok):
|
||||||
|
saveGeom(self._previewWindow, "preview")
|
||||||
|
self.mw.progress.timer(100, self._onClosePreview, False)
|
||||||
|
self.form.previewButton.setChecked(False)
|
||||||
|
|
||||||
|
def _onPreviewPrev(self):
|
||||||
|
if self._previewState == "question":
|
||||||
|
self._previewState = "answer"
|
||||||
|
self._renderPreview()
|
||||||
|
else:
|
||||||
|
self.onPreviousCard()
|
||||||
|
self._updatePreviewButtons()
|
||||||
|
|
||||||
|
def _onPreviewNext(self):
|
||||||
|
if self._previewState == "question":
|
||||||
|
self._previewState = "answer"
|
||||||
|
self._renderPreview()
|
||||||
|
else:
|
||||||
|
self.onNextCard()
|
||||||
|
self._updatePreviewButtons()
|
||||||
|
|
||||||
|
def _updatePreviewButtons(self):
|
||||||
|
if not self._previewWindow:
|
||||||
|
return
|
||||||
|
canBack = self.currentRow() > 0 or self._previewState == "question"
|
||||||
|
self._previewPrev.setEnabled(not not (self.card and canBack))
|
||||||
|
canForward = self.currentRow() < self.model.rowCount(None) - 1 or \
|
||||||
|
self._previewState == "question"
|
||||||
|
self._previewNext.setEnabled(not not (self.card and canForward))
|
||||||
|
|
||||||
|
def _closePreview(self):
|
||||||
|
if self._previewWindow:
|
||||||
|
self._previewWindow.close()
|
||||||
|
self._onClosePreview()
|
||||||
|
|
||||||
|
def _onClosePreview(self):
|
||||||
|
self._previewWindow = self._previewPrev = self._previewNext = None
|
||||||
|
|
||||||
|
def _renderPreview(self, cardChanged=False):
|
||||||
|
if not self._previewWindow:
|
||||||
|
return
|
||||||
|
c = self.card
|
||||||
|
if not c:
|
||||||
|
txt = _("(please select 1 card)")
|
||||||
|
self._previewWeb.stdHtml(txt)
|
||||||
|
self._updatePreviewButtons()
|
||||||
|
return
|
||||||
|
self._updatePreviewButtons()
|
||||||
|
if cardChanged:
|
||||||
|
self._previewState = "question"
|
||||||
|
# need to force reload even if answer
|
||||||
|
txt = c.q(reload=True)
|
||||||
|
if self._previewState == "answer":
|
||||||
|
txt = c.a()
|
||||||
|
txt = re.sub("\[\[type:[^]]+\]\]", "", txt)
|
||||||
|
ti = lambda x: x
|
||||||
|
base = getBase(self.mw.col)
|
||||||
|
self._previewWeb.stdHtml(
|
||||||
|
ti(mungeQA(txt)), self.mw.reviewer._styles(),
|
||||||
|
bodyClass="card card%d" % (c.ord+1), head=base,
|
||||||
|
js=anki.js.browserSel)
|
||||||
|
clearAudioQueue()
|
||||||
|
if self.mw.reviewer.autoplay(c):
|
||||||
|
playFromText(txt)
|
||||||
|
|
||||||
# Card deletion
|
# Card deletion
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ function _typeAnsPress() {
|
|||||||
The front of this card is empty. Please run Tools>Maintenance>Empty Cards.""")
|
The front of this card is empty. Please run Tools>Maintenance>Empty Cards.""")
|
||||||
else:
|
else:
|
||||||
q = c.q()
|
q = c.q()
|
||||||
if self._autoplay(c):
|
if self.autoplay(c):
|
||||||
playFromText(q)
|
playFromText(q)
|
||||||
# render & update bottom
|
# render & update bottom
|
||||||
q = self._mungeQA(q)
|
q = self._mungeQA(q)
|
||||||
@ -200,9 +200,9 @@ The front of this card is empty. Please run Tools>Maintenance>Empty Cards.""")
|
|||||||
# user hook
|
# user hook
|
||||||
runHook('showQuestion')
|
runHook('showQuestion')
|
||||||
|
|
||||||
def _autoplay(self, card):
|
def autoplay(self, card):
|
||||||
return self.mw.col.decks.confForDid(
|
return self.mw.col.decks.confForDid(
|
||||||
self.card.odid or self.card.did)['autoplay']
|
card.odid or card.did)['autoplay']
|
||||||
|
|
||||||
def _replayq(self, card):
|
def _replayq(self, card):
|
||||||
return self.mw.col.decks.confForDid(
|
return self.mw.col.decks.confForDid(
|
||||||
@ -223,7 +223,7 @@ The front of this card is empty. Please run Tools>Maintenance>Empty Cards.""")
|
|||||||
c = self.card
|
c = self.card
|
||||||
a = c.a()
|
a = c.a()
|
||||||
# play audio?
|
# play audio?
|
||||||
if self._autoplay(c):
|
if self.autoplay(c):
|
||||||
playFromText(a)
|
playFromText(a)
|
||||||
# render and update bottom
|
# render and update bottom
|
||||||
a = self._mungeQA(a)
|
a = self._mungeQA(a)
|
||||||
|
@ -96,13 +96,6 @@
|
|||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QPushButton" name="searchButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Search</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QComboBox" name="searchEdit">
|
<widget class="QComboBox" name="searchEdit">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -119,6 +112,26 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QPushButton" name="searchButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Search</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QPushButton" name="previewButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Preview</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+Shift+P</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
Loading…
Reference in New Issue
Block a user