Skip to content

Commit

Permalink
setup mask editor in note editor
Browse files Browse the repository at this point in the history
- add image on mask button click (only one time)
- show hide add button for io on notetype change
  • Loading branch information
krmanik committed Jun 9, 2023
1 parent 1aaf6db commit 8d90149
Show file tree
Hide file tree
Showing 13 changed files with 407 additions and 137 deletions.
2 changes: 2 additions & 0 deletions ftl/core/notetypes.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ notetypes-error-generating-cloze = An error occurred when generating an image oc
notetypes-error-getting-imagecloze = An error occurred while fetching an image occlusion note
notetypes-error-loading-image-occlusion = Error loading image occlusion. Is your Anki version up to date?
notetype-error-no-image-to-show = No image to show.
notetype-create-edit-io-message = Tap the two squares to create or edit an occlusion.
notetype-io-switch-type = Tap 'Type: Image Occlusion' to switch to normal text/media cards.
4 changes: 4 additions & 0 deletions pylib/anki/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,10 @@ def import_json_string(self, json: str) -> ImportLogWithChanges:
def get_image_for_occlusion(self, path: str | None) -> GetImageForOcclusionResponse:
return self._backend.get_image_for_occlusion(path=path)

def add_image_occlusion_notetype(self) -> None:
"Add notetype if missing."
self._backend.add_image_occlusion_notetype()

def add_image_occlusion_note(
self,
notetype_id: int,
Expand Down
1 change: 1 addition & 0 deletions pylib/anki/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
NotetypeNames = notetypes_pb2.NotetypeNames
ChangeNotetypeInfo = notetypes_pb2.ChangeNotetypeInfo
ChangeNotetypeRequest = notetypes_pb2.ChangeNotetypeRequest
StockNotetype = notetypes_pb2.StockNotetype

# legacy types
NotetypeDict = dict[str, Any]
Expand Down
42 changes: 40 additions & 2 deletions qt/aqt/addcards.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from anki._legacy import deprecated
from anki.collection import OpChanges, SearchNode
from anki.decks import DeckId
from anki.models import NotetypeId
from anki.models import NotetypeId, StockNotetype
from anki.notes import Note, NoteFieldsCheckResult, NoteId
from anki.utils import html_to_text_line, is_mac
from aqt import AnkiQt, gui_hooks
Expand Down Expand Up @@ -48,13 +48,16 @@ def __init__(self, mw: AnkiQt) -> None:
self.setMinimumWidth(400)
self.setup_choosers()
self.setupEditor()
self.setupButtons()
add_close_shortcut(self)
self._load_new_note()
self.setupButtons()
self.history: list[NoteId] = []
self._last_added_note: Optional[Note] = None
gui_hooks.operation_did_execute.append(self.on_operation_did_execute)
restoreGeom(self, "add")
self.col.add_image_occlusion_notetype()
# hide io buttons for note type other than image occlusion
self.show_hide_add_buttons()
gui_hooks.add_cards_did_init(self)
self.show()

Expand Down Expand Up @@ -112,6 +115,17 @@ def setupButtons(self) -> None:
self.compat_add_shorcut = QShortcut(QKeySequence("Ctrl+Enter"), self)
qconnect(self.compat_add_shorcut.activated, self.addButton.click)
self.addButton.setToolTip(shortcut(tr.adding_add_shortcut_ctrlandenter()))

# add io hide all button
self.addButtonHideAll = bb.addButton(tr.notetypes_hide_all_guess_one(), ar)
qconnect(self.addButtonHideAll.clicked, self.add_io_hide_all_note)
self.addButtonHideAll.setShortcut(QKeySequence("Ctrl+Return+A"))
self.addButtonHideAll.setVisible(False)
# add io hide one button
self.addButtonHideOne = bb.addButton(tr.notetypes_hide_one_guess_one(), ar)
qconnect(self.addButtonHideOne.clicked, self.add_io_hide_one_note)
self.addButtonHideOne.setShortcut(QKeySequence("Ctrl+Return+O"))

# close
self.closeButton = QPushButton(tr.actions_close())
self.closeButton.setAutoDefault(False)
Expand All @@ -133,6 +147,19 @@ def setupButtons(self) -> None:
b.setEnabled(False)
self.historyButton = b

def show_hide_add_buttons(self) -> None:
if (
self.editor.note.note_type()["originalStockKind"]
== StockNotetype.OriginalStockKind.ORIGINAL_STOCK_KIND_IMAGE_OCCLUSION
):
self.addButton.setVisible(False)
self.addButtonHideAll.setVisible(True)
self.addButtonHideOne.setVisible(True)
else:
self.addButton.setVisible(True)
self.addButtonHideAll.setVisible(False)
self.addButtonHideOne.setVisible(False)

def setAndFocusNote(self, note: Note) -> None:
self.editor.set_note(note, focusTo=0)

Expand Down Expand Up @@ -192,6 +219,9 @@ def on_notetype_change(self, notetype_id: NotetypeId) -> None:
old_note.note_type(), new_note.note_type()
)

