Skip to content

Commit

Permalink
add anki settings
Browse files Browse the repository at this point in the history
  • Loading branch information
mathewthe2 committed Jul 3, 2022
1 parent 781c73d commit c69b8e8
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 58 deletions.
48 changes: 10 additions & 38 deletions src/main/python/anki/anki_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ def request(action, params):
return {'action': action, 'params': params, 'version': 6}

class AnkiConnect():
def __init__(self, model='Basic', anki_models_path=''):
def __init__(self, deck=None, model=None, anki_settings=None):
self.port = 8765
self.model = model
self.anki_models_path = anki_models_path
self.deck = deck
self.anki_settings = anki_settings

def invoke(self, action, **params):
try:
Expand Down Expand Up @@ -80,43 +81,12 @@ def fetch_models(self):
logging.error(result)
return []

def get_user_models(self):
anki_models = []
with open(self.anki_models_path, 'r') as stream:
try:
ankiModels = yaml.safe_load(stream)
return ankiModels
except yaml.YAMLError as exc:
print(exc)
return anki_models

def update_user_model(self, model_name, field_value_map):
new_model = {
'model_name': model_name,
'field_value_map': field_value_map
}
user_models = self.get_user_models()
result = []
if user_models:
result = [user_model for user_model in user_models if user_model['model_name'] != model_name]
result.append(new_model)
self.save_user_models(result)

def save_user_models(self, anki_models):
with open(self.anki_models_path, 'w') as outfile:
yaml.dump(anki_models, outfile, sort_keys=False, default_flow_style=False)
return outfile.name

def get_field_value_map(self, model_name):
models = self.get_user_models()
field_value_map = {}
if models:
field_value_map = next((model['field_value_map'] for model in models if model['model_name'] == model_name), {})
return field_value_map

def set_model(self, model_name):
self.model = model_name

def set_deck(self, deck_name):
self.deck = deck_name

# def store_file(self):
# now = str(time.time())
# filename = '_{}.jpg'.format(now)
Expand All @@ -131,7 +101,9 @@ def set_model(self, model_name):
# return result

def create_anki_note(self, note_data):
field_value_map = self.get_field_value_map(self.model)
if not self.anki_settings:
return
field_value_map = self.anki_settings.get_field_value_map(self.model)
if not field_value_map:
return

Expand All @@ -145,7 +117,7 @@ def create_anki_note(self, note_data):
fields[field] = note_data[value.lower()]

