Merge pull request #1270 from RumovZ/flag-manager
Add flag manager and hook
This commit is contained in:
commit
1e57693b36
@ -18,7 +18,6 @@ from anki.utils import isMac
|
|||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
from aqt.editor import Editor
|
from aqt.editor import Editor
|
||||||
from aqt.exporting import ExportDialog
|
from aqt.exporting import ExportDialog
|
||||||
from aqt.flags import load_flags
|
|
||||||
from aqt.operations.card import set_card_deck, set_card_flag
|
from aqt.operations.card import set_card_deck, set_card_flag
|
||||||
from aqt.operations.collection import redo, undo
|
from aqt.operations.collection import redo, undo
|
||||||
from aqt.operations.note import remove_notes
|
from aqt.operations.note import remove_notes
|
||||||
@ -175,7 +174,7 @@ class Browser(QMainWindow):
|
|||||||
def set_flag_func(desired_flag: int) -> Callable:
|
def set_flag_func(desired_flag: int) -> Callable:
|
||||||
return lambda: self.set_flag_of_selected_cards(desired_flag)
|
return lambda: self.set_flag_of_selected_cards(desired_flag)
|
||||||
|
|
||||||
for flag in load_flags(self.col):
|
for flag in self.mw.flags.all():
|
||||||
qconnect(
|
qconnect(
|
||||||
getattr(self.form, flag.action).triggered, set_flag_func(flag.index)
|
getattr(self.form, flag.action).triggered, set_flag_func(flag.index)
|
||||||
)
|
)
|
||||||
@ -212,6 +211,7 @@ class Browser(QMainWindow):
|
|||||||
self._cleanup_preview()
|
self._cleanup_preview()
|
||||||
self.editor.cleanup()
|
self.editor.cleanup()
|
||||||
self.table.cleanup()
|
self.table.cleanup()
|
||||||
|
self.sidebar.cleanup()
|
||||||
saveSplitter(self.form.splitter, "editor3")
|
saveSplitter(self.form.splitter, "editor3")
|
||||||
saveGeom(self, "editor")
|
saveGeom(self, "editor")
|
||||||
saveState(self, "editor")
|
saveState(self, "editor")
|
||||||
@ -702,13 +702,13 @@ class Browser(QMainWindow):
|
|||||||
flag = self.card and self.card.user_flag()
|
flag = self.card and self.card.user_flag()
|
||||||
flag = flag or 0
|
flag = flag or 0
|
||||||
|
|
||||||
for f in load_flags(self.col):
|
for f in self.mw.flags.all():
|
||||||
getattr(self.form, f.action).setChecked(flag == f.index)
|
getattr(self.form, f.action).setChecked(flag == f.index)
|
||||||
|
|
||||||
qtMenuShortcutWorkaround(self.form.menuFlag)
|
qtMenuShortcutWorkaround(self.form.menuFlag)
|
||||||
|
|
||||||
def _update_flag_labels(self) -> None:
|
def _update_flag_labels(self) -> None:
|
||||||
for flag in load_flags(self.col):
|
for flag in self.mw.flags.all():
|
||||||
getattr(self.form, flag.action).setText(flag.label)
|
getattr(self.form, flag.action).setText(flag.label)
|
||||||
|
|
||||||
def toggle_mark_of_selected_notes(self, checked: bool) -> None:
|
def toggle_mark_of_selected_notes(self, checked: bool) -> None:
|
||||||
@ -782,6 +782,7 @@ class Browser(QMainWindow):
|
|||||||
gui_hooks.backend_did_block.append(self.table.on_backend_did_block)
|
gui_hooks.backend_did_block.append(self.table.on_backend_did_block)
|
||||||
gui_hooks.operation_did_execute.append(self.on_operation_did_execute)
|
gui_hooks.operation_did_execute.append(self.on_operation_did_execute)
|
||||||
gui_hooks.focus_did_change.append(self.on_focus_change)
|
gui_hooks.focus_did_change.append(self.on_focus_change)
|
||||||
|
gui_hooks.flag_label_did_change.append(self._update_flag_labels)
|
||||||
|
|
||||||
def teardownHooks(self) -> None:
|
def teardownHooks(self) -> None:
|
||||||
gui_hooks.undo_state_did_change.remove(self.on_undo_state_change)
|
gui_hooks.undo_state_did_change.remove(self.on_undo_state_change)
|
||||||
@ -789,6 +790,7 @@ class Browser(QMainWindow):
|
|||||||
gui_hooks.backend_did_block.remove(self.table.on_backend_will_block)
|
gui_hooks.backend_did_block.remove(self.table.on_backend_will_block)
|
||||||
gui_hooks.operation_did_execute.remove(self.on_operation_did_execute)
|
gui_hooks.operation_did_execute.remove(self.on_operation_did_execute)
|
||||||
gui_hooks.focus_did_change.remove(self.on_focus_change)
|
gui_hooks.focus_did_change.remove(self.on_focus_change)
|
||||||
|
gui_hooks.flag_label_did_change.remove(self._update_flag_labels)
|
||||||
|
|
||||||
# Undo
|
# Undo
|
||||||
######################################################################
|
######################################################################
|
||||||
|
@ -26,7 +26,6 @@ from aqt.browser.sidebar.searchbar import SidebarSearchBar
|
|||||||
from aqt.browser.sidebar.toolbar import SidebarTool, SidebarToolbar
|
from aqt.browser.sidebar.toolbar import SidebarTool, SidebarToolbar
|
||||||
from aqt.clayout import CardLayout
|
from aqt.clayout import CardLayout
|
||||||
from aqt.fields import FieldDialog
|
from aqt.fields import FieldDialog
|
||||||
from aqt.flags import load_flags
|
|
||||||
from aqt.models import Models
|
from aqt.models import Models
|
||||||
from aqt.operations import CollectionOp, QueryOp
|
from aqt.operations import CollectionOp, QueryOp
|
||||||
from aqt.operations.deck import (
|
from aqt.operations.deck import (
|
||||||
@ -109,6 +108,11 @@ class SidebarTreeView(QTreeView):
|
|||||||
self.toolbar = SidebarToolbar(self)
|
self.toolbar = SidebarToolbar(self)
|
||||||
self.searchBar = SidebarSearchBar(self)
|
self.searchBar = SidebarSearchBar(self)
|
||||||
|
|
||||||
|
gui_hooks.flag_label_did_change.append(self.refresh)
|
||||||
|
|
||||||
|
def cleanup(self) -> None:
|
||||||
|
gui_hooks.flag_label_did_change.remove(self.refresh)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tool(self) -> SidebarTool:
|
def tool(self) -> SidebarTool:
|
||||||
return self._tool
|
return self._tool
|
||||||
@ -677,7 +681,7 @@ class SidebarTreeView(QTreeView):
|
|||||||
)
|
)
|
||||||
root.search_node = SearchNode(flag=SearchNode.FLAG_ANY)
|
root.search_node = SearchNode(flag=SearchNode.FLAG_ANY)
|
||||||
|
|
||||||
for flag in load_flags(self.col):
|
for flag in self.mw.flags.all():
|
||||||
root.add_child(
|
root.add_child(
|
||||||
SidebarItem(
|
SidebarItem(
|
||||||
name=flag.label,
|
name=flag.label,
|
||||||
@ -961,12 +965,8 @@ class SidebarTreeView(QTreeView):
|
|||||||
###########################
|
###########################
|
||||||
|
|
||||||
def rename_flag(self, item: SidebarItem, new_name: str) -> None:
|
def rename_flag(self, item: SidebarItem, new_name: str) -> None:
|
||||||
labels = self.col.get_config("flagLabels", {})
|
|
||||||
labels[str(item.id)] = new_name
|
|
||||||
self.col.set_config("flagLabels", labels)
|
|
||||||
item.name = new_name
|
item.name = new_name
|
||||||
self.browser._update_flag_labels()
|
self.mw.flags.rename_flag(item.id, new_name)
|
||||||
self.refresh()
|
|
||||||
|
|
||||||
# Decks
|
# Decks
|
||||||
###########################
|
###########################
|
||||||
|
138
qt/aqt/flags.py
138
qt/aqt/flags.py
@ -3,11 +3,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Dict, List, cast
|
from typing import Dict, List, Optional, cast
|
||||||
|
|
||||||
from anki import Collection
|
import aqt
|
||||||
from anki.collection import SearchNode
|
from anki.collection import SearchNode
|
||||||
from aqt import colors
|
from aqt import colors, gui_hooks
|
||||||
from aqt.theme import ColoredIcon
|
from aqt.theme import ColoredIcon
|
||||||
from aqt.utils import tr
|
from aqt.utils import tr
|
||||||
|
|
||||||
@ -30,60 +30,82 @@ class Flag:
|
|||||||
action: str
|
action: str
|
||||||
|
|
||||||
|
|
||||||
def load_flags(col: Collection) -> List[Flag]:
|
class FlagManager:
|
||||||
"""Return a list of all flags, reloading labels from the config."""
|
def __init__(self, mw: aqt.main.AnkiQt) -> None:
|
||||||
|
self.mw = mw
|
||||||
|
self._flags: Optional[List[Flag]] = None
|
||||||
|
|
||||||
labels = cast(Dict[str, str], col.get_config("flagLabels", {}))
|
def all(self) -> List[Flag]:
|
||||||
icon = ColoredIcon(path=":/icons/flag.svg", color=colors.DISABLED)
|
"""Return a list of all flags."""
|
||||||
|
if self._flags is None:
|
||||||
|
self._load_flags()
|
||||||
|
return self._flags
|
||||||
|
|
||||||
return [
|
def get_flag(self, flag_index: int) -> Flag:
|
||||||
Flag(
|
if not 1 <= flag_index <= len(self.all()):
|
||||||
1,
|
raise Exception(f"Flag index out of range (1-{len(self.all())}).")
|
||||||
labels["1"] if "1" in labels else tr.actions_flag_red(),
|
return self.all()[flag_index - 1]
|
||||||
icon.with_color(colors.FLAG1_FG),
|
|
||||||
SearchNode(flag=SearchNode.FLAG_RED),
|
def rename_flag(self, flag_index: int, new_name: str) -> None:
|
||||||
"actionRed_Flag",
|
if new_name in ("", self.get_flag(flag_index).label):
|
||||||
),
|
return
|
||||||
Flag(
|
labels = self.mw.col.get_config("flagLabels", {})
|
||||||
2,
|
labels[str(flag_index)] = self.get_flag(flag_index).label = new_name
|
||||||
labels["2"] if "2" in labels else tr.actions_flag_orange(),
|
self.mw.col.set_config("flagLabels", labels)
|
||||||
icon.with_color(colors.FLAG2_FG),
|
gui_hooks.flag_label_did_change()
|
||||||
SearchNode(flag=SearchNode.FLAG_ORANGE),
|
|
||||||
"actionOrange_Flag",
|
def _load_flags(self) -> None:
|
||||||
),
|
labels = cast(Dict[str, str], self.mw.col.get_config("flagLabels", {}))
|
||||||
Flag(
|
icon = ColoredIcon(path=":/icons/flag.svg", color=colors.DISABLED)
|
||||||
3,
|
|
||||||
labels["3"] if "3" in labels else tr.actions_flag_green(),
|
self._flags = [
|
||||||
icon.with_color(colors.FLAG3_FG),
|
Flag(
|
||||||
SearchNode(flag=SearchNode.FLAG_GREEN),
|
1,
|
||||||
"actionGreen_Flag",
|
labels["1"] if "1" in labels else tr.actions_flag_red(),
|
||||||
),
|
icon.with_color(colors.FLAG1_FG),
|
||||||
Flag(
|
SearchNode(flag=SearchNode.FLAG_RED),
|
||||||
4,
|
"actionRed_Flag",
|
||||||
labels["4"] if "4" in labels else tr.actions_flag_blue(),
|
),
|
||||||
icon.with_color(colors.FLAG4_FG),
|
Flag(
|
||||||
SearchNode(flag=SearchNode.FLAG_BLUE),
|
2,
|
||||||
"actionBlue_Flag",
|
labels["2"] if "2" in labels else tr.actions_flag_orange(),
|
||||||
),
|
icon.with_color(colors.FLAG2_FG),
|
||||||
Flag(
|
SearchNode(flag=SearchNode.FLAG_ORANGE),
|
||||||
5,
|
"actionOrange_Flag",
|
||||||
labels["5"] if "5" in labels else tr.actions_flag_pink(),
|
),
|
||||||
icon.with_color(colors.FLAG5_FG),
|
Flag(
|
||||||
SearchNode(flag=SearchNode.FLAG_PINK),
|
3,
|
||||||
"actionPink_Flag",
|
labels["3"] if "3" in labels else tr.actions_flag_green(),
|
||||||
),
|
icon.with_color(colors.FLAG3_FG),
|
||||||
Flag(
|
SearchNode(flag=SearchNode.FLAG_GREEN),
|
||||||
6,
|
"actionGreen_Flag",
|
||||||
labels["6"] if "6" in labels else tr.actions_flag_turquoise(),
|
),
|
||||||
icon.with_color(colors.FLAG6_FG),
|
Flag(
|
||||||
SearchNode(flag=SearchNode.FLAG_TURQUOISE),
|
4,
|
||||||
"actionTurquoise_Flag",
|
labels["4"] if "4" in labels else tr.actions_flag_blue(),
|
||||||
),
|
icon.with_color(colors.FLAG4_FG),
|
||||||
Flag(
|
SearchNode(flag=SearchNode.FLAG_BLUE),
|
||||||
7,
|
"actionBlue_Flag",
|
||||||
labels["7"] if "7" in labels else tr.actions_flag_purple(),
|
),
|
||||||
icon.with_color(colors.FLAG7_FG),
|
Flag(
|
||||||
SearchNode(flag=SearchNode.FLAG_PURPLE),
|
5,
|
||||||
"actionPurple_Flag",
|
labels["5"] if "5" in labels else tr.actions_flag_pink(),
|
||||||
),
|
icon.with_color(colors.FLAG5_FG),
|
||||||
]
|
SearchNode(flag=SearchNode.FLAG_PINK),
|
||||||
|
"actionPink_Flag",
|
||||||
|
),
|
||||||
|
Flag(
|
||||||
|
6,
|
||||||
|
labels["6"] if "6" in labels else tr.actions_flag_turquoise(),
|
||||||
|
icon.with_color(colors.FLAG6_FG),
|
||||||
|
SearchNode(flag=SearchNode.FLAG_TURQUOISE),
|
||||||
|
"actionTurquoise_Flag",
|
||||||
|
),
|
||||||
|
Flag(
|
||||||
|
7,
|
||||||
|
labels["7"] if "7" in labels else tr.actions_flag_purple(),
|
||||||
|
icon.with_color(colors.FLAG7_FG),
|
||||||
|
SearchNode(flag=SearchNode.FLAG_PURPLE),
|
||||||
|
"actionPurple_Flag",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
@ -48,6 +48,7 @@ from aqt import gui_hooks
|
|||||||
from aqt.addons import DownloadLogEntry, check_and_prompt_for_updates, show_log_to_user
|
from aqt.addons import DownloadLogEntry, check_and_prompt_for_updates, show_log_to_user
|
||||||
from aqt.dbcheck import check_db
|
from aqt.dbcheck import check_db
|
||||||
from aqt.emptycards import show_empty_cards
|
from aqt.emptycards import show_empty_cards
|
||||||
|
from aqt.flags import FlagManager
|
||||||
from aqt.legacy import install_pylib_legacy
|
from aqt.legacy import install_pylib_legacy
|
||||||
from aqt.mediacheck import check_media_db
|
from aqt.mediacheck import check_media_db
|
||||||
from aqt.mediasync import MediaSyncer
|
from aqt.mediasync import MediaSyncer
|
||||||
@ -113,6 +114,7 @@ class AnkiQt(QMainWindow):
|
|||||||
self.col: Optional[Collection] = None
|
self.col: Optional[Collection] = None
|
||||||
self.taskman = TaskManager(self)
|
self.taskman = TaskManager(self)
|
||||||
self.media_syncer = MediaSyncer(self)
|
self.media_syncer = MediaSyncer(self)
|
||||||
|
self.flags = FlagManager(self)
|
||||||
aqt.mw = self
|
aqt.mw = self
|
||||||
self.app = app
|
self.app = app
|
||||||
self.pm = profileManager
|
self.pm = profileManager
|
||||||
|
@ -25,7 +25,6 @@ from anki.utils import stripHTML
|
|||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
from aqt.browser.card_info import CardInfoDialog
|
from aqt.browser.card_info import CardInfoDialog
|
||||||
from aqt.deckoptions import confirm_deck_then_display_options
|
from aqt.deckoptions import confirm_deck_then_display_options
|
||||||
from aqt.flags import load_flags
|
|
||||||
from aqt.operations.card import set_card_flag
|
from aqt.operations.card import set_card_flag
|
||||||
from aqt.operations.note import remove_notes
|
from aqt.operations.note import remove_notes
|
||||||
from aqt.operations.scheduling import (
|
from aqt.operations.scheduling import (
|
||||||
@ -447,7 +446,7 @@ class Reviewer:
|
|||||||
(Qt.Key_F5, self.replayAudio),
|
(Qt.Key_F5, self.replayAudio),
|
||||||
*(
|
*(
|
||||||
(f"Ctrl+{flag.index}", self.set_flag_func(flag.index))
|
(f"Ctrl+{flag.index}", self.set_flag_func(flag.index))
|
||||||
for flag in load_flags(self.mw.col)
|
for flag in self.mw.flags.all()
|
||||||
),
|
),
|
||||||
("*", self.toggle_mark_on_current_note),
|
("*", self.toggle_mark_on_current_note),
|
||||||
("=", self.bury_current_note),
|
("=", self.bury_current_note),
|
||||||
@ -904,7 +903,7 @@ time = %(time)d;
|
|||||||
self.set_flag_func(flag.index),
|
self.set_flag_func(flag.index),
|
||||||
dict(checked=currentFlag == flag.index),
|
dict(checked=currentFlag == flag.index),
|
||||||
]
|
]
|
||||||
for flag in load_flags(self.mw.col)
|
for flag in self.mw.flags.all()
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[tr.studying_bury_card(), "-", self.bury_current_card],
|
[tr.studying_bury_card(), "-", self.bury_current_card],
|
||||||
|
@ -946,6 +946,11 @@ gui_hooks.webview_did_inject_style_into_page.append(mytest)
|
|||||||
args=["menu: QMenu", "deck_id: int"],
|
args=["menu: QMenu", "deck_id: int"],
|
||||||
legacy_hook="showDeckOptions",
|
legacy_hook="showDeckOptions",
|
||||||
),
|
),
|
||||||
|
Hook(
|
||||||
|
name="flag_label_did_change",
|
||||||
|
args=[],
|
||||||
|
doc="Used to update the GUI when a new flag label is assigned.",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
suffix = ""
|
suffix = ""
|
||||||
|
Loading…
Reference in New Issue
Block a user