# update buttons for image occlusion on note type change
self.show_hide_add_buttons()

def _load_new_note(self, sticky_fields_from: Optional[Note] = None) -> None:
note = self._new_note()
if old_note := sticky_fields_from:
Expand Down Expand Up @@ -348,6 +378,14 @@ def doClose() -> None:

self.ifCanClose(doClose)

def add_io_hide_all_note(self) -> None:
self.editor.web.eval("setOcclusionField(true)")
self.add_current_note()

def add_io_hide_one_note(self) -> None:
self.editor.web.eval("setOcclusionField(false)")
self.add_current_note()

# legacy aliases

@property
Expand Down
63 changes: 63 additions & 0 deletions qt/aqt/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from anki.consts import MODEL_CLOZE
from anki.hooks import runFilter
from anki.httpclient import HttpClient
from anki.models import StockNotetype
from anki.notes import Note, NoteFieldsCheckResult
from anki.utils import checksum, is_lin, is_win, namedtmp
from aqt import AnkiQt, colors, gui_hooks
Expand Down Expand Up @@ -475,6 +476,11 @@ def onBridgeCmd(self, cmd: str) -> Any:
elif cmd in self._links:
return self._links[cmd](self)

elif cmd.startswith("toggleMaskEditor"):
(_, show_str) = cmd.split(":", 1)
show = show_str == "true"
self.onToggleMaskEditor(show)

else:
print("uncaught cmd", cmd)

Expand Down Expand Up @@ -547,6 +553,7 @@ def oncallback(arg: Any) -> None:
setShrinkImages({json.dumps(self.mw.col.get_config("shrinkEditorImages", True))});
setCloseHTMLTags({json.dumps(self.mw.col.get_config("closeHTMLTags", True))});
triggerChanges();
setOriginalStockKind({json.dumps(self.note.note_type()["originalStockKind"])});
"""

if self.addMode:
Expand Down Expand Up @@ -1176,6 +1183,45 @@ def toggleCloseHTMLTags(self) -> None:
def setTagsCollapsed(self, collapsed: bool) -> None:
aqt.mw.pm.set_tags_collapsed(self.editorMode, collapsed)

def onAddImageForOcclusion(self) -> None:
"""Show a file selection screen, then get selected image path."""
extension_filter = " ".join(
f"*.{extension}" for extension in sorted(itertools.chain(pics))
)
filter = f"{tr.editing_media()} ({extension_filter})"

def accept(file: str) -> None:
try:
html = self._addMedia(file)
options = {"kind": "add", "imagePath": file, "notetypeId": 0}
# pass both html and options
options = {"html": html, "mode": options}
self.web.eval(f"setupMaskEditor({options})")
except Exception as e:
showWarning(str(e))
return

if self.addMode:
file = getFile(
parent=self.widget,
title=tr.editing_add_media(),
cb=cast(Callable[[Any], None], accept),
filter=filter,
key="media",
)
else:
options = {"kind": "edit", "noteId": self.note.id}
options = {"mode": options}
self.web.eval(f"setupMaskEditor({options})")

self.parentWindow.activateWindow()

def onToggleMaskEditor(self, show) -> None:
if show:
self.web.eval("toggleMaskEditor(true)")
else:
self.web.eval("toggleMaskEditor(false)")

# Links from HTML
######################################################################

Expand Down Expand Up @@ -1205,6 +1251,8 @@ def _init_links(self) -> None:
toggleMathjax=Editor.toggleMathjax,
toggleShrinkImages=Editor.toggleShrinkImages,
toggleCloseHTMLTags=Editor.toggleCloseHTMLTags,
addImageForOcclusion=Editor.onAddImageForOcclusion,
toggleMaskEditor=Editor.onToggleMaskEditor,
)


Expand Down Expand Up @@ -1462,4 +1510,19 @@ def set_cloze_button(editor: Editor) -> None:
)


def set_image_occlusion_button(editor: Editor) -> None:
action = (
"show"
if editor.note.note_type()["originalStockKind"]
== StockNotetype.OriginalStockKind.ORIGINAL_STOCK_KIND_IMAGE_OCCLUSION
else "hide"
)
editor.web.eval(
'require("anki/ui").loaded.then(() =>'
f'require("anki/NoteEditor").instances[0].toolbar.toolbar.{action}("image-occlusion-button")'
"); "
)


gui_hooks.editor_did_load_note.append(set_cloze_button)
gui_hooks.editor_did_load_note.append(set_image_occlusion_button)
Loading

0 comments on commit 8d90149

Please sign in to comment.