note = {
"deckName": "Default",
"deckName": self.deck,
"modelName": self.model,
"fields": fields,
"tags": [
Expand Down
93 changes: 93 additions & 0 deletions src/main/python/anki/anki_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import yaml

class AnkiSettings():
def __init__(self, appctxt):
self.anki_models_path = appctxt.get_resource('anki/user_models.yaml')
self.anki_defaults_path = appctxt.get_resource('anki/user_defaults.yaml')
self.active_model = None
self.active_field_value_map = None

def get_default_deck_model(self):
with open(self.anki_defaults_path, 'r') as stream:
try:
result = yaml.safe_load(stream)
if result:
deck = result['deck_name'] if 'deck_name' in result else None
model = result['model_name'] if 'model_name' in result else None
return deck, model
else:
return None, None
except yaml.YAMLError as exc:
print(exc)
return result

def update_default_deck(self, deck):
old_deck, model = self.get_default_deck_model()
self.save_default_deck_model(deck, model)

def update_default_model(self, model):
deck, old_model = self.get_default_deck_model()
self.save_default_deck_model(deck, model)

def get_user_models(self):
anki_models = []
with open(self.anki_models_path, 'r') as stream:
try:
ankiModels = yaml.safe_load(stream)
return ankiModels
except yaml.YAMLError as exc:
print(exc)
return anki_models

def update_user_model(self, model_name, field_value_map):
new_model = {
'model_name': model_name,
'field_value_map': field_value_map
}
user_models = self.get_user_models()
result = []
if user_models:
result = [user_model for user_model in user_models if user_model['model_name'] != model_name]
result.append(new_model)
self.save_user_models(result)

# clear field value cache
if model_name == self.active_model:
self.active_model = None
self.active_field_value_map = None

def save_default_deck_model(self, deck, model):
result = {
'deck_name': deck,
'model_name': model
}
with open(self.anki_defaults_path, 'w') as outfile:
yaml.dump(result, outfile, sort_keys=False, default_flow_style=False)
return outfile.name

def save_user_models(self, anki_models):
with open(self.anki_models_path, 'w') as outfile:
yaml.dump(anki_models, outfile, sort_keys=False, default_flow_style=False)
return outfile.name

def get_field_value_map(self, model_name):
# use cache
if model_name == self.active_model:
return self.active_field_value_map
# fetch
models = self.get_user_models()
field_value_map = {}
if models:
field_value_map = next((model['field_value_map'] for model in models if model['model_name'] == model_name), {})
# cache results
self.active_model = model_name
self.active_field_value_map = field_value_map
# return result
return field_value_map

# if __name__ == '__main__':
# from fbs_runtime.application_context.PyQt5 import ApplicationContext
# appctxt = ApplicationContext()
# settings = AnkiSettings(appctxt)
# settings.update_default_deck('Default')
# settings.update_default_model('Mining')
10 changes: 6 additions & 4 deletions src/main/python/game2text/ocr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@
from util.image import IMAGE_TYPE
from enum import Enum

paddle_models_path = "models/paddleocr"

# Optical Character Recognition Engine
class OCR_Engine(Enum):
PADDLE_OCR = 1
SPACE_OCR = 2
GOOGLE_VISION = 3

ENGINE_PATHS = {
OCR_Engine.PADDLE_OCR: "models/paddleocr"
}

class OCR():
def __init__(self, path, engine=OCR_Engine.PADDLE_OCR):
def __init__(self, appctxt, engine=OCR_Engine.PADDLE_OCR):
self.engine = engine
self.manga_ocr_engine = None
self.paddle_engine = None
self.path = path
self.path = appctxt.get_resource(ENGINE_PATHS[engine])

# PIL image
def get_text(self, image_object):
Expand Down
69 changes: 53 additions & 16 deletions src/main/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
from fbs_runtime.application_context.PyQt5 import ApplicationContext
from PyQt5.QtWidgets import QMainWindow, QWidget
from anki.anki_connect import AnkiConnect
from anki.anki_settings import AnkiSettings
from call_handler import CallHandler
from screenshot.capture_window import CaptureWindow
from screenshot.capture_screen import CaptureScreen
from screenshot import Capture_Mode
from screenshot.hwnd_worker import HWNDWorker
from threading import Thread
from ui.main_ui import UIMain
from game2text.ocr import OCR, OCR_Engine, paddle_models_path
from game2text.ocr import OCR
from game2text import Game2Text

class Main(QMainWindow):
Expand All @@ -18,8 +19,9 @@ def __init__(self, appctxt):
self.setGeometry(500, 500, 400, 400)
self.setWindowTitle("Game2Text Lightning")
self.hwnd_worker = HWNDWorker(interval=1000)
self.anki_connect = AnkiConnect(anki_models_path = appctxt.get_resource('anki/user_models.yaml'))
self.ocr = OCR(appctxt.get_resource(paddle_models_path), OCR_Engine.PADDLE_OCR)
self.anki_settings = AnkiSettings(appctxt)
self.anki_connect = AnkiConnect(anki_settings=self.anki_settings)
self.ocr = OCR(appctxt)
self.call_handler = CallHandler(appctxt, self.anki_connect)
self.control_panel = ControlPanel(self)
self.setCentralWidget(self.control_panel)
Expand All @@ -41,7 +43,7 @@ def fetch_models(self):

def fetch_decks(self):
self.decks = self.anki_connect.fetch_anki_decks()
self.control_panel.update_deck_options(self.decks)
self.control_panel.set_decks(self.decks)

def capture(self):
return self.control_panel.get_capture()
Expand Down Expand Up @@ -73,38 +75,73 @@ def __init__(self, parent):

self.captureComboBox.currentIndexChanged.connect(self.select_capture_mode)
self.captureWindowComboBox.activated.connect(self.select_window)
self.modelComboBox.currentIndexChanged.connect(self.select_model)
self.deckComboBox.currentIndexChanged.connect(self.on_deck_change)
self.deckComboBox.activated.connect(self.select_deck)
self.modelComboBox.currentIndexChanged.connect(self.on_model_change)
self.modelComboBox.activated.connect(self.select_model)
self.selectRegionButton.clicked.connect(self.select_area)
self.start_button.clicked.connect(self.toggle_ocr)
self.reloadAnkiButton.clicked.connect(parent.load_anki)

# Anki Settings
self.anki_connect = parent.anki_connect
self.anki_settings = parent.anki_settings
self.decks = []
self.models = []
self.deck_combo_ready = False
self.model_combo_ready = False
self.selected_model = None
self.tableFields.on_change = self.on_anki_options_update

def select_model(self, index):
def on_deck_change(self, index):
if not self.deck_combo_ready:
deck, model = self.anki_settings.get_default_deck_model()
if deck and deck in self.decks:
index = self.decks.index(deck)
self.deckComboBox.setCurrentIndex(index)
self.select_deck(index, persist=False)
else:
self.deckComboBox.setCurrentIndex(-1)
self.deck_combo_ready = True

def select_deck(self, index, persist=False):
if self.decks:
deck = self.decks[index]
self.anki_connect.set_deck(deck)
if persist:
self.anki_settings.update_default_deck(deck)

def on_model_change(self, index):
if not self.model_combo_ready:
deck, model = self.anki_settings.get_default_deck_model()
model_names = [model.model_name for model in self.models]
if model and model in model_names:
index = model_names.index(model)
self.modelComboBox.setCurrentIndex(index)
self.select_model(index, persist=False)
else:
self.modelComboBox.setCurrentIndex(-1)
self.model_combo_ready = True

def select_model(self, index, persist=True):
if self.models:
self.selected_model = self.models[index]
fields = self.selected_model.fields
self.tableFields.setRowCount(len(fields))
field_value_map = self.anki_connect.get_field_value_map(self.selected_model.model_name)
field_value_map = self.anki_settings.get_field_value_map(self.selected_model.model_name)
self.tableFields.setData(fields, field_value_map)
self.tableFields.show()
self.anki_connect.set_model(self.selected_model.model_name)
if persist:
self.anki_settings.update_default_model(self.selected_model.model_name)

def update_model_options(self, options):
for option in options:
self.modelComboBox.addItem(option)

def update_deck_options(self, options):
for option in options:
self.deckComboBox.addItem(option)
def set_decks(self, decks):
self.decks = decks
self.deckComboBox.addItems(decks)

def set_models(self, models):
self.models = models
self.update_model_options([model.model_name for model in self.models])
self.modelComboBox.addItems([model.model_name for model in self.models])

def set_windows(self, windows):
self.windows = windows
Expand Down Expand Up @@ -155,7 +192,7 @@ def toggle_ocr(self):
self.running_ocr = not self.running_ocr

def on_anki_options_update(self, user_field_map):
self.anki_connect.update_user_model(self.selected_model.model_name, user_field_map)
self.anki_settings.update_user_model(self.selected_model.model_name, user_field_map)

def main():
appctxt = ApplicationContext()
Expand Down
Empty file.

0 comments on commit c69b8e8

Please sign in to comment.