html editor

This commit is contained in:
Damien Elmes 2011-04-06 01:28:27 +09:00
parent 5702ec2da1
commit 6f0168aec1

View file

@ -12,6 +12,7 @@ from anki.hooks import addHook, removeHook, runHook, runFilter
from aqt.sound import getAudio from aqt.sound import getAudio
from aqt.webview import AnkiWebView from aqt.webview import AnkiWebView
from aqt.utils import shortcut, showInfo, showWarning, getBase, getFile from aqt.utils import shortcut, showInfo, showWarning, getBase, getFile
import aqt
import anki.js import anki.js
pics = ("jpg", "jpeg", "png", "tif", "tiff", "gif") pics = ("jpg", "jpeg", "png", "tif", "tiff", "gif")
@ -103,6 +104,7 @@ function onBlur() {
function saveField(type) { function saveField(type) {
// type is either 'blur' or 'key' // type is either 'blur' or 'key'
py.run(type + ":" + currentField.innerHTML); py.run(type + ":" + currentField.innerHTML);
clearChangeTimer();
}; };
function wrap(front, back) { function wrap(front, back) {
@ -117,7 +119,7 @@ function wrap(front, back) {
setFormat('inserthtml', front + span.innerHTML + back); setFormat('inserthtml', front + span.innerHTML + back);
}; };
function setFields(fields) { function setFields(fields, focusTo) {
var txt = ""; var txt = "";
for (var i=0; i<fields.length; i++) { for (var i=0; i<fields.length; i++) {
var n = fields[i][0]; var n = fields[i][0];
@ -129,7 +131,10 @@ function setFields(fields) {
txt += "</td></tr>"; txt += "</td></tr>";
} }
$("#fields").html("<table cellpadding=3>"+txt+"</table>"); $("#fields").html("<table cellpadding=3>"+txt+"</table>");
$("#f0").focus(); if (!focusTo) {
focusTo = 0;
}
$("#f"+focusTo).focus();
}; };
$(function () { $(function () {
@ -165,11 +170,8 @@ class Editor(object):
self.widget = widget self.widget = widget
self.mw = mw self.mw = mw
self.fact = None self.fact = None
self.onChange = None
self._loaded = False self._loaded = False
# to be handled js side self._keepButtons = False
#self.lastFocusedEdit = None
self.changeTimer = None
# current card, for card layout # current card, for card layout
self.card = None self.card = None
addHook("deckClosed", self.deckClosedHook) addHook("deckClosed", self.deckClosedHook)
@ -266,14 +268,15 @@ class Editor(object):
_("Cloze (Ctrl+Shift+c)"), text="[...]") _("Cloze (Ctrl+Shift+c)"), text="[...]")
but.setFixedWidth(24) but.setFixedWidth(24)
# fixme: better image names # fixme: better image names
b("text-speak", self.onAddMedia, "F3", _("Add audio/video (F4)")) b("text-speak", self.onAddMedia, "F3", _("Add pictures/audio/video (F3)"))
b("media-record", self.onRecSound, "F5", _("Record audio (F5)")) b("media-record", self.onRecSound, "F5", _("Record audio (F5)"))
b("tex", self.insertLatex, "Ctrl+t, t", _("LaTeX (Ctrl+t then t)")) b("tex", self.insertLatex, "Ctrl+t, t", _("LaTeX (Ctrl+t then t)"))
b("math_sqrt", self.insertLatexEqn, "Ctrl+t, e", b("math_sqrt", self.insertLatexEqn, "Ctrl+t, e",
_("LaTeX equation (Ctrl+t then e)")) _("LaTeX equation (Ctrl+t then e)"))
b("math_matrix", self.insertLatexMathEnv, "Ctrl+t, m", b("math_matrix", self.insertLatexMathEnv, "Ctrl+t, m",
_("LaTeX math environment (Ctrl+t then m)")) _("LaTeX math environment (Ctrl+t then m)"))
but = b("text-xml", self.onHtmlEdit, "Ctrl+x", _("Source (Ctrl+x)")) but = b("text-xml", self.onHtmlEdit, "Ctrl+Shift+x",
_("Source (Ctrl+Shift+x)"))
def enableButtons(self, val=True): def enableButtons(self, val=True):
for b in self._buttons.values(): for b in self._buttons.values():
@ -296,10 +299,11 @@ class Editor(object):
def bridge(self, str): def bridge(self, str):
# focus lost or key/button pressed? # focus lost or key/button pressed?
if str.startswith("blur") or str.startswith("key"): if str.startswith("blur") or str.startswith("key"):
print "save fact"
(type, txt) = str.split(":", 1) (type, txt) = str.split(":", 1)
self.fact._fields[self.currentField] = txt self.fact._fields[self.currentField] = txt
print "save fact", txt
if type == "blur": if type == "blur":
if not self._keepButtons:
self.disableButtons() self.disableButtons()
runHook("editor.focusLost", self.fact) runHook("editor.focusLost", self.fact)
else: else:
@ -333,9 +337,7 @@ class Editor(object):
def setFact(self, fact): def setFact(self, fact):
"Make FACT the current fact." "Make FACT the current fact."
self.fact = fact self.fact = fact
if self.changeTimer: # change timer
self.changeTimer.stop()
self.changeTimer = None
if self.fact: if self.fact:
self.web.setHtml(_html % (getBase(self.mw.deck), anki.js.all), self.web.setHtml(_html % (getBase(self.mw.deck), anki.js.all),
loadCB=self._loadFinished) loadCB=self._loadFinished)
@ -343,12 +345,13 @@ class Editor(object):
else: else:
self.widget.hide() self.widget.hide()
def loadFact(self): def loadFact(self, field=0):
if not self._loaded: if not self._loaded:
# will be loaded when page is ready # will be loaded when page is ready
return return
# fixme: focus on first widget # fixme: focus on first widget
self.web.eval("setFields(%s);" % simplejson.dumps(self.fact.items())) self.web.eval("setFields(%s, %d);" % (
simplejson.dumps(self.fact.items()), field))
self.widget.show() self.widget.show()
def refresh(self): def refresh(self):
@ -381,21 +384,16 @@ class Editor(object):
"Must call this before adding cards, closing dialog, etc." "Must call this before adding cards, closing dialog, etc."
if not self.fact: if not self.fact:
return return
# disable timer self._keepButtons = True
if self.changeTimer: self.web.eval("saveField('blur');")
self.changeTimer.stop() self._keepButtons = False
self.changeTimer = None
if self.onChange:
self.onChange('field')
# save fields and run features
w = self.focusedEdit()
if w:
self.onFocusLost(w)
self.onTagChange() self.onTagChange()
self.onGroupChange()
# ensure valid # ensure valid
self.checkValid() self.checkValid()
def checkValid(self): def checkValid(self):
return
empty = [] empty = []
dupe = [] dupe = []
for field in self.fact.fields: for field in self.fact.fields:
@ -413,23 +411,22 @@ class Editor(object):
p.setColor(QPalette.Base, QColor("#ffffff")) p.setColor(QPalette.Base, QColor("#ffffff"))
self.fields[field.name][1].setPalette(p) self.fields[field.name][1].setPalette(p)
# HTML editing
######################################################################
def onHtmlEdit(self): def onHtmlEdit(self):
def helpRequested(): self.saveFieldsNow()
aqt.openHelp("HtmlEditor")
w = self.focusedEdit()
if w:
self.saveFields()
d = QDialog(self.widget) d = QDialog(self.widget)
form = aqt.forms.edithtml.Ui_Dialog() form = aqt.forms.edithtml.Ui_Dialog()
form.setupUi(d) form.setupUi(d)
d.connect(form.buttonBox, SIGNAL("helpRequested()"), d.connect(form.buttonBox, SIGNAL("helpRequested()"),
helpRequested) lambda: aqt.openHelp("HtmlEditor"))
form.textEdit.setPlainText(self.widgets[w].value) form.textEdit.setPlainText(self.fact._fields[self.currentField])
form.textEdit.moveCursor(QTextCursor.End) form.textEdit.moveCursor(QTextCursor.End)
d.exec_() d.exec_()
w.setHtml(unicode(form.textEdit.toPlainText()).\ self.fact._fields[self.currentField] = unicode(
replace("\n", "")) form.textEdit.toPlainText())
self.saveFields() self.loadFact(self.currentField)
# Tag and group handling # Tag and group handling
###################################################################### ######################################################################
@ -468,6 +465,7 @@ class Editor(object):
pass pass
def onTagChange(self): def onTagChange(self):
return
if not self.fact: if not self.fact:
return return
old = self.fact.tags old = self.fact.tags
@ -478,8 +476,6 @@ class Editor(object):
self.fact.setModified(textChanged=True, deck=self.deck) self.fact.setModified(textChanged=True, deck=self.deck)
self.deck.flushMod() self.deck.flushMod()
self.mw.reset(runHooks=False) self.mw.reset(runHooks=False)
if self.onChange:
self.onChange('tag')
# Format buttons # Format buttons
###################################################################### ######################################################################