mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
Merge branch 'master' of git://ichi2.net/ankiqt
Conflicts: ankiqt/locale/ankiqt_sv_SE.po
This commit is contained in:
commit
5266233c01
48 changed files with 14973 additions and 6446 deletions
2
README
2
README
|
@ -20,7 +20,7 @@ For audio playing support:
|
|||
|
||||
For audio recording support:
|
||||
|
||||
- sox
|
||||
- sox 14.1+
|
||||
- pyaudio
|
||||
- lame
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from PyQt4.QtCore import *
|
|||
from PyQt4.QtGui import *
|
||||
|
||||
appName="Anki"
|
||||
appVersion="0.9.9.6"
|
||||
appVersion="0.9.9.7"
|
||||
appWebsite="http://ichi2.net/anki/download/"
|
||||
appWiki="http://ichi2.net/anki/wiki/"
|
||||
appHelpSite="http://ichi2.net/anki/wiki/AnkiWiki"
|
||||
|
@ -36,8 +36,23 @@ class SplashScreen(object):
|
|||
self.splash = QSplashScreen(self.pixmap)
|
||||
self.prog = QProgressBar(self.splash)
|
||||
self.prog.setMaximum(max)
|
||||
self.prog.setGeometry(self.splash.width()/10, 8*self.splash.height()/10,
|
||||
8*self.splash.width()/10, self.splash.height()/10)
|
||||
if QApplication.instance().style().objectName() != "plastique":
|
||||
self.style = QStyleFactory.create("plastique")
|
||||
self.prog.setStyle(self.style)
|
||||
self.prog.setStyleSheet("""* {
|
||||
color: #ffffff;
|
||||
background-color: #061824;
|
||||
margin:0px;
|
||||
border:0px;
|
||||
padding: 0px;
|
||||
text-align: center;}
|
||||
*::chunk {
|
||||
color: #13486c;
|
||||
}
|
||||
""")
|
||||
x = 8
|
||||
self.prog.setGeometry(self.splash.width()/10, 8.85*self.splash.height()/10,
|
||||
x*self.splash.width()/10, self.splash.height()/10)
|
||||
self.splash.show()
|
||||
self.val = 1
|
||||
|
||||
|
@ -93,7 +108,7 @@ def run():
|
|||
if anki.version != appVersion:
|
||||
print "You have libanki %s, but this is ankiqt %s" % (
|
||||
anki.version, appVersion)
|
||||
print "\nPlease install the latest libanki."
|
||||
print "\nPlease ensure versions match."
|
||||
return
|
||||
|
||||
# parse args
|
||||
|
|
|
@ -57,6 +57,7 @@ class Config(dict):
|
|||
'saveAfterAddingNum': 1,
|
||||
'saveOnClose': True,
|
||||
'mainWindowGeom': None,
|
||||
'mainWindowState': None,
|
||||
'suppressUpdate': False,
|
||||
'suppressEstimates': False,
|
||||
'showLastCardInterval': False,
|
||||
|
@ -84,6 +85,7 @@ class Config(dict):
|
|||
'editLineSize': 20,
|
||||
'factEditorAdvanced': False,
|
||||
'typeAnswerFontSize': 20,
|
||||
'showProgress': True,
|
||||
'recentColours': ["#000000", "#0000ff"],
|
||||
}
|
||||
for (k,v) in fields.items():
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
2893
ankiqt/locale/ankiqt_ee_EE.po
Normal file
2893
ankiqt/locale/ankiqt_ee_EE.po
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
2845
ankiqt/locale/ankiqt_zh_CN.po
Normal file
2845
ankiqt/locale/ankiqt_zh_CN.po
Normal file
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -13,7 +13,6 @@ def importAll():
|
|||
import exporting
|
||||
import facteditor
|
||||
import help
|
||||
import importing
|
||||
import lookup
|
||||
import modelchooser
|
||||
import modelproperties
|
||||
|
@ -26,6 +25,7 @@ def importAll():
|
|||
import update
|
||||
import utils
|
||||
import view
|
||||
import getshared
|
||||
|
||||
class DialogManager(object):
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||
# -*- coding: utf-8 -*-
|
||||
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
|
||||
|
||||
from PyQt4.QtGui import *
|
||||
|
@ -10,12 +11,31 @@ def show(parent):
|
|||
abt = ankiqt.forms.about.Ui_About()
|
||||
abt.setupUi(dialog)
|
||||
abt.label.setText(_("""
|
||||
<h1>Anki</h1>
|
||||
<img src=":/icons/anki.png">
|
||||
<center><img src=":/icons/anki-logo-thin.png"></center>
|
||||
<p>
|
||||
<span>Anki is a spaced repetition flashcard program designed to maximise your
|
||||
memory potential.<p/>It's free and licensed under the GPL.<p/>
|
||||
Version %s<br>
|
||||
Anki is a friendly, intelligent spaced learning system. It's free and open
|
||||
source.<p>
|
||||
Version %(ver)s<br>
|
||||
<a href="http://ichi2.net/anki/">Visit website</a></span>
|
||||
""") % appVersion)
|
||||
<p>
|
||||
Written by Damien Elmes, with patches, translation, testing and design from:<p>%(cont)s
|
||||
<p>
|
||||
If you have contributed and are not on this list, please get in touch.
|
||||
<p>
|
||||
A big thanks to all the people who have provided suggestions, bug reports and
|
||||
donations.""") % {
|
||||
'cont': u"""
|
||||
|
||||
Alex Fraser, Andreas Klauer, Bananeweizen, Bernhard Ibertsberger, Christian
|
||||
Rusche, David Smith, Dave Druelinger, Emmanuel Jarri, Frank Harper, Ian Lewis,
|
||||
Iroiro, Jin Eun-Deok, Jo Nakashima, Krause Chr, LaC, Laurent Steffan, Marco
|
||||
Giancotti, Mark Wilbur, Meelis Vasser, Michael Penkov, Michal Čadil, Nathanael
|
||||
Law, Nick Cook, Niklas Laxström, Pcsl88, Piotr Kubowicz, Richard Colley,
|
||||
Samson Melamed, Susanna Björverud, Timm Preetz, Timo Paulssen, Victor Suba,
|
||||
and Xtru.
|
||||
|
||||
""",
|
||||
'ver': appVersion})
|
||||
dialog.show()
|
||||
dialog.adjustSize()
|
||||
dialog.exec_()
|
||||
|
|
|
@ -24,11 +24,19 @@ class ActiveTagsChooser(QDialog):
|
|||
self.items = []
|
||||
self.suspended = {}
|
||||
for t in parseTags(self.parent.deck.suspended):
|
||||
if t == "Suspended":
|
||||
continue
|
||||
self.suspended[t] = 1
|
||||
if t not in self.tags:
|
||||
self.tags.append(t)
|
||||
self.tags.sort()
|
||||
try:
|
||||
self.tags.remove("Suspended")
|
||||
except ValueError:
|
||||
pass
|
||||
for t in self.tags:
|
||||
if t == "Suspended":
|
||||
continue
|
||||
item = QListWidgetItem(t, self.dialog.list)
|
||||
self.dialog.list.addItem(item)
|
||||
self.items.append(item)
|
||||
|
|
|
@ -56,7 +56,6 @@ class AddCards(QDialog):
|
|||
self.addButton.setToolTip(_("Add (shortcut: command+return)"))
|
||||
else:
|
||||
self.addButton.setToolTip(_("Add (shortcut: ctrl+return)"))
|
||||
self.addButton.setAutoDefault(False)
|
||||
s = QShortcut(QKeySequence(_("Ctrl+Enter")), self)
|
||||
s.connect(s, SIGNAL("activated()"), self.addButton, SLOT("click()"))
|
||||
self.connect(self.addButton, SIGNAL("clicked()"), self.addCards)
|
||||
|
@ -95,6 +94,7 @@ class AddCards(QDialog):
|
|||
fact.tags = self.parent.deck.lastTags
|
||||
# set the new fact
|
||||
self.editor.setFact(fact, check=True)
|
||||
self.setTabOrder(self.editor.tags, self.addButton)
|
||||
|
||||
def addCards(self):
|
||||
# make sure updated
|
||||
|
@ -131,6 +131,14 @@ question or answer on all cards."""), parent=self)
|
|||
self.editor.tags.addTags(parseTags(self.parent.deck.lastTags))
|
||||
self.maybeSave()
|
||||
|
||||
def keyPressEvent(self, evt):
|
||||
"Show answer on RET or register answer."
|
||||
if (evt.key() in (Qt.Key_Enter, Qt.Key_Return)
|
||||
and self.editor.tags.hasFocus()):
|
||||
evt.accept()
|
||||
return
|
||||
return QDialog.keyPressEvent(self, evt)
|
||||
|
||||
def closeEvent(self, evt):
|
||||
if self.onClose():
|
||||
evt.accept()
|
||||
|
|
|
@ -106,11 +106,12 @@ class DeckModel(QAbstractTableModel):
|
|||
d = {'str': [],
|
||||
'tag': [],
|
||||
}
|
||||
for elem in search.split():
|
||||
if len(elem) > 2 and elem.startswith("t:"):
|
||||
d['tag'].append(elem[2:])
|
||||
else:
|
||||
d['str'].append(elem)
|
||||
if search:
|
||||
for elem in search.split():
|
||||
if len(elem) > 2 and elem.startswith("t:"):
|
||||
d['tag'].append(elem[2:])
|
||||
else:
|
||||
d['str'].append(elem)
|
||||
return d
|
||||
|
||||
def showMatching(self):
|
||||
|
@ -189,8 +190,8 @@ class DeckModel(QAbstractTableModel):
|
|||
self.cards[index.row()] = self.deck.s.first("""
|
||||
select id, question, answer, due, reps, factId, created, modified,
|
||||
interval, factor from cards where id = :id""", id=self.cards[index.row()][0])
|
||||
self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
|
||||
index, self.index(index.row(), 1))
|
||||
#self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
|
||||
# index, self.index(index.row(), 1))
|
||||
except IndexError:
|
||||
# called after search changed
|
||||
pass
|
||||
|
@ -259,12 +260,12 @@ class DeckModel(QAbstractTableModel):
|
|||
self.columns[-1][0] = k
|
||||
|
||||
def createdColumn(self, index):
|
||||
return fmtTimeSpan(
|
||||
time.time() - self.cards[index.row()][CARD_CREATED]) + " ago"
|
||||
return time.strftime("%Y-%m-%d", time.localtime(
|
||||
self.cards[index.row()][CARD_CREATED]))
|
||||
|
||||
def modifiedColumn(self, index):
|
||||
return fmtTimeSpan(
|
||||
time.time() - self.cards[index.row()][CARD_MODIFIED]) + " ago"
|
||||
return time.strftime("%Y-%m-%d", time.localtime(
|
||||
self.cards[index.row()][CARD_MODIFIED]))
|
||||
|
||||
def intervalColumn(self, index):
|
||||
return fmtTimeSpan(
|
||||
|
@ -279,7 +280,7 @@ class DeckModel(QAbstractTableModel):
|
|||
class EditDeck(QMainWindow):
|
||||
|
||||
def __init__(self, parent):
|
||||
QDialog.__init__(self, parent, Qt.Window)
|
||||
QMainWindow.__init__(self, parent)
|
||||
self.parent = parent
|
||||
self.deck = self.parent.deck
|
||||
self.config = parent.config
|
||||
|
@ -354,8 +355,8 @@ class EditDeck(QMainWindow):
|
|||
self.dialog.tagList.setFixedWidth(130)
|
||||
self.dialog.tagList.clear()
|
||||
self.dialog.tagList.addItems(QStringList(
|
||||
[_('All cards'), _('No tags')] + self.alltags))
|
||||
self.dialog.tagList.view().setFixedWidth(300)
|
||||
[_('<Tag filter>'), _('No tags')] + self.alltags))
|
||||
self.dialog.tagList.view().setFixedWidth(200)
|
||||
|
||||
def drawSort(self):
|
||||
self.sortList = [
|
||||
|
@ -515,12 +516,12 @@ class EditDeck(QMainWindow):
|
|||
if not sys.platform.startswith("win32"):
|
||||
self.dialog.tableView.verticalHeader().hide()
|
||||
self.dialog.tableView.horizontalHeader().show()
|
||||
for i in range(2):
|
||||
self.dialog.tableView.horizontalHeader().setResizeMode(i, QHeaderView.Stretch)
|
||||
self.dialog.tableView.horizontalHeader().setResizeMode(2, QHeaderView.Interactive)
|
||||
restoreHeader(self.dialog.tableView.horizontalHeader(), "editor")
|
||||
self.dialog.tableView.verticalHeader().setDefaultSectionSize(
|
||||
self.parent.config['editLineSize'])
|
||||
for i in range(2):
|
||||
self.dialog.tableView.horizontalHeader().setResizeMode(i, QHeaderView.Stretch)
|
||||
self.dialog.tableView.horizontalHeader().setResizeMode(2, QHeaderView.Interactive)
|
||||
|
||||
def setupMenus(self):
|
||||
# actions
|
||||
|
@ -723,18 +724,28 @@ where id in %s""" % ids2str(sf))
|
|||
_("Can only operate on one model at a time."),
|
||||
parent=self)
|
||||
return
|
||||
# get cards to enable
|
||||
cms = [x.id for x in self.deck.s.query(Fact).get(sf[0]).\
|
||||
model.cardModels]
|
||||
d = AddCardChooser(self, cms)
|
||||
if not d.exec_():
|
||||
return
|
||||
# for each fact id, generate
|
||||
n = _("Generate Cards")
|
||||
self.parent.setProgressParent(self)
|
||||
self.deck.startProgress()
|
||||
self.deck.setUndoStart(n)
|
||||
for id in sf:
|
||||
self.deck.addCards(self.deck.s.query(Fact).get(id),
|
||||
d.selectedCms)
|
||||
facts = self.deck.s.query(Fact).filter(
|
||||
text("id in %s" % ids2str(sf))).order_by(Fact.created).all()
|
||||
self.deck.updateProgress(_("Generating Cards..."))
|
||||
for c, fact in enumerate(facts):
|
||||
self.deck.addCards(fact, d.selectedCms)
|
||||
if c % 50 == 0:
|
||||
self.deck.updateProgress()
|
||||
self.deck.flushMod()
|
||||
self.deck.updateAllPriorities()
|
||||
self.deck.finishProgress()
|
||||
self.parent.setProgressParent(None)
|
||||
self.deck.setUndoEnd(n)
|
||||
self.updateSearch()
|
||||
self.updateAfterCardChange()
|
||||
|
@ -811,14 +822,25 @@ where id in %s""" % ids2str(sf))
|
|||
######################################################################
|
||||
|
||||
def onFindReplace(self):
|
||||
sf = self.selectedFacts()
|
||||
if not sf:
|
||||
return
|
||||
mods = self.deck.s.column0("""
|
||||
select distinct modelId from facts
|
||||
where id in %s""" % ids2str(sf))
|
||||
if not len(mods) == 1:
|
||||
ui.utils.showInfo(
|
||||
_("Can only operate on one model at a time."),
|
||||
parent=self)
|
||||
return
|
||||
d = QDialog(self)
|
||||
frm = ankiqt.forms.findreplace.Ui_Dialog()
|
||||
frm.setupUi(d)
|
||||
fields = sorted(self.currentCard.fact.model.fieldModels, key=attrgetter("name"))
|
||||
frm.field.addItems(QStringList(
|
||||
[_("All Fields")] + [f.name for f in fields]))
|
||||
self.connect(frm.buttonBox, SIGNAL("helpRequested()"),
|
||||
self.onFindReplaceHelp)
|
||||
frm.type.insertItems(0, [
|
||||
_("Fields"),
|
||||
_("Tags")])
|
||||
if not d.exec_():
|
||||
return
|
||||
n = _("Find and Replace")
|
||||
|
@ -826,17 +848,20 @@ where id in %s""" % ids2str(sf))
|
|||
self.deck.startProgress(2)
|
||||
self.deck.updateProgress(_("Replacing..."))
|
||||
self.deck.setUndoStart(n)
|
||||
sf = self.selectedFacts()
|
||||
self.deck.updateProgress()
|
||||
changed = None
|
||||
try:
|
||||
changed = self.deck.findReplace(self.selectedFacts(),
|
||||
unicode(frm.find.text()),
|
||||
unicode(frm.replace.text()),
|
||||
frm.type.currentIndex(),
|
||||
frm.re.isChecked())
|
||||
if frm.field.currentIndex() == 0:
|
||||
field = None
|
||||
else:
|
||||
field = fields[frm.field.currentIndex()-1].id
|
||||
changed = self.deck.findReplace(sf,
|
||||
unicode(frm.find.text()),
|
||||
unicode(frm.replace.text()),
|
||||
frm.re.isChecked(),
|
||||
field)
|
||||
except sre_constants.error:
|
||||
ui.utils.showInfo(_("Invalid regexp."),
|
||||
ui.utils.showInfo(_("Invalid regular expression."),
|
||||
parent=self)
|
||||
self.deck.setUndoEnd(n)
|
||||
self.deck.finishProgress()
|
||||
|
@ -850,7 +875,6 @@ where id in %s""" % ids2str(sf))
|
|||
'b': len(sf),
|
||||
}, parent=self)
|
||||
|
||||
|
||||
def onFindReplaceHelp(self):
|
||||
QDesktopServices.openUrl(QUrl(ankiqt.appWiki +
|
||||
"Editor#FindReplace"))
|
||||
|
@ -861,18 +885,21 @@ where id in %s""" % ids2str(sf))
|
|||
def onFirstCard(self):
|
||||
if not self.model.cards:
|
||||
return
|
||||
self.editor.saveFieldsNow()
|
||||
self.dialog.tableView.selectionModel().clear()
|
||||
self.dialog.tableView.selectRow(0)
|
||||
|
||||
def onLastCard(self):
|
||||
if not self.model.cards:
|
||||
return
|
||||
self.editor.saveFieldsNow()
|
||||
self.dialog.tableView.selectionModel().clear()
|
||||
self.dialog.tableView.selectRow(len(self.model.cards) - 1)
|
||||
|
||||
def onPreviousCard(self):
|
||||
if not self.model.cards:
|
||||
return
|
||||
self.editor.saveFieldsNow()
|
||||
row = self.dialog.tableView.currentIndex().row()
|
||||
row = max(0, row - 1)
|
||||
self.dialog.tableView.selectionModel().clear()
|
||||
|
@ -881,6 +908,7 @@ where id in %s""" % ids2str(sf))
|
|||
def onNextCard(self):
|
||||
if not self.model.cards:
|
||||
return
|
||||
self.editor.saveFieldsNow()
|
||||
row = self.dialog.tableView.currentIndex().row()
|
||||
row = min(len(self.model.cards) - 1, row + 1)
|
||||
self.dialog.tableView.selectionModel().clear()
|
||||
|
|
|
@ -243,6 +243,7 @@ class DeckProperties(QDialog):
|
|||
*60*60 + time.timezone)
|
||||
except:
|
||||
pass
|
||||
was = self.d.modified
|
||||
self.updateField(self.d, 'collapseTime',
|
||||
self.dialog.collapse.isChecked() and 1 or 0)
|
||||
self.updateField(self.d,
|
||||
|
@ -257,6 +258,7 @@ class DeckProperties(QDialog):
|
|||
self.updateField(self.d,
|
||||
"suspended",
|
||||
unicode(self.dialog.postponing.text()))
|
||||
prioritiesChanged = was != self.d.modified
|
||||
# sources
|
||||
d = {}
|
||||
d.update(self.sources)
|
||||
|
@ -289,8 +291,8 @@ insert into sources values
|
|||
self.d.setModified()
|
||||
# mark deck dirty and close
|
||||
if self.origMod != self.d.modified:
|
||||
self.d.updateCardTags()
|
||||
self.d.updateAllPriorities()
|
||||
if prioritiesChanged:
|
||||
self.d.updateAllPriorities()
|
||||
ankiqt.mw.reset()
|
||||
self.d.setUndoEnd(n)
|
||||
self.d.finishProgress()
|
||||
|
|
|
@ -4,10 +4,20 @@
|
|||
from PyQt4.QtGui import *
|
||||
from PyQt4.QtCore import *
|
||||
import anki, ankiqt
|
||||
from anki.exporting import exporters
|
||||
from anki.exporting import exporters as exporters_
|
||||
from anki.utils import parseTags
|
||||
from ankiqt import ui
|
||||
|
||||
class PackagedAnkiExporter(object):
|
||||
def __init__(self, *args):
|
||||
pass
|
||||
|
||||
def exporters():
|
||||
l = list(exporters_())
|
||||
l.insert(1, (_("Packaged Anki Deck (*.zip)"),
|
||||
PackagedAnkiExporter))
|
||||
return l
|
||||
|
||||
class ExportDialog(QDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
|
@ -35,7 +45,7 @@ class ExportDialog(QDialog):
|
|||
self.setTabOrder(self.tags,
|
||||
self.dialog.includeScheduling)
|
||||
# save button
|
||||
b = QPushButton(_("Export to..."))
|
||||
b = QPushButton(_("Export..."))
|
||||
self.dialog.buttonBox.addButton(b, QDialogButtonBox.AcceptRole)
|
||||
|
||||
def exporterChanged(self, idx):
|
||||
|
@ -50,6 +60,9 @@ class ExportDialog(QDialog):
|
|||
self.dialog.includeTags.hide()
|
||||
|
||||
def accept(self):
|
||||
if isinstance(self.exporter, PackagedAnkiExporter):
|
||||
self.parent.onShare(parseTags(unicode(self.tags.text())))
|
||||
return QDialog.accept(self)
|
||||
file = ui.utils.getSaveFile(self, _("Choose file to export to"), "export",
|
||||
self.exporter.key, self.exporter.ext)
|
||||
self.hide()
|
||||
|
|
|
@ -14,6 +14,7 @@ from ankiqt import ui
|
|||
import ankiqt
|
||||
from ankiqt.ui.utils import mungeQA, saveGeom, restoreGeom
|
||||
from anki.hooks import addHook
|
||||
from sqlalchemy.exceptions import InvalidRequestError
|
||||
|
||||
clozeColour = "#0000ff"
|
||||
|
||||
|
@ -38,6 +39,7 @@ class FactEditor(object):
|
|||
self.changeTimer = None
|
||||
self.lastCloze = None
|
||||
addHook("deckClosed", self.deckClosedHook)
|
||||
addHook("guiReset", self.refresh)
|
||||
|
||||
def setFact(self, fact, noFocus=False, check=False):
|
||||
"Make FACT the current fact."
|
||||
|
@ -63,6 +65,15 @@ class FactEditor(object):
|
|||
if self.deck.mediaDir(create=False):
|
||||
self.initMedia()
|
||||
|
||||
def refresh(self):
|
||||
if self.fact:
|
||||
try:
|
||||
self.deck.s.refresh(self.fact)
|
||||
except InvalidRequestError:
|
||||
# not attached to session yet, add cards dialog will handle
|
||||
return
|
||||
self.setFact(self.fact, check=True)
|
||||
|
||||
def focusFirst(self):
|
||||
if self.focusTarget:
|
||||
self.focusTarget.setFocus()
|
||||
|
@ -253,12 +264,12 @@ class FactEditor(object):
|
|||
self.preview.setStyle(self.plastiqueStyle)
|
||||
# cloze
|
||||
self.cloze = QPushButton(self.widget)
|
||||
self.clozeSC = QShortcut(QKeySequence(_("F6")), self.widget)
|
||||
self.clozeSC = QShortcut(QKeySequence(_("F9")), self.widget)
|
||||
self.cloze.connect(self.cloze, SIGNAL("clicked()"),
|
||||
self.onCloze)
|
||||
self.cloze.connect(self.clozeSC, SIGNAL("activated()"),
|
||||
self.onCloze)
|
||||
self.cloze.setToolTip(_("Cloze (F6)"))
|
||||
self.cloze.setToolTip(_("Cloze (F9)"))
|
||||
#self.cloze.setIcon(QIcon(":/icons/document-cloze.png"))
|
||||
self.cloze.setFixedWidth(30)
|
||||
self.cloze.setFixedHeight(26)
|
||||
|
@ -306,12 +317,12 @@ class FactEditor(object):
|
|||
self.latexMathEnv.setStyle(self.plastiqueStyle)
|
||||
# html
|
||||
self.htmlEdit = QPushButton(self.widget)
|
||||
self.htmlEdit.setToolTip(_("HTML Editor (F9)"))
|
||||
self.htmlEditSC = QShortcut(QKeySequence(_("F9")), self.widget)
|
||||
self.htmlEdit.setToolTip(_("HTML Editor"))
|
||||
self.htmlEditSC = QShortcut(QKeySequence(_("Ctrl+F9")), self.widget)
|
||||
self.htmlEdit.connect(self.htmlEdit, SIGNAL("clicked()"),
|
||||
self.onHtmlEdit)
|
||||
self.htmlEdit.connect(self.htmlEditSC, SIGNAL("activated()"),
|
||||
self.onHtmlEdit)
|
||||
self.onHtmlEdit)
|
||||
self.htmlEdit.setIcon(QIcon(":/icons/text-xml.png"))
|
||||
self.htmlEdit.setFocusPolicy(Qt.NoFocus)
|
||||
self.htmlEdit.setEnabled(False)
|
||||
|
@ -679,17 +690,24 @@ class FactEditor(object):
|
|||
src = self.focusedEdit()
|
||||
if not src:
|
||||
return
|
||||
re1 = "\[.+?(:(.+?))?\]"
|
||||
re2 = "\[(.+?)(:.+?)?\]"
|
||||
# add brackets because selected?
|
||||
cursor = src.textCursor()
|
||||
oldSrc = None
|
||||
if cursor.hasSelection():
|
||||
oldSrc = src.toHtml()
|
||||
s = cursor.selectionStart()
|
||||
e = cursor.selectionEnd()
|
||||
cursor.setPosition(e)
|
||||
cursor.insertText("]")
|
||||
cursor.insertText("]]")
|
||||
cursor.setPosition(s)
|
||||
cursor.insertText("[")
|
||||
cursor.insertText("[[")
|
||||
re1 = "\[" + re1 + "\]"
|
||||
re2 = "\[" + re2 + "\]"
|
||||
dst = None
|
||||
for (name, (field, w)) in self.fields.items():
|
||||
for field in self.fact.fields:
|
||||
w = self.fields[field.name][1]
|
||||
if w.hasFocus():
|
||||
dst = False
|
||||
continue
|
||||
|
@ -697,11 +715,12 @@ class FactEditor(object):
|
|||
dst = w
|
||||
break
|
||||
if not dst:
|
||||
dst = self.fields.values()[0][1]
|
||||
dst = self.fields[self.fact.fields[0].name][1]
|
||||
if dst == w:
|
||||
return
|
||||
# check if there's alredy something there
|
||||
oldSrc = src.toHtml()
|
||||
if not oldSrc:
|
||||
oldSrc = src.toHtml()
|
||||
oldDst = dst.toHtml()
|
||||
if unicode(dst.toPlainText()):
|
||||
if (self.lastCloze and
|
||||
|
@ -729,10 +748,9 @@ class FactEditor(object):
|
|||
exp = match.group(2)
|
||||
return '<font color="%s"><b>[...%s]</b></font>' % (
|
||||
clozeColour, exp)
|
||||
new = re.sub("\[.+?(:(.+?))?\]", repl, s)
|
||||
old = re.sub("\[(.+?)(:.+?)?\]", '<font color="%s"><b>\\1</b></font>'
|
||||
new = re.sub(re1, repl, s)
|
||||
old = re.sub(re2, '<font color="%s"><b>\\1</b></font>'
|
||||
% clozeColour, s)
|
||||
oldSrc = unicode(src.toHtml())
|
||||
src.setHtml(new)
|
||||
dst.setHtml(old)
|
||||
self.lastCloze = (oldSrc, unicode(src.toHtml()),
|
||||
|
|
227
ankiqt/ui/getshared.py
Normal file
227
ankiqt/ui/getshared.py
Normal file
|
@ -0,0 +1,227 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
|
||||
|
||||
from PyQt4.QtGui import *
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtNetwork import *
|
||||
import ankiqt, simplejson, time, cStringIO, zipfile, tempfile, os, re
|
||||
from ankiqt.ui.utils import saveGeom, restoreGeom, showInfo
|
||||
from anki.utils import fmtTimeSpan
|
||||
|
||||
R_ID = 0
|
||||
R_USERNAME = 1
|
||||
R_TITLE = 2
|
||||
R_DESCRIPTION = 3
|
||||
R_TAGS = 4
|
||||
R_VERSION = 5
|
||||
R_FACTS = 6
|
||||
R_SIZE = 7
|
||||
R_COUNT = 8
|
||||
R_MODIFIED = 9
|
||||
R_FNAME = 10
|
||||
|
||||
class GetShared(QDialog):
|
||||
|
||||
def __init__(self, parent, type):
|
||||
QDialog.__init__(self, parent, Qt.Window)
|
||||
self.parent = parent
|
||||
self.form = ankiqt.forms.getshared.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
restoreGeom(self, "getshared")
|
||||
self.setupTable()
|
||||
self.onChangeType(type)
|
||||
self.ok = False
|
||||
if type == 0:
|
||||
self.setWindowTitle(_("Download Shared Deck"))
|
||||
else:
|
||||
self.setWindowTitle(_("Download Shared Plugin"))
|
||||
self.exec_()
|
||||
|
||||
def setupTable(self):
|
||||
self.connect(
|
||||
self.form.table, SIGNAL("currentCellChanged(int,int,int,int)"),
|
||||
self.onCellChanged)
|
||||
self.form.table.verticalHeader().setDefaultSectionSize(
|
||||
self.parent.config['editLineSize'])
|
||||
self.connect(self.form.search, SIGNAL("textChanged(QString)"),
|
||||
self.limit)
|
||||
|
||||
def fetchData(self):
|
||||
h = QHttp(self)
|
||||
h.connect(h, SIGNAL("requestFinished(int,bool)"), self.onReqFin)
|
||||
h.setHost("anki.ichi2.net")
|
||||
#h.setHost("localhost", 8001)
|
||||
self.conId = h.get("/file/search?t=%d" % self.type)
|
||||
self.http = h
|
||||
self.parent.setProgressParent(self)
|
||||
self.parent.startProgress()
|
||||
|
||||
def onReqFin(self, id, err):
|
||||
"List fetched."
|
||||
if id != self.conId:
|
||||
return
|
||||
self.parent.finishProgress()
|
||||
self.parent.setProgressParent(None)
|
||||
if err:
|
||||
showInfo(_("Unable to connect to server."), parent=self)
|
||||
self.close()
|
||||
return
|
||||
data = self.http.readAll()
|
||||
self.allList = simplejson.loads(unicode(data))
|
||||
self.typeChanged()
|
||||
self.limit()
|
||||
|
||||
def limit(self, txt=""):
|
||||
if not txt:
|
||||
self.curList = self.allList
|
||||
else:
|
||||
txt = unicode(txt).lower()
|
||||
self.curList = [
|
||||
l for l in self.allList
|
||||
if (txt in l[R_TITLE].lower() or
|
||||
txt in l[R_DESCRIPTION].lower() or
|
||||
txt in l[R_TAGS].lower())]
|
||||
self.redraw()
|
||||
|
||||
def redraw(self):
|
||||
self.form.table.setSortingEnabled(False)
|
||||
self.form.table.setRowCount(len(self.curList))
|
||||
self.items = {}
|
||||
if self.type == 0:
|
||||
cols = (R_TITLE, R_FACTS, R_COUNT)
|
||||
else:
|
||||
cols = (R_TITLE, R_COUNT)
|
||||
for rc, r in enumerate(self.curList):
|
||||
for cc, c in enumerate(cols):
|
||||
if c == R_FACTS or c == R_COUNT:
|
||||
txt = unicode("%15d" % r[c])
|
||||
else:
|
||||
txt = unicode(r[c])
|
||||
item = QTableWidgetItem(txt)
|
||||
item.setFlags(item.flags() & ~Qt.ItemIsEditable)
|
||||
self.items[item] = r
|
||||
self.form.table.setItem(rc, cc, item)
|
||||
self.form.table.setSortingEnabled(True)
|
||||
if self.type == 0:
|
||||
self.form.table.sortItems(2, Qt.DescendingOrder)
|
||||
else:
|
||||
self.form.table.sortItems(1, Qt.DescendingOrder)
|
||||
self.form.table.selectRow(0)
|
||||
|
||||
def onCellChanged(self, row, col, x, y):
|
||||
ci = self.form.table.currentItem()
|
||||
if not ci:
|
||||
self.form.bottomLabel.setText(_("Nothing selected."))
|
||||
return
|
||||
r = self.items[ci]
|
||||
self.curRow = r
|
||||
self.form.bottomLabel.setText(_("""\
|
||||
<b>Title</b>: %(title)s<br>
|
||||
<b>Tags</b>: %(tags)s<br>
|
||||
<b>Size</b>: %(size)0.2fKB<br>
|
||||
<b>Uploader</b>: %(author)s<br>
|
||||
<b>Downloads</b>: %(count)s<br>
|
||||
<b>Description</b>:<br>%(description)s""") % {
|
||||
'title': r[R_TITLE],
|
||||
'tags': r[R_TAGS],
|
||||
'size': r[R_SIZE] / 1024.0,
|
||||
'author': r[R_USERNAME],
|
||||
'count': r[R_COUNT],
|
||||
'description': r[R_DESCRIPTION].replace("\n", "<br>"),
|
||||
})
|
||||
self.form.scrollAreaWidgetContents.adjustSize()
|
||||
self.form.scrollArea.setWidget(self.form.scrollAreaWidgetContents)
|
||||
|
||||
def onChangeType(self, type):
|
||||
self.type = type
|
||||
self.fetchData()
|
||||
|
||||
def typeChanged(self):
|
||||
self.form.table.clear()
|
||||
if self.type == 0:
|
||||
self.form.table.setColumnCount(3)
|
||||
self.form.table.setHorizontalHeaderLabels([
|
||||
_("Title"), _("Facts"), _("Downloads")])
|
||||
else:
|
||||
self.form.table.setColumnCount(2)
|
||||
self.form.table.setHorizontalHeaderLabels([
|
||||
_("Title"), _("Downloads")])
|
||||
self.form.table.horizontalHeader().setResizeMode(
|
||||
0, QHeaderView.Stretch)
|
||||
self.form.table.verticalHeader().hide()
|
||||
self.form.table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
|
||||
def accept(self):
|
||||
h = QHttp(self)
|
||||
h.connect(h, SIGNAL("requestFinished(int,bool)"), self.onReqFin2)
|
||||
h.setHost("anki.ichi2.net")
|
||||
#h.setHost("localhost", 8001)
|
||||
self.conId = h.get("/file/get?id=%d" % self.curRow[R_ID])
|
||||
self.http = h
|
||||
self.parent.setProgressParent(self)
|
||||
self.parent.startProgress()
|
||||
|
||||
def onReqFin2(self, id, err):
|
||||
"File fetched."
|
||||
if id != self.conId:
|
||||
return
|
||||
try:
|
||||
self.parent.finishProgress()
|
||||
self.parent.setProgressParent(None)
|
||||
if err:
|
||||
showInfo(_("Unable to connect to server."), parent=self)
|
||||
self.close()
|
||||
return
|
||||
data = self.http.readAll()
|
||||
ext = os.path.splitext(self.curRow[R_FNAME])[1]
|
||||
if ext == ".zip":
|
||||
f = cStringIO.StringIO()
|
||||
f.write(data)
|
||||
z = zipfile.ZipFile(f)
|
||||
else:
|
||||
z = None
|
||||
tit = self.curRow[R_TITLE]
|
||||
tit = re.sub("[^][A-Za-z0-9 ()\-]", "", tit)
|
||||
tit = tit[0:40]
|
||||
if self.type == 0:
|
||||
# deck
|
||||
dd = self.parent.documentDir
|
||||
p = os.path.join(dd, tit + ".anki")
|
||||
if os.path.exists(p):
|
||||
tit += "%d" % time.time()
|
||||
for l in z.namelist():
|
||||
if l == "shared.anki":
|
||||
dpath = os.path.join(dd, tit + ".anki")
|
||||
open(dpath, "wb").write(z.read(l))
|
||||
elif l.startswith("shared.media/"):
|
||||
try:
|
||||
os.mkdir(os.path.join(dd, tit + ".media"))
|
||||
except OSError:
|
||||
pass
|
||||
open(os.path.join(dd, tit + ".media",
|
||||
os.path.basename(l)),"wb").write(z.read(l))
|
||||
self.parent.loadDeck(dpath)
|
||||
self.ok = True
|
||||
else:
|
||||
pd = self.parent.pluginsFolder()
|
||||
if z:
|
||||
for l in z.infolist():
|
||||
if not l.file_size:
|
||||
continue
|
||||
try:
|
||||
os.makedirs(os.path.join(
|
||||
pd, os.path.dirname(l.filename)))
|
||||
except OSError:
|
||||
pass
|
||||
open(os.path.join(pd, l.filename), "wb").\
|
||||
write(z.read(l.filename))
|
||||
else:
|
||||
open(os.path.join(pd, tit + ext), "wb").write(data)
|
||||
self.ok = True
|
||||
showInfo(_("Plugin downloaded. Please restart Anki."),
|
||||
parent=self)
|
||||
return
|
||||
finally:
|
||||
QDialog.accept(self)
|
||||
|
|
@ -41,7 +41,8 @@ class HelpArea(object):
|
|||
|
||||
def showText(self, text, py={}):
|
||||
if "hide" in self.handlers:
|
||||
self.handlers["hide"]()
|
||||
if self.handlers['hide'] != py.get('hide'):
|
||||
self.handlers["hide"]()
|
||||
self.show()
|
||||
self.buffer = text
|
||||
self.addHider()
|
||||
|
|
|
@ -132,7 +132,7 @@ class ImportDialog(QDialog):
|
|||
self.parent.deck.finishProgress()
|
||||
self.parent.deck.setUndoEnd(n)
|
||||
txt = (
|
||||
_("Importing complete. %(num)d cards imported from %(file)s.\n") %
|
||||
_("Importing complete. %(num)d facts imported from %(file)s.\n") %
|
||||
{"num": self.importer.total, "file": os.path.basename(self.file)})
|
||||
txt += _("Click the close button or import another file.\n\n")
|
||||
if self.importer.log:
|
||||
|
|
|
@ -6,8 +6,8 @@ from PyQt4.QtGui import *
|
|||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtWebKit import QWebPage
|
||||
|
||||
import os, sys, re, types, gettext, stat, traceback
|
||||
import shutil, time, glob, tempfile, datetime
|
||||
import os, sys, re, types, gettext, stat, traceback, inspect
|
||||
import shutil, time, glob, tempfile, datetime, zipfile, locale
|
||||
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
|
@ -49,8 +49,6 @@ class AnkiQt(QMainWindow):
|
|||
self.setupTray()
|
||||
self.connectMenuActions()
|
||||
ui.splash.update()
|
||||
if self.config['mainWindowGeom']:
|
||||
self.restoreGeometry(self.config['mainWindowGeom'])
|
||||
self.setupViews()
|
||||
self.setupEditor()
|
||||
self.setupStudyScreen()
|
||||
|
@ -58,6 +56,9 @@ class AnkiQt(QMainWindow):
|
|||
self.setupAnchors()
|
||||
self.setupToolbar()
|
||||
self.setupProgressInfo()
|
||||
if self.config['mainWindowState']:
|
||||
self.restoreGeometry(self.config['mainWindowGeom'])
|
||||
self.restoreState(self.config['mainWindowState'])
|
||||
if sys.platform.startswith("darwin"):
|
||||
self.setUnifiedTitleAndToolBarOnMac(True)
|
||||
pass
|
||||
|
@ -68,10 +69,11 @@ class AnkiQt(QMainWindow):
|
|||
self.moveToState("auto")
|
||||
# check for updates
|
||||
ui.splash.update()
|
||||
self.setupAutoUpdate()
|
||||
self.errorOccurred = False
|
||||
self.setupErrorHandler()
|
||||
self.setupMisc()
|
||||
self.loadPlugins()
|
||||
self.setupAutoUpdate()
|
||||
self.rebuildPluginsMenu()
|
||||
# run after-init hook
|
||||
try:
|
||||
|
@ -82,6 +84,9 @@ class AnkiQt(QMainWindow):
|
|||
ui.splash.update()
|
||||
ui.splash.finish(self)
|
||||
self.show()
|
||||
if (self.deck and self.config['syncOnLoad'] and
|
||||
self.deck.syncName):
|
||||
self.syncDeck(interactive=False)
|
||||
|
||||
def setupMainWindow(self):
|
||||
# main window
|
||||
|
@ -142,9 +147,11 @@ class AnkiQt(QMainWindow):
|
|||
# hack for matplotlib errors on osx
|
||||
self.pool = ""
|
||||
stdText = _("""\
|
||||
An error occurred.<br>
|
||||
Please run <b>Tools > Advanced > Check DB</b>.<br>
|
||||
<br>
|
||||
An error occurred. Please:<p>
|
||||
<ol>
|
||||
<li><b>Restart Anki</b>.
|
||||
<li><b>Tools > Advanced > Check DB</b>.
|
||||
</ol>
|
||||
If it does not fix the problem, please copy the following<br>
|
||||
into a bug report:<br><br>
|
||||
""")
|
||||
|
@ -156,6 +163,7 @@ Please do not file a bug report with Anki.<br><br>""")
|
|||
else:
|
||||
txt = stdText
|
||||
if self.pool:
|
||||
self.parent.errorOccurred = True
|
||||
ui.utils.showText(txt + self.pool[0:10000].replace(
|
||||
"\n", "<br>"))
|
||||
self.pool = ""
|
||||
|
@ -197,6 +205,7 @@ Please do not file a bug report with Anki.<br><br>""")
|
|||
if count:
|
||||
self.deck.rebuildCounts()
|
||||
self.deck.rebuildQueue()
|
||||
runHook("guiReset")
|
||||
self.moveToState("initial")
|
||||
|
||||
def moveToState(self, state):
|
||||
|
@ -349,12 +358,12 @@ Please do not file a bug report with Anki.<br><br>""")
|
|||
"Reschedule current card and move back to getQuestion state."
|
||||
if self.state != "showAnswer":
|
||||
return
|
||||
# remove card from session before updating it
|
||||
try:
|
||||
self.deck.s.expunge(self.currentCard)
|
||||
except:
|
||||
# session has been reset
|
||||
pass
|
||||
# force refresh of card then remove from session as we update in pure sql
|
||||
self.deck.s.refresh(self.currentCard)
|
||||
self.deck.s.refresh(self.currentCard.fact)
|
||||
self.deck.s.refresh(self.currentCard.cardModel)
|
||||
self.deck.s.expunge(self.currentCard)
|
||||
# answer
|
||||
self.deck.answerCard(self.currentCard, quality)
|
||||
self.lastScheduledTime = anki.utils.fmtTimeSpan(
|
||||
self.currentCard.due - time.time())
|
||||
|
@ -611,10 +620,10 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
|
|||
# try a command line argument if available
|
||||
if args:
|
||||
f = unicode(args[0], sys.getfilesystemencoding())
|
||||
return self.loadDeck(f)
|
||||
return self.loadDeck(f, sync=False)
|
||||
# try recent deck paths
|
||||
for path in self.config['recentDeckPaths']:
|
||||
r = self.loadDeck(path, interactive=False)
|
||||
r = self.loadDeck(path, interactive=False, sync=False)
|
||||
if r:
|
||||
return r
|
||||
self.onNew(initial=True)
|
||||
|
@ -626,50 +635,10 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
|
|||
latest = self.config['recentDeckPaths'][0]
|
||||
defaultDir = os.path.dirname(latest)
|
||||
else:
|
||||
if save:
|
||||
defaultDir = unicode(os.path.expanduser("~/"),
|
||||
sys.getfilesystemencoding())
|
||||
else:
|
||||
samples = self.getSamplesDir()
|
||||
if samples:
|
||||
return samples
|
||||
defaultDir = unicode(os.path.expanduser("~/"),
|
||||
sys.getfilesystemencoding())
|
||||
return defaultDir
|
||||
|
||||
def getSamplesDir(self):
|
||||
path = os.path.join(ankiqt.runningDir, "libanki")
|
||||
if not os.path.exists(path):
|
||||
path = os.path.join(
|
||||
os.path.join(ankiqt.runningDir, ".."), "libanki")
|
||||
if not os.path.exists(path):
|
||||
path = ankiqt.runningDir
|
||||
if sys.platform.startswith("win32"):
|
||||
path = os.path.split(
|
||||
os.path.split(ankiqt.runningDir)[0])[0]
|
||||
elif sys.platform.startswith("darwin"):
|
||||
path = ankiqt.runningDir + "/../../.."
|
||||
path = os.path.join(path, "samples")
|
||||
path = os.path.normpath(path)
|
||||
if os.path.exists(path):
|
||||
if sys.platform.startswith("darwin"):
|
||||
return self.openMacSamplesDir(path)
|
||||
return path
|
||||
return ""
|
||||
|
||||
def openMacSamplesDir(self, path):
|
||||
# some versions of macosx don't allow the open dialog to point inside
|
||||
# a .App file, it seems - so we copy the files onto the desktop.
|
||||
newDir = os.path.expanduser("~/Documents/Anki 0.9 Sample Decks")
|
||||
import shutil
|
||||
if os.path.exists(newDir):
|
||||
files = os.listdir(path)
|
||||
for file in files:
|
||||
loc = os.path.join(path, file)
|
||||
if not os.path.exists(os.path.join(newDir, file)):
|
||||
shutil.copy2(loc, newDir)
|
||||
return newDir
|
||||
shutil.copytree(path, newDir)
|
||||
return newDir
|
||||
|
||||
def updateRecentFiles(self, path):
|
||||
"Add the current deck to the list of recent files."
|
||||
path = os.path.normpath(path)
|
||||
|
@ -761,6 +730,7 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
|
|||
return True
|
||||
|
||||
def inMainWindow(self):
|
||||
return True
|
||||
return self.app.activeWindow() == self
|
||||
|
||||
def onNew(self, initial=False, path=None):
|
||||
|
@ -826,23 +796,27 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
|
|||
self.deck = None
|
||||
self.moveToState("initial")
|
||||
|
||||
def onOpen(self, samples=False):
|
||||
def onGetSharedDeck(self):
|
||||
if not self.inMainWindow(): return
|
||||
if not self.saveAndClose(hideWelcome=True): return
|
||||
s = ui.getshared.GetShared(self, 0)
|
||||
if not s.ok:
|
||||
self.deck = None
|
||||
self.moveToState("initial")
|
||||
|
||||
def onGetSharedPlugin(self):
|
||||
if not self.inMainWindow(): return
|
||||
ui.getshared.GetShared(self, 1)
|
||||
|
||||
def onOpen(self):
|
||||
if not self.inMainWindow(): return
|
||||
key = _("Deck files (*.anki)")
|
||||
if samples: defaultDir = self.getSamplesDir()
|
||||
else: defaultDir = self.getDefaultDir()
|
||||
defaultDir = self.getDefaultDir()
|
||||
file = QFileDialog.getOpenFileName(self, _("Open deck"),
|
||||
defaultDir, key)
|
||||
file = unicode(file)
|
||||
if not file:
|
||||
return False
|
||||
if samples:
|
||||
# we need to copy into a writeable location
|
||||
d = unicode(
|
||||
os.path.join(self.documentDir, os.path.basename(file)))
|
||||
if not os.path.exists(d):
|
||||
shutil.copy(file, d)
|
||||
file = d
|
||||
ret = self.loadDeck(file, interactive=True)
|
||||
if not ret:
|
||||
if ret is None:
|
||||
|
@ -853,9 +827,6 @@ To upgrade an old deck, download Anki 0.9.8.7."""))
|
|||
self.updateRecentFiles(file)
|
||||
return True
|
||||
|
||||
def onOpenSamples(self):
|
||||
self.onOpen(samples=True)
|
||||
|
||||
def onUnsavedTimer(self):
|
||||
QToolTip.showText(
|
||||
self.mainWin.statusbar.mapToGlobal(QPoint(0, -100)),
|
||||
|
@ -925,6 +896,7 @@ your deck."""))
|
|||
runHook("quit")
|
||||
self.help.hide()
|
||||
self.config['mainWindowGeom'] = self.saveGeometry()
|
||||
self.config['mainWindowState'] = self.saveState()
|
||||
# save config
|
||||
try:
|
||||
self.config.save()
|
||||
|
@ -950,14 +922,12 @@ your deck."""))
|
|||
def onWelcomeAnchor(self, str):
|
||||
if str == "new":
|
||||
self.onNew()
|
||||
elif str == "sample":
|
||||
self.onOpenSamples()
|
||||
elif str == "open":
|
||||
self.onOpen()
|
||||
elif str == "sample":
|
||||
self.onGetSharedDeck()
|
||||
elif str == "openrem":
|
||||
self.onOpenOnline()
|
||||
elif str == "more":
|
||||
self.onGetMoreDecks()
|
||||
if str == "addfacts":
|
||||
if not self.deck:
|
||||
self.onNew()
|
||||
|
@ -1175,7 +1145,6 @@ day = :d""", d=yesterday)
|
|||
self.deck.newCardSpacing = self.mainWin.newCardScheduling.currentIndex()
|
||||
self.deck.revCardOrder = self.mainWin.revCardOrder.currentIndex()
|
||||
self.deck.setFailedCardPolicy(self.mainWin.failedCardsOption.currentIndex())
|
||||
self.deck.updateDynamicIndices()
|
||||
self.deck.startSession()
|
||||
self.deck.flushMod()
|
||||
self.moveToState("getQuestion")
|
||||
|
@ -1401,13 +1370,11 @@ day = :d""", d=yesterday)
|
|||
def onActiveTags(self):
|
||||
ui.activetags.show(self)
|
||||
|
||||
def onGetMoreDecks(self):
|
||||
QDesktopServices.openUrl(QUrl(ankiqt.appMoreDecks))
|
||||
|
||||
# Importing & exporting
|
||||
##########################################################################
|
||||
|
||||
def onImport(self):
|
||||
import ui.importing
|
||||
if self.deck is None:
|
||||
self.onNew()
|
||||
ui.importing.ImportDialog(self)
|
||||
|
@ -1415,9 +1382,20 @@ day = :d""", d=yesterday)
|
|||
def onExport(self):
|
||||
ui.exporting.ExportDialog(self)
|
||||
|
||||
# Cramming
|
||||
# Cramming & Sharing
|
||||
##########################################################################
|
||||
|
||||
def _copyToTmpDeck(self, name="cram.anki", tags=""):
|
||||
ndir = tempfile.mkdtemp(prefix="anki")
|
||||
path = os.path.join(ndir, name)
|
||||
from anki.exporting import AnkiExporter
|
||||
e = AnkiExporter(self.deck)
|
||||
if tags:
|
||||
e.limitTags = parseTags(tags)
|
||||
path = unicode(path, sys.getfilesystemencoding())
|
||||
e.exportInto(path)
|
||||
return (e, path)
|
||||
|
||||
def onCram(self):
|
||||
if self.deck.name() == "cram":
|
||||
ui.utils.showInfo(
|
||||
|
@ -1431,14 +1409,7 @@ day = :d""", d=yesterday)
|
|||
return
|
||||
s = unicode(s)
|
||||
# open tmp deck
|
||||
ndir = tempfile.mkdtemp(prefix="anki")
|
||||
path = os.path.join(ndir, "cram.anki")
|
||||
from anki.exporting import AnkiExporter
|
||||
e = AnkiExporter(self.deck)
|
||||
if s:
|
||||
e.limitTags = parseTags(s)
|
||||
path = unicode(path, sys.getfilesystemencoding())
|
||||
e.exportInto(path)
|
||||
(e, path) = self._copyToTmpDeck(tags=s)
|
||||
if not e.exportedCards:
|
||||
ui.utils.showInfo(_("No cards matched the provided tags."))
|
||||
return
|
||||
|
@ -1482,6 +1453,80 @@ day = :d""", d=yesterday)
|
|||
self.reset()
|
||||
p.finish()
|
||||
|
||||
def onShare(self, tags):
|
||||
pwd = os.getcwd()
|
||||
# open tmp deck
|
||||
(e, path) = self._copyToTmpDeck(name="shared.anki", tags=tags)
|
||||
if not e.exportedCards:
|
||||
ui.utils.showInfo(_("No cards matched the provided tags."))
|
||||
return
|
||||
self.deck.startProgress()
|
||||
self.deck.updateProgress()
|
||||
d = DeckStorage.Deck(path)
|
||||
# reset scheduling to defaults
|
||||
d.newCardsPerDay = 20
|
||||
d.delay0 = 600
|
||||
d.delay1 = 600
|
||||
d.delay2 = 0
|
||||
d.hardIntervalMin = 0.333
|
||||
d.hardIntervalMax = 0.5
|
||||
d.midIntervalMin = 3.0
|
||||
d.midIntervalMax = 5.0
|
||||
d.easyIntervalMin = 7.0
|
||||
d.easyIntervalMax = 9.0
|
||||
d.syncName = None
|
||||
d.suspended = u"Suspended"
|
||||
self.deck.updateProgress()
|
||||
d.updateAllPriorities()
|
||||
d.utcOffset = -1
|
||||
d.flushMod()
|
||||
d.save()
|
||||
self.deck.updateProgress()
|
||||
# remove indices
|
||||
indices = d.s.column0(
|
||||
"select name from sqlite_master where type = 'index' "
|
||||
"and sql != ''")
|
||||
for i in indices:
|
||||
d.s.statement("drop index %s" % i)
|
||||
# and q/a cache
|
||||
d.s.statement("update cards set question = '', answer = ''")
|
||||
self.deck.updateProgress()
|
||||
d.s.statement("vacuum")
|
||||
self.deck.updateProgress()
|
||||
nfacts = d.factCount
|
||||
mdir = d.mediaDir()
|
||||
d.close()
|
||||
dir = os.path.dirname(path)
|
||||
zippath = os.path.join(dir, "shared-%d.zip" % time.time())
|
||||
# zip it up
|
||||
zip = zipfile.ZipFile(zippath, "w", zipfile.ZIP_DEFLATED)
|
||||
zip.writestr("facts", str(nfacts))
|
||||
readmep = os.path.join(dir, "README.html")
|
||||
readme = open(readmep, "w")
|
||||
readme.write('''\
|
||||
<html><body>
|
||||
This is an exported packaged deck created by Anki.<p>
|
||||
|
||||
To share this deck with other people, upload it to
|
||||
<a href="http://anki.ichi2.net/file/upload">
|
||||
http://anki.ichi2.net/file/upload</a>, or email
|
||||
it to your friends.
|
||||
</body></html>''')
|
||||
readme.close()
|
||||
zip.write(readmep, "README.txt")
|
||||
zip.write(path, "shared.anki")
|
||||
if mdir:
|
||||
for f in os.listdir(mdir):
|
||||
zip.write(os.path.join(mdir, f),
|
||||
str(os.path.join("shared.media/", f)))
|
||||
shutil.rmtree(mdir)
|
||||
self.deck.updateProgress()
|
||||
zip.close()
|
||||
os.chdir(pwd)
|
||||
os.unlink(path)
|
||||
self.deck.finishProgress()
|
||||
self.onOpenPluginFolder(dir)
|
||||
|
||||
# Reviewing and learning ahead
|
||||
##########################################################################
|
||||
|
||||
|
@ -1498,6 +1543,7 @@ day = :d""", d=yesterday)
|
|||
|
||||
def setLang(self):
|
||||
"Set the user interface language."
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
languageDir=os.path.join(ankiqt.modDir, "locale")
|
||||
self.languageTrans = gettext.translation('ankiqt', languageDir,
|
||||
languages=[self.config["interfaceLang"]],
|
||||
|
@ -1698,10 +1744,12 @@ day = :d""", d=yesterday)
|
|||
s = SIGNAL("triggered()")
|
||||
self.connect(m.actionNew, s, self.onNew)
|
||||
self.connect(m.actionOpenOnline, s, self.onOpenOnline)
|
||||
self.connect(m.actionDownloadSharedDeck, s, self.onGetSharedDeck)
|
||||
self.connect(m.actionDownloadSharedPlugin, s, self.onGetSharedPlugin)
|
||||
self.connect(m.actionOpen, s, self.onOpen)
|
||||
self.connect(m.actionOpenSamples, s, self.onOpenSamples)
|
||||
self.connect(m.actionSave, s, self.onSave)
|
||||
self.connect(m.actionSaveAs, s, self.onSaveAs)
|
||||
self.connect(m.actionShare, s, self.onShare)
|
||||
self.connect(m.actionClose, s, self.onClose)
|
||||
self.connect(m.actionExit, s, self, SLOT("close()"))
|
||||
self.connect(m.actionSyncdeck, s, self.syncDeck)
|
||||
|
@ -1742,7 +1790,6 @@ day = :d""", d=yesterday)
|
|||
self.connect(m.actionDisableAllPlugins, s, self.onDisableAllPlugins)
|
||||
self.connect(m.actionActiveTags, s, self.onActiveTags)
|
||||
self.connect(m.actionReleaseNotes, s, self.onReleaseNotes)
|
||||
self.connect(m.actionGetMoreDecks, s, self.onGetMoreDecks)
|
||||
self.connect(m.actionCacheLatex, s, self.onCacheLatex)
|
||||
self.connect(m.actionUncacheLatex, s, self.onUncacheLatex)
|
||||
self.connect(m.actionStudyOptions, s, self.onStudyOptions)
|
||||
|
@ -1835,7 +1882,13 @@ day = :d""", d=yesterday)
|
|||
self.mainWin.menu_Lookup.menuAction().setVisible(True)
|
||||
else:
|
||||
self.mainWin.menu_Lookup.menuAction().setVisible(False)
|
||||
enable = False
|
||||
self.mainWin.menu_Lookup.setEnabled(enable)
|
||||
self.mainWin.actionLookup_es.setEnabled(enable)
|
||||
self.mainWin.actionLookup_esk.setEnabled(enable)
|
||||
self.mainWin.actionLookup_expr.setEnabled(enable)
|
||||
self.mainWin.actionLookup_mean.setEnabled(enable)
|
||||
self.mainWin.actionLookup_as.setEnabled(enable)
|
||||
|
||||
def maybeEnableUndo(self):
|
||||
if self.deck and self.deck.undoAvailable():
|
||||
|
@ -1904,6 +1957,7 @@ day = :d""", d=yesterday)
|
|||
sys.path.insert(0, plugdir)
|
||||
plugins = self.enabledPlugins()
|
||||
plugins.sort()
|
||||
self.registeredPlugins = {}
|
||||
for plugin in plugins:
|
||||
try:
|
||||
nopy = plugin.replace(".py", "")
|
||||
|
@ -1911,6 +1965,7 @@ day = :d""", d=yesterday)
|
|||
except:
|
||||
print "Error in %s" % plugin
|
||||
traceback.print_exc()
|
||||
self.checkForUpdatedPlugins()
|
||||
|
||||
def rebuildPluginsMenu(self):
|
||||
if getattr(self, "pluginActions", None) is None:
|
||||
|
@ -1922,6 +1977,8 @@ day = :d""", d=yesterday)
|
|||
for fname in all:
|
||||
enabled = fname.endswith(".py")
|
||||
p = re.sub("\.py(\.off)?", "", fname)
|
||||
if p+".py" in self.registeredPlugins:
|
||||
p = self.registeredPlugins[p+".py"]['name']
|
||||
a = QAction(p, self)
|
||||
a.setCheckable(True)
|
||||
a.setChecked(enabled)
|
||||
|
@ -1942,13 +1999,16 @@ day = :d""", d=yesterday)
|
|||
return [p for p in os.listdir(self.pluginsFolder())
|
||||
if p.endswith(".py.off") or p.endswith(".py")]
|
||||
|
||||
def onOpenPluginFolder(self):
|
||||
def onOpenPluginFolder(self, path=None):
|
||||
if path is None:
|
||||
path = self.pluginsFolder()
|
||||
if sys.platform == "win32":
|
||||
# reuse our process handling code from latex
|
||||
anki.latex.call(["explorer", self.pluginsFolder().encode(
|
||||
sys.getfilesystemencoding())])
|
||||
anki.latex.call(["explorer", path.encode(
|
||||
sys.getfilesystemencoding())],
|
||||
wait=False)
|
||||
else:
|
||||
QDesktopServices.openUrl(QUrl("file://" + self.pluginsFolder()))
|
||||
QDesktopServices.openUrl(QUrl("file://" + path))
|
||||
|
||||
def onGetPlugins(self):
|
||||
QDesktopServices.openUrl(QUrl("http://ichi2.net/anki/wiki/Plugins"))
|
||||
|
@ -1980,6 +2040,14 @@ day = :d""", d=yesterday)
|
|||
self.enablePlugin(plugin)
|
||||
self.rebuildPluginsMenu()
|
||||
|
||||
def registerPlugin(self, name, updateId):
|
||||
src = os.path.basename(inspect.getfile(inspect.currentframe(1)))
|
||||
self.registeredPlugins[src] = {'name': name,
|
||||
'id': updateId}
|
||||
|
||||
def checkForUpdatedPlugins(self):
|
||||
pass
|
||||
|
||||
# Font localisation
|
||||
##########################################################################
|
||||
|
||||
|
@ -2011,9 +2079,9 @@ day = :d""", d=yesterday)
|
|||
##########################################################################
|
||||
|
||||
def setupProgressInfo(self):
|
||||
addHook("startProgress", self.onStartProgress)
|
||||
addHook("updateProgress", self.onUpdateProgress)
|
||||
addHook("finishProgress", self.onFinishProgress)
|
||||
addHook("startProgress", self.startProgress)
|
||||
addHook("updateProgress", self.updateProgress)
|
||||
addHook("finishProgress", self.finishProgress)
|
||||
addHook("dbProgress", self.onDbProgress)
|
||||
addHook("dbFinished", self.onDbFinished)
|
||||
self.progressParent = None
|
||||
|
@ -2024,7 +2092,7 @@ day = :d""", d=yesterday)
|
|||
def setProgressParent(self, parent):
|
||||
self.progressParent = parent
|
||||
|
||||
def onStartProgress(self, max=100, min=0, title=None):
|
||||
def startProgress(self, max=0, min=0, title=None):
|
||||
if self.mainThread != QThread.currentThread():
|
||||
return
|
||||
self.setBusy()
|
||||
|
@ -2034,14 +2102,14 @@ day = :d""", d=yesterday)
|
|||
p = ui.utils.ProgressWin(parent, max, min, title)
|
||||
self.progressWins.append(p)
|
||||
|
||||
def onUpdateProgress(self, label=None, value=None):
|
||||
def updateProgress(self, label=None, value=None):
|
||||
if self.mainThread != QThread.currentThread():
|
||||
return
|
||||
if self.progressWins:
|
||||
self.progressWins[-1].update(label, value)
|
||||
self.app.processEvents()
|
||||
|
||||
def onFinishProgress(self):
|
||||
def finishProgress(self):
|
||||
if self.mainThread != QThread.currentThread():
|
||||
return
|
||||
if self.progressWins:
|
||||
|
@ -2077,6 +2145,10 @@ day = :d""", d=yesterday)
|
|||
|
||||
def onCheckDB(self):
|
||||
"True if no problems"
|
||||
if self.errorOccurred:
|
||||
ui.utils.showWarning(_(
|
||||
"Please restart Anki before checking the DB."))
|
||||
return
|
||||
if not ui.utils.askUser(_("""\
|
||||
This operation will find and fix some common problems.<br>
|
||||
<br>
|
||||
|
@ -2098,7 +2170,7 @@ Proceed?""")):
|
|||
|
||||
def onOptimizeDB(self):
|
||||
size = self.deck.optimize()
|
||||
ui.utils.showInfo("Database optimized.\nShrunk by %dKB" % (size/1024.0))
|
||||
ui.utils.showInfo(_("Database optimized.\nShrunk by %dKB") % (size/1024.0))
|
||||
|
||||
def onCheckMediaDB(self):
|
||||
mb = QMessageBox(self)
|
||||
|
|
|
@ -492,7 +492,7 @@ order by n""", id=card.id)
|
|||
self.deck.setModified()
|
||||
# if changed, reset deck
|
||||
if self.origModTime != self.deck.modified:
|
||||
self.deck.updateCardTags()
|
||||
self.deck.updateTagsForModel(self.m)
|
||||
ankiqt.mw.reset()
|
||||
if self.onFinish:
|
||||
self.onFinish()
|
||||
|
|
|
@ -28,8 +28,10 @@ class Preferences(QDialog):
|
|||
self.supportedLanguages = [
|
||||
(_("English"), "en_US"),
|
||||
(_("Brazillian Portuguese"), "pt_BR"),
|
||||
(_("Chinese Traditional"), "zh_TW"),
|
||||
(_("Chinese - Simplified"), "zh_CN"),
|
||||
(_("Chinese - Traditional"), "zh_TW"),
|
||||
(_("Czech"), "cs_CZ"),
|
||||
(_("Estonian"), "ee_EE"),
|
||||
(_("Finnish"), "fi_FI"),
|
||||
(_("French"), "fr_FR"),
|
||||
(_("German"), "de_DE"),
|
||||
|
@ -111,6 +113,7 @@ class Preferences(QDialog):
|
|||
self.dialog.splitQA.setChecked(self.config['splitQA'])
|
||||
self.dialog.addZeroSpace.setChecked(self.config['addZeroSpace'])
|
||||
self.dialog.alternativeTheme.setChecked(self.config['alternativeTheme'])
|
||||
self.dialog.showProgress.setChecked(self.config['showProgress'])
|
||||
|
||||
def updateAdvanced(self):
|
||||
self.config['showTrayIcon'] = self.dialog.showTray.isChecked()
|
||||
|
@ -121,6 +124,7 @@ class Preferences(QDialog):
|
|||
self.config['splitQA'] = self.dialog.splitQA.isChecked()
|
||||
self.config['addZeroSpace'] = self.dialog.addZeroSpace.isChecked()
|
||||
self.config['alternativeTheme'] = self.dialog.alternativeTheme.isChecked()
|
||||
self.config['showProgress'] = self.dialog.showProgress.isChecked()
|
||||
|
||||
def codeToIndex(self, code):
|
||||
n = 0
|
||||
|
|
|
@ -74,7 +74,8 @@ class StatusView(object):
|
|||
# remaining & eta
|
||||
self.remText = QLabel()
|
||||
self.addWidget(self.remText, 0)
|
||||
self.addWidget(self.vertSep(), 0)
|
||||
sep1 = self.vertSep()
|
||||
self.addWidget(sep1, 0)
|
||||
self.etaText = QLabel()
|
||||
self.etaText.setToolTip(_(
|
||||
"<h1>Estimated time</h1>"
|
||||
|
@ -82,7 +83,8 @@ class StatusView(object):
|
|||
"at your current pace."))
|
||||
self.addWidget(self.etaText, 0)
|
||||
# progress&retention
|
||||
self.addWidget(self.vertSep(), 0)
|
||||
sep2 = self.vertSep()
|
||||
self.addWidget(sep2, 0)
|
||||
vbox = QVBoxLayout()
|
||||
vbox.setSpacing(0)
|
||||
vbox.setMargin(0)
|
||||
|
@ -105,13 +107,23 @@ class StatusView(object):
|
|||
self.retentionBar.setStyle(self.plastiqueStyle)
|
||||
self.addWidget(self.combinedBar, 0)
|
||||
# timer
|
||||
self.addWidget(self.vertSep(), 0)
|
||||
sep3 = self.vertSep()
|
||||
self.addWidget(sep3, 0)
|
||||
self.timer = QClickableLabel()
|
||||
self.timer.setText("00:00")
|
||||
self.addWidget(self.timer)
|
||||
self.redraw()
|
||||
if not self.main.config['showTimer']:
|
||||
self.timer.setShown(False)
|
||||
if not self.main.config['showProgress']:
|
||||
self.progressBar.hide()
|
||||
self.retentionBar.hide()
|
||||
self.timer.hide()
|
||||
self.etaText.hide()
|
||||
self.remText.hide()
|
||||
sep1.hide()
|
||||
sep2.hide()
|
||||
sep3.hide()
|
||||
|
||||
def addWidget(self, w, stretch=0):
|
||||
self.statusbar.addWidget(w, stretch)
|
||||
|
@ -164,7 +176,7 @@ class StatusView(object):
|
|||
"There are <b>%(rev)d</b> cards awaiting review.<br>"
|
||||
"There are <b>%(new)d</b> new cards due today.<br><br>"
|
||||
"There are <b>%(new2)d</b> new cards in total.<br>"
|
||||
"There are <b>%(spaced)d</b> spaced cards.") % stats)
|
||||
"There are <b>%(spaced)d</b> delayed cards.") % stats)
|
||||
# eta
|
||||
self.etaText.setText(_("ETA: <b>%(timeLeft)s</b>") % stats)
|
||||
# retention & progress bars
|
||||
|
@ -177,31 +189,27 @@ class StatusView(object):
|
|||
self.progressBar.setPalette(p)
|
||||
self.progressBar.setValue(stats['dYesTotal%'])
|
||||
# tooltips
|
||||
stats['avgTime'] = anki.utils.fmtTimeSpan(stats['dAverageTime'], point=2)
|
||||
stats['revTime'] = anki.utils.fmtTimeSpan(stats['dReviewTime'], point=2)
|
||||
tip = _("""<h1>Performance</h1>
|
||||
The top bar shows your performance today. The bottom bar shows your<br>
|
||||
tip = "<h1>" + _("Performance") + "</h1>"
|
||||
tip += _("""The top bar shows your performance today. The bottom bar shows your<br>
|
||||
performance on cards scheduled for 21 days or more. The bottom bar should<br>
|
||||
generally be between 80-95%% - lower and you're forgetting mature cards<br>
|
||||
too often, higher and you're spending too much time reviewing.
|
||||
<h2>Reviews today</h2>
|
||||
<b>Correct today: %(dYesTotal%)0.1f%%
|
||||
(%(dYesTotal)d of %(dTotal)d)</b><br>
|
||||
Average time per answer: %(avgTime)s<br>
|
||||
Total review time: %(revTime)s""") % stats
|
||||
stats['avgTime'] = anki.utils.fmtTimeSpan(stats['gAverageTime'], point=2)
|
||||
stats['revTime'] = anki.utils.fmtTimeSpan(stats['gReviewTime'], point=2)
|
||||
tip += _("""<h2>All Reviews</h2>
|
||||
<b>Correct over a month: %(gMatureYes%)0.1f%%
|
||||
(%(gMatureYes)d of %(gMatureTotal)d)</b><br>
|
||||
Average time per answer: %(avgTime)s<br>
|
||||
Total review time: %(revTime)s<br>
|
||||
Correct under a month: %(gYoungYes%)0.1f%%
|
||||
(%(gYoungYes)d of %(gYoungTotal)d)<br>
|
||||
Correct first time: %(gNewYes%)0.1f%%
|
||||
(%(gNewYes)d of %(gNewTotal)d)<br>
|
||||
Total correct: %(gYesTotal%)0.1f%%
|
||||
(%(gYesTotal)d of %(gTotal)d)""") % stats
|
||||
generally be between 80-95% - lower and you're forgetting mature cards<br>
|
||||
too often, higher and you're spending too much time reviewing.""")
|
||||
tip += "<h2>" + _("Reviews today") + "</h2>"
|
||||
tip += "<b>" + _("Correct today: ") + anki.utils.fmtPercentage(stats['dYesTotal%'], point=1)
|
||||
tip += " (" + _("%(partOf)d of %(totalSum)d") % {'partOf' : stats['dYesTotal'], 'totalSum' : stats['dTotal'] } + ")</b><br>"
|
||||
tip += _("Average time per answer: ") + anki.utils.fmtTimeSpan(stats['dAverageTime'], point=2) +"<br>"
|
||||
tip += _("Total review time: ") + anki.utils.fmtTimeSpan(stats['dReviewTime'], point=2)
|
||||
tip += "<h2>" + _("All Reviews") + "</h2>"
|
||||
tip += "<b>" + _("Correct over a month: ") + anki.utils.fmtPercentage(stats['gMatureYes%'], point=1)
|
||||
tip += " (" + _("%(partOf)d of %(totalSum)d") % {'partOf' : stats['gMatureYes'], 'totalSum' : stats['gMatureTotal'] } + ")</b><br>"
|
||||
tip += _("Average time per answer: ") + anki.utils.fmtTimeSpan(stats['gAverageTime'], point=2) +"<br>"
|
||||
tip += _("Total review time: ") + anki.utils.fmtTimeSpan(stats['gReviewTime'], point=2) +"<br>"
|
||||
tip += _("Correct under a month: ") + anki.utils.fmtPercentage(stats['gYoungYes%'], point=1)
|
||||
tip += " (" + _("%(partOf)d of %(totalSum)d") % {'partOf' : stats['gYoungYes'], 'totalSum' : stats['gYoungTotal'] } + ")</b><br>"
|
||||
tip += _("Correct first time: ") + anki.utils.fmtPercentage(stats['gNewYes%'], point=1)
|
||||
tip += " (" + _("%(partOf)d of %(totalSum)d") % {'partOf' : stats['gNewYes'], 'totalSum' : stats['gNewTotal'] } + ")</b><br>"
|
||||
tip += _("Total correct: ") + anki.utils.fmtPercentage(stats['gYesTotal%'], point=1)
|
||||
tip += " (" + _("%(partOf)d of %(totalSum)d") % {'partOf' : stats['gYesTotal'], 'totalSum' : stats['gTotal'] } + ")</b><br>"
|
||||
self.combinedBar.setToolTip(tip)
|
||||
if self.main.config['showTimer']:
|
||||
self.drawTimer()
|
||||
|
|
|
@ -52,7 +52,9 @@ class Sync(QThread):
|
|||
else:
|
||||
msg=_("""\
|
||||
Syncing failed. Please try again in a few minutes.
|
||||
If the problem persists, please report it on the forum.""")
|
||||
If the problem persists, please report it on the forum.
|
||||
|
||||
Error: %s""" % `error`)
|
||||
return msg
|
||||
|
||||
def connect(self, *args):
|
||||
|
|
|
@ -56,7 +56,7 @@ class View(object):
|
|||
self.haveTop = (self.main.lastCard and (
|
||||
self.main.config['showLastCardContent'] or
|
||||
self.main.config['showLastCardInterval'])) or (
|
||||
self.main.currentCard and self.main.currentCard.due > time.time())
|
||||
self.needFutureWarning())
|
||||
self.drawRule = (self.main.config['qaDivider'] and
|
||||
self.main.currentCard and
|
||||
not self.main.currentCard.cardModel.questionInAnswer)
|
||||
|
@ -204,13 +204,18 @@ class View(object):
|
|||
self.drawLastCard()
|
||||
self.buffer += "</center>"
|
||||
|
||||
def drawFutureWarning(self):
|
||||
def needFutureWarning(self):
|
||||
if not self.main.currentCard:
|
||||
return
|
||||
if self.main.currentCard.due <= time.time():
|
||||
return
|
||||
if self.main.currentCard.due - time.time() <= self.main.deck.delay0:
|
||||
return
|
||||
return True
|
||||
|
||||
def drawFutureWarning(self):
|
||||
if not self.needFutureWarning():
|
||||
return
|
||||
self.write("<span style='color: %s'>" % futureWarningColour +
|
||||
_("This card was due in %s.") % fmtTimeSpan(
|
||||
self.main.currentCard.due - time.time()) +
|
||||
|
@ -247,8 +252,8 @@ class View(object):
|
|||
##########################################################################
|
||||
|
||||
def drawWelcomeMessage(self):
|
||||
self.main.mainWin.welcomeText.setText(_("""\
|
||||
<h1>Welcome to Anki!</h1>
|
||||
self.main.mainWin.welcomeText.setText("""\
|
||||
<h1>%(welcome)s</h1>
|
||||
<p>
|
||||
<table>
|
||||
|
||||
|
@ -256,8 +261,8 @@ class View(object):
|
|||
<td width=50>
|
||||
<a href="welcome:addfacts"><img src=":/icons/list-add.png"></a>
|
||||
</td>
|
||||
<td valign=middle><h1><a href="welcome:addfacts">Add material</a></h1>
|
||||
Start adding your own material.</td>
|
||||
<td valign=middle><h1><a href="welcome:addfacts">%(add)s</a></h1>
|
||||
%(start)s</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
@ -269,31 +274,30 @@ Start adding your own material.</td>
|
|||
<td>
|
||||
<a href="welcome:open"><img src=":/icons/document-open.png"></a>
|
||||
</td>
|
||||
<td valign=middle><h2><a href="welcome:open">Open Local Deck</a></h2></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<a href="welcome:openrem"><img src=":/icons/document-open-remote.png"></a>
|
||||
</td>
|
||||
<td valign=middle><h2><a href="welcome:openrem">Open Online Deck</a></h2></td>
|
||||
<td valign=middle><h2><a href="welcome:open">%(local)s</a></h2></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width=50>
|
||||
<a href="welcome:sample"><img src=":/icons/anki.png"></a>
|
||||
</td>
|
||||
<td valign=middle><h2><a href="welcome:sample">Open Sample Deck</a></h2></td>
|
||||
<td valign=middle><h2><a href="welcome:sample">%(dl_shared)s</a></h2></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width=50>
|
||||
<a href="welcome:more"><img src=":/icons/khtml_kget.png"></a>
|
||||
<td>
|
||||
<a href="welcome:openrem"><img src=":/icons/document-open-remote.png"></a>
|
||||
</td>
|
||||
<td valign=middle><h2><a href="welcome:more">Get More Decks</a></h2></td>
|
||||
<td valign=middle><h2><a href="welcome:openrem">%(dl_personal)s</a></h2></td>
|
||||
</tr>
|
||||
|
||||
</table>"""))
|
||||
</table>""" % \
|
||||
{"welcome":_("Welcome to Anki!"),
|
||||
"add":_("Add material"),
|
||||
"start":_("Start adding your own material."),
|
||||
"local":_("Open Local Deck"),
|
||||
"dl_shared":_("Download Shared Deck"),
|
||||
"dl_personal":_("Download Personal Deck")})
|
||||
|
||||
def drawDeckFinishedMessage(self):
|
||||
"Tell the user the deck is finished."
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>224</width>
|
||||
<height>310</height>
|
||||
<width>410</width>
|
||||
<height>447</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
|
|
|
@ -13,6 +13,14 @@
|
|||
<string>Edit Items</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>23</y>
|
||||
<width>599</width>
|
||||
<height>439</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
|
@ -162,7 +170,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>599</width>
|
||||
<height>25</height>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuEdit" >
|
||||
|
@ -226,7 +234,7 @@
|
|||
<string>Delete</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Del</string>
|
||||
<string>Ctrl+Del</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAddTag" >
|
||||
|
|
|
@ -300,8 +300,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>960</width>
|
||||
<height>480</height>
|
||||
<width>348</width>
|
||||
<height>317</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="title" >
|
||||
|
@ -556,6 +556,9 @@
|
|||
<property name="text" >
|
||||
<string>Close</string>
|
||||
</property>
|
||||
<property name="autoDefault" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -613,6 +616,31 @@
|
|||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>cardList</tabstop>
|
||||
<tabstop>questionFont</tabstop>
|
||||
<tabstop>questionSize</tabstop>
|
||||
<tabstop>questionColour</tabstop>
|
||||
<tabstop>questionAlign</tabstop>
|
||||
<tabstop>answerFont</tabstop>
|
||||
<tabstop>answerSize</tabstop>
|
||||
<tabstop>answerColour</tabstop>
|
||||
<tabstop>answerAlign</tabstop>
|
||||
<tabstop>backgroundColour</tabstop>
|
||||
<tabstop>fieldList</tabstop>
|
||||
<tabstop>useFamily</tabstop>
|
||||
<tabstop>fontFamily</tabstop>
|
||||
<tabstop>useSize</tabstop>
|
||||
<tabstop>fontSize</tabstop>
|
||||
<tabstop>useColour</tabstop>
|
||||
<tabstop>fontColour</tabstop>
|
||||
<tabstop>useFamilyEdit</tabstop>
|
||||
<tabstop>fontFamilyEdit</tabstop>
|
||||
<tabstop>useSizeEdit</tabstop>
|
||||
<tabstop>fontSizeEdit</tabstop>
|
||||
<tabstop>helpButton</tabstop>
|
||||
<tabstop>preview</tabstop>
|
||||
<tabstop>closeButton</tabstop>
|
||||
<tabstop>question</tabstop>
|
||||
<tabstop>answer</tabstop>
|
||||
</tabstops>
|
||||
|
|
|
@ -58,6 +58,19 @@
|
|||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
|
|
|
@ -18,32 +18,22 @@
|
|||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Find</string>
|
||||
<string><b>Find</b>:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLineEdit" name="find" />
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Replace</string>
|
||||
<string><b>Replace With</b>:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLineEdit" name="replace" />
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QComboBox" name="type" />
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="replace" />
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QCheckBox" name="re" >
|
||||
|
@ -52,6 +42,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string><b>In</b>:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QComboBox" name="field" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -81,8 +81,8 @@
|
|||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>find</tabstop>
|
||||
<tabstop>field</tabstop>
|
||||
<tabstop>replace</tabstop>
|
||||
<tabstop>type</tabstop>
|
||||
<tabstop>re</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
|
@ -95,8 +95,8 @@
|
|||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>252</x>
|
||||
<y>127</y>
|
||||
<x>256</x>
|
||||
<y>154</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
|
@ -111,8 +111,8 @@
|
|||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>286</x>
|
||||
<y>127</y>
|
||||
<x>290</x>
|
||||
<y>154</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
|
|
133
designer/getshared.ui
Normal file
133
designer/getshared.ui
Normal file
|
@ -0,0 +1,133 @@
|
|||
<ui version="4.0" >
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>517</width>
|
||||
<height>411</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="searchLabel" >
|
||||
<property name="text" >
|
||||
<string>Search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="search" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTableWidget" name="table" />
|
||||
<widget class="QScrollArea" name="scrollArea" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy" >
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy" >
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>494</width>
|
||||
<height>54</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" >
|
||||
<item>
|
||||
<widget class="QLabel" name="bottomLabel" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Loading...</string>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags" >
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<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>
|
131
designer/main.ui
131
designer/main.ui
|
@ -6,7 +6,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>723</width>
|
||||
<height>504</height>
|
||||
<height>513</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
|
@ -28,7 +28,7 @@
|
|||
<x>0</x>
|
||||
<y>69</y>
|
||||
<width>723</width>
|
||||
<height>415</height>
|
||||
<height>424</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
|
@ -145,8 +145,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>422</width>
|
||||
<height>57</height>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
|
@ -224,8 +224,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>422</width>
|
||||
<height>57</height>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" >
|
||||
|
@ -371,8 +371,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>422</width>
|
||||
<height>57</height>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -397,7 +397,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex" >
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="blankPage" >
|
||||
<property name="geometry" >
|
||||
|
@ -405,7 +405,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>446</width>
|
||||
<height>358</height>
|
||||
<height>367</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -415,7 +415,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>446</width>
|
||||
<height>358</height>
|
||||
<height>367</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5" >
|
||||
|
@ -440,7 +440,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>446</width>
|
||||
<height>358</height>
|
||||
<height>367</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" >
|
||||
|
@ -478,7 +478,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>446</width>
|
||||
<height>358</height>
|
||||
<height>367</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4" >
|
||||
|
@ -530,7 +530,7 @@
|
|||
<item>
|
||||
<widget class="QLabel" name="optionsLabel" >
|
||||
<property name="text" >
|
||||
<string>xxx</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="textInteractionFlags" >
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
|
@ -736,6 +736,12 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Review</string>
|
||||
</property>
|
||||
|
@ -743,10 +749,22 @@
|
|||
<iconset resource="../icons.qrc" >
|
||||
<normaloff>:/icons/player-time.png</normaloff>:/icons/player-time.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="default" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QPushButton" name="optionsButton" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>More>></string>
|
||||
</property>
|
||||
|
@ -763,6 +781,12 @@
|
|||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QPushButton" name="optionsHelpButton" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Help</string>
|
||||
</property>
|
||||
|
@ -813,7 +837,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>446</width>
|
||||
<height>358</height>
|
||||
<height>367</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8" >
|
||||
|
@ -878,7 +902,7 @@
|
|||
<item>
|
||||
<widget class="QLabel" name="congratsLabel" >
|
||||
<property name="text" >
|
||||
<string>xxx</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
|
@ -1174,7 +1198,6 @@
|
|||
<addaction name="actionReportbug" />
|
||||
<addaction name="actionForum" />
|
||||
<addaction name="actionReleaseNotes" />
|
||||
<addaction name="actionGetMoreDecks" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionDonate" />
|
||||
<addaction name="actionAbout" />
|
||||
|
@ -1208,10 +1231,23 @@
|
|||
<normaloff>:/icons/document-open-recent.png</normaloff>:/icons/document-open-recent.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuDownload" >
|
||||
<property name="title" >
|
||||
<string>&Download...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="../icons.qrc" >
|
||||
<normaloff>:/icons/document-open-remote.png</normaloff>:/icons/document-open-remote.png</iconset>
|
||||
</property>
|
||||
<addaction name="actionOpenOnline" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionDownloadSharedDeck" />
|
||||
<addaction name="actionDownloadSharedPlugin" />
|
||||
</widget>
|
||||
<addaction name="actionNew" />
|
||||
<addaction name="actionOpen" />
|
||||
<addaction name="menuOpenRecent" />
|
||||
<addaction name="actionOpenOnline" />
|
||||
<addaction name="menuDownload" />
|
||||
<addaction name="actionImport" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionSave" />
|
||||
|
@ -1288,7 +1324,6 @@
|
|||
<addaction name="actionDisableAllPlugins" />
|
||||
<addaction name="separator" />
|
||||
</widget>
|
||||
<addaction name="actionGetPlugins" />
|
||||
<addaction name="actionOpenPluginFolder" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="menuStartup" />
|
||||
|
@ -1313,7 +1348,7 @@
|
|||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>484</y>
|
||||
<y>493</y>
|
||||
<width>723</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
|
@ -1427,6 +1462,9 @@
|
|||
<property name="shortcut" >
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
<property name="shortcutContext" >
|
||||
<enum>Qt::ApplicationShortcut</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSyncdeck" >
|
||||
<property name="icon" >
|
||||
|
@ -1762,15 +1800,6 @@
|
|||
<string>Check Media Database...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenOnline" >
|
||||
<property name="icon" >
|
||||
<iconset resource="../icons.qrc" >
|
||||
<normaloff>:/icons/document-open-remote.png</normaloff>:/icons/document-open-remote.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Open On&line...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCram" >
|
||||
<property name="icon" >
|
||||
<iconset resource="../icons.qrc" >
|
||||
|
@ -1823,15 +1852,6 @@
|
|||
<string>Active &Tags...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGetMoreDecks" >
|
||||
<property name="icon" >
|
||||
<iconset resource="../icons.qrc" >
|
||||
<normaloff>:/icons/download.png</normaloff>:/icons/download.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Get More Decks...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEditCurrent" >
|
||||
<property name="icon" >
|
||||
<iconset resource="../icons.qrc" >
|
||||
|
@ -1861,6 +1881,9 @@
|
|||
<property name="text" >
|
||||
<string>&Delete Card</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+Del</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Delete_Fact" >
|
||||
<property name="text" >
|
||||
|
@ -1904,6 +1927,34 @@
|
|||
<string>&Record Noise Profile...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGetShared" >
|
||||
<property name="text" >
|
||||
<string>Get Shared...</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Open a pre-made deck or plugin</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShare" >
|
||||
<property name="text" >
|
||||
<string>Share...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenOnline" >
|
||||
<property name="text" >
|
||||
<string>Personal Deck</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDownloadSharedDeck" >
|
||||
<property name="text" >
|
||||
<string>Shared Deck</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDownloadSharedPlugin" >
|
||||
<property name="text" >
|
||||
<string>Shared Plugin</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>newPerDay</tabstop>
|
||||
|
@ -1921,11 +1972,11 @@
|
|||
<tabstop>help</tabstop>
|
||||
<tabstop>welcomeText</tabstop>
|
||||
<tabstop>showAnswerButton</tabstop>
|
||||
<tabstop>saveEditorButton</tabstop>
|
||||
<tabstop>easeButton2</tabstop>
|
||||
<tabstop>easeButton1</tabstop>
|
||||
<tabstop>easeButton2</tabstop>
|
||||
<tabstop>easeButton3</tabstop>
|
||||
<tabstop>easeButton4</tabstop>
|
||||
<tabstop>saveEditorButton</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../icons.qrc" />
|
||||
|
|
|
@ -97,6 +97,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showProgress" >
|
||||
<property name="text" >
|
||||
<string>Show information in status bar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer" >
|
||||
<property name="orientation" >
|
||||
|
@ -110,6 +117,16 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Some settings will take effect after you restart Anki.</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2" >
|
||||
|
@ -318,7 +335,7 @@
|
|||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string><h1>Advanced settings</h1>Some settings require a restart.</string>
|
||||
<string><h1>Advanced settings</h1></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -388,6 +405,16 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="text" >
|
||||
<string>Some settings will take effect after you restart Anki.</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
@ -411,6 +438,7 @@
|
|||
<tabstop>showDivider</tabstop>
|
||||
<tabstop>splitQA</tabstop>
|
||||
<tabstop>showEstimates</tabstop>
|
||||
<tabstop>showProgress</tabstop>
|
||||
<tabstop>saveWhenClosing</tabstop>
|
||||
<tabstop>saveAfterEvery</tabstop>
|
||||
<tabstop>saveAfterEveryNum</tabstop>
|
||||
|
@ -422,7 +450,9 @@
|
|||
<tabstop>syncOnClose</tabstop>
|
||||
<tabstop>alternativeTheme</tabstop>
|
||||
<tabstop>showTimer</tabstop>
|
||||
<tabstop>showTray</tabstop>
|
||||
<tabstop>showStudyOptions</tabstop>
|
||||
<tabstop>addZeroSpace</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
|
|
134
designer/share.ui
Normal file
134
designer/share.ui
Normal file
|
@ -0,0 +1,134 @@
|
|||
<ui version="4.0" >
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>517</width>
|
||||
<height>411</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Get Shared Decks/Plugins</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="searchLabel" >
|
||||
<property name="text" >
|
||||
<string>Search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="search" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="type" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTableWidget" name="table" />
|
||||
<widget class="QScrollArea" name="scrollArea" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy" >
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy" >
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>494</width>
|
||||
<height>54</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" >
|
||||
<item>
|
||||
<widget class="QLabel" name="bottomLabel" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<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,5 +1,6 @@
|
|||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>icons/anki-logo-thin.png</file>
|
||||
<file>icons/anki-logo.png</file>
|
||||
<file>icons/download.png</file>
|
||||
<file>icons/preferences-plugin.png</file>
|
||||
|
|
BIN
icons/anki-logo-thin.png
Normal file
BIN
icons/anki-logo-thin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 6.6 KiB |
|
@ -45,7 +45,6 @@ DATA_FILES = [
|
|||
'ankiqt/ankiqt/locale',
|
||||
'kakasi',
|
||||
#'audio',
|
||||
'libanki/samples',
|
||||
'ankiqt/imageformats',
|
||||
'libanki/anki/features/chinese/unihan.db',
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue