mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
refactor card layout, reviewing
This commit is contained in:
parent
f2a39aad2a
commit
cf87d19905
30 changed files with 1377 additions and 1195 deletions
0
anki.bat
Normal file → Executable file
0
anki.bat
Normal file → Executable file
14
aqt/about.py
14
aqt/about.py
|
@ -29,13 +29,13 @@ Duggan, Matthew Holtz, Meelis Vasser, Michael Penkov, Michael Keppler, Michal
|
|||
Petr Michalec, Piotr Kubowicz, Richard Colley, Samson Melamed, Stefaan
|
||||
De Pooter, Susanna Björverud, Tacutu, Timm Preetz, Timo Paulssen, Ursus, Victor
|
||||
Suba, and Xtru.
|
||||
|
||||
Anki icon by Alex Fraser (CC GNU GPL)
|
||||
Deck icon by Laurent Baumann (CC BY-NC-SA 3.0)
|
||||
Deck browser icons from:
|
||||
http://led24.de/iconset
|
||||
http://p.yusukekamiyamane.com/
|
||||
Other icons under LGPL or public domain.
|
||||
<p>
|
||||
Anki icon by Alex Fraser (CC GNU GPL)<br>
|
||||
Deck icon by Laurent Baumann (CC BY-NC-SA 3.0)<br>
|
||||
Deck browser icons from:<br>
|
||||
http://led24.de/iconset<br>
|
||||
http://p.yusukekamiyamane.com/<br>
|
||||
Other icons under LGPL or public domain.<br>
|
||||
"""
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import anki
|
|||
from anki.errors import *
|
||||
from anki.utils import stripHTML
|
||||
from aqt.utils import saveGeom, restoreGeom, showWarning, askUser, shortcut, \
|
||||
tooltip
|
||||
tooltip, openHelp
|
||||
from anki.sound import clearAudioQueue
|
||||
from anki.hooks import addHook, removeHook
|
||||
from anki.utils import stripHTMLMedia, isMac
|
||||
|
@ -46,7 +46,7 @@ class AddCards(QDialog):
|
|||
self.mw, self.form.modelArea)
|
||||
|
||||
def helpRequested(self):
|
||||
aqt.openHelp("AddItems")
|
||||
openHelp("AddItems")
|
||||
|
||||
def setupButtons(self):
|
||||
bb = self.form.buttonBox
|
||||
|
|
|
@ -10,7 +10,7 @@ import anki, anki.utils, aqt.forms
|
|||
from anki.utils import fmtTimeSpan, ids2str, stripHTMLMedia, isWin, intTime
|
||||
from aqt.utils import saveGeom, restoreGeom, saveSplitter, restoreSplitter, \
|
||||
saveHeader, restoreHeader, saveState, restoreState, applyStyles, getTag, \
|
||||
showInfo, askUser, tooltip
|
||||
showInfo, askUser, tooltip, openHelp
|
||||
from anki.errors import *
|
||||
from anki.db import *
|
||||
from anki.hooks import runHook, addHook, removeHook
|
||||
|
@ -69,7 +69,7 @@ class DataModel(QAbstractTableModel):
|
|||
return
|
||||
if role == Qt.FontRole:
|
||||
f = QFont()
|
||||
f.setPixelSize(self.browser.mw.config['editFontSize'])
|
||||
f.setPixelSize(self.browser.mw.pm.profile['editFontSize'])
|
||||
return f
|
||||
if role == Qt.TextAlignmentRole:
|
||||
align = Qt.AlignVCenter
|
||||
|
@ -112,7 +112,7 @@ class DataModel(QAbstractTableModel):
|
|||
# the db progress handler may cause a refresh, so we need to zero out
|
||||
# old data first
|
||||
self.cards = []
|
||||
self.cards = self.col.findCards(txt, self.browser.mw.config['fullSearch'])
|
||||
self.cards = self.col.findCards(txt, self.browser.mw.pm.profile['fullSearch'])
|
||||
print "fetch cards in %dms" % ((time.time() - t)*1000)
|
||||
if reset:
|
||||
self.endReset()
|
||||
|
@ -332,8 +332,8 @@ class Browser(QMainWindow):
|
|||
self.onSearch()
|
||||
|
||||
def setupToolbar(self):
|
||||
self.form.toolBar.setIconSize(QSize(self.mw.config['iconSize'],
|
||||
self.mw.config['iconSize']))
|
||||
self.form.toolBar.setIconSize(QSize(self.mw.pm.profile['iconSize'],
|
||||
self.mw.pm.profile['iconSize']))
|
||||
self.form.toolBar.toggleViewAction().setText(_("Toggle Toolbar"))
|
||||
|
||||
def setupMenus(self):
|
||||
|
@ -372,10 +372,10 @@ class Browser(QMainWindow):
|
|||
|
||||
def updateFont(self):
|
||||
self.form.tableView.setFont(QFont(
|
||||
self.mw.config['editFontFamily'],
|
||||
self.mw.config['editFontSize']))
|
||||
self.mw.pm.profile['editFontFamily'],
|
||||
self.mw.pm.profile['editFontSize']))
|
||||
self.form.tableView.verticalHeader().setDefaultSectionSize(
|
||||
self.mw.config['editLineSize'])
|
||||
self.mw.pm.profile['editLineSize'])
|
||||
|
||||
def closeEvent(self, evt):
|
||||
saveSplitter(self.form.splitter_2, "editor2")
|
||||
|
@ -432,7 +432,7 @@ class Browser(QMainWindow):
|
|||
self.onSearch)
|
||||
self.setTabOrder(self.form.searchEdit, self.form.tableView)
|
||||
self.compModel = QStringListModel()
|
||||
self.compModel.setStringList(self.mw.config['searchHistory'])
|
||||
self.compModel.setStringList(self.mw.pm.profile['searchHistory'])
|
||||
self.searchComp = QCompleter(self.compModel, self.form.searchEdit)
|
||||
self.searchComp.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
|
||||
self.searchComp.setCaseSensitivity(Qt.CaseInsensitive)
|
||||
|
@ -441,18 +441,18 @@ class Browser(QMainWindow):
|
|||
def onSearch(self, reset=True):
|
||||
"Careful: if reset is true, the current note is saved."
|
||||
txt = unicode(self.form.searchEdit.text()).strip()
|
||||
sh = self.mw.config['searchHistory']
|
||||
sh = self.mw.pm.profile['searchHistory']
|
||||
if txt not in sh:
|
||||
sh.insert(0, txt)
|
||||
sh = sh[:30]
|
||||
self.compModel.setStringList(sh)
|
||||
self.mw.config['searchHistory'] = sh
|
||||
self.mw.pm.profile['searchHistory'] = sh
|
||||
self.model.search(txt, reset)
|
||||
if not self.model.cards:
|
||||
# no row change will fire
|
||||
self.onRowChanged(None, None)
|
||||
txt = _("No matches found.")
|
||||
if not self.mw.config['fullSearch']:
|
||||
if not self.mw.pm.profile['fullSearch']:
|
||||
txt += "<p>" + _(
|
||||
_("If your cards have formatting, you may want <br>"
|
||||
"to enable 'search within formatting' in the<br>"
|
||||
|
@ -834,7 +834,7 @@ where id in %s""" % ids2str(sf))
|
|||
return sf
|
||||
|
||||
def onHelp(self):
|
||||
aqt.openHelp("Browser")
|
||||
openHelp("Browser")
|
||||
|
||||
# Misc menu options
|
||||
######################################################################
|
||||
|
@ -1066,18 +1066,18 @@ where id in %s""" % ids2str(self.selectedCards()), mod)
|
|||
frm = aqt.forms.browseropts.Ui_Dialog()
|
||||
frm.setupUi(d)
|
||||
frm.fontCombo.setCurrentFont(QFont(
|
||||
self.mw.config['editFontFamily']))
|
||||
frm.fontSize.setValue(self.mw.config['editFontSize'])
|
||||
frm.lineSize.setValue(self.mw.config['editLineSize'])
|
||||
frm.fullSearch.setChecked(self.mw.config['fullSearch'])
|
||||
self.mw.pm.profile['editFontFamily']))
|
||||
frm.fontSize.setValue(self.mw.pm.profile['editFontSize'])
|
||||
frm.lineSize.setValue(self.mw.pm.profile['editLineSize'])
|
||||
frm.fullSearch.setChecked(self.mw.pm.profile['fullSearch'])
|
||||
if d.exec_():
|
||||
self.mw.config['editFontFamily'] = (
|
||||
self.mw.pm.profile['editFontFamily'] = (
|
||||
unicode(frm.fontCombo.currentFont().family()))
|
||||
self.mw.config['editFontSize'] = (
|
||||
self.mw.pm.profile['editFontSize'] = (
|
||||
int(frm.fontSize.value()))
|
||||
self.mw.config['editLineSize'] = (
|
||||
self.mw.pm.profile['editLineSize'] = (
|
||||
int(frm.lineSize.value()))
|
||||
self.mw.config['fullSearch'] = frm.fullSearch.isChecked()
|
||||
self.mw.pm.profile['fullSearch'] = frm.fullSearch.isChecked()
|
||||
self.updateFont()
|
||||
|
||||
# Edit: replacing
|
||||
|
@ -1130,7 +1130,7 @@ where id in %s""" % ids2str(self.selectedCards()), mod)
|
|||
})
|
||||
|
||||
def onFindReplaceHelp(self):
|
||||
aqt.openHelp("Browser#FindReplace")
|
||||
openHelp("Browser#FindReplace")
|
||||
|
||||
# Edit: finding dupes
|
||||
######################################################################
|
||||
|
@ -1311,7 +1311,7 @@ select id from cards where nid in %s and ord in %s""" % (
|
|||
self.browser.onSearch()
|
||||
|
||||
def onHelp(self):
|
||||
aqt.openHelp("Browser#GenerateCards")
|
||||
openHelp("Browser#GenerateCards")
|
||||
|
||||
# Change model dialog
|
||||
######################################################################
|
||||
|
@ -1477,4 +1477,4 @@ Are you sure you want to continue?""")):
|
|||
return QDialog.accept(self)
|
||||
|
||||
def onHelp(self):
|
||||
aqt.openHelp("Browser#ChangeModel")
|
||||
openHelp("Browser#ChangeModel")
|
||||
|
|
552
aqt/clayout.py
552
aqt/clayout.py
|
@ -7,439 +7,217 @@ from anki.consts import *
|
|||
import aqt
|
||||
from anki.sound import playFromText, clearAudioQueue
|
||||
from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA, \
|
||||
saveSplitter, restoreSplitter, showInfo, askUser, getText
|
||||
saveSplitter, restoreSplitter, showInfo, askUser, getOnlyText, \
|
||||
showWarning, openHelp
|
||||
from anki.utils import isMac, isWin
|
||||
import aqt.templates
|
||||
|
||||
# fixme: replace font substitutions with native comma list
|
||||
|
||||
class ResizingTextEdit(QTextEdit):
|
||||
def sizeHint(self):
|
||||
return QSize(200, 800)
|
||||
# raise Exception("Remember to disallow media&latex refs in edit.")
|
||||
|
||||
class CardLayout(QDialog):
|
||||
|
||||
# type is previewCards() type
|
||||
def __init__(self, mw, note, type=0, ord=0, parent=None):
|
||||
def __init__(self, mw, note, ord=0, parent=None):
|
||||
QDialog.__init__(self, parent or mw, Qt.Window)
|
||||
raise Exception("Remember to disallow media&latex refs in edit.")
|
||||
self.mw = aqt.mw
|
||||
self.parent = parent or mw
|
||||
self.note = note
|
||||
self.type = type
|
||||
self.ord = ord
|
||||
self.col = self.mw.col
|
||||
self.mm = self.mw.col.models
|
||||
self.model = note.model()
|
||||
self.form = aqt.forms.clayout.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
self.setupTabs()
|
||||
self.setWindowTitle(_("%s Layout") % self.model['name'])
|
||||
self.plastiqueStyle = None
|
||||
if isMac or isWin:
|
||||
self.plastiqueStyle = QStyleFactory.create("plastique")
|
||||
self.connect(self.form.buttonBox, SIGNAL("helpRequested()"),
|
||||
v1 = QVBoxLayout()
|
||||
v1.addWidget(self.tabs)
|
||||
self.bbox = QDialogButtonBox(
|
||||
QDialogButtonBox.Close|QDialogButtonBox.Help)
|
||||
v1.addWidget(self.bbox)
|
||||
self.setLayout(v1)
|
||||
|
||||
self.connect(self.bbox, SIGNAL("helpRequested()"),
|
||||
self.onHelp)
|
||||
self.setupCards()
|
||||
self.setupFields()
|
||||
self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False)
|
||||
self.form.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False)
|
||||
restoreSplitter(self.form.splitter, "clayout")
|
||||
self.bbox.button(QDialogButtonBox.Help).setAutoDefault(False)
|
||||
self.bbox.button(QDialogButtonBox.Close).setAutoDefault(False)
|
||||
self.mw.checkpoint(_("Card Layout"))
|
||||
self.redraw()
|
||||
restoreGeom(self, "CardLayout")
|
||||
if not self.reload(first=True):
|
||||
return
|
||||
self.exec_()
|
||||
|
||||
def reload(self, first=False):
|
||||
self.cards = self.col.previewCards(self.note, self.type)
|
||||
if not self.cards:
|
||||
self.accept()
|
||||
if first:
|
||||
showInfo(_("Please enter some text first."))
|
||||
else:
|
||||
showInfo(_("The current note was deleted."))
|
||||
return
|
||||
self.fillCardList()
|
||||
self.fillFieldList()
|
||||
self.fieldChanged()
|
||||
self.readField()
|
||||
return True
|
||||
def redraw(self):
|
||||
self.cards = self.col.previewCards(self.note, 2)
|
||||
self.redrawing = True
|
||||
self.updateTabs()
|
||||
self.redrawing = False
|
||||
self.selectCard(self.ord)
|
||||
|
||||
def setupTabs(self):
|
||||
c = self.connect
|
||||
self.tabs = QTabWidget()
|
||||
self.tabs.setTabsClosable(True)
|
||||
self.tabs.setUsesScrollButtons(True)
|
||||
add = QPushButton("+")
|
||||
add.setFixedWidth(30)
|
||||
c(add, SIGNAL("clicked()"), self.onAddCard)
|
||||
self.tabs.setCornerWidget(add)
|
||||
c(self.tabs, SIGNAL("currentChanged(int)"), self.selectCard)
|
||||
c(self.tabs, SIGNAL("tabCloseRequested(int)"), self.onRemoveTab)
|
||||
|
||||
def updateTabs(self):
|
||||
self.forms = []
|
||||
self.tabs.clear()
|
||||
for t in self.model['tmpls']:
|
||||
self.addTab(t)
|
||||
|
||||
def addTab(self, t):
|
||||
c = self.connect
|
||||
w = QWidget()
|
||||
h = QHBoxLayout()
|
||||
h.addStretch()
|
||||
rename = QPushButton("Rename")
|
||||
c(rename, SIGNAL("clicked()"), self.onRename)
|
||||
h.addWidget(rename)
|
||||
order = QPushButton(_("Reposition"))
|
||||
h.addWidget(order)
|
||||
c(order, SIGNAL("clicked()"), self.onReorder)
|
||||
h.addStretch()
|
||||
v = QVBoxLayout()
|
||||
v.setMargin(3)
|
||||
v.setSpacing(3)
|
||||
v.addLayout(h)
|
||||
l = QHBoxLayout()
|
||||
l.setMargin(0)
|
||||
l.setSpacing(3)
|
||||
left = QWidget()
|
||||
# template area
|
||||
tform = aqt.forms.template.Ui_Form()
|
||||
tform.setupUi(left)
|
||||
c(tform.front, SIGNAL("textChanged()"), self.onTemplateEdit)
|
||||
c(tform.back, SIGNAL("textChanged()"), self.onTemplateEdit)
|
||||
l.addWidget(left, 5)
|
||||
# preview area
|
||||
right = QWidget()
|
||||
pform = aqt.forms.preview.Ui_Form()
|
||||
pform.setupUi(right)
|
||||
def linkClicked(url):
|
||||
QDesktopServices.openUrl(QUrl(url))
|
||||
for wig in pform.front, pform.back:
|
||||
wig.page().setLinkDelegationPolicy(
|
||||
QWebPage.DelegateExternalLinks)
|
||||
c(wig, SIGNAL("linkClicked(QUrl)"), linkClicked)
|
||||
l.addWidget(right, 5)
|
||||
v.addLayout(l)
|
||||
w.setLayout(v)
|
||||
self.forms.append({'tform': tform, 'pform': pform})
|
||||
self.tabs.addTab(w, t['name'])
|
||||
|
||||
def onRemoveTab(self, idx):
|
||||
if not self.mm.remTemplate(self.model, self.cards[idx].template()):
|
||||
return showWarning(_("""\
|
||||
Removing this card would cause one or more notes to be deleted. \
|
||||
Please create a new card first."""))
|
||||
self.redraw()
|
||||
|
||||
# Cards & Preview
|
||||
##########################################################################
|
||||
|
||||
def setupCards(self):
|
||||
self.updatingCards = False
|
||||
self.playedAudio = {}
|
||||
f = self.form
|
||||
if self.type == 0:
|
||||
f.templateType.setText(
|
||||
_("Templates that will be created:"))
|
||||
elif self.type == 1:
|
||||
f.templateType.setText(
|
||||
_("Templates used by note:"))
|
||||
else:
|
||||
f.templateType.setText(
|
||||
_("All templates:"))
|
||||
# replace with more appropriate size hints
|
||||
for e in ("cardQuestion", "cardAnswer"):
|
||||
w = getattr(f, e)
|
||||
idx = f.templateLayout.indexOf(w)
|
||||
r = f.templateLayout.getItemPosition(idx)
|
||||
f.templateLayout.removeWidget(w)
|
||||
w.hide()
|
||||
w.deleteLater()
|
||||
w = ResizingTextEdit(self)
|
||||
setattr(f, e, w)
|
||||
f.templateLayout.addWidget(w, r[0], r[1])
|
||||
c = self.connect
|
||||
c(f.cardList, SIGNAL("activated(int)"), self.cardChanged)
|
||||
c(f.editTemplates, SIGNAL("clicked()"), self.onEdit)
|
||||
c(f.cardQuestion, SIGNAL("textChanged()"), self.formatChanged)
|
||||
c(f.cardAnswer, SIGNAL("textChanged()"), self.formatChanged)
|
||||
c(f.alignment, SIGNAL("activated(int)"), self.saveCard)
|
||||
c(f.background, SIGNAL("clicked()"),
|
||||
lambda w=f.background:\
|
||||
self.chooseColour(w, "card"))
|
||||
c(f.questionInAnswer, SIGNAL("clicked()"), self.saveCard)
|
||||
c(f.allowEmptyAnswer, SIGNAL("clicked()"), self.saveCard)
|
||||
c(f.typeAnswer, SIGNAL("activated(int)"), self.saveCard)
|
||||
c(f.flipButton, SIGNAL("clicked()"), self.onFlip)
|
||||
c(f.clozectx, SIGNAL("clicked()"), self.saveCard)
|
||||
def linkClicked(url):
|
||||
QDesktopServices.openUrl(QUrl(url))
|
||||
f.preview.page().setLinkDelegationPolicy(
|
||||
QWebPage.DelegateExternalLinks)
|
||||
self.connect(f.preview,
|
||||
SIGNAL("linkClicked(QUrl)"),
|
||||
linkClicked)
|
||||
if self.plastiqueStyle:
|
||||
f.background.setStyle(self.plastiqueStyle)
|
||||
f.alignment.addItems(alignmentLabels().values())
|
||||
self.typeFieldNames = self.mm.fieldMap(self.model)
|
||||
s = [_("Don't ask me to type in the answer")]
|
||||
s += [_("Compare with field '%s'") % fi
|
||||
for fi in self.typeFieldNames.keys()]
|
||||
f.typeAnswer.insertItems(0, s)
|
||||
|
||||
def formatToScreen(self, fmt):
|
||||
fmt = fmt.replace("}}<br>", "}}\n")
|
||||
return fmt
|
||||
|
||||
def screenToFormat(self, fmt):
|
||||
fmt = fmt.replace("}}\n", "}}<br>")
|
||||
return fmt
|
||||
|
||||
def onEdit(self):
|
||||
aqt.templates.Templates(self.mw, self.model, self)
|
||||
self.reload()
|
||||
|
||||
def formatChanged(self):
|
||||
if self.updatingCards:
|
||||
def selectCard(self, idx):
|
||||
if self.redrawing:
|
||||
return
|
||||
text = unicode(self.form.cardQuestion.toPlainText())
|
||||
self.card.template()['qfmt'] = self.screenToFormat(text)
|
||||
text = unicode(self.form.cardAnswer.toPlainText())
|
||||
self.card.template()['afmt'] = self.screenToFormat(text)
|
||||
self.renderPreview()
|
||||
|
||||
def onFlip(self):
|
||||
q = unicode(self.form.cardQuestion.toPlainText())
|
||||
a = unicode(self.form.cardAnswer.toPlainText())
|
||||
self.form.cardAnswer.setPlainText(q)
|
||||
self.form.cardQuestion.setPlainText(a)
|
||||
|
||||
def readCard(self):
|
||||
self.updatingCards = True
|
||||
t = self.card.template()
|
||||
f = self.form
|
||||
f.background.setPalette(QPalette(QColor(t['bg'])))
|
||||
f.cardQuestion.setPlainText(self.formatToScreen(t['qfmt']))
|
||||
f.cardAnswer.setPlainText(self.formatToScreen(t['afmt']))
|
||||
f.questionInAnswer.setChecked(t['hideQ'])
|
||||
f.allowEmptyAnswer.setChecked(t['emptyAns'])
|
||||
f.alignment.setCurrentIndex(t['align'])
|
||||
if t['typeAns'] is None:
|
||||
f.typeAnswer.setCurrentIndex(0)
|
||||
else:
|
||||
f.typeAnswer.setCurrentIndex(t['typeAns'] + 1)
|
||||
# model-level, but there's nowhere else to put this
|
||||
f.clozectx.setChecked(self.model['clozectx'])
|
||||
self.updatingCards = False
|
||||
|
||||
def fillCardList(self):
|
||||
self.form.cardList.clear()
|
||||
cards = []
|
||||
idx = 0
|
||||
for n, c in enumerate(self.cards):
|
||||
if c.ord == self.ord:
|
||||
cards.append(_("%s (current)") % c.template()['name'])
|
||||
idx = n
|
||||
else:
|
||||
cards.append(c.template()['name'])
|
||||
self.form.cardList.addItems(cards)
|
||||
self.form.cardList.setCurrentIndex(idx)
|
||||
self.cardChanged(idx)
|
||||
self.form.cardList.setFocus()
|
||||
|
||||
def cardChanged(self, idx):
|
||||
self.ord = idx
|
||||
self.card = self.cards[idx]
|
||||
self.tab = self.forms[idx]
|
||||
self.tabs.setCurrentIndex(idx)
|
||||
self.readCard()
|
||||
self.renderPreview()
|
||||
|
||||
def saveCard(self):
|
||||
if self.updatingCards:
|
||||
return
|
||||
def readCard(self):
|
||||
t = self.card.template()
|
||||
t['align'] = self.form.alignment.currentIndex()
|
||||
t['bg'] = unicode(
|
||||
self.form.background.palette().window().color().name())
|
||||
t['hideQ'] = self.form.questionInAnswer.isChecked()
|
||||
t['emptyAns'] = self.form.allowEmptyAnswer.isChecked()
|
||||
idx = self.form.typeAnswer.currentIndex()
|
||||
if not idx:
|
||||
t['typeAns'] = None
|
||||
else:
|
||||
t['typeAns'] = idx-1
|
||||
self.model['clozectx'] = self.form.clozectx.isChecked()
|
||||
self.redrawing = True
|
||||
self.tab['tform'].front.setPlainText(t['qfmt'])
|
||||
self.tab['tform'].back.setPlainText(t['afmt'])
|
||||
self.redrawing = False
|
||||
|
||||
def onTemplateEdit(self):
|
||||
if self.redrawing:
|
||||
return
|
||||
text = self.tab['tform'].front.toPlainText()
|
||||
self.card.template()['qfmt'] = text
|
||||
text = self.tab['tform'].back.toPlainText()
|
||||
self.card.template()['afmt'] = text
|
||||
self.renderPreview()
|
||||
|
||||
def chooseColour(self, button, type="field"):
|
||||
new = QColorDialog.getColor(button.palette().window().color(), self,
|
||||
_("Choose Color"),
|
||||
QColorDialog.DontUseNativeDialog)
|
||||
if new.isValid():
|
||||
button.setPalette(QPalette(new))
|
||||
if type == "field":
|
||||
self.saveField()
|
||||
else:
|
||||
self.saveCard()
|
||||
def saveCard(self):
|
||||
t = self.card.template()
|
||||
self.renderPreview()
|
||||
|
||||
def renderPreview(self):
|
||||
print "preview"
|
||||
c = self.card
|
||||
styles = self.model['css']
|
||||
styles += "\n.cloze { font-weight: bold; color: blue; }"
|
||||
self.form.preview.setHtml(
|
||||
('<html><head>%s</head><body class="%s">' %
|
||||
(getBase(self.col), c.cssClass())) +
|
||||
"<style>" + styles + "</style>" +
|
||||
mungeQA(c.q(reload=True)) +
|
||||
self.maybeTextInput() +
|
||||
"<hr>" +
|
||||
mungeQA(c.a())
|
||||
+ "</body></html>")
|
||||
clearAudioQueue()
|
||||
if c.id not in self.playedAudio:
|
||||
playFromText(c.q())
|
||||
playFromText(c.a())
|
||||
self.playedAudio[c.id] = True
|
||||
styles = "\n.cloze { font-weight: bold; color: blue; }"
|
||||
html = '<html><body id=card><style>%s</style>%s</body></html>'
|
||||
self.tab['pform'].front.setHtml(
|
||||
html % (styles, mungeQA(c.q(reload=True))))
|
||||
self.tab['pform'].back.setHtml(
|
||||
html % (styles, mungeQA(c.a())))
|
||||
|
||||
def maybeTextInput(self):
|
||||
return "text input"
|
||||
if self.card.template()['typeAns'] is not None:
|
||||
return "<center><input type=text></center>"
|
||||
return ""
|
||||
|
||||
def onRename(self):
|
||||
name = getOnlyText(_("New name:"))
|
||||
if not name:
|
||||
return
|
||||
if name in [c.template()['name'] for c in self.cards
|
||||
if c.template()['ord'] != self.ord]:
|
||||
return showWarning(_("That name is already used."))
|
||||
self.card.template()['name'] = name
|
||||
self.tabs.setTabText(self.tabs.currentIndex(), name)
|
||||
|
||||
def onReorder(self):
|
||||
n = len(self.cards)
|
||||
cur = self.card.template()['ord']+1
|
||||
pos = getOnlyText(
|
||||
_("Enter new card position (1..%s):") % n,
|
||||
default=str(cur))
|
||||
if not pos:
|
||||
return
|
||||
try:
|
||||
pos = int(pos)
|
||||
except ValueError:
|
||||
return
|
||||
if pos < 1 or pos > n:
|
||||
return
|
||||
if pos == cur:
|
||||
return
|
||||
pos -= 1
|
||||
self.mm.moveTemplate(self.model, self.card.template(), pos)
|
||||
self.ord = pos
|
||||
self.redraw()
|
||||
|
||||
def onAddCard(self):
|
||||
name = getOnlyText(_("Name:"))
|
||||
if not name:
|
||||
return
|
||||
if name in [c.template()['name'] for c in self.cards]:
|
||||
return showWarning(_("That name is already used."))
|
||||
t = self.mm.newTemplate(name)
|
||||
self.mm.addTemplate(self.model, t)
|
||||
self.redraw()
|
||||
|
||||
# Closing & Help
|
||||
######################################################################
|
||||
|
||||
def accept(self):
|
||||
self.reject()
|
||||
|
||||
def reject(self):
|
||||
self.mm.save(self.model)
|
||||
saveGeom(self, "CardLayout")
|
||||
saveSplitter(self.form.splitter, "clayout")
|
||||
self.mw.reset()
|
||||
saveGeom(self, "CardLayout")
|
||||
return QDialog.reject(self)
|
||||
|
||||
|
||||
modified = False
|
||||
self.mw.startProgress()
|
||||
self.col.updateProgress(_("Applying changes..."))
|
||||
reset=True
|
||||
if len(self.fieldOrdinalUpdatedIds) > 0:
|
||||
self.col.rebuildFieldOrdinals(self.model.id, self.fieldOrdinalUpdatedIds)
|
||||
modified = True
|
||||
if self.needFieldRebuild:
|
||||
modified = True
|
||||
if modified:
|
||||
self.note.model.setModified()
|
||||
self.col.flushMod()
|
||||
if self.noteedit and self.noteedit.onChange:
|
||||
self.noteedit.onChange("all")
|
||||
reset=False
|
||||
if reset:
|
||||
self.mw.reset()
|
||||
self.col.finishProgress()
|
||||
QDialog.reject(self)
|
||||
|
||||
def onHelp(self):
|
||||
aqt.openHelp("CardLayout")
|
||||
|
||||
# Fields
|
||||
##########################################################################
|
||||
|
||||
def setupFields(self):
|
||||
self.fieldOrdinalUpdatedIds = []
|
||||
self.updatingFields = False
|
||||
self.needFieldRebuild = False
|
||||
c = self.connect; f = self.form
|
||||
sc = SIGNAL("stateChanged(int)")
|
||||
cl = SIGNAL("clicked()")
|
||||
c(f.fieldAdd, cl, self.addField)
|
||||
c(f.fieldDelete, cl, self.deleteField)
|
||||
c(f.fieldUp, cl, self.moveFieldUp)
|
||||
c(f.fieldDown, cl, self.moveFieldDown)
|
||||
c(f.preserveWhitespace, sc, self.saveField)
|
||||
c(f.fieldUnique, sc, self.saveField)
|
||||
c(f.fieldRequired, sc, self.saveField)
|
||||
c(f.sticky, sc, self.saveField)
|
||||
c(f.fieldList, SIGNAL("currentRowChanged(int)"),
|
||||
self.fieldChanged)
|
||||
c(f.fieldName, SIGNAL("lostFocus()"),
|
||||
self.saveField)
|
||||
c(f.fontFamily, SIGNAL("currentFontChanged(QFont)"),
|
||||
self.saveField)
|
||||
c(f.fontSize, SIGNAL("valueChanged(int)"),
|
||||
self.saveField)
|
||||
c(f.fontSizeEdit, SIGNAL("valueChanged(int)"),
|
||||
self.saveField)
|
||||
w = self.form.fontColour
|
||||
if self.plastiqueStyle:
|
||||
w.setStyle(self.plastiqueStyle)
|
||||
c(w, SIGNAL("clicked()"),
|
||||
lambda w=w: self.chooseColour(w))
|
||||
c(self.form.rtl,
|
||||
SIGNAL("stateChanged(int)"),
|
||||
self.saveField)
|
||||
|
||||
def fieldChanged(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row == -1:
|
||||
row = 0
|
||||
self.field = self.model['flds'][row]
|
||||
self.readField()
|
||||
self.enableFieldMoveButtons()
|
||||
|
||||
def readField(self):
|
||||
fld = self.field
|
||||
f = self.form
|
||||
self.updatingFields = True
|
||||
f.fieldName.setText(fld['name'])
|
||||
f.fieldUnique.setChecked(fld['uniq'])
|
||||
f.fieldRequired.setChecked(fld['req'])
|
||||
f.fontFamily.setCurrentFont(QFont(fld['font']))
|
||||
f.fontSize.setValue(fld['qsize'])
|
||||
f.fontSizeEdit.setValue(fld['esize'])
|
||||
f.fontColour.setPalette(QPalette(QColor(fld['qcol'])))
|
||||
f.rtl.setChecked(fld['rtl'])
|
||||
f.preserveWhitespace.setChecked(fld['pre'])
|
||||
f.sticky.setChecked(fld['sticky'])
|
||||
self.updatingFields = False
|
||||
|
||||
def saveField(self, *args):
|
||||
self.needFieldRebuild = True
|
||||
if self.updatingFields:
|
||||
return
|
||||
self.updatingFields = True
|
||||
fld = self.field
|
||||
# get name; we'll handle it last
|
||||
name = unicode(self.form.fieldName.text())
|
||||
if not name:
|
||||
return
|
||||
fld['uniq'] = self.form.fieldUnique.isChecked()
|
||||
fld['req'] = self.form.fieldRequired.isChecked()
|
||||
fld['font'] = unicode(
|
||||
self.form.fontFamily.currentFont().family())
|
||||
fld['qsize'] = self.form.fontSize.value()
|
||||
fld['esize'] = self.form.fontSizeEdit.value()
|
||||
fld['qcol'] = str(
|
||||
self.form.fontColour.palette().window().color().name())
|
||||
fld['rtl'] = self.form.rtl.isChecked()
|
||||
fld['pre'] = self.form.preserveWhitespace.isChecked()
|
||||
fld['sticky'] = self.form.sticky.isChecked()
|
||||
self.updatingFields = False
|
||||
if fld['name'] != name:
|
||||
self.mm.renameField(self.model, fld, name)
|
||||
# as the field name has changed, we have to regenerate cards
|
||||
self.cards = self.col.previewCards(self.note, self.type)
|
||||
self.cardChanged(0)
|
||||
self.renderPreview()
|
||||
self.fillFieldList()
|
||||
|
||||
def fillFieldList(self, row = None):
|
||||
oldRow = self.form.fieldList.currentRow()
|
||||
if oldRow == -1:
|
||||
oldRow = 0
|
||||
self.form.fieldList.clear()
|
||||
n = 1
|
||||
for field in self.model['flds']:
|
||||
label = field['name']
|
||||
item = QListWidgetItem(label)
|
||||
self.form.fieldList.addItem(item)
|
||||
n += 1
|
||||
count = self.form.fieldList.count()
|
||||
if row != None:
|
||||
self.form.fieldList.setCurrentRow(row)
|
||||
else:
|
||||
while (count > 0 and oldRow > (count - 1)):
|
||||
oldRow -= 1
|
||||
self.form.fieldList.setCurrentRow(oldRow)
|
||||
self.enableFieldMoveButtons()
|
||||
|
||||
def enableFieldMoveButtons(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row < 1:
|
||||
self.form.fieldUp.setEnabled(False)
|
||||
else:
|
||||
self.form.fieldUp.setEnabled(True)
|
||||
if row == -1 or row >= (self.form.fieldList.count() - 1):
|
||||
self.form.fieldDown.setEnabled(False)
|
||||
else:
|
||||
self.form.fieldDown.setEnabled(True)
|
||||
|
||||
def addField(self):
|
||||
f = self.mm.newField(self.model)
|
||||
l = len(self.model['flds'])
|
||||
f['name'] = _("Field %d") % l
|
||||
self.mw.progress.start()
|
||||
self.mm.addField(self.model, f)
|
||||
self.mw.progress.finish()
|
||||
self.reload()
|
||||
self.form.fieldList.setCurrentRow(l)
|
||||
self.form.fieldName.setFocus()
|
||||
self.form.fieldName.selectAll()
|
||||
|
||||
def deleteField(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row == -1:
|
||||
return
|
||||
if len(self.model.fields) < 2:
|
||||
showInfo(_("Please add a new field first."))
|
||||
return
|
||||
if askUser(_("Delete this field and its data from all notes?")):
|
||||
self.mw.progress.start()
|
||||
self.model.delField(self.field)
|
||||
self.mw.progress.finish()
|
||||
# need to update q/a format
|
||||
self.reload()
|
||||
|
||||
def moveFieldUp(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row == -1:
|
||||
return
|
||||
if row == 0:
|
||||
return
|
||||
self.mw.progress.start()
|
||||
self.model.moveField(self.field, row-1)
|
||||
self.mw.progress.finish()
|
||||
self.form.fieldList.setCurrentRow(row-1)
|
||||
self.reload()
|
||||
|
||||
def moveFieldDown(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row == -1:
|
||||
return
|
||||
if row == len(self.model.fields) - 1:
|
||||
return
|
||||
self.mw.progress.start()
|
||||
self.model.moveField(self.field, row+1)
|
||||
self.mw.progress.finish()
|
||||
self.form.fieldList.setCurrentRow(row+1)
|
||||
self.reload()
|
||||
openHelp("CardLayout")
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from aqt.qt import *
|
||||
from aqt.utils import askUser
|
||||
from aqt.utils import askUser, getOnlyText
|
||||
|
||||
class DeckBrowser(object):
|
||||
|
||||
|
@ -27,7 +27,7 @@ class DeckBrowser(object):
|
|||
if cmd == "open":
|
||||
self._selDeck(arg)
|
||||
elif cmd == "opts":
|
||||
self._optsForRow(int(arg))
|
||||
self._showOptions(arg)
|
||||
elif cmd == "download":
|
||||
self.mw.onGetSharedDeck()
|
||||
elif cmd == "new":
|
||||
|
@ -43,7 +43,7 @@ class DeckBrowser(object):
|
|||
|
||||
def _selDeck(self, did):
|
||||
self.mw.col.decks.select(did)
|
||||
self.mw.moveToState("overview")
|
||||
self.mw.onOverview()
|
||||
|
||||
# HTML generation
|
||||
##########################################################################
|
||||
|
@ -85,13 +85,15 @@ body { margin: 1em; }
|
|||
|
||||
def _deckRow(self, node, depth):
|
||||
name, did, due, new, children = node
|
||||
def indent():
|
||||
return " "*3*depth
|
||||
# due image
|
||||
buf = "<tr><td colspan=5>" + self._dueImg(due, new)
|
||||
buf = "<tr><td colspan=5>" + indent() + self._dueImg(due, new)
|
||||
# deck link
|
||||
buf += " <a class=deck href='open:%d'>%s</a></td>"% (did, name)
|
||||
# options
|
||||
buf += "<td align=right class=opts>%s</td></tr>" % self.mw.button(
|
||||
link="opts:%d"%did, name=_("Options")+'▾')
|
||||
link="opts:%d"%did, name="<img valign=bottom src='qrc:/icons/gears.png'>▾")
|
||||
# children
|
||||
buf += self._renderDeckTree(children, depth+1)
|
||||
return buf
|
||||
|
@ -108,25 +110,29 @@ body { margin: 1em; }
|
|||
# Options
|
||||
##########################################################################
|
||||
|
||||
def _optsForRow(self, n):
|
||||
def _showOptions(self, did):
|
||||
m = QMenu(self.mw)
|
||||
# delete
|
||||
a = m.addAction(QIcon(":/icons/editdelete.png"), _("Delete"))
|
||||
a.connect(a, SIGNAL("triggered()"), lambda n=n: self._deleteRow(n))
|
||||
a = m.addAction(_("Rename"))
|
||||
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._rename(did))
|
||||
a = m.addAction(_("Delete"))
|
||||
a.connect(a, SIGNAL("triggered()"), lambda did=did: self._delete(did))
|
||||
m.exec_(QCursor.pos())
|
||||
|
||||
def _deleteRow(self, c):
|
||||
d = self._decks[c]
|
||||
if d['state'] == 'missing':
|
||||
return self._hideRow(c)
|
||||
def _rename(self, did):
|
||||
deck = self.mw.col.decks.get(did)
|
||||
newName = getOnlyText(_("New deck name:"))
|
||||
if not newName:
|
||||
return
|
||||
if deck in self.mw.col.decks.allNames():
|
||||
return showWarning(_("That deck already exists."))
|
||||
self.mw.col.decks.rename(deck, newName)
|
||||
self.show()
|
||||
|
||||
def _delete(self, did):
|
||||
if did == 1:
|
||||
return showWarning(_("The default deck can't be deleted."))
|
||||
deck = self.mw.col.decks.get(did)
|
||||
if askUser(_("""\
|
||||
Delete %s? If this deck is synchronized the online version will \
|
||||
not be touched.""") % d['name']):
|
||||
deck = d['path']
|
||||
os.unlink(deck)
|
||||
try:
|
||||
shutil.rmtree(re.sub(".anki$", ".media", deck))
|
||||
except OSError:
|
||||
pass
|
||||
self.mw.config.delRecentDeck(deck)
|
||||
self.refresh()
|
||||
Are you sure you wish to delete all of the cards in %s?""")%deck['name']):
|
||||
self.mw.col.decks.rem(did, True)
|
||||
self.show()
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
from aqt.qt import *
|
||||
import sys, re
|
||||
import aqt
|
||||
from aqt.utils import maybeHideClose
|
||||
from aqt.utils import maybeHideClose, openHelp
|
||||
|
||||
class ColOptions(QDialog):
|
||||
|
||||
|
@ -28,7 +28,7 @@ class ColOptions(QDialog):
|
|||
self.form.mediaURL.setText(self.d.conf['mediaURL'])
|
||||
|
||||
def helpRequested(self):
|
||||
aqt.openHelp("ColOptions")
|
||||
openHelp("ColOptions")
|
||||
|
||||
def reject(self):
|
||||
needSync = False
|
||||
|
|
|
@ -9,7 +9,8 @@ from anki.sound import play
|
|||
from anki.hooks import runHook
|
||||
from aqt.sound import getAudio
|
||||
from aqt.webview import AnkiWebView
|
||||
from aqt.utils import shortcut, showInfo, showWarning, getBase, getFile
|
||||
from aqt.utils import shortcut, showInfo, showWarning, getBase, getFile, \
|
||||
openHelp
|
||||
import aqt
|
||||
import anki.js
|
||||
|
||||
|
@ -449,7 +450,7 @@ class Editor(object):
|
|||
form = aqt.forms.edithtml.Ui_Dialog()
|
||||
form.setupUi(d)
|
||||
d.connect(form.buttonBox, SIGNAL("helpRequested()"),
|
||||
lambda: aqt.openHelp("HtmlEditor"))
|
||||
lambda: openHelp("HtmlEditor"))
|
||||
form.textEdit.setPlainText(self.note.fields[self.currentField])
|
||||
form.textEdit.moveCursor(QTextCursor.End)
|
||||
d.exec_()
|
||||
|
@ -582,7 +583,7 @@ class Editor(object):
|
|||
txtcol)
|
||||
|
||||
def colourChanged(self):
|
||||
recent = self.mw.config['recentColours']
|
||||
recent = self.mw.pm.profile['recentColours']
|
||||
self._updateForegroundButton(recent[-1])
|
||||
|
||||
def onForeground(self):
|
||||
|
@ -606,7 +607,7 @@ class Editor(object):
|
|||
self.colourChoose = QShortcut(QKeySequence("F6"), p)
|
||||
p.connect(self.colourChoose, SIGNAL("activated()"),
|
||||
self.onChooseColourKey)
|
||||
for n, c in enumerate(reversed(self.mw.config['recentColours'])):
|
||||
for n, c in enumerate(reversed(self.mw.pm.profile['recentColours'])):
|
||||
col = QToolButton()
|
||||
col.setAutoRaise(True)
|
||||
col.setFixedWidth(64)
|
||||
|
@ -640,7 +641,7 @@ class Editor(object):
|
|||
p.show()
|
||||
|
||||
def onRemoveColour(self, colour):
|
||||
recent = self.mw.config['recentColours']
|
||||
recent = self.mw.pm.profile['recentColours']
|
||||
recent.remove(colour)
|
||||
if not recent:
|
||||
recent.append("#000000")
|
||||
|
@ -659,7 +660,7 @@ class Editor(object):
|
|||
pass
|
||||
|
||||
def onChooseColour(self, colour):
|
||||
recent = self.mw.config['recentColours']
|
||||
recent = self.mw.pm.profile['recentColours']
|
||||
recent.remove(colour)
|
||||
recent.append(colour)
|
||||
self.web.eval("setFormat('forecolor', '%s')" % colour)
|
||||
|
@ -669,7 +670,7 @@ class Editor(object):
|
|||
def onNewColour(self):
|
||||
new = QColorDialog.getColor(Qt.white, self.widget)
|
||||
self.widget.raise_()
|
||||
recent = self.mw.config['recentColours']
|
||||
recent = self.mw.pm.profile['recentColours']
|
||||
if new.isValid():
|
||||
txtcol = unicode(new.name())
|
||||
if txtcol not in recent:
|
||||
|
@ -698,7 +699,7 @@ class Editor(object):
|
|||
# copy to media folder
|
||||
name = self.mw.col.media.addFile(path)
|
||||
# remove original?
|
||||
if canDelete and self.mw.config['deleteMedia']:
|
||||
if canDelete and self.mw.pm.profile['deleteMedia']:
|
||||
if os.path.abspath(name) != os.path.abspath(path):
|
||||
try:
|
||||
os.unlink(old)
|
||||
|
@ -738,7 +739,7 @@ class Editor(object):
|
|||
######################################################################
|
||||
|
||||
def setupKeyboard(self):
|
||||
if isWin and self.mw.config['preserveKeyboard']:
|
||||
if isWin and self.mw.pm.profile['preserveKeyboard']:
|
||||
a = ctypes.windll.user32.ActivateKeyboardLayout
|
||||
a.restype = ctypes.c_void_p
|
||||
a.argtypes = [ctypes.c_void_p, ctypes.c_uint]
|
||||
|
@ -773,7 +774,7 @@ class EditorWebView(AnkiWebView):
|
|||
AnkiWebView.__init__(self, parent)
|
||||
self.editor = editor
|
||||
self.errtxt = _("An error occured while opening %s")
|
||||
self.strip = self.editor.mw.config['stripHTML']
|
||||
self.strip = self.editor.mw.pm.profile['stripHTML']
|
||||
|
||||
def keyPressEvent(self, evt):
|
||||
self._curKey = True
|
||||
|
|
495
aqt/fields.py
Normal file
495
aqt/fields.py
Normal file
|
@ -0,0 +1,495 @@
|
|||
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from aqt.qt import *
|
||||
import re
|
||||
from anki.consts import *
|
||||
import aqt
|
||||
from anki.sound import playFromText, clearAudioQueue
|
||||
from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA, \
|
||||
saveSplitter, restoreSplitter, showInfo, askUser, getText, \
|
||||
openHelp
|
||||
from anki.utils import isMac, isWin
|
||||
import aqt.templates
|
||||
|
||||
# raise Exception("Remember to disallow media&latex refs in edit.")
|
||||
|
||||
# need to strip the field management code out of this
|
||||
|
||||
class CardLayout(QDialog):
|
||||
|
||||
def __init__(self, mw, note, ord=0, parent=None):
|
||||
QDialog.__init__(self, parent or mw, Qt.Window)
|
||||
self.mw = aqt.mw
|
||||
self.parent = parent or mw
|
||||
self.note = note
|
||||
self.ord = ord
|
||||
self.col = self.mw.col
|
||||
self.mm = self.mw.col.models
|
||||
self.model = note.model()
|
||||
self.setupTabs()
|
||||
v1 = QVBoxLayout()
|
||||
v1.addWidget(self.tabs)
|
||||
self.bbox = QDialogButtonBox(QDialogButtonBox.Close)
|
||||
v1.addWidget(self.bbox)
|
||||
self.setLayout(v1)
|
||||
self.updateTabs()
|
||||
self.exec_()
|
||||
return
|
||||
|
||||
def setupTabs(self):
|
||||
self.tabs = QTabWidget()
|
||||
self.tabs.setTabsClosable(True)
|
||||
self.tabs.setUsesScrollButtons(True)
|
||||
self.tabs.setMovable(True)
|
||||
add = QPushButton("+")
|
||||
add.setFixedWidth(30)
|
||||
self.tabs.setCornerWidget(add)
|
||||
|
||||
def updateTabs(self):
|
||||
self.forms = []
|
||||
self.tabs.clear()
|
||||
for t in self.model['tmpls']:
|
||||
self.addTab(t)
|
||||
|
||||
def addTab(self, t):
|
||||
w = QWidget()
|
||||
h = QHBoxLayout()
|
||||
h.addStretch()
|
||||
label = QLabel(_("Name:"))
|
||||
h.addWidget(label)
|
||||
edit = QLineEdit()
|
||||
edit.setFixedWidth(200)
|
||||
h.addWidget(edit)
|
||||
h.addStretch()
|
||||
v = QVBoxLayout()
|
||||
v.addLayout(h)
|
||||
l = QHBoxLayout()
|
||||
l.setMargin(0)
|
||||
l.setSpacing(3)
|
||||
left = QWidget()
|
||||
# template area
|
||||
tform = aqt.forms.template.Ui_Form()
|
||||
tform.setupUi(left)
|
||||
l.addWidget(left, 5)
|
||||
# preview area
|
||||
right = QWidget()
|
||||
pform = aqt.forms.preview.Ui_Form()
|
||||
pform.setupUi(right)
|
||||
l.addWidget(right, 5)
|
||||
v.addLayout(l)
|
||||
w.setLayout(v)
|
||||
self.tabs.addTab(w, t['name'])
|
||||
self.forms.append([tform, pform, edit])
|
||||
|
||||
def old():
|
||||
self.form = aqt.forms.clayout.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
self.setWindowTitle(_("%s Layout") % self.model['name'])
|
||||
self.plastiqueStyle = None
|
||||
if isMac or isWin:
|
||||
self.plastiqueStyle = QStyleFactory.create("plastique")
|
||||
self.connect(self.form.buttonBox, SIGNAL("helpRequested()"),
|
||||
self.onHelp)
|
||||
self.setupCards()
|
||||
self.setupFields()
|
||||
self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False)
|
||||
self.form.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False)
|
||||
restoreSplitter(self.form.splitter, "clayout")
|
||||
restoreGeom(self, "CardLayout")
|
||||
if not self.reload(first=True):
|
||||
return
|
||||
self.exec_()
|
||||
|
||||
|
||||
def reload(self, first=False):
|
||||
self.cards = self.col.previewCards(self.note, self.type)
|
||||
if not self.cards:
|
||||
self.accept()
|
||||
if first:
|
||||
showInfo(_("Please enter some text first."))
|
||||
else:
|
||||
showInfo(_("The current note was deleted."))
|
||||
return
|
||||
self.fillCardList()
|
||||
self.fillFieldList()
|
||||
self.fieldChanged()
|
||||
self.readField()
|
||||
return True
|
||||
|
||||
# Cards & Preview
|
||||
##########################################################################
|
||||
|
||||
def setupCards(self):
|
||||
self.updatingCards = False
|
||||
self.playedAudio = {}
|
||||
f = self.form
|
||||
if self.type == 0:
|
||||
f.templateType.setText(
|
||||
_("Templates that will be created:"))
|
||||
elif self.type == 1:
|
||||
f.templateType.setText(
|
||||
_("Templates used by note:"))
|
||||
else:
|
||||
f.templateType.setText(
|
||||
_("All templates:"))
|
||||
# replace with more appropriate size hints
|
||||
for e in ("cardQuestion", "cardAnswer"):
|
||||
w = getattr(f, e)
|
||||
idx = f.templateLayout.indexOf(w)
|
||||
r = f.templateLayout.getItemPosition(idx)
|
||||
f.templateLayout.removeWidget(w)
|
||||
w.hide()
|
||||
w.deleteLater()
|
||||
w = ResizingTextEdit(self)
|
||||
setattr(f, e, w)
|
||||
f.templateLayout.addWidget(w, r[0], r[1])
|
||||
c = self.connect
|
||||
c(f.cardList, SIGNAL("activated(int)"), self.cardChanged)
|
||||
c(f.editTemplates, SIGNAL("clicked()"), self.onEdit)
|
||||
c(f.cardQuestion, SIGNAL("textChanged()"), self.formatChanged)
|
||||
c(f.cardAnswer, SIGNAL("textChanged()"), self.formatChanged)
|
||||
c(f.alignment, SIGNAL("activated(int)"), self.saveCard)
|
||||
c(f.background, SIGNAL("clicked()"),
|
||||
lambda w=f.background:\
|
||||
self.chooseColour(w, "card"))
|
||||
c(f.questionInAnswer, SIGNAL("clicked()"), self.saveCard)
|
||||
c(f.allowEmptyAnswer, SIGNAL("clicked()"), self.saveCard)
|
||||
c(f.typeAnswer, SIGNAL("activated(int)"), self.saveCard)
|
||||
c(f.flipButton, SIGNAL("clicked()"), self.onFlip)
|
||||
c(f.clozectx, SIGNAL("clicked()"), self.saveCard)
|
||||
def linkClicked(url):
|
||||
QDesktopServices.openUrl(QUrl(url))
|
||||
f.preview.page().setLinkDelegationPolicy(
|
||||
QWebPage.DelegateExternalLinks)
|
||||
self.connect(f.preview,
|
||||
SIGNAL("linkClicked(QUrl)"),
|
||||
linkClicked)
|
||||
f.alignment.addItems(alignmentLabels().values())
|
||||
self.typeFieldNames = self.mm.fieldMap(self.model)
|
||||
s = [_("Don't ask me to type in the answer")]
|
||||
s += [_("Compare with field '%s'") % fi
|
||||
for fi in self.typeFieldNames.keys()]
|
||||
f.typeAnswer.insertItems(0, s)
|
||||
|
||||
def formatToScreen(self, fmt):
|
||||
fmt = fmt.replace("}}<br>", "}}\n")
|
||||
return fmt
|
||||
|
||||
def screenToFormat(self, fmt):
|
||||
fmt = fmt.replace("}}\n", "}}<br>")
|
||||
return fmt
|
||||
|
||||
def onEdit(self):
|
||||
aqt.templates.Templates(self.mw, self.model, self)
|
||||
self.reload()
|
||||
|
||||
def formatChanged(self):
|
||||
if self.updatingCards:
|
||||
return
|
||||
text = unicode(self.form.cardQuestion.toPlainText())
|
||||
self.card.template()['qfmt'] = self.screenToFormat(text)
|
||||
text = unicode(self.form.cardAnswer.toPlainText())
|
||||
self.card.template()['afmt'] = self.screenToFormat(text)
|
||||
self.renderPreview()
|
||||
|
||||
def onFlip(self):
|
||||
q = unicode(self.form.cardQuestion.toPlainText())
|
||||
a = unicode(self.form.cardAnswer.toPlainText())
|
||||
self.form.cardAnswer.setPlainText(q)
|
||||
self.form.cardQuestion.setPlainText(a)
|
||||
|
||||
def readCard(self):
|
||||
self.updatingCards = True
|
||||
t = self.card.template()
|
||||
f = self.form
|
||||
f.background.setPalette(QPalette(QColor(t['bg'])))
|
||||
f.cardQuestion.setPlainText(self.formatToScreen(t['qfmt']))
|
||||
f.cardAnswer.setPlainText(self.formatToScreen(t['afmt']))
|
||||
f.questionInAnswer.setChecked(t['hideQ'])
|
||||
f.allowEmptyAnswer.setChecked(t['emptyAns'])
|
||||
f.alignment.setCurrentIndex(t['align'])
|
||||
if t['typeAns'] is None:
|
||||
f.typeAnswer.setCurrentIndex(0)
|
||||
else:
|
||||
f.typeAnswer.setCurrentIndex(t['typeAns'] + 1)
|
||||
# model-level, but there's nowhere else to put this
|
||||
f.clozectx.setChecked(self.model['clozectx'])
|
||||
self.updatingCards = False
|
||||
|
||||
def fillCardList(self):
|
||||
self.form.cardList.clear()
|
||||
cards = []
|
||||
idx = 0
|
||||
for n, c in enumerate(self.cards):
|
||||
if c.ord == self.ord:
|
||||
cards.append(_("%s (current)") % c.template()['name'])
|
||||
idx = n
|
||||
else:
|
||||
cards.append(c.template()['name'])
|
||||
self.form.cardList.addItems(cards)
|
||||
self.form.cardList.setCurrentIndex(idx)
|
||||
self.cardChanged(idx)
|
||||
self.form.cardList.setFocus()
|
||||
|
||||
def cardChanged(self, idx):
|
||||
self.card = self.cards[idx]
|
||||
self.readCard()
|
||||
self.renderPreview()
|
||||
|
||||
def saveCard(self):
|
||||
if self.updatingCards:
|
||||
return
|
||||
t = self.card.template()
|
||||
t['align'] = self.form.alignment.currentIndex()
|
||||
t['bg'] = unicode(
|
||||
self.form.background.palette().window().color().name())
|
||||
t['hideQ'] = self.form.questionInAnswer.isChecked()
|
||||
t['emptyAns'] = self.form.allowEmptyAnswer.isChecked()
|
||||
idx = self.form.typeAnswer.currentIndex()
|
||||
if not idx:
|
||||
t['typeAns'] = None
|
||||
else:
|
||||
t['typeAns'] = idx-1
|
||||
self.model['clozectx'] = self.form.clozectx.isChecked()
|
||||
self.renderPreview()
|
||||
|
||||
def chooseColour(self, button, type="field"):
|
||||
new = QColorDialog.getColor(button.palette().window().color(), self,
|
||||
_("Choose Color"),
|
||||
QColorDialog.DontUseNativeDialog)
|
||||
if new.isValid():
|
||||
button.setPalette(QPalette(new))
|
||||
if type == "field":
|
||||
self.saveField()
|
||||
else:
|
||||
self.saveCard()
|
||||
|
||||
def renderPreview(self):
|
||||
c = self.card
|
||||
styles = self.model['css']
|
||||
styles += "\n.cloze { font-weight: bold; color: blue; }"
|
||||
self.form.preview.setHtml(
|
||||
('<html><head>%s</head><body class="%s">' %
|
||||
(getBase(self.col), c.cssClass())) +
|
||||
"<style>" + styles + "</style>" +
|
||||
mungeQA(c.q(reload=True)) +
|
||||
self.maybeTextInput() +
|
||||
"<hr>" +
|
||||
mungeQA(c.a())
|
||||
+ "</body></html>")
|
||||
clearAudioQueue()
|
||||
if c.id not in self.playedAudio:
|
||||
playFromText(c.q())
|
||||
playFromText(c.a())
|
||||
self.playedAudio[c.id] = True
|
||||
|
||||
def maybeTextInput(self):
|
||||
if self.card.template()['typeAns'] is not None:
|
||||
return "<center><input type=text></center>"
|
||||
return ""
|
||||
|
||||
def accept(self):
|
||||
self.reject()
|
||||
|
||||
def reject(self):
|
||||
return QDialog.reject(self)
|
||||
self.mm.save(self.model)
|
||||
saveGeom(self, "CardLayout")
|
||||
saveSplitter(self.form.splitter, "clayout")
|
||||
self.mw.reset()
|
||||
return QDialog.reject(self)
|
||||
|
||||
|
||||
modified = False
|
||||
self.mw.startProgress()
|
||||
self.col.updateProgress(_("Applying changes..."))
|
||||
reset=True
|
||||
if len(self.fieldOrdinalUpdatedIds) > 0:
|
||||
self.col.rebuildFieldOrdinals(self.model.id, self.fieldOrdinalUpdatedIds)
|
||||
modified = True
|
||||
if self.needFieldRebuild:
|
||||
modified = True
|
||||
if modified:
|
||||
self.note.model.setModified()
|
||||
self.col.flushMod()
|
||||
if self.noteedit and self.noteedit.onChange:
|
||||
self.noteedit.onChange("all")
|
||||
reset=False
|
||||
if reset:
|
||||
self.mw.reset()
|
||||
self.col.finishProgress()
|
||||
QDialog.reject(self)
|
||||
|
||||
def onHelp(self):
|
||||
openHelp("CardLayout")
|
||||
|
||||
# Fields
|
||||
##########################################################################
|
||||
|
||||
def setupFields(self):
|
||||
self.fieldOrdinalUpdatedIds = []
|
||||
self.updatingFields = False
|
||||
self.needFieldRebuild = False
|
||||
c = self.connect; f = self.form
|
||||
sc = SIGNAL("stateChanged(int)")
|
||||
cl = SIGNAL("clicked()")
|
||||
c(f.fieldAdd, cl, self.addField)
|
||||
c(f.fieldDelete, cl, self.deleteField)
|
||||
c(f.fieldUp, cl, self.moveFieldUp)
|
||||
c(f.fieldDown, cl, self.moveFieldDown)
|
||||
c(f.preserveWhitespace, sc, self.saveField)
|
||||
c(f.fieldUnique, sc, self.saveField)
|
||||
c(f.fieldRequired, sc, self.saveField)
|
||||
c(f.sticky, sc, self.saveField)
|
||||
c(f.fieldList, SIGNAL("currentRowChanged(int)"),
|
||||
self.fieldChanged)
|
||||
c(f.fieldName, SIGNAL("lostFocus()"),
|
||||
self.saveField)
|
||||
c(f.fontFamily, SIGNAL("currentFontChanged(QFont)"),
|
||||
self.saveField)
|
||||
c(f.fontSize, SIGNAL("valueChanged(int)"),
|
||||
self.saveField)
|
||||
c(f.fontSizeEdit, SIGNAL("valueChanged(int)"),
|
||||
self.saveField)
|
||||
w = self.form.fontColour
|
||||
c(w, SIGNAL("clicked()"),
|
||||
lambda w=w: self.chooseColour(w))
|
||||
c(self.form.rtl,
|
||||
SIGNAL("stateChanged(int)"),
|
||||
self.saveField)
|
||||
|
||||
def fieldChanged(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row == -1:
|
||||
row = 0
|
||||
self.field = self.model['flds'][row]
|
||||
self.readField()
|
||||
self.enableFieldMoveButtons()
|
||||
|
||||
def readField(self):
|
||||
fld = self.field
|
||||
f = self.form
|
||||
self.updatingFields = True
|
||||
f.fieldName.setText(fld['name'])
|
||||
f.fieldUnique.setChecked(fld['uniq'])
|
||||
f.fieldRequired.setChecked(fld['req'])
|
||||
f.fontFamily.setCurrentFont(QFont(fld['font']))
|
||||
f.fontSize.setValue(fld['qsize'])
|
||||
f.fontSizeEdit.setValue(fld['esize'])
|
||||
f.fontColour.setPalette(QPalette(QColor(fld['qcol'])))
|
||||
f.rtl.setChecked(fld['rtl'])
|
||||
f.preserveWhitespace.setChecked(fld['pre'])
|
||||
f.sticky.setChecked(fld['sticky'])
|
||||
self.updatingFields = False
|
||||
|
||||
def saveField(self, *args):
|
||||
self.needFieldRebuild = True
|
||||
if self.updatingFields:
|
||||
return
|
||||
self.updatingFields = True
|
||||
fld = self.field
|
||||
# get name; we'll handle it last
|
||||
name = unicode(self.form.fieldName.text())
|
||||
if not name:
|
||||
return
|
||||
fld['uniq'] = self.form.fieldUnique.isChecked()
|
||||
fld['req'] = self.form.fieldRequired.isChecked()
|
||||
fld['font'] = unicode(
|
||||
self.form.fontFamily.currentFont().family())
|
||||
fld['qsize'] = self.form.fontSize.value()
|
||||
fld['esize'] = self.form.fontSizeEdit.value()
|
||||
fld['qcol'] = str(
|
||||
self.form.fontColour.palette().window().color().name())
|
||||
fld['rtl'] = self.form.rtl.isChecked()
|
||||
fld['pre'] = self.form.preserveWhitespace.isChecked()
|
||||
fld['sticky'] = self.form.sticky.isChecked()
|
||||
self.updatingFields = False
|
||||
if fld['name'] != name:
|
||||
self.mm.renameField(self.model, fld, name)
|
||||
# as the field name has changed, we have to regenerate cards
|
||||
self.cards = self.col.previewCards(self.note, self.type)
|
||||
self.cardChanged(0)
|
||||
self.renderPreview()
|
||||
self.fillFieldList()
|
||||
|
||||
def fillFieldList(self, row = None):
|
||||
oldRow = self.form.fieldList.currentRow()
|
||||
if oldRow == -1:
|
||||
oldRow = 0
|
||||
self.form.fieldList.clear()
|
||||
n = 1
|
||||
for field in self.model['flds']:
|
||||
label = field['name']
|
||||
item = QListWidgetItem(label)
|
||||
self.form.fieldList.addItem(item)
|
||||
n += 1
|
||||
count = self.form.fieldList.count()
|
||||
if row != None:
|
||||
self.form.fieldList.setCurrentRow(row)
|
||||
else:
|
||||
while (count > 0 and oldRow > (count - 1)):
|
||||
oldRow -= 1
|
||||
self.form.fieldList.setCurrentRow(oldRow)
|
||||
self.enableFieldMoveButtons()
|
||||
|
||||
def enableFieldMoveButtons(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row < 1:
|
||||
self.form.fieldUp.setEnabled(False)
|
||||
else:
|
||||
self.form.fieldUp.setEnabled(True)
|
||||
if row == -1 or row >= (self.form.fieldList.count() - 1):
|
||||
self.form.fieldDown.setEnabled(False)
|
||||
else:
|
||||
self.form.fieldDown.setEnabled(True)
|
||||
|
||||
def addField(self):
|
||||
f = self.mm.newField(self.model)
|
||||
l = len(self.model['flds'])
|
||||
f['name'] = _("Field %d") % l
|
||||
self.mw.progress.start()
|
||||
self.mm.addField(self.model, f)
|
||||
self.mw.progress.finish()
|
||||
self.reload()
|
||||
self.form.fieldList.setCurrentRow(l)
|
||||
self.form.fieldName.setFocus()
|
||||
self.form.fieldName.selectAll()
|
||||
|
||||
def deleteField(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row == -1:
|
||||
return
|
||||
if len(self.model.fields) < 2:
|
||||
showInfo(_("Please add a new field first."))
|
||||
return
|
||||
if askUser(_("Delete this field and its data from all notes?")):
|
||||
self.mw.progress.start()
|
||||
self.model.delField(self.field)
|
||||
self.mw.progress.finish()
|
||||
# need to update q/a format
|
||||
self.reload()
|
||||
|
||||
def moveFieldUp(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row == -1:
|
||||
return
|
||||
if row == 0:
|
||||
return
|
||||
self.mw.progress.start()
|
||||
self.model.moveField(self.field, row-1)
|
||||
self.mw.progress.finish()
|
||||
self.form.fieldList.setCurrentRow(row-1)
|
||||
self.reload()
|
||||
|
||||
def moveFieldDown(self):
|
||||
row = self.form.fieldList.currentRow()
|
||||
if row == -1:
|
||||
return
|
||||
if row == len(self.model.fields) - 1:
|
||||
return
|
||||
self.mw.progress.start()
|
||||
self.model.moveField(self.field, row+1)
|
||||
self.mw.progress.finish()
|
||||
self.form.fieldList.setCurrentRow(row+1)
|
||||
self.reload()
|
|
@ -51,7 +51,7 @@ Error was:<pre>%s</pre>""")
|
|||
self.form.table, SIGNAL("currentCellChanged(int,int,int,int)"),
|
||||
self.onCellChanged)
|
||||
self.form.table.verticalHeader().setDefaultSectionSize(
|
||||
self.parent.config['editLineSize'])
|
||||
self.parent.pm.profile['editLineSize'])
|
||||
self.connect(self.form.search, SIGNAL("textChanged(QString)"),
|
||||
self.limit)
|
||||
|
||||
|
@ -222,7 +222,7 @@ Error was:<pre>%s</pre>""")
|
|||
tit = tit[0:40]
|
||||
if self.type == 0:
|
||||
# col
|
||||
dd = self.parent.config['documentDir']
|
||||
dd = self.parent.pm.profile['documentDir']
|
||||
p = os.path.join(dd, tit + ".anki")
|
||||
if os.path.exists(p):
|
||||
tit += "%d" % time.time()
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
from aqt.qt import *
|
||||
import aqt, simplejson
|
||||
from anki.utils import ids2str
|
||||
from aqt.utils import showInfo, showWarning
|
||||
from aqt.utils import showInfo, showWarning, openHelp
|
||||
|
||||
# Configuration editing
|
||||
##########################################################################
|
||||
|
@ -24,7 +24,7 @@ class GroupConf(QDialog):
|
|||
self.setup()
|
||||
self.connect(self.form.buttonBox,
|
||||
SIGNAL("helpRequested()"),
|
||||
lambda: aqt.openHelp("GroupOptions"))
|
||||
lambda: openHelp("GroupOptions"))
|
||||
self.connect(self.form.buttonBox.button(QDialogButtonBox.RestoreDefaults),
|
||||
SIGNAL("clicked()"),
|
||||
self.onRestore)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
from aqt.qt import *
|
||||
import aqt
|
||||
from aqt.utils import showInfo, getOnlyText
|
||||
from aqt.utils import showInfo, getOnlyText, openHelp
|
||||
|
||||
COLNAME = 0
|
||||
COLOPTS = 1
|
||||
|
@ -79,7 +79,7 @@ class Groups(QDialog):
|
|||
button(f.delete_2, self.onDelete)
|
||||
self.connect(self.form.buttonBox,
|
||||
SIGNAL("helpRequested()"),
|
||||
lambda: aqt.openHelp("Groups"))
|
||||
lambda: openHelp("Groups"))
|
||||
|
||||
def onSelectAll(self):
|
||||
for i in self.items:
|
||||
|
|
|
@ -65,7 +65,7 @@ class UpdateMap(QDialog):
|
|||
self.exec_()
|
||||
|
||||
def helpRequested(self):
|
||||
aqt.openHelp("FileImport")
|
||||
openHelp("FileImport")
|
||||
|
||||
def accept(self):
|
||||
self.updateKey = (
|
||||
|
@ -311,4 +311,4 @@ you can enter it here. Use \\t to represent tab."""),
|
|||
QDialog.reject(self)
|
||||
|
||||
def helpRequested(self):
|
||||
aqt.openHelp("FileImport")
|
||||
openHelp("FileImport")
|
||||
|
|
|
@ -191,8 +191,10 @@ Are you sure?"""):
|
|||
# maybe sync
|
||||
self.onSync()
|
||||
# then load collection and launch into the deck browser
|
||||
print "fixme: safeguard against multiple instances"
|
||||
self.col = Collection(self.pm.collectionPath())
|
||||
self.moveToState("overview")
|
||||
# skip the reset step; open overview directly
|
||||
self.moveToState("review")
|
||||
|
||||
def unloadProfile(self):
|
||||
self.col = None
|
||||
|
@ -633,8 +635,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
|||
|
||||
def onCardLayout(self):
|
||||
from aqt.clayout import CardLayout
|
||||
CardLayout(self, self.reviewer.card.note(), type=1,
|
||||
ord=self.reviewer.card.ord)
|
||||
CardLayout(self, self.reviewer.card.note(), ord=self.reviewer.card.ord)
|
||||
|
||||
def onDeckOpts(self):
|
||||
import aqt.deckopts
|
||||
|
@ -797,7 +798,7 @@ Please choose a new deck name:"""))
|
|||
self.form.actionDelete.setEnabled(True)
|
||||
self.form.actionBuryNote.setEnabled(True)
|
||||
self.form.actionEditCurrent.setEnabled(True)
|
||||
self.form.actionEditdeck.setEnabled(True)
|
||||
self.form.actionBrowse.setEnabled(True)
|
||||
self.updateMarkAction()
|
||||
runHook("enableCardMenuItems")
|
||||
|
||||
|
|
|
@ -196,4 +196,4 @@ class AddModel(QDialog):
|
|||
QDialog.accept(self)
|
||||
|
||||
def onHelp(self):
|
||||
aqt.openHelp("AddModel")
|
||||
openHelp("AddModel")
|
||||
|
|
|
@ -15,7 +15,7 @@ class Models(QDialog):
|
|||
self.form = aqt.forms.models.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
self.connect(self.form.buttonBox, SIGNAL("helpRequested()"),
|
||||
lambda: aqt.openHelp("Models"))
|
||||
lambda: openHelp("Models"))
|
||||
self.setupModels()
|
||||
self.exec_()
|
||||
|
||||
|
|
121
aqt/overview.py
121
aqt/overview.py
|
@ -6,7 +6,7 @@ import simplejson
|
|||
from aqt.qt import *
|
||||
from anki.consts import NEW_CARDS_RANDOM
|
||||
from anki.hooks import addHook
|
||||
from aqt.utils import limitedCount, showInfo
|
||||
from aqt.utils import showInfo
|
||||
|
||||
class Overview(object):
|
||||
"Deck overview."
|
||||
|
@ -57,9 +57,6 @@ class Overview(object):
|
|||
############################################################
|
||||
|
||||
def _renderPage(self):
|
||||
css = self.mw.sharedCSS + self._overviewCSS
|
||||
fc = self._ovForecast()
|
||||
tbl = self._overviewTable()
|
||||
but = self.mw.button
|
||||
deck = self.mw.col.decks.current()
|
||||
sid = deck.get("sharedFrom")
|
||||
|
@ -67,85 +64,67 @@ class Overview(object):
|
|||
shareLink = '<a class=smallLink href="review">Reviews and Updates</a>'
|
||||
else:
|
||||
shareLink = ""
|
||||
header = ""
|
||||
self.web.stdHtml(self._overviewBody % dict(
|
||||
title=_("Overview"),
|
||||
table=tbl,
|
||||
fcsub=_("Reviews over next two weeks"),
|
||||
print self._body % dict(
|
||||
deck=deck['name'],
|
||||
shareLink=shareLink,
|
||||
desc="",
|
||||
header=header,
|
||||
fcdata=fc,
|
||||
), css)
|
||||
desc=self._desc(deck),
|
||||
table=self._table())
|
||||
self.web.stdHtml(self._body % dict(
|
||||
deck=deck['name'],
|
||||
shareLink=shareLink,
|
||||
desc=self._desc(deck),
|
||||
table=self._table()
|
||||
), self.mw.sharedCSS + self._css)
|
||||
|
||||
_overviewBody = """
|
||||
%(header)s
|
||||
def _desc(self, deck):
|
||||
desc = deck.get("desc", "")
|
||||
if not desc:
|
||||
return ""
|
||||
if len(desc) < 160:
|
||||
return '<div class="descfont description">%s</div>' % desc
|
||||
else:
|
||||
return '''
|
||||
<div class="descfont description descmid" id=shortdesc>%s\
|
||||
<a href=# onclick="$('shortdesc').hide();$('fulldesc').show();">...More</a></div>
|
||||
<div class="descfont description descmid" id=fulldesc>%s</div>''' % (
|
||||
desc[:160], desc)
|
||||
|
||||
def _table(self):
|
||||
counts = self.mw.col.sched.repCounts()
|
||||
finished = not sum(counts)
|
||||
but = self.mw.button
|
||||
if finished:
|
||||
return '<div class=fin style="white-space: pre-wrap;">%s</div>' % (
|
||||
self.mw.col.sched.finishedMsg())
|
||||
else:
|
||||
return '''
|
||||
<table width=300 cellpadding=5>
|
||||
<tr><td align=center valign=top>
|
||||
<table cellspacing=5>
|
||||
<tr><td>%s:</td><td><b><font color=#00a>%s</font></b></td></tr>
|
||||
<tr><td>%s:</td><td><b><font color=#a00>%s</font></b></td></tr>
|
||||
<tr><td>%s:</td><td><b><font color=#0a0>%s</font></b></td></tr>
|
||||
</table>
|
||||
</td><td>%s</td></tr></table>''' % (_("New"), counts[0],
|
||||
_("In Learning"), counts[1],
|
||||
_("To Review"), counts[2],
|
||||
but("study", _("Study")))
|
||||
|
||||
_body = """
|
||||
<center>
|
||||
<h3>%(deck)s</h3>
|
||||
%(shareLink)s
|
||||
%(desc)s
|
||||
<p>
|
||||
<div id="placeholder" style="width:350px; height:100px;"></div>
|
||||
<span class=sub>%(fcsub)s</span>
|
||||
<p>
|
||||
%(table)s
|
||||
</center>
|
||||
|
||||
<script>
|
||||
$("#study").focus();
|
||||
$(function () {
|
||||
var d = %(fcdata)s;
|
||||
if (typeof(d) !== "string") {
|
||||
$.plot($("#placeholder"), [
|
||||
{ data: d, bars: { show: true, barWidth: 0.8 }, color: "#0c0" }
|
||||
], {
|
||||
xaxis: { ticks: [[0.4, "Today"]] },
|
||||
yaxis: { tickDecimals: 0 }
|
||||
});
|
||||
} else {
|
||||
$("#placeholder").text(d);
|
||||
$(".sub").hide();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
"""
|
||||
|
||||
_overviewCSS = """
|
||||
.due { text-align: right; }
|
||||
.new { text-align: right; }
|
||||
.sub { font-size: 80%; color: #555; }
|
||||
.smallLink { font-size: 12px; }
|
||||
_css = """
|
||||
.smallLink { font-size: 10px; }
|
||||
h3 { margin-bottom: 0; }
|
||||
.fin { font-size: 12px; font-weight: normal; }
|
||||
td { font-size: 14px; }
|
||||
"""
|
||||
|
||||
def _overviewTable(self):
|
||||
return ""
|
||||
but = self.mw.button
|
||||
buf = "<table cellspacing=0 cellpadding=3 width=400>"
|
||||
buf += "<tr><th></th><th align=right>%s</th>" % _("Due")
|
||||
buf += "<th align=right>%s</th><th></th></tr>" % _("New")
|
||||
line = "<tr><td><b>%s</b></td><td class=due>%s</td>"
|
||||
line += "<td class=new>%s</td><td>%s</td></tr>"
|
||||
buf += line % (
|
||||
"<a href=chgrp>%s</a>" % _("Selected Groups"),
|
||||
counts[0], counts[1],
|
||||
but("study", _("Study"), _("s"), "gbut", id="study") +
|
||||
but("cram", _("Cram"), "c"))
|
||||
buf += line % (
|
||||
_("Whole Deck"),
|
||||
counts[2], counts[3],
|
||||
but("opts", _("Study Options")))
|
||||
buf += "</table>"
|
||||
return buf
|
||||
|
||||
def _ovOpts(self):
|
||||
return ""
|
||||
|
||||
# Data
|
||||
##########################################################################
|
||||
|
||||
def _ovForecast(self):
|
||||
fc = self.mw.col.sched.dueForecast(14)
|
||||
if not sum(fc):
|
||||
return "'%s'" % _('No cards due in next two weeks')
|
||||
return simplejson.dumps(tuple(enumerate(fc)))
|
||||
|
|
|
@ -13,12 +13,12 @@ class Preferences(QDialog):
|
|||
def __init__(self, mw):
|
||||
QDialog.__init__(self, mw, Qt.Window)
|
||||
self.mw = mw
|
||||
self.config = mw.config
|
||||
self.config = mw.pm.config
|
||||
self.form = aqt.forms.preferences.Ui_Preferences()
|
||||
self.form.setupUi(self)
|
||||
self.needDeckClose = False
|
||||
self.connect(self.form.buttonBox, SIGNAL("helpRequested()"),
|
||||
lambda: aqt.openHelp("Preferences"))
|
||||
lambda: openHelp("Preferences"))
|
||||
self.setupLang()
|
||||
self.setupNetwork()
|
||||
self.setupBackup()
|
||||
|
|
|
@ -89,36 +89,18 @@ class Reviewer(object):
|
|||
##########################################################################
|
||||
|
||||
_revHtml = """
|
||||
<table width=100%% height=100%%><tr valign=%(align)s><td>
|
||||
<div id=q></div>
|
||||
<hr class=inv id=midhr>
|
||||
<div id=a></div>
|
||||
<div id=filler></div>
|
||||
</td></tr></table>
|
||||
<a id=ansbut class="ansbut ansbutbig" href=ans onclick="_showans();">
|
||||
<div class=ansbuttxt>%(showans)s</div>
|
||||
</a>
|
||||
<div id=easebuts>
|
||||
</div>
|
||||
<div id=qa></div>
|
||||
<script>
|
||||
var ankiPlatform = "desktop";
|
||||
var hideq;
|
||||
var ans;
|
||||
var typeans;
|
||||
function _updateQA (qa) {
|
||||
hideq = qa[4];
|
||||
function _updateQA (q) {
|
||||
location.hash = "";
|
||||
$("#q").html(qa[0]);
|
||||
if (hideq) {
|
||||
ans = qa[1];
|
||||
$("#a").html("");
|
||||
} else {
|
||||
$("#a").html(qa[1]).addClass("inv");
|
||||
}
|
||||
$("#midhr").addClass("inv");
|
||||
$("#easebuts").html(qa[2]).addClass("inv");
|
||||
$("#ansbut").show();
|
||||
$("body").removeClass().addClass(qa[3]);
|
||||
$("#qa").html(q[0]);
|
||||
$("#qa:first").css("height", "100%%");
|
||||
//$("#easebuts").html(q[1]).addClass("inv");
|
||||
//$("#ansbut").show();
|
||||
typeans = document.getElementById("typeans");
|
||||
if (typeans) {
|
||||
typeans.focus();
|
||||
|
@ -128,7 +110,8 @@ function _updateQA (qa) {
|
|||
onQuestion();
|
||||
}
|
||||
};
|
||||
function _showans () {
|
||||
function _showans (a) {
|
||||
$("#qa").html(a);
|
||||
if (typeans) {
|
||||
py.link("typeans:"+typeans.value);
|
||||
}
|
||||
|
@ -139,7 +122,7 @@ function _showans () {
|
|||
} else {
|
||||
location.hash = "a";
|
||||
}
|
||||
$("#ansbut").hide();
|
||||
//$("#ansbut").hide();
|
||||
$("#defease").focus();
|
||||
// user hook
|
||||
if (typeof(onAnswer) === "function") {
|
||||
|
@ -167,8 +150,8 @@ $(".ansbut").focus();
|
|||
|
||||
def _initWeb(self):
|
||||
self.web.stdHtml(self._revHtml % dict(
|
||||
align="middle" if self.mw.config['centerQA'] else "top",
|
||||
showans=_("Show Answer")), self._styles(),
|
||||
bodyID="card",
|
||||
loadCB=lambda x: self._showQuestion())
|
||||
|
||||
# Showing the question (and preparing answer)
|
||||
|
@ -181,15 +164,14 @@ $(".ansbut").focus();
|
|||
c = self.card
|
||||
q = c.q()
|
||||
a = c.a()
|
||||
if self.mw.config['autoplaySounds']:
|
||||
if self.mw.pm.profile['autoplay']:
|
||||
playFromText(q)
|
||||
# render
|
||||
esc = self.mw.col.media.escapeImages
|
||||
q=esc(mungeQA(q)) + self.typeAnsInput()
|
||||
a=esc(mungeQA(a))
|
||||
self.web.eval("_updateQA(%s);" % simplejson.dumps(
|
||||
[q, a, self._answerButtons(), c.cssClass(),
|
||||
c.template()['hideQ']]))
|
||||
(q, self._answerButtons())))
|
||||
runHook('showQuestion')
|
||||
|
||||
# Showing the answer
|
||||
|
@ -199,7 +181,7 @@ $(".ansbut").focus();
|
|||
self.state = "answer"
|
||||
c = self.card
|
||||
a = c.a()
|
||||
if self.mw.config['autoplaySounds']:
|
||||
if self.mw.pm.profile['autoplay']:
|
||||
playFromText(a)
|
||||
# render
|
||||
runHook('showAnswer')
|
||||
|
@ -238,7 +220,7 @@ $(".ansbut").focus();
|
|||
return buf
|
||||
|
||||
def _buttonTime(self, i, green):
|
||||
if self.mw.config['suppressEstimates']:
|
||||
if self.mw.pm.profile['showDueTimes']:
|
||||
return ""
|
||||
txt = self.mw.col.sched.nextIvlStr(self.card, i+1, True)
|
||||
if i == 0:
|
||||
|
@ -335,9 +317,7 @@ div.ansbuttxt {
|
|||
position: relative; top: 25%;
|
||||
}
|
||||
|
||||
div#q, div#a {
|
||||
margin: 0px;
|
||||
}
|
||||
body { margin:1em; }
|
||||
|
||||
#easebuts {
|
||||
bottom: 1em;
|
||||
|
@ -373,7 +353,6 @@ div#filler {
|
|||
|
||||
def _styles(self):
|
||||
css = self.mw.sharedCSS
|
||||
css += self.mw.col.models.css()
|
||||
css += self._css
|
||||
return css
|
||||
|
||||
|
@ -385,10 +364,10 @@ div#filler {
|
|||
|
||||
def typeAns(self):
|
||||
"None if answer typing disabled."
|
||||
return self.card.template()['typeAns']
|
||||
self.card.template()['typeAns']
|
||||
|
||||
def typeAnsInput(self):
|
||||
if self.typeAns() is None:
|
||||
if not self.typeAns():
|
||||
return ""
|
||||
return """
|
||||
<center>
|
||||
|
@ -412,6 +391,8 @@ div#filler {
|
|||
self.web.eval("_processTyped(%s);" % simplejson.dumps(res))
|
||||
|
||||
def getFont(self):
|
||||
print "fix getFont()"
|
||||
return ("arial", 20)
|
||||
f = self.card.model().fields[self.typeAns()]
|
||||
return (f['font'], f['qsize'])
|
||||
|
||||
|
@ -549,7 +530,7 @@ div#filler {
|
|||
addWgt(vertSep())
|
||||
class QClickableProgress(QProgressBar):
|
||||
def mouseReleaseEvent(self, evt):
|
||||
aqt.openHelp("ProgressBars")
|
||||
openHelp("ProgressBars")
|
||||
progressBarSize = (50, 14)
|
||||
self.progressBar = QClickableProgress()
|
||||
self.progressBar.setFixedSize(*progressBarSize)
|
||||
|
@ -561,6 +542,7 @@ div#filler {
|
|||
addWgt(self.progressBar, 0)
|
||||
|
||||
def _showStatus(self):
|
||||
return
|
||||
self._showStatusWidgets(True)
|
||||
self._updateRemaining()
|
||||
self._updateProgress()
|
||||
|
@ -569,6 +551,7 @@ div#filler {
|
|||
self._showStatusWidgets(False)
|
||||
|
||||
def _showStatusWidgets(self, shown=True):
|
||||
return
|
||||
for w in self._statusWidgets:
|
||||
w.setShown(shown)
|
||||
self.mw.form.statusbar.hideOrShow()
|
||||
|
|
|
@ -26,7 +26,7 @@ class StudyOptions(QDialog):
|
|||
0, c.revCardOrderLabels().values())
|
||||
self.connect(self.form.buttonBox,
|
||||
SIGNAL("helpRequested()"),
|
||||
lambda: aqt.openHelp("StudyOptions"))
|
||||
lambda: openHelp("StudyOptions"))
|
||||
|
||||
def load(self):
|
||||
f = self.form
|
||||
|
|
20
aqt/sync.py
20
aqt/sync.py
|
@ -25,8 +25,8 @@ class SyncManager(object):
|
|||
# vet input
|
||||
if interactive:
|
||||
self.ensureSyncParams()
|
||||
u=self.config['syncUsername']
|
||||
p=self.config['syncPassword']
|
||||
u=self.pm.profile['syncUsername']
|
||||
p=self.pm.profile['syncPassword']
|
||||
if not u or not p:
|
||||
return
|
||||
if self.deck:
|
||||
|
@ -35,7 +35,7 @@ class SyncManager(object):
|
|||
return
|
||||
if self.deck and not self.deck.syncName:
|
||||
if interactive:
|
||||
if (not self.config['mediaLocation']
|
||||
if (not self.pm.profile['mediaLocation']
|
||||
and self.deck.db.scalar("select 1 from media limit 1")):
|
||||
showInfo(_("""\
|
||||
Syncing sounds and images requires a free file synchronization service like \
|
||||
|
@ -105,7 +105,7 @@ will sync automatically from then on."""))
|
|||
|
||||
def decksToSync(self):
|
||||
ok = []
|
||||
for d in self.config['recentDeckPaths']:
|
||||
for d in self.pm.profile['recentDeckPaths']:
|
||||
if os.path.exists(d):
|
||||
ok.append(d)
|
||||
return ok
|
||||
|
@ -159,7 +159,7 @@ Are you sure?""" % deckName),
|
|||
elif self.loadAfterSync and self.deckPath:
|
||||
if self.loadAfterSync == 2:
|
||||
name = re.sub("[<>]", "", self.syncName)
|
||||
p = os.path.join(self.config['documentDir'], name + ".anki")
|
||||
p = os.path.join(self.pm.profile['documentDir'], name + ".anki")
|
||||
shutil.copy2(self.deckPath, p)
|
||||
self.deckPath = p
|
||||
# since we've moved the deck, we have to set sync path
|
||||
|
@ -195,7 +195,7 @@ Are you sure?""" % deckName),
|
|||
self.syncName = name
|
||||
if name:
|
||||
# name chosen
|
||||
p = os.path.join(self.config['documentDir'], name + ".anki")
|
||||
p = os.path.join(self.pm.profile['documentDir'], name + ".anki")
|
||||
if os.path.exists(p):
|
||||
d = askUserDialog(_("""\
|
||||
This deck already exists on your computer. Overwrite the local copy?"""),
|
||||
|
@ -237,7 +237,7 @@ This deck already exists on your computer. Overwrite the local copy?"""),
|
|||
self.setStatus("")
|
||||
|
||||
def badUserPass(self):
|
||||
aqt.preferences.Preferences(self, self.config).dialog.tabWidget.\
|
||||
aqt.preferences.Preferences(self, self.pm.profile).dialog.tabWidget.\
|
||||
setCurrentIndex(1)
|
||||
|
||||
def openSyncProgress(self):
|
||||
|
@ -282,7 +282,7 @@ This deck already exists on your computer. Overwrite the local copy?"""),
|
|||
self.updateProgress(label=s % (val / 1024))
|
||||
|
||||
def ensureSyncParams(self):
|
||||
if not self.config['syncUsername'] or not self.config['syncPassword']:
|
||||
if not self.pm.profile['syncUsername'] or not self.pm.profile['syncPassword']:
|
||||
d = QDialog(self)
|
||||
vbox = QVBoxLayout()
|
||||
l = QLabel(_(
|
||||
|
@ -310,8 +310,8 @@ This deck already exists on your computer. Overwrite the local copy?"""),
|
|||
vbox.addWidget(bb)
|
||||
d.setLayout(vbox)
|
||||
d.exec_()
|
||||
self.config['syncUsername'] = unicode(user.text())
|
||||
self.config['syncPassword'] = unicode(passwd.text())
|
||||
self.pm.profile['syncUsername'] = unicode(user.text())
|
||||
self.pm.profile['syncPassword'] = unicode(passwd.text())
|
||||
|
||||
|
||||
# Synchronising a deck with a public server
|
||||
|
|
|
@ -17,7 +17,7 @@ class LatestVersionFinder(QThread):
|
|||
print "autoupdate"
|
||||
return
|
||||
self.main = main
|
||||
self.config = main.config
|
||||
self.config = main.pm.profile
|
||||
plat=sys.platform
|
||||
pver=platform.platform()
|
||||
d = {"ver": aqt.appVersion,
|
||||
|
|
16
aqt/utils.py
16
aqt/utils.py
|
@ -13,7 +13,7 @@ def openHelp(name):
|
|||
name = name[0] + ".html#" + name[1]
|
||||
else:
|
||||
name = name + ".html"
|
||||
QDesktopServices.openUrl(QUrl(appHelpSite + name))
|
||||
QDesktopServices.openUrl(QUrl(aqt.appHelpSite + name))
|
||||
|
||||
def openLink(link):
|
||||
QDesktopServices.openUrl(QUrl(link))
|
||||
|
@ -44,7 +44,7 @@ def showInfo(text, parent=None, help="", type="info"):
|
|||
b.setDefault(True)
|
||||
if help:
|
||||
b = mb.addButton(QMessageBox.Help)
|
||||
b.connect(b, SIGNAL("clicked()"), lambda: aqt.openHelp(help))
|
||||
b.connect(b, SIGNAL("clicked()"), lambda: openHelp(help))
|
||||
b.setAutoDefault(False)
|
||||
return mb.exec_()
|
||||
|
||||
|
@ -84,7 +84,8 @@ def askUser(text, parent=None, help="", defaultno=False):
|
|||
r = QMessageBox.question(parent, "Anki", text, sb,
|
||||
default)
|
||||
if r == QMessageBox.Help:
|
||||
aqt.openHelp(help)
|
||||
|
||||
openHelp(help)
|
||||
else:
|
||||
break
|
||||
return r == QMessageBox.Yes
|
||||
|
@ -115,7 +116,7 @@ class ButtonedDialog(QMessageBox):
|
|||
but = self.clickedButton().text()
|
||||
if but == "Help":
|
||||
# FIXME stop dialog closing?
|
||||
aqt.openHelp(self.help)
|
||||
openHelp(self.help)
|
||||
return self.clickedButton().text()
|
||||
|
||||
def setDefault(self, idx):
|
||||
|
@ -166,7 +167,7 @@ class GetTextDialog(QDialog):
|
|||
return QDialog.reject(self)
|
||||
|
||||
def helpRequested(self):
|
||||
aqt.openHelp(self.help)
|
||||
openHelp(self.help)
|
||||
|
||||
def getText(prompt, parent=None, help=None, edit=None, default=u"", title="Anki"):
|
||||
if not parent:
|
||||
|
@ -347,11 +348,6 @@ def maybeHideClose(bbox):
|
|||
if b:
|
||||
bbox.removeButton(b)
|
||||
|
||||
def limitedCount(count):
|
||||
if count >= 1000:
|
||||
return "1000+"
|
||||
return str(count)
|
||||
|
||||
# Tooltips
|
||||
######################################################################
|
||||
|
||||
|
|
|
@ -83,13 +83,13 @@ class AnkiWebView(QWebView):
|
|||
if loadCB:
|
||||
self._loadFinishedCB = loadCB
|
||||
QWebView.setHtml(self, html)
|
||||
def stdHtml(self, body, css="", bodyClass="", loadCB=None):
|
||||
def stdHtml(self, body, css="", bodyID="", loadCB=None):
|
||||
self.setHtml("""
|
||||
<html><head><style>%s</style>
|
||||
<script>%s</script>
|
||||
</head>
|
||||
<body class="%s">%s</body></html>""" % (
|
||||
css, anki.js.all, bodyClass, body), loadCB)
|
||||
<body id="%s">%s</body></html>""" % (
|
||||
css, anki.js.all, bodyID, body), loadCB)
|
||||
# ensure we're focused
|
||||
self.setFocus()
|
||||
def setBridge(self, bridge):
|
||||
|
|
|
@ -6,546 +6,152 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>759</width>
|
||||
<height>560</height>
|
||||
<width>1311</width>
|
||||
<height>658</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Appearance</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="templateLayout">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="1">
|
||||
<widget class="QTextEdit" name="cardQuestion">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QTextEdit" name="cardAnswer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="acceptRichText">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" rowspan="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Question</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="flipButton">
|
||||
<property name="text">
|
||||
<string>Flip</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/multisynk.png</normaloff>:/icons/multisynk.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Answer</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Alignment</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="alignment"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Background</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QPushButton" name="background">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="templateType">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QComboBox" name="cardList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="editTemplates">
|
||||
<property name="text">
|
||||
<string>&Manage...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+M</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="typeAnswer"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="questionInAnswer">
|
||||
<property name="text">
|
||||
<string>Hide the question when showing answer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="allowEmptyAnswer">
|
||||
<property name="text">
|
||||
<string>Add cards even if answer is blank</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="clozectx">
|
||||
<property name="text">
|
||||
<string>Include context in cloze answers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Fields</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="fieldList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="fieldAdd">
|
||||
<property name="text">
|
||||
<string>&Add</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fieldUp">
|
||||
<property name="toolTip">
|
||||
<string>Move selected field up</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Up</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fieldDown">
|
||||
<property name="toolTip">
|
||||
<string>Move selected field down</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dow&n</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fieldDelete">
|
||||
<property name="text">
|
||||
<string>&Delete</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="_2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="fieldName"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Font</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QFontComboBox" name="fontFamily">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="fontColour">
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Reviewing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="fontSize">
|
||||
<property name="minimum">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>300</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Editing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QSpinBox" name="fontSizeEdit">
|
||||
<property name="minimum">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>300</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="rtl">
|
||||
<property name="text">
|
||||
<string>Reverse text direction (RTL)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="fieldRequired">
|
||||
<property name="text">
|
||||
<string>Require text in field</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="fieldUnique">
|
||||
<property name="text">
|
||||
<string>Prevent duplicates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="preserveWhitespace">
|
||||
<property name="text">
|
||||
<string>Preserve whitespace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="sticky">
|
||||
<property name="text">
|
||||
<string>Keep previous input when adding cards</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Help</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="previewGroup">
|
||||
<widget class="QWidget" name="">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>120</y>
|
||||
<width>360</width>
|
||||
<height>366</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="templateLayout">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QTextEdit" name="cardQuestion">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Preview</string>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="_3">
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWebView" name="preview">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="url">
|
||||
<url>
|
||||
<string>about:blank</string>
|
||||
</url>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QTextEdit" name="cardAnswer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="acceptRichText">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Question</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Answer</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="typeAnswer">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>500</y>
|
||||
<width>366</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="clozectx">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>540</y>
|
||||
<width>371</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Include context in cloze answers</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWebView" name="preview">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>450</x>
|
||||
<y>90</y>
|
||||
<width>308</width>
|
||||
<height>499</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="url">
|
||||
<url>
|
||||
<string>about:blank</string>
|
||||
</url>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -555,70 +161,11 @@
|
|||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>cardList</tabstop>
|
||||
<tabstop>editTemplates</tabstop>
|
||||
<tabstop>cardQuestion</tabstop>
|
||||
<tabstop>flipButton</tabstop>
|
||||
<tabstop>cardAnswer</tabstop>
|
||||
<tabstop>alignment</tabstop>
|
||||
<tabstop>background</tabstop>
|
||||
<tabstop>typeAnswer</tabstop>
|
||||
<tabstop>questionInAnswer</tabstop>
|
||||
<tabstop>allowEmptyAnswer</tabstop>
|
||||
<tabstop>clozectx</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
<tabstop>fieldList</tabstop>
|
||||
<tabstop>fieldAdd</tabstop>
|
||||
<tabstop>fieldUp</tabstop>
|
||||
<tabstop>fieldDown</tabstop>
|
||||
<tabstop>fieldDelete</tabstop>
|
||||
<tabstop>fieldName</tabstop>
|
||||
<tabstop>fontFamily</tabstop>
|
||||
<tabstop>fontSize</tabstop>
|
||||
<tabstop>fontSizeEdit</tabstop>
|
||||
<tabstop>fontColour</tabstop>
|
||||
<tabstop>fieldUnique</tabstop>
|
||||
<tabstop>fieldRequired</tabstop>
|
||||
<tabstop>sticky</tabstop>
|
||||
<tabstop>preserveWhitespace</tabstop>
|
||||
<tabstop>rtl</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
243
designer/fields.ui
Normal file
243
designer/fields.ui
Normal file
|
@ -0,0 +1,243 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>372</width>
|
||||
<height>340</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Fields</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="fieldList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="fieldAdd">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fieldDelete">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/editdelete.png</normaloff>:/icons/editdelete.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fieldUp">
|
||||
<property name="toolTip">
|
||||
<string>Move selected field up</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/arrow-up.png</normaloff>:/icons/arrow-up.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fieldDown">
|
||||
<property name="toolTip">
|
||||
<string>Move selected field down</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/arrow-down.png</normaloff>:/icons/arrow-down.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="_2">
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="fieldName"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Font</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QFontComboBox" name="fontFamily">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="rtl">
|
||||
<property name="text">
|
||||
<string>Reverse text direction (RTL)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="fontSize">
|
||||
<property name="minimum">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>300</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="sticky">
|
||||
<property name="text">
|
||||
<string>Remember last input</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Help</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>fieldList</tabstop>
|
||||
<tabstop>fieldAdd</tabstop>
|
||||
<tabstop>fieldDelete</tabstop>
|
||||
<tabstop>fieldUp</tabstop>
|
||||
<tabstop>fieldDown</tabstop>
|
||||
<tabstop>fieldName</tabstop>
|
||||
<tabstop>fontFamily</tabstop>
|
||||
<tabstop>fontSize</tabstop>
|
||||
<tabstop>sticky</tabstop>
|
||||
<tabstop>rtl</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -1,6 +1,9 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>icons/arrow-up.png</file>
|
||||
<file>icons/arrow-down.png</file>
|
||||
<file>icons/blue.png</file>
|
||||
<file>icons/gears.png</file>
|
||||
<file>icons/both.png</file>
|
||||
<file>icons/green.png</file>
|
||||
<file>icons/clock-icon.png</file>
|
||||
|
|
BIN
designer/icons/gears.png
Normal file
BIN
designer/icons/gears.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 701 B |
82
designer/preview.ui
Normal file
82
designer/preview.ui
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>335</width>
|
||||
<height>282</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Front Preview</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWebView" name="front">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="url">
|
||||
<url>
|
||||
<string>about:blank</string>
|
||||
</url>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Back Preview</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWebView" name="back">
|
||||
<property name="url">
|
||||
<url>
|
||||
<string>about:blank</string>
|
||||
</url>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QWebView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>QtWebKit/QWebView</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
68
designer/template.ui
Normal file
68
designer/template.ui
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>279</width>
|
||||
<height>251</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Front Template</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="front"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>10</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Back Template</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="back"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in a new issue