|
# -*- mode: Python ; coding: utf-8 -*- |
|
# |
|
# Copyright © 2013–16 Roland Sieker <ospalh@gmail.com> |
|
# |
|
# License: GNU AGPL, version 3 or later; |
|
# http://www.gnu.org/copyleft/agpl.html |
|
|
|
"""Add-on for Anki 2 to add AnkiDroid-style replay buttons.""" |
|
|
|
import os |
|
import re |
|
import shutil |
|
|
|
from BeautifulSoup import BeautifulSoup |
|
from PyQt4.QtCore import QUrl |
|
from PyQt4.QtGui import QDesktopServices |
|
|
|
from anki.cards import Card |
|
from anki.hooks import addHook, wrap |
|
from anki.sound import play, stopMplayer, clearMplayerQueue |
|
from aqt import mw |
|
from aqt.browser import Browser |
|
from aqt.browser import DataModel |
|
from aqt.clayout import CardLayout |
|
from aqt.sound import getAudio |
|
from aqt.reviewer import Reviewer |
|
|
|
__version__ = "1.0.0" |
|
|
|
sound_re = ur"\[sound:(.*?)\]" |
|
|
|
hide_class_name = u'browserhide' |
|
|
|
|
|
def svg_css(Card): |
|
"""Add the svg button style to the card style""" |
|
return u"""<style scoped> |
|
.replaybutton span { |
|
display: inline-block; |
|
vertical-align: middle; |
|
padding: 5px; |
|
} |
|
|
|
.replaybutton span svg { |
|
stroke: none; |
|
fill: black; |
|
display: inline; |
|
height: 1em; |
|
width: 1em; |
|
min-width: 12px; |
|
min-height: 12px; |
|
} |
|
</style> |
|
""" + old_css(Card) |
|
|
|
|
|
def play_button_filter( |
|
qa_html, qa_type, dummy_fields, dummy_model, dummy_data, dummy_col): |
|
|
|
return qa_html + u"""<a href='javascript:py.link("ankirecord");' \ |
|
title="" class="replaybutton browserhide"><span><svg height="12" width="12">\ |
|
<circle cx="12" cy="11" r="6" fill="red" />\ |
|
Record Own Voice</svg></span></a>\ |
|
<span style="display: none;">[sound:]</span>\ |
|
<a href='javascript:py.link("ankiplayrecord");' \ |
|
title="" class="replaybutton browserhide"><span><span><svg viewBox="0 0 32 32">\ |
|
<polygon points="11,25 25,16 11,7" fill="green"/>Replay Own Voice</svg></span></a>\ |
|
<span style="display: none;">[sound:]</span>""" |
|
|
|
def review_link_handler_wrapper(reviewer, url): |
|
u"""Play the sound or call the original link handler.""" |
|
if url.startswith("ankirecord"): |
|
reviewer._recordedAudio = getAudio(reviewer.mw, encode=False) |
|
elif url.startswith("ankiplayrecord"): |
|
reviewer.onReplayRecorded() |
|
else: |
|
original_review_link_handler(reviewer, url) |
|
|
|
def reduce_format_qa(self, text): |
|
u"""Remove elements with a given class before displaying.""" |
|
soup = BeautifulSoup(text) |
|
for hide in soup.findAll(True, {'class': re.compile( |
|
'\\b' + hide_class_name + '\\b')}): |
|
hide.extract() |
|
return original_format_qa(self, unicode(soup)) |
|
|
|
|
|
original_review_link_handler = Reviewer._linkHandler |
|
Reviewer._linkHandler = review_link_handler_wrapper |
|
|
|
original_format_qa = DataModel.formatQA |
|
DataModel.formatQA = reduce_format_qa |
|
|
|
old_css = Card.css |
|
Card.css = svg_css |
|
|
|
addHook("mungeQA", play_button_filter) |