Remove support for Anki 2.0 and Python 2
This commit is contained in:
parent
bb62a1e93f
commit
6118d01de1
@ -47,48 +47,24 @@ TICK_INTERVAL = 25
|
|||||||
URL_TIMEOUT = 10
|
URL_TIMEOUT = 10
|
||||||
URL_UPGRADE = 'https://raw.githubusercontent.com/FooSoft/anki-connect/master/AnkiConnect.py'
|
URL_UPGRADE = 'https://raw.githubusercontent.com/FooSoft/anki-connect/master/AnkiConnect.py'
|
||||||
|
|
||||||
ANKI21 = anki.version.startswith('2.1')
|
|
||||||
|
|
||||||
config = aqt.mw.addonManager.getConfig('AnkiConnect')
|
config = aqt.mw.addonManager.getConfig('AnkiConnect')
|
||||||
|
|
||||||
#
|
#
|
||||||
# Helpers
|
# Helpers
|
||||||
#
|
#
|
||||||
|
|
||||||
if sys.version_info[0] < 3:
|
from anki.sync import AnkiRequestsClient
|
||||||
import urllib2
|
def download(url):
|
||||||
def download(url):
|
contents = None
|
||||||
contents = None
|
client = AnkiRequestsClient()
|
||||||
resp = urllib2.urlopen(url, timeout=URL_TIMEOUT)
|
client.timeout = URL_TIMEOUT
|
||||||
if resp.code == 200:
|
resp = client.get(url)
|
||||||
contents = resp.read()
|
if resp.status_code == 200:
|
||||||
return (resp.code, contents)
|
contents = client.streamContent(resp)
|
||||||
|
return (resp.status_code, contents)
|
||||||
|
|
||||||
from PyQt4.QtCore import QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
from PyQt4.QtGui import QMessageBox
|
from PyQt5.QtWidgets import QMessageBox
|
||||||
else:
|
|
||||||
unicode = str
|
|
||||||
|
|
||||||
from anki.sync import AnkiRequestsClient
|
|
||||||
def download(url):
|
|
||||||
contents = None
|
|
||||||
client = AnkiRequestsClient()
|
|
||||||
client.timeout = URL_TIMEOUT
|
|
||||||
resp = client.get(url)
|
|
||||||
if resp.status_code == 200:
|
|
||||||
contents = client.streamContent(resp)
|
|
||||||
return (resp.status_code, contents)
|
|
||||||
|
|
||||||
from PyQt5.QtCore import QTimer
|
|
||||||
from PyQt5.QtWidgets import QMessageBox
|
|
||||||
|
|
||||||
|
|
||||||
def makeBytes(data):
|
|
||||||
return data.encode('utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
def makeStr(data):
|
|
||||||
return data.decode('utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
def api(*versions):
|
def api(*versions):
|
||||||
@ -162,17 +138,17 @@ class WebClient:
|
|||||||
|
|
||||||
|
|
||||||
def parseRequest(self, data):
|
def parseRequest(self, data):
|
||||||
parts = data.split(makeBytes('\r\n\r\n'), 1)
|
parts = data.split('\r\n\r\n'.encode('utf-8'), 1)
|
||||||
if len(parts) == 1:
|
if len(parts) == 1:
|
||||||
return None, 0
|
return None, 0
|
||||||
|
|
||||||
headers = {}
|
headers = {}
|
||||||
for line in parts[0].split(makeBytes('\r\n')):
|
for line in parts[0].split('\r\n'.encode('utf-8')):
|
||||||
pair = line.split(makeBytes(': '))
|
pair = line.split(': '.encode('utf-8'))
|
||||||
headers[pair[0].lower()] = pair[1] if len(pair) > 1 else None
|
headers[pair[0].lower()] = pair[1] if len(pair) > 1 else None
|
||||||
|
|
||||||
headerLength = len(parts[0]) + 4
|
headerLength = len(parts[0]) + 4
|
||||||
bodyLength = int(headers.get(makeBytes('content-length'), 0))
|
bodyLength = int(headers.get('content-length'.encode('utf-8'), 0))
|
||||||
totalLength = headerLength + bodyLength
|
totalLength = headerLength + bodyLength
|
||||||
|
|
||||||
if totalLength > len(data):
|
if totalLength > len(data):
|
||||||
@ -248,13 +224,13 @@ class WebServer:
|
|||||||
|
|
||||||
def handlerWrapper(self, req):
|
def handlerWrapper(self, req):
|
||||||
if len(req.body) == 0:
|
if len(req.body) == 0:
|
||||||
body = makeBytes('AnkiConnect v.{}'.format(API_VERSION))
|
body = 'AnkiConnect v.{}'.format(API_VERSION).encode('utf-8')
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
params = json.loads(makeStr(req.body))
|
params = json.loads(req.body.decode('utf-8'))
|
||||||
body = makeBytes(json.dumps(self.handler(params)))
|
body = json.dumps(self.handler(params)).encode('utf-8')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
body = makeBytes(json.dumps(None))
|
body = json.dumps(None).encode('utf-8')
|
||||||
|
|
||||||
resp = bytes()
|
resp = bytes()
|
||||||
|
|
||||||
@ -263,11 +239,11 @@ class WebServer:
|
|||||||
|
|
||||||
for key, value in headers:
|
for key, value in headers:
|
||||||
if value is None:
|
if value is None:
|
||||||
resp += makeBytes('{}\r\n'.format(key))
|
resp += '{}\r\n'.format(key).encode('utf-8')
|
||||||
else:
|
else:
|
||||||
resp += makeBytes('{}: {}\r\n'.format(key, value))
|
resp += '{}: {}\r\n'.format(key, value).encode('utf-8')
|
||||||
|
|
||||||
resp += makeBytes('\r\n')
|
resp += '\r\n'.encode('utf-8')
|
||||||
resp += body
|
resp += body
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
@ -498,7 +474,7 @@ class AnkiConnect:
|
|||||||
data = self.download(URL_UPGRADE)
|
data = self.download(URL_UPGRADE)
|
||||||
path = os.path.splitext(__file__)[0] + '.py'
|
path = os.path.splitext(__file__)[0] + '.py'
|
||||||
with open(path, 'w') as fp:
|
with open(path, 'w') as fp:
|
||||||
fp.write(makeStr(data))
|
fp.write(data.decode('utf-8'))
|
||||||
QMessageBox.information(
|
QMessageBox.information(
|
||||||
self.window(),
|
self.window(),
|
||||||
'AnkiConnect',
|
'AnkiConnect',
|
||||||
@ -1168,85 +1144,47 @@ class AnkiConnect:
|
|||||||
randomString = ''.join(choice(ascii_letters) for _ in range(10))
|
randomString = ''.join(choice(ascii_letters) for _ in range(10))
|
||||||
windowName = 'AddCardsAndClose' + randomString
|
windowName = 'AddCardsAndClose' + randomString
|
||||||
|
|
||||||
if ANKI21:
|
class AddCardsAndClose(aqt.addcards.AddCards):
|
||||||
class AddCardsAndClose(aqt.addcards.AddCards):
|
|
||||||
|
|
||||||
def __init__(self, mw):
|
def __init__(self, mw):
|
||||||
# the window must only reset if
|
# the window must only reset if
|
||||||
# * function `onModelChange` has been called prior
|
# * function `onModelChange` has been called prior
|
||||||
# * window was newly opened
|
# * window was newly opened
|
||||||
|
|
||||||
|
self.modelHasChanged = True
|
||||||
|
super().__init__(mw)
|
||||||
|
|
||||||
|
self.addButton.setText("Add and Close")
|
||||||
|
self.addButton.setShortcut(aqt.qt.QKeySequence("Ctrl+Return"))
|
||||||
|
|
||||||
|
def _addCards(self):
|
||||||
|
super()._addCards()
|
||||||
|
|
||||||
|
# if adding was successful it must mean it was added to the history of the window
|
||||||
|
if len(self.history):
|
||||||
|
self.reject()
|
||||||
|
|
||||||
|
def onModelChange(self):
|
||||||
|
if self.isActiveWindow():
|
||||||
|
super().onModelChange()
|
||||||
self.modelHasChanged = True
|
self.modelHasChanged = True
|
||||||
super().__init__(mw)
|
|
||||||
|
|
||||||
self.addButton.setText("Add and Close")
|
def onReset(self, model=None, keep=False):
|
||||||
self.addButton.setShortcut(aqt.qt.QKeySequence("Ctrl+Return"))
|
if self.isActiveWindow() or self.modelHasChanged:
|
||||||
|
super().onReset(model, keep)
|
||||||
|
self.modelHasChanged = False
|
||||||
|
|
||||||
def _addCards(self):
|
else:
|
||||||
super()._addCards()
|
# modelchoosers text is changed by a reset hook
|
||||||
|
# therefore we need to change it back manually
|
||||||
|
self.modelChooser.models.setText(self.editor.note.model()['name'])
|
||||||
|
self.modelHasChanged = False
|
||||||
|
|
||||||
# if adding was successful it must mean it was added to the history of the window
|
def _reject(self):
|
||||||
if len(self.history):
|
savedMarkClosed = aqt.dialogs.markClosed
|
||||||
self.reject()
|
aqt.dialogs.markClosed = lambda _: savedMarkClosed(windowName)
|
||||||
|
super()._reject()
|
||||||
def onModelChange(self):
|
aqt.dialogs.markClosed = savedMarkClosed
|
||||||
if self.isActiveWindow():
|
|
||||||
super().onModelChange()
|
|
||||||
self.modelHasChanged = True
|
|
||||||
|
|
||||||
def onReset(self, model=None, keep=False):
|
|
||||||
if self.isActiveWindow() or self.modelHasChanged:
|
|
||||||
super().onReset(model, keep)
|
|
||||||
self.modelHasChanged = False
|
|
||||||
|
|
||||||
else:
|
|
||||||
# modelchoosers text is changed by a reset hook
|
|
||||||
# therefore we need to change it back manually
|
|
||||||
self.modelChooser.models.setText(self.editor.note.model()['name'])
|
|
||||||
self.modelHasChanged = False
|
|
||||||
|
|
||||||
def _reject(self):
|
|
||||||
savedMarkClosed = aqt.dialogs.markClosed
|
|
||||||
aqt.dialogs.markClosed = lambda _: savedMarkClosed(windowName)
|
|
||||||
super()._reject()
|
|
||||||
aqt.dialogs.markClosed = savedMarkClosed
|
|
||||||
|
|
||||||
else:
|
|
||||||
class AddCardsAndClose(aqt.addcards.AddCards):
|
|
||||||
|
|
||||||
def __init__(self, mw):
|
|
||||||
self.modelHasChanged = True
|
|
||||||
super(AddCardsAndClose, self).__init__(mw)
|
|
||||||
|
|
||||||
self.addButton.setText("Add and Close")
|
|
||||||
self.addButton.setShortcut(aqt.qt.QKeySequence("Ctrl+Return"))
|
|
||||||
|
|
||||||
def addCards(self):
|
|
||||||
super(AddCardsAndClose, self).addCards()
|
|
||||||
|
|
||||||
# if adding was successful it must mean it was added to the history of the window
|
|
||||||
if len(self.history):
|
|
||||||
self.reject()
|
|
||||||
|
|
||||||
def onModelChange(self):
|
|
||||||
if self.isActiveWindow():
|
|
||||||
super(AddCardsAndClose, self).onModelChange()
|
|
||||||
self.modelHasChanged = True
|
|
||||||
|
|
||||||
def onReset(self, model=None, keep=False):
|
|
||||||
if self.isActiveWindow() or self.modelHasChanged:
|
|
||||||
super(AddCardsAndClose, self).onReset(model, keep)
|
|
||||||
self.modelHasChanged = False
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.modelChooser.models.setText(self.editor.note.model()['name'])
|
|
||||||
self.modelHasChanged = False
|
|
||||||
|
|
||||||
def reject(self):
|
|
||||||
savedClose = aqt.dialogs.close
|
|
||||||
aqt.dialogs.close = lambda _: savedClose(windowName)
|
|
||||||
super(AddCardsAndClose, self).reject()
|
|
||||||
aqt.dialogs.close = savedClose
|
|
||||||
|
|
||||||
aqt.dialogs._dialogs[windowName] = [AddCardsAndClose, None]
|
aqt.dialogs._dialogs[windowName] = [AddCardsAndClose, None]
|
||||||
addCards = aqt.dialogs.open(windowName, self.window())
|
addCards = aqt.dialogs.open(windowName, self.window())
|
||||||
@ -1270,8 +1208,7 @@ class AnkiConnect:
|
|||||||
# if Anki does not Focus, the window will not notice that the
|
# if Anki does not Focus, the window will not notice that the
|
||||||
# fields are actually filled
|
# fields are actually filled
|
||||||
aqt.dialogs.open(windowName, self.window())
|
aqt.dialogs.open(windowName, self.window())
|
||||||
if ANKI21:
|
addCards.setAndFocusNote(editor.note)
|
||||||
addCards.setAndFocusNote(editor.note)
|
|
||||||
|
|
||||||
elif note is not None:
|
elif note is not None:
|
||||||
currentWindow = aqt.dialogs._dialogs['AddCards'][1]
|
currentWindow = aqt.dialogs._dialogs['AddCards'][1]
|
||||||
@ -1300,15 +1237,10 @@ class AnkiConnect:
|
|||||||
addCards.activateWindow()
|
addCards.activateWindow()
|
||||||
|
|
||||||
aqt.dialogs.open('AddCards', self.window())
|
aqt.dialogs.open('AddCards', self.window())
|
||||||
if ANKI21:
|
addCards.setAndFocusNote(editor.note)
|
||||||
addCards.setAndFocusNote(editor.note)
|
|
||||||
|
|
||||||
if currentWindow is not None:
|
if currentWindow is not None:
|
||||||
if ANKI21:
|
currentWindow.closeWithCallback(openNewWindow)
|
||||||
currentWindow.closeWithCallback(openNewWindow)
|
|
||||||
else:
|
|
||||||
currentWindow.reject()
|
|
||||||
openNewWindow()
|
|
||||||
else:
|
else:
|
||||||
openNewWindow()
|
openNewWindow()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user