early work on new editor

This commit is contained in:
Damien Elmes 2011-04-01 22:05:26 +09:00
parent bdf36c7d5a
commit a4b08ff766
6 changed files with 223 additions and 453 deletions

View file

@ -50,8 +50,7 @@ class DialogManager(object):
return instance return instance
def close(self, name): def close(self, name):
self._dialogs[name] = ( self._dialogs[name] = [self._dialogs[name][0], None]
self._dialogs[name][0], None)
def closeAll(self): def closeAll(self):
for (n, (creator, instance)) in self._dialogs.items(): for (n, (creator, instance)) in self._dialogs.items():

View file

@ -9,10 +9,10 @@ import anki
from anki.facts import Fact from anki.facts import Fact
from anki.errors import * from anki.errors import *
from anki.utils import stripHTML, parseTags from anki.utils import stripHTML, parseTags
from aqt.utils import saveGeom, restoreGeom, saveSplitter, restoreSplitter from aqt.utils import saveGeom, restoreGeom
from anki.sound import clearAudioQueue from anki.sound import clearAudioQueue
from anki.hooks import addHook, removeHook from anki.hooks import addHook, removeHook
import aqt.facteditor, aqt.modelchooser import aqt.editor, aqt.modelchooser
class FocusButton(QPushButton): class FocusButton(QPushButton):
def focusInEvent(self, evt): def focusInEvent(self, evt):
@ -22,39 +22,31 @@ class FocusButton(QPushButton):
class AddCards(QDialog): class AddCards(QDialog):
def __init__(self, parent): def __init__(self, mw):
windParent = None windParent = None
QDialog.__init__(self, windParent, Qt.Window) QDialog.__init__(self, windParent, Qt.Window)
self.parent = parent self.mw = mw
self.config = parent.config self.dialog = aqt.forms.addcards.Ui_Dialog()
self.dialog = aqt.forms.addcards.Ui_AddCards()
self.dialog.setupUi(self) self.dialog.setupUi(self)
self.setWindowTitle(_("Add Items - %s") % parent.deck.name()) self.setWindowTitle(_("Add"))
self.setupEditor() self.setupEditor()
self.addChooser() self.addChooser()
self.addButtons() self.addButtons()
self.setupStatus()
self.modelChanged() self.modelChanged()
self.addedItems = 0 self.addedItems = 0
self.forceClose = False self.forceClose = False
restoreGeom(self, "add") restoreGeom(self, "add")
restoreSplitter(self.dialog.splitter, "add")
self.dialog.splitter.setChildrenCollapsible(False)
self.show() self.show()
addHook('guiReset', self.modelChanged) addHook('guiReset', self.modelChanged)
def setupEditor(self): def setupEditor(self):
self.editor = aqt.facteditor.FactEditor(self, self.editor = aqt.editor.Editor(self.mw, self.dialog.fieldsArea)
self.dialog.fieldsArea,
self.parent.deck)
self.editor.addMode = True
self.editor.resetOnEdit = False
def addChooser(self): def addChooser(self):
return return
self.modelChooser = aqt.modelchooser.ModelChooser(self, self.modelChooser = aqt.modelchooser.ModelChooser(self,
self.parent, self.mw,
self.parent.deck, self.mw.deck,
self.modelChanged) self.modelChanged)
self.dialog.modelArea.setLayout(self.modelChooser) self.dialog.modelArea.setLayout(self.modelChooser)
@ -83,18 +75,8 @@ class AddCards(QDialog):
QDialogButtonBox.HelpRole) QDialogButtonBox.HelpRole)
self.connect(self.helpButton, SIGNAL("clicked()"), self.helpRequested) self.connect(self.helpButton, SIGNAL("clicked()"), self.helpRequested)
def setupStatus(self):
"Make the status background the same colour as the frame."
if not sys.platform.startswith("darwin"):
p = self.dialog.status.palette()
c = unicode(p.color(QPalette.Window).name())
self.dialog.status.setStyleSheet(
"* { background: %s; }" % c)
self.connect(self.dialog.status, SIGNAL("anchorClicked(QUrl)"),
self.onLink)
def onLink(self, url): def onLink(self, url):
browser = ui.dialogs.open("CardList", self.parent) browser = ui.dialogs.open("CardList", self.mw)
browser.dialog.filterEdit.setText("fid:" + url.toString()) browser.dialog.filterEdit.setText("fid:" + url.toString())
browser.updateSearch() browser.updateSearch()
browser.onFact() browser.onFact()
@ -103,7 +85,7 @@ class AddCards(QDialog):
return return
oldFact = self.editor.fact oldFact = self.editor.fact
# create a new fact # create a new fact
fact = self.parent.deck.newFact() fact = self.mw.deck.newFact()
# copy fields from old fact # copy fields from old fact
if oldFact: if oldFact:
n = 0 n = 0
@ -115,7 +97,7 @@ class AddCards(QDialog):
n += 1 n += 1
fact.tags = oldFact.tags fact.tags = oldFact.tags
else: else:
fact.tags = "last" #self.parent.deck.lastTags fact.tags = "last" #self.mw.deck.lastTags
# set the new fact # set the new fact
self.editor.setFact(fact, check=True, forceRedraw=True) self.editor.setFact(fact, check=True, forceRedraw=True)
self.setTabOrder(self.editor.tags, self.addButton) self.setTabOrder(self.editor.tags, self.addButton)
@ -134,7 +116,7 @@ class AddCards(QDialog):
def addFact(self, fact): def addFact(self, fact):
try: try:
fact = self.parent.deck.addFact(fact, False) fact = self.mw.deck.addFact(fact, False)
except FactInvalidError: except FactInvalidError:
ui.utils.showInfo(_( ui.utils.showInfo(_(
"Some fields are missing or not unique."), "Some fields are missing or not unique."),
@ -151,15 +133,15 @@ question or answer on all cards."""), parent=self)
return fact return fact
def initializeNewFact(self, old_fact): def initializeNewFact(self, old_fact):
f = self.parent.deck.newFact() f = self.mw.deck.newFact()
f.tags = self.parent.deck.lastTags f.tags = self.mw.deck.lastTags
return f return f
def clearOldFact(self, old_fact): def clearOldFact(self, old_fact):
f = self.initializeNewFact(old_fact) f = self.initializeNewFact(old_fact)
self.editor.setFact(f, check=True, scroll=True) self.editor.setFact(f, check=True, scroll=True)
# let completer know our extra tags # let completer know our extra tags
self.editor.tags.addTags(parseTags(self.parent.deck.lastTags)) self.editor.tags.addTags(parseTags(self.mw.deck.lastTags))
return f return f
def addCards(self): def addCards(self):
@ -167,7 +149,7 @@ question or answer on all cards."""), parent=self)
self.editor.saveFieldsNow() self.editor.saveFieldsNow()
fact = self.editor.fact fact = self.editor.fact
n = _("Add") n = _("Add")
self.parent.deck.setUndoStart(n) self.mw.deck.setUndoStart(n)
fact = self.addFact(fact) fact = self.addFact(fact)
if not fact: if not fact:
@ -176,15 +158,14 @@ question or answer on all cards."""), parent=self)
# stop anything playing # stop anything playing
clearAudioQueue() clearAudioQueue()
self.parent.deck.setUndoEnd(n) self.mw.deck.setUndoEnd(n)
self.parent.deck.rebuildCounts() self.mw.deck.rebuildCounts()
self.parent.updateTitleBar() self.mw.updateTitleBar()
self.parent.statusView.redraw()
# start a new fact # start a new fact
self.clearOldFact(fact) self.clearOldFact(fact)
self.maybeSave() self.mw.autosave()
def keyPressEvent(self, evt): def keyPressEvent(self, evt):
"Show answer on RET or register answer." "Show answer on RET or register answer."
@ -201,11 +182,17 @@ question or answer on all cards."""), parent=self)
evt.ignore() evt.ignore()
def reject(self): def reject(self):
# remove dupe
aqt.dialogs.close("AddCards")
QDialog.reject(self)
if self.onClose(): if self.onClose():
self.modelChooser.deinit() self.modelChooser.deinit()
QDialog.reject(self) QDialog.reject(self)
def onClose(self): def onClose(self):
return
removeHook('guiReset', self.modelChanged) removeHook('guiReset', self.modelChanged)
# stop anything playing # stop anything playing
clearAudioQueue() clearAudioQueue()
@ -215,19 +202,10 @@ question or answer on all cards."""), parent=self)
self.modelChooser.deinit() self.modelChooser.deinit()
self.editor.close() self.editor.close()
ui.dialogs.close("AddCards") ui.dialogs.close("AddCards")
self.parent.deck.db.flush() self.mw.deck.db.flush()
self.parent.deck.rebuildCSS() self.mw.deck.rebuildCSS()
self.parent.reset() self.mw.reset()
saveGeom(self, "add") saveGeom(self, "add")
saveSplitter(self.dialog.splitter, "add")
return True return True
else: else:
return False return False
def maybeSave(self):
"Increment added count and maybe save deck."
self.addedItems += 1
if not self.parent.config['saveAfterAdding']:
return
if (self.addedItems % self.parent.config['saveAfterAddingNum']) == 0:
self.parent.save()

View file

@ -45,8 +45,7 @@ class CardLayout(QDialog):
restoreGeom(self, "CardLayout") restoreGeom(self, "CardLayout")
self.reload() self.reload()
if not self.cards: if not self.cards:
showInfo(_("Please enter some text first."), showInfo(_("Please enter some text first."))
parent=self.parent)
return return
self.exec_() self.exec_()
@ -411,12 +410,9 @@ class CardLayout(QDialog):
if row == -1: if row == -1:
return return
if len(self.model.fields) < 2: if len(self.model.fields) < 2:
showInfo( showInfo(_("Please add a new field first."))
_("Please add a new field first."),
parent=self)
return return
if askUser(_("Delete this field and its data from all facts?"), if askUser(_("Delete this field and its data from all facts?")):
self.parent):
self.mw.progress.start() self.mw.progress.start()
self.model.delField(self.field) self.model.delField(self.field)
self.mw.progress.finish() self.mw.progress.finish()

View file

@ -29,8 +29,6 @@ class EditCurrent(object):
self.editor = aqt.facteditor.FactEditor( self.editor = aqt.facteditor.FactEditor(
self, self.form.fieldsArea, self.deck) self, self.form.fieldsArea, self.deck)
self.editor.clayout.setShortcut("") self.editor.clayout.setShortcut("")
self.editor.onFactValid = self.onFactValid
self.editor.onFactInvalid = self.onFactInvalid
self.editor.resetOnEdit = False self.editor.resetOnEdit = False
# editor # editor
self.connect(self.form.saveEditorButton, SIGNAL("clicked()"), self.connect(self.form.saveEditorButton, SIGNAL("clicked()"),
@ -41,9 +39,3 @@ class EditCurrent(object):
self.switchToEditScreen() self.switchToEditScreen()
self.editor.setFact(self.currentCard.fact) self.editor.setFact(self.currentCard.fact)
self.editor.card = self.currentCard self.editor.card = self.currentCard
def onFactValid(self, fact):
self.form.saveEditorButton.setEnabled(True)
def onFactInvalid(self, fact):
self.form.saveEditorButton.setEnabled(False)

View file

@ -4,21 +4,17 @@
from PyQt4.QtGui import * from PyQt4.QtGui import *
from PyQt4.QtCore import * from PyQt4.QtCore import *
from PyQt4.QtSvg import * from PyQt4.QtSvg import * # fixme: obsolete?
from PyQt4.QtWebKit import QWebPage
import re, os, sys, tempfile, urllib2, ctypes import re, os, sys, tempfile, urllib2, ctypes
from anki.utils import stripHTML, tidyHTML, canonifyTags, fieldChecksum from anki.utils import stripHTML
from aqt.sound import getAudio from anki.sound import play
import anki.sound
import aqt
from aqt.utils import mungeQA, saveGeom, restoreGeom
from anki.hooks import addHook, removeHook, runHook, runFilter from anki.hooks import addHook, removeHook, runHook, runFilter
from sqlalchemy.exceptions import InvalidRequestError from aqt.sound import getAudio
from aqt.webview import AnkiWebView
from aqt.utils import shortcut
# fixme: use shortcut() for mac shortcuts # fixme: use shortcut() for mac shortcuts
clozeColour = "#0000ff"
if sys.platform.startswith("win32"): if sys.platform.startswith("win32"):
ActivateKeyboardLayout = ctypes.windll.user32.ActivateKeyboardLayout ActivateKeyboardLayout = ctypes.windll.user32.ActivateKeyboardLayout
ActivateKeyboardLayout.restype = ctypes.c_void_p ActivateKeyboardLayout.restype = ctypes.c_void_p
@ -27,38 +23,173 @@ if sys.platform.startswith("win32"):
GetKeyboardLayout.restype = ctypes.c_void_p GetKeyboardLayout.restype = ctypes.c_void_p
GetKeyboardLayout.argtypes = [ctypes.c_uint] GetKeyboardLayout.argtypes = [ctypes.c_uint]
class FactEditor(object): class Editor(object):
"""An editor for new/existing facts. def __init__(self, mw, widget):
The fact is updated as it is edited.
Extra widgets can be added to 'fieldsGrid' to represent card-specific
information, etc."""
def __init__(self, parent, widget, deck=None):
self.widget = widget self.widget = widget
self.parent = parent self.mw = mw
self.deck = deck
self.fact = None self.fact = None
self.fontChanged = False
self.addMode = False
#self.setupFields()
self.onChange = None self.onChange = None
self.onFactValid = None # to be handled js side
self.onFactInvalid = None #self.lastFocusedEdit = None
self.lastFocusedEdit = None
self.changeTimer = None self.changeTimer = None
self.lastCloze = None # current card, for card layout
self.resetOnEdit = True
self.card = None self.card = None
addHook("deckClosed", self.deckClosedHook) addHook("deckClosed", self.deckClosedHook)
addHook("guiReset", self.refresh) addHook("guiReset", self.refresh)
addHook("colourChanged", self.colourChanged) addHook("colourChanged", self.colourChanged)
self.setupOuter()
self.setupButtons()
self.setupWeb()
self.setupTags()
def close(self): def close(self):
removeHook("deckClosed", self.deckClosedHook) removeHook("deckClosed", self.deckClosedHook)
removeHook("guiReset", self.refresh) removeHook("guiReset", self.refresh)
removeHook("colourChanged", self.colourChanged) removeHook("colourChanged", self.colourChanged)
# Initial setup
############################################################
def setupOuter(self):
l = QVBoxLayout()#self.widget)
l.setMargin(0)
l.setSpacing(3)
self.widget.setLayout(l)
self.outerLayout = l
def _addButton(self, name, func, key=None, tip=None, size=True, text="",
check=False):
b = QPushButton(text)
if check:
b.connect(b, SIGNAL("toggled(bool)"), func)
else:
b.connect(b, SIGNAL("clicked()"), func)
if size:
b.setFixedHeight(20)
b.setFixedWidth(20)
b.setStyle(self.plastiqueStyle)
b.setFocusPolicy(Qt.NoFocus)
if not text:
b.setIcon(QIcon(":/icons/%s.png" % name))
if key:
b.setShortcut(key)
if tip:
b.setToolTip(tip)
if check:
b.setCheckable(True)
self.iconsBox.addWidget(b)
self._buttons[name] = b
return b
def setupButtons(self):
self._buttons = {}
# button styles for mac
self.plastiqueStyle = QStyleFactory.create("plastique")
self.widget.setStyle(self.plastiqueStyle)
# icons
self.iconsBox = QHBoxLayout()
self.iconsBox.setMargin(0)
self.iconsBox.setSpacing(0)
self.outerLayout.addLayout(self.iconsBox)
# align to right
self.iconsBox.addItem(QSpacerItem(20,1, QSizePolicy.Expanding))
b = self._addButton
b("layout", self.onCardLayout, "Ctrl+l",
shortcut(_("Layout (Ctrl+l)")), size=False, text=_("Layout..."))
b("text_bold", self.toggleBold, "Ctrl+b", _("Bold text (Ctrl+b)"),
check=True)
b("text_italic", self.toggleItalic, "Ctrl+i", _("Italic text (Ctrl+i)"),
check=True)
b("text_under", self.toggleUnderline, "Ctrl+i",
_("Underline text (Ctrl+i)"), check=True)
#self.setupForegroundButton()
but = b("cloze", self.onCloze, "F9", _("Cloze (F9)"), text="[...]")
but.setFixedWidth(24)
# fixme: better image names
but = b("colors", self.onAddPicture, "F3", _("Add picture (F3)"))
but = b("text-speak", self.onAddSound, "F3", _("Add audio/video (F4)"))
but = b("media-record", self.onRecSound, "F5", _("Record audio (F5)"))
but = b("tex", self.latexMenu, "Ctrl+t", _("LaTeX (Ctrl+t)"))
# insertLatex, insertLatexEqn, insertLatexMathEnv
but = b("text-xml", self.onHtmlEdit, "Ctrl+x", _("Source (Ctrl+x)"))
def setupForegroundButton(self):
# foreground color
self.foreground = QPushButton()
self.foreground.connect(self.foreground, SIGNAL("clicked()"), self.onForeground)
self.foreground.setToolTip(
_("Set colour (F7; repeat to choose next; F6 to use)"))
self.foreground.setShortcut(_("F7"))
self.foreground.setFocusPolicy(Qt.NoFocus)
self.foreground.setEnabled(False)
self.foreground.setFixedWidth(20)
self.foreground.setFixedHeight(20)
self.foregroundFrame = QFrame()
self.foregroundFrame.setAutoFillBackground(True)
self.colourChanged()
hbox = QHBoxLayout()
hbox.addWidget(self.foregroundFrame)
hbox.setMargin(5)
self.foreground.setLayout(hbox)
self.iconsBox.addWidget(self.foreground)
self.foreground.setStyle(self.plastiqueStyle)
self.iconsBox.addItem(QSpacerItem(5,1, QSizePolicy.Fixed))
def setupWeb(self):
self.web = AnkiWebView(self.widget)
self.outerLayout.addWidget(self.web)
# pick up the window colour
p = self.web.palette()
p.setBrush(QPalette.Base, Qt.transparent)
self.web.page().setPalette(p)
self.web.setAttribute(Qt.WA_OpaquePaintEvent, False)
self.web.setHtml("""
<html><head><style></style></head>
<body>
<table>
<tr>
<td valign=center>Expression</td>
<td width=100%><div contentEditable=true style="border: 1px solid #aaa; padding: 5px; background:#fff; color:#000;">this is some field
text</div></td>
</tr>
<tr>
<td valign=center>Meaning</td>
<td width=100%><div contentEditable=true style="border: 1px solid #aaa; padding: 5px; background:#fff; color:#000;">this is some field
text</div></td>
</tr>
<tr>
<td valign=center>Reading</td>
<td width=100%><div contentEditable=true style="border: 1px solid #aaa; padding: 5px; background:#fff; color:#000;">this is some field
text</div></td>
</tr>
</table>
</body></html>""")
def setupTags(self):
# # scrollarea
# self.fieldsScroll = QScrollArea()
# self.fieldsScroll.setWidgetResizable(True)
# self.fieldsScroll.setLineWidth(0)
# self.fieldsScroll.setFrameStyle(0)
# self.fieldsScroll.setFocusPolicy(Qt.NoFocus)
# self.fieldsBox.addWidget(self.fieldsScroll)
# # tags
# self.tagsBox = QHBoxLayout()
# self.tagsLabel = QLabel(_("Tags"))
# self.tagsBox.addWidget(self.tagsLabel)
# import aqt.tagedit
# self.tags = aqt.tagedit.TagEdit(self.parent)
# self.tags.connect(self.tags, SIGNAL("lostFocus"),
# self.onTagChange)
# self.tagsBox.addWidget(self.tags)
# self.fieldsBox.addLayout(self.tagsBox)
pass
def setFact(self, fact, noFocus=False, check=False, scroll=False, def setFact(self, fact, noFocus=False, check=False, scroll=False,
forceRedraw=False): forceRedraw=False):
"Make FACT the current fact." "Make FACT the current fact."
@ -82,7 +213,6 @@ class FactEditor(object):
if not noFocus: if not noFocus:
# update focus to first field # update focus to first field
self.fields[self.fact.fields[0].name][1].setFocus() self.fields[self.fact.fields[0].name][1].setFocus()
self.fontChanged = False
self.deck.setUndoBarrier() self.deck.setUndoBarrier()
if self.deck.mediaDir(create=False): if self.deck.mediaDir(create=False):
self.initMedia() self.initMedia()
@ -106,243 +236,6 @@ class FactEditor(object):
def deckClosedHook(self): def deckClosedHook(self):
self.fact = None self.fact = None
def setupFields(self):
# init for later
self.fields = {}
# button styles for mac
self.plastiqueStyle = QStyleFactory.create("plastique")
self.widget.setStyle(self.plastiqueStyle)
# top level vbox
self.fieldsBox = QVBoxLayout(self.widget)
self.fieldsBox.setMargin(0)
self.fieldsBox.setSpacing(3)
# icons
self.iconsBox = QHBoxLayout()
self.iconsBox2 = QHBoxLayout()
self.fieldsBox.addLayout(self.iconsBox)
self.fieldsBox.addLayout(self.iconsBox2)
# card layout
self.iconsBox.addItem(QSpacerItem(20,1, QSizePolicy.Expanding))
self.clayout = QPushButton(_("Card Layout"))
self.clayout.connect(self.clayout, SIGNAL("clicked()"), self.onCardLayout)
self.clayout.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
self.clayout.setFixedHeight(20)
# self.clayout.setFixedWidth(48)
self.clayout.setIcon(QIcon(":/icons/layout.png"))
#self.clayout.setIconSize(QSize(32,32))
self.clayout.setToolTip(_("Edit how cards are displayed (F2)"))
self.clayout.setShortcut(_("F2"))
self.clayout.setFocusPolicy(Qt.NoFocus)
self.iconsBox.addWidget(self.clayout)
self.clayout.setStyle(self.plastiqueStyle)
# scrollarea
self.fieldsScroll = QScrollArea()
self.fieldsScroll.setWidgetResizable(True)
self.fieldsScroll.setLineWidth(0)
self.fieldsScroll.setFrameStyle(0)
self.fieldsScroll.setFocusPolicy(Qt.NoFocus)
self.fieldsBox.addWidget(self.fieldsScroll)
# tags
self.tagsBox = QHBoxLayout()
self.tagsLabel = QLabel(_("Tags"))
self.tagsBox.addWidget(self.tagsLabel)
import aqt.tagedit
self.tags = aqt.tagedit.TagEdit(self.parent)
self.tags.connect(self.tags, SIGNAL("lostFocus"),
self.onTagChange)
self.tagsBox.addWidget(self.tags)
self.fieldsBox.addLayout(self.tagsBox)
# icons
self.iconsBox.setMargin(0)
self.iconsBox2.setMargin(0)
# bold
spc = QSpacerItem(5,5)
self.iconsBox.addItem(spc)
self.bold = QPushButton()
self.bold.setFixedHeight(20)
self.bold.setFixedWidth(20)
self.bold.setCheckable(True)
self.bold.connect(self.bold, SIGNAL("toggled(bool)"), self.toggleBold)
self.bold.setIcon(QIcon(":/icons/text_bold.png"))
self.bold.setToolTip(_("Bold text (Ctrl+b)"))
self.bold.setShortcut(_("Ctrl+b"))
self.bold.setFocusPolicy(Qt.NoFocus)
self.bold.setEnabled(False)
self.iconsBox.addWidget(self.bold)
self.bold.setStyle(self.plastiqueStyle)
# italic
self.italic = QPushButton(self.widget)
self.italic.setFixedHeight(20)
self.italic.setFixedWidth(20)
self.italic.setCheckable(True)
self.italic.connect(self.italic, SIGNAL("toggled(bool)"), self.toggleItalic)
self.italic.setIcon(QIcon(":/icons/text_italic.png"))
self.italic.setToolTip(_("Italic text (Ctrl+i)"))
self.italic.setShortcut(_("Ctrl+i"))
self.italic.setFocusPolicy(Qt.NoFocus)
self.italic.setEnabled(False)
self.iconsBox.addWidget(self.italic)
self.italic.setStyle(self.plastiqueStyle)
# underline
self.underline = QPushButton(self.widget)
self.underline.setFixedHeight(20)
self.underline.setFixedWidth(20)
self.underline.setCheckable(True)
self.underline.connect(self.underline, SIGNAL("toggled(bool)"), self.toggleUnderline)
self.underline.setIcon(QIcon(":/icons/text_under.png"))
self.underline.setToolTip(_("Underline text (Ctrl+u)"))
self.underline.setShortcut(_("Ctrl+u"))
self.underline.setFocusPolicy(Qt.NoFocus)
self.underline.setEnabled(False)
self.iconsBox.addWidget(self.underline)
self.underline.setStyle(self.plastiqueStyle)
# foreground color
self.foreground = QPushButton()
self.foreground.connect(self.foreground, SIGNAL("clicked()"), self.onForeground)
self.foreground.setToolTip(
_("Set colour (F7; repeat to choose next; F6 to use)"))
self.foreground.setShortcut(_("F7"))
self.foreground.setFocusPolicy(Qt.NoFocus)
self.foreground.setEnabled(False)
self.foreground.setFixedWidth(20)
self.foreground.setFixedHeight(20)
self.foregroundFrame = QFrame()
self.foregroundFrame.setAutoFillBackground(True)
self.colourChanged()
hbox = QHBoxLayout()
hbox.addWidget(self.foregroundFrame)
hbox.setMargin(5)
self.foreground.setLayout(hbox)
self.iconsBox.addWidget(self.foreground)
self.foreground.setStyle(self.plastiqueStyle)
self.iconsBox.addItem(QSpacerItem(5,1, QSizePolicy.Fixed))
# cloze
self.cloze = QPushButton(self.widget)
self.cloze.setFixedHeight(20)
self.clozeSC = QShortcut(QKeySequence(_("F9")), self.widget)
self.cloze.connect(self.cloze, SIGNAL("clicked()"),
self.onCloze)
self.cloze.connect(self.clozeSC, SIGNAL("activated()"),
self.onCloze)
self.cloze.setToolTip(_("Cloze (F9)"))
self.cloze.setFixedWidth(24)
self.cloze.setText("[...]")
self.cloze.setFocusPolicy(Qt.NoFocus)
self.cloze.setEnabled(False)
self.iconsBox.addWidget(self.cloze)
self.cloze.setStyle(self.plastiqueStyle)
# pictures
self.addPicture = QPushButton(self.widget)
self.addPicture.setFixedHeight(20)
self.addPicture.setFixedWidth(20)
self.addPicture.connect(self.addPicture, SIGNAL("clicked()"), self.onAddPicture)
self.addPicture.setFocusPolicy(Qt.NoFocus)
self.addPicture.setShortcut(_("F3"))
self.addPicture.setIcon(QIcon(":/icons/colors.png"))
self.addPicture.setEnabled(False)
self.addPicture.setToolTip(_("Add a picture (F3)"))
self.iconsBox.addWidget(self.addPicture)
self.addPicture.setStyle(self.plastiqueStyle)
# sounds
self.addSound = QPushButton(self.widget)
self.addSound.setFixedHeight(20)
self.addSound.setFixedWidth(20)
self.addSound.connect(self.addSound, SIGNAL("clicked()"), self.onAddSound)
self.addSound.setFocusPolicy(Qt.NoFocus)
self.addSound.setShortcut(_("F4"))
self.addSound.setEnabled(False)
self.addSound.setIcon(QIcon(":/icons/text-speak.png"))
self.addSound.setToolTip(_("Add audio/video (F4)"))
self.iconsBox.addWidget(self.addSound)
self.addSound.setStyle(self.plastiqueStyle)
# sounds
self.recSound = QPushButton(self.widget)
self.recSound.setFixedHeight(20)
self.recSound.setFixedWidth(20)
self.recSound.connect(self.recSound, SIGNAL("clicked()"), self.onRecSound)
self.recSound.setFocusPolicy(Qt.NoFocus)
self.recSound.setShortcut(_("F5"))
self.recSound.setEnabled(False)
self.recSound.setIcon(QIcon(":/icons/media-record.png"))
self.recSound.setToolTip(_("Record audio (F5)"))
self.iconsBox.addWidget(self.recSound)
self.recSound.setStyle(self.plastiqueStyle)
# more
self.more = QPushButton(self.widget)
self.more.setFixedHeight(20)
self.more.setFixedWidth(20)
self.more.connect(self.more, SIGNAL("clicked()"),
self.onMore)
self.more.setToolTip(_("Show advanced options"))
self.more.setText(">>")
self.more.setFocusPolicy(Qt.NoFocus)
self.iconsBox.addWidget(self.more)
self.more.setStyle(self.plastiqueStyle)
# latex
spc = QSpacerItem(5,5, QSizePolicy.Expanding)
self.iconsBox2.addItem(spc)
self.latex = QPushButton(self.widget)
self.latex.setFixedHeight(20)
self.latex.setFixedWidth(20)
self.latex.setToolTip(_("Latex (Ctrl+l then l)"))
self.latexSC = QShortcut(QKeySequence(_("Ctrl+l, l")), self.widget)
self.latex.connect(self.latex, SIGNAL("clicked()"), self.insertLatex)
self.latex.connect(self.latexSC, SIGNAL("activated()"), self.insertLatex)
self.latex.setIcon(QIcon(":/icons/tex.png"))
self.latex.setFocusPolicy(Qt.NoFocus)
self.latex.setEnabled(False)
self.iconsBox2.addWidget(self.latex)
self.latex.setStyle(self.plastiqueStyle)
# latex eqn
self.latexEqn = QPushButton(self.widget)
self.latexEqn.setFixedHeight(20)
self.latexEqn.setFixedWidth(20)
self.latexEqn.setToolTip(_("Latex equation (Ctrl+l then e)"))
self.latexEqnSC = QShortcut(QKeySequence(_("Ctrl+l, e")), self.widget)
self.latexEqn.connect(self.latexEqn, SIGNAL("clicked()"), self.insertLatexEqn)
self.latexEqn.connect(self.latexEqnSC, SIGNAL("activated()"), self.insertLatexEqn)
self.latexEqn.setIcon(QIcon(":/icons/math_sqrt.png"))
self.latexEqn.setFocusPolicy(Qt.NoFocus)
self.latexEqn.setEnabled(False)
self.iconsBox2.addWidget(self.latexEqn)
self.latexEqn.setStyle(self.plastiqueStyle)
# latex math env
self.latexMathEnv = QPushButton(self.widget)
self.latexMathEnv.setFixedHeight(20)
self.latexMathEnv.setFixedWidth(20)
self.latexMathEnv.setToolTip(_("Latex math environment (Ctrl+l then m)"))
self.latexMathEnvSC = QShortcut(QKeySequence(_("Ctrl+l, m")), self.widget)
self.latexMathEnv.connect(self.latexMathEnv, SIGNAL("clicked()"),
self.insertLatexMathEnv)
self.latexMathEnv.connect(self.latexMathEnvSC, SIGNAL("activated()"),
self.insertLatexMathEnv)
self.latexMathEnv.setIcon(QIcon(":/icons/math_matrix.png"))
self.latexMathEnv.setFocusPolicy(Qt.NoFocus)
self.latexMathEnv.setEnabled(False)
self.iconsBox2.addWidget(self.latexMathEnv)
self.latexMathEnv.setStyle(self.plastiqueStyle)
# html
self.htmlEdit = QPushButton(self.widget)
self.htmlEdit.setFixedHeight(20)
self.htmlEdit.setFixedWidth(20)
self.htmlEdit.setToolTip(_("HTML Editor (Ctrl+F9)"))
self.htmlEditSC = QShortcut(QKeySequence(_("Ctrl+F9")), self.widget)
self.htmlEdit.connect(self.htmlEdit, SIGNAL("clicked()"),
self.onHtmlEdit)
self.htmlEdit.connect(self.htmlEditSC, SIGNAL("activated()"),
self.onHtmlEdit)
self.htmlEdit.setIcon(QIcon(":/icons/text-xml.png"))
self.htmlEdit.setFocusPolicy(Qt.NoFocus)
self.htmlEdit.setEnabled(False)
self.iconsBox2.addWidget(self.htmlEdit)
self.htmlEdit.setStyle(self.plastiqueStyle)
#
self.fieldsFrame = None
self.widget.setLayout(self.fieldsBox)
# show advanced buttons?
if not aqt.mw.config['factEditorAdvanced']:
self.onMore(False)
def _makeGrid(self): def _makeGrid(self):
"Rebuild the grid to avoid trigging QT bugs." "Rebuild the grid to avoid trigging QT bugs."
self.fieldsFrame = QWidget() self.fieldsFrame = QWidget()
@ -367,7 +260,6 @@ class FactEditor(object):
w.setLayoutDirection(Qt.RightToLeft) w.setLayoutDirection(Qt.RightToLeft)
else: else:
w.setLayoutDirection(Qt.LeftToRight) w.setLayoutDirection(Qt.LeftToRight)
runHook("makeField", w, field)
self.fieldsGrid.addWidget(w, n, 1) self.fieldsGrid.addWidget(w, n, 1)
self.fields[field.name] = (field, w) self.fields[field.name] = (field, w)
self.widgets[w] = field self.widgets[w] = field
@ -428,7 +320,7 @@ class FactEditor(object):
for field in self.fact.fields: for field in self.fact.fields:
if field.name not in self.fields: if field.name not in self.fields:
return True return True
return self.fontChanged return False
def loadFields(self, check=True, font=True): def loadFields(self, check=True, font=True):
"Update field text (if changed) and font/colours." "Update field text (if changed) and font/colours."
@ -438,7 +330,7 @@ class FactEditor(object):
self.fields[field.name] = (field, w) self.fields[field.name] = (field, w)
self.widgets[w] = field self.widgets[w] = field
new = self.fact[field.name] new = self.fact[field.name]
old = tidyHTML(unicode(w.toHtml())) #old = tidyHTML(unicode(w.toHtml()))
# only update if something has changed # only update if something has changed
if new != old: if new != old:
cur = w.textCursor() cur = w.textCursor()
@ -468,7 +360,7 @@ class FactEditor(object):
n = _("Edit") n = _("Edit")
self.deck.setUndoStart(n, merge=True) self.deck.setUndoStart(n, merge=True)
for (w, f) in self.widgets.items(): for (w, f) in self.widgets.items():
v = tidyHTML(unicode(w.toHtml())) #v = tidyHTML(unicode(w.toHtml()))
if self.fact[f.name] != v: if self.fact[f.name] != v:
self.fact[f.name] = v self.fact[f.name] = v
modified = True modified = True
@ -491,7 +383,7 @@ class FactEditor(object):
self.fact.focusLost(field) self.fact.focusLost(field)
self.fact.setModified(textChanged=True, deck=self.deck) self.fact.setModified(textChanged=True, deck=self.deck)
self.loadFields(font=False) self.loadFields(font=False)
if modified and self.resetOnEdit: if modified:
aqt.mw.reset(runHooks=False) aqt.mw.reset(runHooks=False)
def onTextChanged(self): def onTextChanged(self):
@ -555,18 +447,14 @@ class FactEditor(object):
# call relevant hooks # call relevant hooks
invalid = len(empty+dupe) invalid = len(empty+dupe)
if self.factState != "valid" and not invalid: if self.factState != "valid" and not invalid:
if self.onFactValid:
self.onFactValid(self.fact)
self.factState = "valid" self.factState = "valid"
elif self.factState != "invalid" and invalid: elif self.factState != "invalid" and invalid:
if self.onFactInvalid:
self.onFactInvalid(self.fact)
self.factState = "invalid" self.factState = "invalid"
def textForField(self, field): def textForField(self, field):
"Current edited value for field." "Current edited value for field."
w = self.fields[field.name][1] w = self.fields[field.name][1]
v = tidyHTML(unicode(w.toHtml())) #v = tidyHTML(unicode(w.toHtml()))
return v return v
def fieldValid(self, field): def fieldValid(self, field):
@ -594,7 +482,6 @@ class FactEditor(object):
self.deck.updateFactTags([self.fact.id]) self.deck.updateFactTags([self.fact.id])
self.fact.setModified(textChanged=True, deck=self.deck) self.fact.setModified(textChanged=True, deck=self.deck)
self.deck.flushMod() self.deck.flushMod()
if self.resetOnEdit:
aqt.mw.reset(runHooks=False) aqt.mw.reset(runHooks=False)
if self.onChange: if self.onChange:
self.onChange('tag') self.onChange('tag')
@ -648,19 +535,16 @@ class FactEditor(object):
def toggleBold(self, bool): def toggleBold(self, bool):
w = self.focusedEdit() w = self.focusedEdit()
if w: if w:
self.fontChanged = True
w.setFontWeight(bool and QFont.Bold or QFont.Normal) w.setFontWeight(bool and QFont.Bold or QFont.Normal)
def toggleItalic(self, bool): def toggleItalic(self, bool):
w = self.focusedEdit() w = self.focusedEdit()
if w: if w:
self.fontChanged = True
w.setFontItalic(bool) w.setFontItalic(bool)
def toggleUnderline(self, bool): def toggleUnderline(self, bool):
w = self.focusedEdit() w = self.focusedEdit()
if w: if w:
self.fontChanged = True
w.setFontUnderline(bool) w.setFontUnderline(bool)
def _updateForegroundButton(self, txtcol): def _updateForegroundButton(self, txtcol):
@ -748,7 +632,6 @@ class FactEditor(object):
recent.append(colour) recent.append(colour)
w = self.lastFocusedEdit w = self.lastFocusedEdit
w.setTextColor(QColor(colour)) w.setTextColor(QColor(colour))
self.fontChanged = True
self.colourDiag.close() self.colourDiag.close()
runHook("colourChanged") runHook("colourChanged")
@ -763,6 +646,9 @@ class FactEditor(object):
runHook("colourChanged") runHook("colourChanged")
self.onChooseColour(txtcol) self.onChooseColour(txtcol)
def latexMenu(self):
pass
def insertLatex(self): def insertLatex(self):
w = self.focusedEdit() w = self.focusedEdit()
if w: if w:
@ -906,7 +792,7 @@ class FactEditor(object):
def fieldsAreBlank(self): def fieldsAreBlank(self):
for (field, widget) in self.fields.values(): for (field, widget) in self.fields.values():
value = tidyHTML(unicode(widget.toHtml())) #value = tidyHTML(unicode(widget.toHtml()))
if value: if value:
return False return False
return True return True
@ -1104,6 +990,7 @@ class FactEdit(QTextEdit):
def simplifyHTML(self, html): def simplifyHTML(self, html):
"Remove all style information and P tags." "Remove all style information and P tags."
# fixme
if not aqt.mw.config['stripHTML']: if not aqt.mw.config['stripHTML']:
return html return html
html = re.sub("\n", " ", html) html = re.sub("\n", " ", html)

View file

@ -1,28 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>AddCards</class> <class>Dialog</class>
<widget class="QDialog" name="AddCards"> <widget class="QDialog" name="Dialog">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>509</width> <width>743</width>
<height>381</height> <height>727</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Add Items</string> <string>Add</string>
</property> </property>
<property name="windowIcon"> <property name="windowIcon">
<iconset resource="../icons.qrc"> <iconset>
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset> <normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>3</number>
</property> </property>
<property name="margin"> <property name="margin">
<number>4</number> <number>0</number>
</property> </property>
<item> <item>
<layout class="QGridLayout"> <layout class="QGridLayout">
@ -57,13 +57,6 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QWidget" name="fieldsArea" native="true"> <widget class="QWidget" name="fieldsArea" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding"> <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
@ -75,79 +68,6 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
<widget class="QTextBrowser" name="status">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>228</red>
<green>228</green>
<blue>228</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>228</red>
<green>228</green>
<blue>228</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
</property>
<property name="openLinks">
<bool>false</bool>
</property>
</widget>
</widget>
</item> </item>
<item> <item>
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
@ -164,14 +84,12 @@
<tabstops> <tabstops>
<tabstop>buttonBox</tabstop> <tabstop>buttonBox</tabstop>
</tabstops> </tabstops>
<resources> <resources/>
<include location="../icons.qrc"/>
</resources>
<connections> <connections>
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>AddCards</receiver> <receiver>Dialog</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">