Work on remote API
This commit is contained in:
parent
820348f7c2
commit
6e7938a93c
@ -29,14 +29,14 @@ class AjaxRequest:
|
|||||||
|
|
||||||
|
|
||||||
class AjaxClient:
|
class AjaxClient:
|
||||||
def __init__(self, sock, callback):
|
def __init__(self, sock, handler):
|
||||||
self.sock = sock
|
self.sock = sock
|
||||||
self.callback = callback
|
self.handler = handler
|
||||||
self.readBuff = ''
|
|
||||||
self.readBuff = ''
|
self.readBuff = ''
|
||||||
|
self.writeBuff = ''
|
||||||
|
|
||||||
|
|
||||||
def advance(self, recvSize=1):
|
def advance(self, recvSize=1024):
|
||||||
if self.sock is None:
|
if self.sock is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -53,12 +53,12 @@ class AjaxClient:
|
|||||||
req, length = self.parseRequest(self.readBuff)
|
req, length = self.parseRequest(self.readBuff)
|
||||||
if req is not None:
|
if req is not None:
|
||||||
self.readBuff = self.readBuff[length:]
|
self.readBuff = self.readBuff[length:]
|
||||||
self.readBuff += self.callback(req)
|
self.writeBuff += self.handler(req)
|
||||||
|
|
||||||
if wlist and self.readBuff:
|
if wlist and self.writeBuff:
|
||||||
length = self.sock.send(self.readBuff)
|
length = self.sock.send(self.writeBuff)
|
||||||
self.readBuff = self.readBuff[length:]
|
self.writeBuff = self.writeBuff[length:]
|
||||||
if not self.readBuff:
|
if not self.writeBuff:
|
||||||
self.close()
|
self.close()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ class AjaxClient:
|
|||||||
self.sock = None
|
self.sock = None
|
||||||
|
|
||||||
self.readBuff = ''
|
self.readBuff = ''
|
||||||
self.readBuff = ''
|
self.writeBuff = ''
|
||||||
|
|
||||||
|
|
||||||
def parseRequest(self, data):
|
def parseRequest(self, data):
|
||||||
@ -96,8 +96,8 @@ class AjaxClient:
|
|||||||
|
|
||||||
|
|
||||||
class AjaxServer:
|
class AjaxServer:
|
||||||
def __init__(self, callback):
|
def __init__(self, handler):
|
||||||
self.callback = callback
|
self.handler = handler
|
||||||
self.clients = []
|
self.clients = []
|
||||||
self.sock = None
|
self.sock = None
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ class AjaxServer:
|
|||||||
clientSock = self.sock.accept()[0]
|
clientSock = self.sock.accept()[0]
|
||||||
if clientSock is not None:
|
if clientSock is not None:
|
||||||
clientSock.setblocking(False)
|
clientSock.setblocking(False)
|
||||||
self.clients.append(AjaxClient(clientSock, self.callbackWrapper))
|
self.clients.append(AjaxClient(clientSock, self.handlerWrapper))
|
||||||
|
|
||||||
|
|
||||||
def advanceClients(self):
|
def advanceClients(self):
|
||||||
@ -133,8 +133,8 @@ class AjaxServer:
|
|||||||
self.sock.listen(backlog)
|
self.sock.listen(backlog)
|
||||||
|
|
||||||
|
|
||||||
def callbackWrapper(self, req):
|
def handlerWrapper(self, req):
|
||||||
body = json.dumps(self.callback(json.loads(req.body)))
|
body = json.dumps(self.handler(json.loads(req.body)))
|
||||||
resp = ''
|
resp = ''
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
|
@ -21,7 +21,7 @@ import aqt
|
|||||||
|
|
||||||
|
|
||||||
class Anki:
|
class Anki:
|
||||||
def addNote(self, deckName, modelName, fields, tags=list()):
|
def addNote(self, deckName, modelName, fields, tags=[]):
|
||||||
note = self.createNote(deckName, modelName, fields, tags)
|
note = self.createNote(deckName, modelName, fields, tags)
|
||||||
if note is not None:
|
if note is not None:
|
||||||
collection = self.collection()
|
collection = self.collection()
|
||||||
@ -35,7 +35,7 @@ class Anki:
|
|||||||
return bool(self.createNote(deckName, modelName, fields))
|
return bool(self.createNote(deckName, modelName, fields))
|
||||||
|
|
||||||
|
|
||||||
def createNote(self, deckName, modelName, fields, tags=list()):
|
def createNote(self, deckName, modelName, fields, tags=[]):
|
||||||
model = self.models().byName(modelName)
|
model = self.models().byName(modelName)
|
||||||
if model is None:
|
if model is None:
|
||||||
return None
|
return None
|
||||||
|
@ -65,15 +65,15 @@ class DialogPreferences(QtGui.QDialog, gen.preferences_ui.Ui_DialogPreferences):
|
|||||||
|
|
||||||
|
|
||||||
def dialogToData(self):
|
def dialogToData(self):
|
||||||
self.preferences['checkForUpdates'] = self.checkCheckForUpdates.isChecked()
|
self.preferences['checkForUpdates'] = self.checkCheckForUpdates.isChecked()
|
||||||
self.preferences['rememberTextContent'] = self.checkRememberTextContent.isChecked()
|
self.preferences['rememberTextContent'] = self.checkRememberTextContent.isChecked()
|
||||||
self.preferences['allowEditing'] = self.checkAllowEditing.isChecked()
|
self.preferences['allowEditing'] = self.checkAllowEditing.isChecked()
|
||||||
self.preferences['loadRecentFile'] = self.checkLoadRecentFile.isChecked()
|
self.preferences['loadRecentFile'] = self.checkLoadRecentFile.isChecked()
|
||||||
self.preferences['maxResults'] = self.spinMaxResults.value()
|
self.preferences['maxResults'] = self.spinMaxResults.value()
|
||||||
self.preferences['scanLength'] = self.spinScanLength.value()
|
self.preferences['scanLength'] = self.spinScanLength.value()
|
||||||
self.preferences['stripReadings'] = self.checkStripReadings.isChecked()
|
self.preferences['stripReadings'] = self.checkStripReadings.isChecked()
|
||||||
self.preferences['enableRemoteApi'] = self.checkEnableRemoteApi.isChecked()
|
self.preferences['enableRemoteApi'] = self.checkEnableRemoteApi.isChecked()
|
||||||
self.preferences['firstRun'] = False
|
self.preferences['firstRun'] = False
|
||||||
|
|
||||||
if self.anki is not None:
|
if self.anki is not None:
|
||||||
self.dialogToProfile()
|
self.dialogToProfile()
|
||||||
|
@ -30,30 +30,31 @@ import updates
|
|||||||
class MainWindowReader(QtGui.QMainWindow, gen.reader_ui.Ui_MainWindowReader):
|
class MainWindowReader(QtGui.QMainWindow, gen.reader_ui.Ui_MainWindowReader):
|
||||||
class State:
|
class State:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.filename = unicode()
|
self.filename = unicode()
|
||||||
self.kanjiDefs = list()
|
self.kanjiDefs = []
|
||||||
self.scanPosition = 0
|
self.scanPosition = 0
|
||||||
self.searchPosition = 0
|
self.searchPosition = 0
|
||||||
self.searchText = unicode()
|
self.searchText = unicode()
|
||||||
self.vocabDefs = list()
|
self.vocabDefs = []
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, parent, preferences, language, filename=None, anki=None, closed=None):
|
def __init__(self, parent, preferences, language, filename=None, anki=None, remoteApi=None, closed=None):
|
||||||
QtGui.QMainWindow.__init__(self, parent)
|
QtGui.QMainWindow.__init__(self, parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.textContent.mouseMoveEvent = self.onContentMouseMove
|
self.textContent.mouseMoveEvent = self.onContentMouseMove
|
||||||
self.textContent.mousePressEvent = self.onContentMousePress
|
self.textContent.mousePressEvent = self.onContentMousePress
|
||||||
self.dockAnki.setEnabled(anki is not None)
|
self.dockAnki.setEnabled(anki is not None)
|
||||||
|
|
||||||
self.facts = list()
|
self.facts = []
|
||||||
self.anki = anki
|
self.anki = anki
|
||||||
self.closed = closed
|
self.remoteApi = remoteApi
|
||||||
self.language = language
|
self.closed = closed
|
||||||
|
self.language = language
|
||||||
self.preferences = preferences
|
self.preferences = preferences
|
||||||
self.state = self.State()
|
self.state = self.State()
|
||||||
self.updates = updates.UpdateFinder()
|
self.updates = updates.UpdateFinder()
|
||||||
self.zoom = 0
|
self.zoom = 0
|
||||||
|
|
||||||
self.applyPreferences()
|
self.applyPreferences()
|
||||||
self.updateRecentFiles()
|
self.updateRecentFiles()
|
||||||
@ -103,6 +104,9 @@ class MainWindowReader(QtGui.QMainWindow, gen.reader_ui.Ui_MainWindowReader):
|
|||||||
if self.preferences['windowSize'] is not None:
|
if self.preferences['windowSize'] is not None:
|
||||||
self.resize(QtCore.QSize(*self.preferences['windowSize']))
|
self.resize(QtCore.QSize(*self.preferences['windowSize']))
|
||||||
|
|
||||||
|
if self.remoteApi is not None:
|
||||||
|
self.remoteApi.enable(self.preferences['enableRemoteApi'])
|
||||||
|
|
||||||
self.comboTags.addItems(self.preferences['tags'])
|
self.comboTags.addItems(self.preferences['tags'])
|
||||||
self.applyPreferencesContent()
|
self.applyPreferencesContent()
|
||||||
|
|
||||||
@ -587,8 +591,8 @@ class MainWindowReader(QtGui.QMainWindow, gen.reader_ui.Ui_MainWindowReader):
|
|||||||
|
|
||||||
|
|
||||||
def importWordList(self, words):
|
def importWordList(self, words):
|
||||||
self.state.vocabDefs = list()
|
self.state.vocabDefs = []
|
||||||
self.state.kanjiDefs = list()
|
self.state.kanjiDefs = []
|
||||||
|
|
||||||
for word in words:
|
for word in words:
|
||||||
if self.dockVocab.isVisible():
|
if self.dockVocab.isVisible():
|
||||||
|
80
yomi_base/remote_api.py
Normal file
80
yomi_base/remote_api.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (C) 2016 Alex Yatskov <alex@foosoft.net>
|
||||||
|
# Author: Alex Yatskov <alex@foosoft.net>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt4 import QtCore
|
||||||
|
from ajax import AjaxServer
|
||||||
|
import constants
|
||||||
|
|
||||||
|
|
||||||
|
class RemoteApi:
|
||||||
|
def __init__(self, anki, enabled, interval=50):
|
||||||
|
self.server = None
|
||||||
|
self.enable(enabled)
|
||||||
|
self.timer = QtCore.QTimer()
|
||||||
|
self.timer.timeout.connect(self.advance)
|
||||||
|
self.timer.start(interval)
|
||||||
|
|
||||||
|
self.handlers = {
|
||||||
|
'addNote': self.apiAddNote,
|
||||||
|
'apiCanAddNote': self.apiCanAddNote,
|
||||||
|
'getVersion': self.apiGetVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def enable(self, enabled=True):
|
||||||
|
if self.server is None and enabled:
|
||||||
|
self.server = AjaxServer(self.handler)
|
||||||
|
self.server.listen()
|
||||||
|
elif self.server is not None and not enabled:
|
||||||
|
self.server.close()
|
||||||
|
self.server = None
|
||||||
|
|
||||||
|
|
||||||
|
def advance(self):
|
||||||
|
if self.server is not None:
|
||||||
|
self.server.advance()
|
||||||
|
|
||||||
|
|
||||||
|
def handler(self, request):
|
||||||
|
self.handlers.get(request.get('action'), self.apiInvalidRequest)(request.get('data'))
|
||||||
|
|
||||||
|
|
||||||
|
def apiAddNote(self, data):
|
||||||
|
deckName = data.get('deckName', unicode())
|
||||||
|
modelName = data.get('modelName', unicode())
|
||||||
|
fields = data.get('fields', {})
|
||||||
|
tags = data.get('tags', [])
|
||||||
|
|
||||||
|
return self.anki.addNote(deckName, modelName, fields, tags)
|
||||||
|
|
||||||
|
|
||||||
|
def apiCanAddNote(self, data):
|
||||||
|
deckName = data.get('deckName', unicode())
|
||||||
|
modelName = data.get('modelName', unicode())
|
||||||
|
fields = data.get('fields', {})
|
||||||
|
|
||||||
|
return self.anki.canAddNote(deckName, modelName, fields)
|
||||||
|
|
||||||
|
|
||||||
|
def apiGetVersion(self, data):
|
||||||
|
return {'version': constants.c['appVersion']}
|
||||||
|
|
||||||
|
|
||||||
|
def apiInvalidRequest(self, data):
|
||||||
|
return {}
|
@ -17,10 +17,11 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui
|
||||||
from yomi_base import japanese
|
from yomi_base import japanese
|
||||||
from yomi_base.preference_data import Preferences
|
from yomi_base.preference_data import Preferences
|
||||||
from yomi_base.reader import MainWindowReader
|
from yomi_base.reader import MainWindowReader
|
||||||
|
from yomi_base.remote_api import RemoteApi
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ class YomichanPlugin(Yomichan):
|
|||||||
self.window = None
|
self.window = None
|
||||||
self.anki = anki_bridge.Anki()
|
self.anki = anki_bridge.Anki()
|
||||||
self.parent = self.anki.window()
|
self.parent = self.anki.window()
|
||||||
|
self.remoteApi = RemoteApi(self.anki, self.preferences['enableRemoteApi'])
|
||||||
|
|
||||||
separator = QtGui.QAction(self.parent)
|
separator = QtGui.QAction(self.parent)
|
||||||
separator.setSeparator(True)
|
separator.setSeparator(True)
|
||||||
@ -62,6 +64,7 @@ class YomichanPlugin(Yomichan):
|
|||||||
self.language,
|
self.language,
|
||||||
None,
|
None,
|
||||||
self.anki,
|
self.anki,
|
||||||
|
self.remoteApi,
|
||||||
self.onWindowClose
|
self.onWindowClose
|
||||||
)
|
)
|
||||||
self.window.show()
|
self.window.show()
|
||||||
|
Loading…
Reference in New Issue
Block a user