mirror of
https://github.com/ankitects/anki.git
synced 2025-11-11 07:07:13 -05:00
html editor
This commit is contained in:
parent
5702ec2da1
commit
6f0168aec1
1 changed files with 39 additions and 43 deletions
|
|
@ -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
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue