Merge branch 'master' into install-local-addons
This commit is contained in:
commit
ff7b06fbda
@ -417,7 +417,7 @@ insert into cards values (?,?,?,?,?,?,0,0,?,0,0,0,0,0,0,0,0,"")""",
|
|||||||
# type 0 - when previewing in add dialog, only non-empty
|
# type 0 - when previewing in add dialog, only non-empty
|
||||||
# type 1 - when previewing edit, only existing
|
# type 1 - when previewing edit, only existing
|
||||||
# type 2 - when previewing in models dialog, all templates
|
# type 2 - when previewing in models dialog, all templates
|
||||||
def previewCards(self, note, type=0):
|
def previewCards(self, note, type=0, did=None):
|
||||||
if type == 0:
|
if type == 0:
|
||||||
cms = self.findTemplates(note)
|
cms = self.findTemplates(note)
|
||||||
elif type == 1:
|
elif type == 1:
|
||||||
@ -428,19 +428,23 @@ insert into cards values (?,?,?,?,?,?,0,0,?,0,0,0,0,0,0,0,0,"")""",
|
|||||||
return []
|
return []
|
||||||
cards = []
|
cards = []
|
||||||
for template in cms:
|
for template in cms:
|
||||||
cards.append(self._newCard(note, template, 1, flush=False))
|
cards.append(self._newCard(note, template, 1, flush=False, did=did))
|
||||||
return cards
|
return cards
|
||||||
|
|
||||||
def _newCard(self, note, template, due, flush=True):
|
def _newCard(self, note, template, due, flush=True, did=None):
|
||||||
"Create a new card."
|
"Create a new card."
|
||||||
card = anki.cards.Card(self)
|
card = anki.cards.Card(self)
|
||||||
card.nid = note.id
|
card.nid = note.id
|
||||||
card.ord = template['ord']
|
card.ord = template['ord']
|
||||||
# Use template did (deck override) if valid, otherwise model did
|
card.did = self.db.scalar("select did from cards where nid = ? and ord = ?", card.nid, card.ord)
|
||||||
if template['did'] and str(template['did']) in self.decks.decks:
|
# Use template did (deck override) if valid, otherwise did in argument, otherwise model did
|
||||||
card.did = template['did']
|
if not card.did:
|
||||||
else:
|
if template['did'] and str(template['did']) in self.decks.decks:
|
||||||
card.did = note.model()['did']
|
card.did = template['did']
|
||||||
|
elif did:
|
||||||
|
card.did = did
|
||||||
|
else:
|
||||||
|
card.did = note.model()['did']
|
||||||
# if invalid did, use default instead
|
# if invalid did, use default instead
|
||||||
deck = self.decks.get(card.did)
|
deck = self.decks.get(card.did)
|
||||||
if deck['dyn']:
|
if deck['dyn']:
|
||||||
|
@ -10,6 +10,7 @@ import requests
|
|||||||
from anki.db import DB, DBError
|
from anki.db import DB, DBError
|
||||||
from anki.utils import ids2str, intTime, json, platDesc, checksum, devMode
|
from anki.utils import ids2str, intTime, json, platDesc, checksum, devMode
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
|
from aqt.utils import versionWithBuild
|
||||||
from .hooks import runHook
|
from .hooks import runHook
|
||||||
import anki
|
import anki
|
||||||
from .lang import ngettext
|
from .lang import ngettext
|
||||||
@ -585,7 +586,7 @@ class RemoteServer(HttpSyncer):
|
|||||||
)
|
)
|
||||||
ret = self.req(
|
ret = self.req(
|
||||||
"meta", io.BytesIO(json.dumps(dict(
|
"meta", io.BytesIO(json.dumps(dict(
|
||||||
v=SYNC_VER, cv="ankidesktop,%s,%s"%(anki.version, platDesc()))).encode("utf8")),
|
v=SYNC_VER, cv="ankidesktop,%s,%s"%(versionWithBuild(), platDesc()))).encode("utf8")),
|
||||||
badAuthRaises=False)
|
badAuthRaises=False)
|
||||||
if not ret:
|
if not ret:
|
||||||
# invalid auth
|
# invalid auth
|
||||||
|
@ -117,6 +117,7 @@ system. It's free and open source.")
|
|||||||
"黃文龍",
|
"黃文龍",
|
||||||
"David Bailey",
|
"David Bailey",
|
||||||
"Arman High",
|
"Arman High",
|
||||||
|
"Arthur Milchior",
|
||||||
))
|
))
|
||||||
|
|
||||||
abouttext += '<p>' + _("Written by Damien Elmes, with patches, translation,\
|
abouttext += '<p>' + _("Written by Damien Elmes, with patches, translation,\
|
||||||
|
@ -316,7 +316,7 @@ Are you sure you want to continue?"""
|
|||||||
updated = []
|
updated = []
|
||||||
for dir, ts in mods:
|
for dir, ts in mods:
|
||||||
sid = str(dir)
|
sid = str(dir)
|
||||||
if self.addonMeta(sid).get("mod") < ts:
|
if self.addonMeta(sid).get("mod",0) < ts:
|
||||||
updated.append(sid)
|
updated.append(sid)
|
||||||
return updated
|
return updated
|
||||||
|
|
||||||
@ -426,6 +426,7 @@ class AddonsDialog(QDialog):
|
|||||||
self.form.addonList.currentRowChanged.connect(self._onAddonItemSelected)
|
self.form.addonList.currentRowChanged.connect(self._onAddonItemSelected)
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
self.redrawAddons()
|
self.redrawAddons()
|
||||||
|
restoreGeom(self, "addons")
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def dragEnterEvent(self, event):
|
def dragEnterEvent(self, event):
|
||||||
@ -446,6 +447,10 @@ class AddonsDialog(QDialog):
|
|||||||
paths.append(path)
|
paths.append(path)
|
||||||
self.onInstallFiles(paths)
|
self.onInstallFiles(paths)
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
saveGeom(self, "addons")
|
||||||
|
return QDialog.reject(self)
|
||||||
|
|
||||||
def redrawAddons(self):
|
def redrawAddons(self):
|
||||||
self.addons = [(self.annotatedName(d), d) for d in self.mgr.allAddons()]
|
self.addons = [(self.annotatedName(d), d) for d in self.mgr.allAddons()]
|
||||||
self.addons.sort()
|
self.addons.sort()
|
||||||
|
@ -61,7 +61,10 @@ class CardLayout(QDialog):
|
|||||||
self.setFocus()
|
self.setFocus()
|
||||||
|
|
||||||
def redraw(self):
|
def redraw(self):
|
||||||
self.cards = self.col.previewCards(self.note, 2)
|
did = None
|
||||||
|
if hasattr(self.parent,"deckChooser"):
|
||||||
|
did = self.parent.deckChooser.selectedId()
|
||||||
|
self.cards = self.col.previewCards(self.note, 2, did=did)
|
||||||
idx = self.ord
|
idx = self.ord
|
||||||
if idx >= len(self.cards):
|
if idx >= len(self.cards):
|
||||||
self.ord = len(self.cards) - 1
|
self.ord = len(self.cards) - 1
|
||||||
|
@ -30,8 +30,8 @@ class EditCurrent(QDialog):
|
|||||||
addHook("reset", self.onReset)
|
addHook("reset", self.onReset)
|
||||||
self.mw.requireReset()
|
self.mw.requireReset()
|
||||||
self.show()
|
self.show()
|
||||||
# reset focus after open
|
# reset focus after open, taking care not to retain webview
|
||||||
self.mw.progress.timer(100, self.editor.web.setFocus, False)
|
self.mw.progress.timer(100, lambda: self.editor.web.setFocus(), False)
|
||||||
|
|
||||||
def onReset(self):
|
def onReset(self):
|
||||||
# lazy approach for now: throw away edits
|
# lazy approach for now: throw away edits
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import sys, traceback
|
import sys, traceback
|
||||||
import html
|
import html
|
||||||
|
import re
|
||||||
|
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.utils import showText, showWarning
|
from aqt.utils import showText, showWarning
|
||||||
|
from aqt import mw
|
||||||
|
|
||||||
if not os.environ.get("DEBUG"):
|
if not os.environ.get("DEBUG"):
|
||||||
def excepthook(etype,val,tb):
|
def excepthook(etype,val,tb):
|
||||||
@ -121,16 +123,29 @@ report the issue on the <a href="https://help.ankiweb.net/discussions/add-ons/">
|
|||||||
add-ons section</a> of our support site.
|
add-ons section</a> of our support site.
|
||||||
|
|
||||||
<p>Debug info:</p>
|
<p>Debug info:</p>
|
||||||
""")
|
""")
|
||||||
if self.mw.addonManager.dirty:
|
if self.mw.addonManager.dirty:
|
||||||
txt = pluginText
|
txt = pluginText
|
||||||
|
error = self._supportText() + self._addonText(error) + "\n" + error
|
||||||
else:
|
else:
|
||||||
txt = stdText
|
txt = stdText
|
||||||
|
error = self._supportText() + "\n" + error
|
||||||
|
|
||||||
# show dialog
|
# show dialog
|
||||||
error = self._supportText() + "\n" + error
|
|
||||||
|
|
||||||
txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
|
txt = txt + "<div style='white-space: pre-wrap'>" + error + "</div>"
|
||||||
showText(txt, type="html")
|
showText(txt, type="html", copyBtn=True)
|
||||||
|
|
||||||
|
def _addonText(self, error):
|
||||||
|
matches = re.findall(r"addons21/(.*?)/", error)
|
||||||
|
if not matches:
|
||||||
|
return ""
|
||||||
|
# reverse to list most likely suspect first, dict to deduplicate:
|
||||||
|
addons = [mw.addonManager.addonName(i) for i in
|
||||||
|
dict.fromkeys(reversed(matches))]
|
||||||
|
txt = _("""Add-ons possibly involved: {}\n""")
|
||||||
|
# highlight importance of first add-on:
|
||||||
|
addons[0] = "<b>{}</b>".format(addons[0])
|
||||||
|
return txt.format(", ".join(addons))
|
||||||
|
|
||||||
def _supportText(self):
|
def _supportText(self):
|
||||||
import platform
|
import platform
|
||||||
|
19
aqt/main.py
19
aqt/main.py
@ -1171,11 +1171,19 @@ will be lost. Continue?"""))
|
|||||||
d.silentlyClose = True
|
d.silentlyClose = True
|
||||||
frm = aqt.forms.debug.Ui_Dialog()
|
frm = aqt.forms.debug.Ui_Dialog()
|
||||||
frm.setupUi(d)
|
frm.setupUi(d)
|
||||||
|
font = QFontDatabase.systemFont(QFontDatabase.FixedFont)
|
||||||
|
font.setPointSize(frm.text.font().pointSize() + 1)
|
||||||
|
frm.text.setFont(font)
|
||||||
|
frm.log.setFont(font)
|
||||||
s = self.debugDiagShort = QShortcut(QKeySequence("ctrl+return"), d)
|
s = self.debugDiagShort = QShortcut(QKeySequence("ctrl+return"), d)
|
||||||
s.activated.connect(lambda: self.onDebugRet(frm))
|
s.activated.connect(lambda: self.onDebugRet(frm))
|
||||||
s = self.debugDiagShort = QShortcut(
|
s = self.debugDiagShort = QShortcut(
|
||||||
QKeySequence("ctrl+shift+return"), d)
|
QKeySequence("ctrl+shift+return"), d)
|
||||||
s.activated.connect(lambda: self.onDebugPrint(frm))
|
s.activated.connect(lambda: self.onDebugPrint(frm))
|
||||||
|
s = self.debugDiagShort = QShortcut(QKeySequence("ctrl+l"), d)
|
||||||
|
s.activated.connect(frm.log.clear)
|
||||||
|
s = self.debugDiagShort = QShortcut(QKeySequence("ctrl+shift+l"), d)
|
||||||
|
s.activated.connect(frm.text.clear)
|
||||||
d.show()
|
d.show()
|
||||||
|
|
||||||
def _captureOutput(self, on):
|
def _captureOutput(self, on):
|
||||||
@ -1201,7 +1209,16 @@ will be lost. Continue?"""))
|
|||||||
return aqt.dialogs._dialogs['Browser'][1].card.__dict__
|
return aqt.dialogs._dialogs['Browser'][1].card.__dict__
|
||||||
|
|
||||||
def onDebugPrint(self, frm):
|
def onDebugPrint(self, frm):
|
||||||
frm.text.setPlainText("pp(%s)" % frm.text.toPlainText())
|
cursor = frm.text.textCursor()
|
||||||
|
position = cursor.position()
|
||||||
|
cursor.select(QTextCursor.LineUnderCursor)
|
||||||
|
line = cursor.selectedText()
|
||||||
|
pfx, sfx = "pp(", ")"
|
||||||
|
if not line.startswith(pfx):
|
||||||
|
line = "{}{}{}".format(pfx, line, sfx)
|
||||||
|
cursor.insertText(line)
|
||||||
|
cursor.setPosition(position + len(pfx))
|
||||||
|
frm.text.setTextCursor(cursor)
|
||||||
self.onDebugRet(frm)
|
self.onDebugRet(frm)
|
||||||
|
|
||||||
def onDebugRet(self, frm):
|
def onDebugRet(self, frm):
|
||||||
|
@ -10,6 +10,7 @@ import aqt
|
|||||||
from aqt.utils import openLink
|
from aqt.utils import openLink
|
||||||
from anki.utils import json, platDesc
|
from anki.utils import json, platDesc
|
||||||
from aqt.utils import showText
|
from aqt.utils import showText
|
||||||
|
from aqt.utils import versionWithBuild
|
||||||
|
|
||||||
class LatestVersionFinder(QThread):
|
class LatestVersionFinder(QThread):
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ class LatestVersionFinder(QThread):
|
|||||||
self.config = main.pm.meta
|
self.config = main.pm.meta
|
||||||
|
|
||||||
def _data(self):
|
def _data(self):
|
||||||
d = {"ver": aqt.appVersion,
|
d = {"ver": versionWithBuild(),
|
||||||
"os": platDesc(),
|
"os": platDesc(),
|
||||||
"id": self.config['id'],
|
"id": self.config['id'],
|
||||||
"lm": self.config['lastMsg'],
|
"lm": self.config['lastMsg'],
|
||||||
|
@ -50,7 +50,7 @@ def showInfo(text, parent=False, help="", type="info", title="Anki"):
|
|||||||
return mb.exec_()
|
return mb.exec_()
|
||||||
|
|
||||||
def showText(txt, parent=None, type="text", run=True, geomKey=None, \
|
def showText(txt, parent=None, type="text", run=True, geomKey=None, \
|
||||||
minWidth=500, minHeight=400, title="Anki"):
|
minWidth=500, minHeight=400, title="Anki", copyBtn=False):
|
||||||
if not parent:
|
if not parent:
|
||||||
parent = aqt.mw.app.activeWindow() or aqt.mw
|
parent = aqt.mw.app.activeWindow() or aqt.mw
|
||||||
diag = QDialog(parent)
|
diag = QDialog(parent)
|
||||||
@ -66,6 +66,12 @@ def showText(txt, parent=None, type="text", run=True, geomKey=None, \
|
|||||||
layout.addWidget(text)
|
layout.addWidget(text)
|
||||||
box = QDialogButtonBox(QDialogButtonBox.Close)
|
box = QDialogButtonBox(QDialogButtonBox.Close)
|
||||||
layout.addWidget(box)
|
layout.addWidget(box)
|
||||||
|
if copyBtn:
|
||||||
|
def onCopy():
|
||||||
|
QApplication.clipboard().setText(text.toPlainText())
|
||||||
|
btn = QPushButton(_("Copy to Clipboard"))
|
||||||
|
btn.clicked.connect(onCopy)
|
||||||
|
box.addButton(btn, QDialogButtonBox.ActionRole)
|
||||||
def onReject():
|
def onReject():
|
||||||
if geomKey:
|
if geomKey:
|
||||||
saveGeom(diag, geomKey)
|
saveGeom(diag, geomKey)
|
||||||
|
@ -41,11 +41,6 @@
|
|||||||
<verstretch>8</verstretch>
|
<verstretch>8</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Courier</family>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::ClickFocus</enum>
|
<enum>Qt::ClickFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
Loading…
Reference in New Issue
Block a user