7171_CONTEXT_MENU : str = "am_context_menu"
7272
7373_startup_sync : bool = True
74+ _showed_update_warning : bool = False
7475_updated_seen_morphs_for_profile : bool = False
7576
7677
@@ -81,6 +82,7 @@ def main() -> None:
8182 gui_hooks .top_toolbar_did_init_links .append (init_toolbar_items )
8283
8384 gui_hooks .profile_did_open .append (load_am_profile_configs )
85+ gui_hooks .profile_did_open .append (reset_startup_sync_variable )
8486 gui_hooks .profile_did_open .append (init_db )
8587 gui_hooks .profile_did_open .append (create_am_directories_and_files )
8688 gui_hooks .profile_did_open .append (register_addon_dialogs )
@@ -90,6 +92,7 @@ def main() -> None:
9092 gui_hooks .profile_did_open .append (replace_card_reviewer )
9193 gui_hooks .profile_did_open .append (text_preprocessing .update_translation_table )
9294 gui_hooks .profile_did_open .append (spacy_wrapper .maybe_delete_spacy_venv )
95+ gui_hooks .profile_did_open .append (maybe_show_version_warning_wrapper )
9396
9497 gui_hooks .sync_will_start .append (recalc_on_sync )
9598
@@ -165,12 +168,19 @@ def load_am_profile_configs() -> None:
165168 # This is reached when we load a new anki profile that hasn't saved
166169 # any ankimorphs settings yet. It's important that we don't carry over
167170 # any settings from the previous profile because they can be somewhat
168- # hidden (note filter tags), which could lead to completely unexpected
171+ # hidden (like note filter tags), which could lead to completely unexpected
169172 # results for no apparent reason. We therefore reset meta.json to
170173 # config.json (default settings)
171174 ankimorphs_config .reset_all_configs ()
172175
173176
177+ def reset_startup_sync_variable () -> None :
178+ # we have to reset this variable on profile_did_open rather than
179+ # profile_will_close, because sync can trigger after the latter.
180+ global _startup_sync
181+ _startup_sync = True
182+
183+
174184def init_db () -> None :
175185 with AnkiMorphsDB () as am_db :
176186 am_db .create_all_tables ()
@@ -201,7 +211,8 @@ def register_addon_dialogs() -> None:
201211 # We use the Anki dialog manager to handle our dialogs
202212
203213 aqt .dialogs .register_dialog (
204- name = am_globals .SETTINGS_DIALOG_NAME , creator = SettingsDialog
214+ name = am_globals .SETTINGS_DIALOG_NAME ,
215+ creator = SettingsDialog ,
205216 )
206217 aqt .dialogs .register_dialog (
207218 name = am_globals .GENERATOR_DIALOG_NAME ,
@@ -288,6 +299,7 @@ def setup_browser_menu(_browser: Browser) -> None:
288299 )
289300 assert am_browse_menu_creation_action is not None
290301 am_browse_menu_creation_action .setObjectName (_BROWSE_MENU )
302+
291303 am_browse_menu .addAction (view_action )
292304 am_browse_menu .addAction (learn_now_action )
293305 am_browse_menu .addAction (browse_morph_action )
@@ -302,6 +314,7 @@ def setup_context_menu(_browser: Browser, context_menu: QMenu) -> None:
302314
303315 context_menu_creation_action = context_menu .insertSeparator (learn_now_action )
304316 assert context_menu_creation_action is not None
317+
305318 context_menu .addAction (view_action )
306319 context_menu .addAction (learn_now_action )
307320 context_menu .addAction (browse_morph_action )
@@ -315,17 +328,21 @@ def setup_context_menu(_browser: Browser, context_menu: QMenu) -> None:
315328
316329
317330def recalc_on_sync () -> None :
318- # Anki automatically syncs on startup, but we want to avoid running
319- # recalc at that time as it may be unnecessary.
320-
331+ # Anki can sync automatically on startup, but we don't
332+ # want to recalc at that point.
321333 global _startup_sync
322334
323- if _startup_sync :
324- _startup_sync = False
325- else :
326- am_config = AnkiMorphsConfig ()
327- if am_config .recalc_on_sync :
328- recalc_main .recalc ()
335+ if mw .pm .auto_syncing_enabled ():
336+ if _startup_sync :
337+ # trivial bug: this will cause recalc to not run on the first profile close
338+ # sync after the user first activates the Anki 'auto_syncing_enabled'
339+ # setting, but that's not a big deal.
340+ _startup_sync = False
341+ return
342+
343+ am_config = AnkiMorphsConfig ()
344+ if am_config .recalc_on_sync :
345+ recalc_main .recalc ()
329346
330347
331348def replace_card_reviewer () -> None :
@@ -341,6 +358,49 @@ def replace_card_reviewer() -> None:
341358 )
342359
343360
361+ def maybe_show_version_warning_wrapper () -> None :
362+ assert mw is not None
363+ assert mw .pm is not None
364+
365+ if mw .pm .auto_syncing_enabled ():
366+ # we wait for sync to finish before we display
367+ # our warning dialog to prevent gui race conditions
368+ gui_hooks .sync_did_finish .append (maybe_show_version_warning )
369+ else :
370+ maybe_show_version_warning ()
371+
372+
373+ def maybe_show_version_warning () -> None :
374+ global _showed_update_warning
375+
376+ if _showed_update_warning :
377+ return
378+ _showed_update_warning = True
379+
380+ am_extra_settings = AnkiMorphsExtraSettings ()
381+
382+ previous_local_am_version : list [str ] = am_extra_settings .value (
383+ extra_settings_keys .General .ANKIMORPHS_VERSION ,
384+ defaultValue = am_globals .__version__ ,
385+ type = str ,
386+ ).split ("." )
387+
388+ try :
389+ if int (previous_local_am_version [0 ]) < 6 :
390+ _title = "AnkiMoprhs"
391+ _body = (
392+ "Some 'Card Handling' settings have been changed, please make"
393+ " sure they are correct before using recalc."
394+ "<br><br>"
395+ "See <a href='https://github.com/mortii/anki-morphs/releases/tag/v6.0.0'>"
396+ "the v6.0.0 release notes</a> for more info."
397+ )
398+ message_box_utils .show_info_box (title = _title , body = _body , parent = mw )
399+ except ValueError :
400+ # the extra settings file is broken somehow
401+ pass
402+
403+
344404def insert_seen_morphs (
345405 _reviewer : Reviewer , card : Card , _ease : Literal [1 , 2 , 3 , 4 ]
346406) -> None :
@@ -357,7 +417,7 @@ def update_seen_morphs(_overview: Overview) -> None:
357417 """
358418 # Overview is NOT the starting screen; it's the screen you see
359419 # when you click on a deck. This is a good time to run this function,
360- # as 'seen morphs' only need to be known before starting a review.
420+ # as 'seen morphs' only needs to be known before starting a review.
361421 # Previously, this function ran on the profile_did_open hook,
362422 # but that sometimes caused interference with the add-on updater
363423 # since both occurred simultaneously.
@@ -431,11 +491,13 @@ def reset_am_tags() -> None:
431491
432492 title = "Reset Tags?"
433493 body = (
434- 'Clicking "Yes" will remove the following tags from all cards:\n \n '
435- f"- { am_config .tag_known_automatically } \n \n "
436- f"- { am_config .tag_ready } \n \n "
437- f"- { am_config .tag_not_ready } \n \n "
438- f"- { am_config .tag_fresh } \n \n "
494+ 'Clicking "Yes" will remove the following tags from all cards:'
495+ "<ul>"
496+ f"<li> { am_config .tag_known_automatically } "
497+ f"<li> { am_config .tag_ready } "
498+ f"<li> { am_config .tag_not_ready } "
499+ f"<li> { am_config .tag_fresh } "
500+ "</ul>"
439501 )
440502 want_reset = message_box_utils .show_warning_box (title , body , parent = mw )
441503 if want_reset :
@@ -630,6 +692,20 @@ def test_function() -> None:
630692 assert mw is not None
631693 assert mw .col .db is not None
632694
695+ # am_config = AnkiMorphsConfig()
696+ # title = "AnkiMorphs Error"
697+ # body = (
698+ # 'Clicking "Yes" will remove the following tags from all cards:'
699+ # "<ul>"
700+ # f"<li> {am_config.tag_known_automatically}"
701+ # f"<li> {am_config.tag_ready}"
702+ # f"<li> {am_config.tag_not_ready}"
703+ # f"<li> {am_config.tag_fresh}"
704+ # "</ul>"
705+ # )
706+
707+ # message_box_utils.show_error_box(title=title, body=body, parent=mw)
708+
633709 # with AnkiMorphsDB() as am_db:
634710 # print("Seen_Morphs:")
635711 # am_db.print_table("Seen_Morphs")
0 commit comments