Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Personal Fields + Import Config Window #72

Merged
merged 35 commits into from
Jul 5, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
164f692
Merge pull request #3 from Stvad/master
ohare93 Nov 11, 2019
0b22491
Merge pull request #4 from Stvad/master
ohare93 Nov 13, 2019
4344a33
Personal Fields - First proof of concept
ohare93 Nov 18, 2019
4a2f7b4
Added "newlyAdded" to the export_filter_set for Notes
ohare93 Apr 15, 2020
79c0226
Start of Import UI Popup
ohare93 May 10, 2020
9b94127
Merge branch 'master' into PersonalFields
ohare93 May 10, 2020
5065d44
Working GUI Passthrough; In-progress Usage in system
ohare93 May 22, 2020
06b26cc
Hotfix Import on Latest
ohare93 May 24, 2020
67f13bc
Personal Field Selection Working fully;
ohare93 May 24, 2020
96a14fc
Revert Hotfix
ohare93 Jun 1, 2020
c7d9f35
Minor Changes
ohare93 Jun 1, 2020
2d859a6
Personal Fields - First proof of concept
ohare93 Nov 18, 2019
76603ae
Start of Import UI Popup
ohare93 May 10, 2020
d3d25c6
Working GUI Passthrough; In-progress Usage in system
ohare93 May 22, 2020
a359729
Hotfix Import on Latest
ohare93 May 24, 2020
9d574aa
Personal Field Selection Working fully;
ohare93 May 24, 2020
ac2c312
Revert Hotfix
ohare93 Jun 1, 2020
a39dcb4
Minor Changes
ohare93 Jun 1, 2020
8a69180
Fix Config.ui file
ohare93 Jun 1, 2020
555f887
Merge branch 'PersonalFields' of github.com:ll-in-anki/CrowdAnki into…
ohare93 Jun 1, 2020
4878140
Add ImportConfig to ExportFilter
ohare93 Jun 1, 2020
1547104
Merge Upstream/Master
ohare93 Jun 1, 2020
7b23d9e
Import_Config as Yaml file;
ohare93 Jun 1, 2020
66b8cdf
Minor changes
ohare93 Jun 20, 2020
a0d9878
Default True for Import Deck Parts
ohare93 Jun 20, 2020
fb93158
Structural Changes and Fixes
ohare93 Jun 21, 2020
6994cba
Use Notes and Note Models Toggles
ohare93 Jun 21, 2020
2f5db24
Deck Parts Counter
ohare93 Jun 21, 2020
008cbcf
Improved Counter to Show 0s
ohare93 Jun 21, 2020
2e97a78
Tidy up and Revisions
ohare93 Jul 4, 2020
4627c0c
Remove Deck Header option
ohare93 Jul 5, 2020
6586d1e
Simplify Deck save_to_collection
ohare93 Jul 5, 2020
957ad7c
Manager -> Maintainer
ohare93 Jul 5, 2020
9c172f8
Deck Part Checkboxes Separate Function
ohare93 Jul 5, 2020
92a09d0
Remove Note Model option, for new PR
ohare93 Jul 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions crowd_anki/importer/anki_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ def load_deck(self, directory_path) -> bool:
"""
deck_json = self.read_deck(self.get_deck_path(directory_path))

import_config, ui_accepted = self.read_import_config(directory_path, deck_json)
if not ui_accepted:
import_config = self.read_import_config(directory_path, deck_json)
if import_config is None:
return False

if aqt.mw:
Expand Down Expand Up @@ -90,9 +90,9 @@ def read_import_config(directory_path, deck_json):

import_dialog = ImportDialog(deck_json, import_dict)
if import_dialog.exec_() == QDialog.Rejected:
return None, False
return None

return import_dialog.final_import_config, True
return import_dialog.final_import_config

@staticmethod
def import_deck_from_path(collection, directory_path):
Expand Down
76 changes: 28 additions & 48 deletions crowd_anki/importer/import_dialog.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from collections import namedtuple
from collections import namedtuple, defaultdict
from dataclasses import dataclass, field
from enum import Enum

Expand All @@ -20,24 +20,16 @@ class ConfigEntry:

@dataclass
class PersonalFieldsHolder:
personal_fields: Dict[str, List[str]] = field(init=False, default_factory=lambda: dict())

def has_pf(self, field_name, *keys):
def _check_pfs(key):
if key in self.personal_fields:
if field_name in self.personal_fields[key]:
return True
return False
return any(_check_pfs(key) for key in keys)

def add_field(self, model_name, model_id, field_name):
def _add(key):
if key not in self.personal_fields:
self.personal_fields.setdefault(key, [field_name])
else:
self.personal_fields[key].append(field_name)
_add(model_id)
_add(model_name)
personal_fields: defaultdict = field(init=False, default_factory=lambda: defaultdict(list))

def is_personal_field(self, model_name, field_name):
if model_name in self.personal_fields:
if field_name in self.personal_fields[model_name]:
return True
return False

def add_field(self, model_name, field_name):
self.personal_fields[model_name].append(field_name)


@dataclass
Expand All @@ -58,9 +50,9 @@ def from_dict(cls, settings_dict: dict) -> 'ImportDefaults':
return new_cls

def _setup_personal_fields(self, settings_dict):
models = settings_dict.get("note_models", [])
for model_name_or_id in models:
self.personal_fields.setdefault(model_name_or_id, models[model_name_or_id].get("personal_fields", []))
models = settings_dict.get("note_models", dict())
for model_name, keys in models.items():
self.personal_fields.setdefault(model_name, keys.get("personal_fields", []))


@dataclass
Expand All @@ -74,11 +66,6 @@ class ImportConfig(PersonalFieldsHolder):

ignore_deck_movement: bool

def __repr__(self):
return f"ImportConfig({self.personal_fields!r}, {self.add_tag_to_cards!r}, " \
f"{self.use_header!r}, {self.use_notes!r}, {self.use_note_models!r}, {self.use_media!r} " \
f"{self.ignore_deck_movement!r})"


class ImportDialog(QDialog):
def __init__(self, deck_json, config, parent=None):
Expand All @@ -89,6 +76,7 @@ def __init__(self, deck_json, config, parent=None):
self.userConfig = ConfigSettings.get_instance()
self.deck_json = deck_json
self.import_defaults = ImportDefaults.from_dict(config)
self.personal_field_ui_dict = defaultdict(dict)
self.ui_initial_setup()

self.final_import_config: ImportConfig = None
Expand All @@ -97,9 +85,6 @@ def accept(self):
self.read_import_config()
super().accept()

def reject(self):
super().reject()

def ui_initial_setup(self):
self.setup_personal_field_selection()
self.setup_misc()
Expand All @@ -116,11 +101,12 @@ def add_header(name):
heading_ui.setFont(heading_font)
self.form.list_personal_fields.addItem(heading_ui)

def add_field(name, is_personal):
def add_field(name, is_personal) -> QListWidgetItem:
field_ui = QListWidgetItem(name)
field_ui.setCheckState(Qt.Checked if is_personal else Qt.Unchecked)
field_ui.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
self.form.list_personal_fields.addItem(field_ui)
return field_ui

for model in self.deck_json["note_models"]:
model_name = model["name"]
Expand All @@ -129,7 +115,8 @@ def add_field(name, is_personal):

for field in model["flds"]:
field_name = field["name"]
add_field(field_name, self.import_defaults.has_pf(field_name, model_name, model_id))
field_ui = add_field(field_name, self.import_defaults.is_personal_field(model_name, field_name))
self.personal_field_ui_dict[model_name].setdefault(field_name, field_ui)

def setup_misc(self):
self.form.import_message_textbox.setText(self.import_defaults.import_message)
Expand All @@ -149,10 +136,12 @@ def set_checked_and_text(checkbox, text, count, checked: bool = True):
text = f"{text}: {'{:,}'.format(count)}"
checkbox.setText(text)

set_checked_and_text(self.form.cb_headers, "Headers", None)
self.form.cb_headers.setVisible(False) # TODO: implement header selection functionality. Disabled for now
# set_checked_and_text(self.form.cb_headers, "Headers", None)
ohare93 marked this conversation as resolved.
Show resolved Hide resolved

set_checked_and_text(self.form.cb_note_models, "Note Models", len(self.deck_json['note_models']))
set_checked_and_text(self.form.cb_notes, f"Notes", len(self.deck_json['notes']))
set_checked_and_text(self.form.cb_media, f"Media Files", len(self.deck_json['media_files']))
set_checked_and_text(self.form.cb_notes, "Notes", len(self.deck_json['notes']))
set_checked_and_text(self.form.cb_media, "Media Files", len(self.deck_json['media_files']))

# TODO: Deck Parts to Use, check which are actually in the deck_json

Expand All @@ -174,16 +163,7 @@ def read_import_config(self):
self.final_import_config = config

def read_personal_fields(self, config):
current_note_model = ""
current_uuid = ""
ui_fields: List[QListWidgetItem] = self.get_ui_pf_items()
for ui_field in ui_fields:
if not ui_field.flags() & Qt.ItemIsUserCheckable: # Note Model Header
current_note_model = ui_field.text()
current_uuid = next(model[UUID_FIELD_NAME]
for model in self.deck_json["note_models"] if model["name"] == current_note_model)
elif ui_field.checkState() == Qt.Checked: # Field
config.add_field(current_note_model, current_uuid, ui_field.text())

def get_ui_pf_items(self):
return [self.form.list_personal_fields.item(i) for i in range(self.form.list_personal_fields.count())]
for model_name, fields_dict in self.personal_field_ui_dict.items():
for field_name, widget_item in fields_dict.items():
if widget_item.checkState() == Qt.Checked:
config.add_field(model_name, field_name)
1 change: 0 additions & 1 deletion crowd_anki/representation/deck_initializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from .note import Note
from ..anki.adapters.anki_deck import AnkiDeck
from ..anki.adapters.note_model_file_provider import NoteModelFileProvider
from ..importer.import_dialog import ImportConfig


def from_collection(collection, name, deck_metadata=None, is_child=False) -> Deck:
Expand Down
4 changes: 2 additions & 2 deletions crowd_anki/representation/note.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ def save_to_collection(self, collection, deck, model_map_cache, import_config):

def handle_import_config_changes(self, import_config, note_model):
# Personal Fields
for num, field in enumerate(self.anki_object_dict["fields"]):
if import_config.has_pf(note_model.anki_dict['flds'][num]['name'], note_model.anki_dict['name']):
for num in range(len(self.anki_object_dict["fields"])):
if import_config.is_personal_field(note_model.anki_dict['name'], note_model.anki_dict['flds'][num]['name']):
self.anki_object_dict["fields"][num] = self.anki_object.fields[num]

# Tag Cards on Import
Expand Down