Esempio n. 1
0
    def _section_root(
        self,
        *,
        root: SidebarItem,
        name: str,
        icon: Union[str, ColoredIcon],
        collapse_key: Config.Bool.V,
        type: SidebarItemType | None = None,
    ) -> SidebarItem:
        def update(expanded: bool) -> None:
            CollectionOp(
                self.browser,
                lambda col: col.set_config_bool(collapse_key, not expanded),
            ).run_in_background(initiator=self)

        top = SidebarItem(
            name,
            icon,
            on_expanded=update,
            expanded=not self.col.get_config_bool(collapse_key),
            item_type=type,
        )
        root.add_child(top)

        return top
Esempio n. 2
0
        def render(root: SidebarItem,
                   nodes: Iterable[DeckTreeNode],
                   head: str = "") -> None:
            def toggle_expand(node: DeckTreeNode) -> Callable[[bool], None]:
                return lambda expanded: set_deck_collapsed(
                    parent=self,
                    deck_id=DeckId(node.deck_id),
                    collapsed=not expanded,
                    scope=DeckCollapseScope.BROWSER,
                ).run_in_background(initiator=self, )

            for node in nodes:
                item = SidebarItem(
                    name=node.name,
                    icon=icon_filtered if node.filtered else icon,
                    search_node=SearchNode(deck=head + node.name),
                    on_expanded=toggle_expand(node),
                    expanded=not node.collapsed,
                    item_type=SidebarItemType.DECK,
                    id=node.deck_id,
                    name_prefix=head,
                )
                root.add_child(item)
                newhead = f"{head + node.name}::"
                render(item, node.children, newhead)
Esempio n. 3
0
    def rename_tag(self, item: SidebarItem, new_name: str) -> None:
        if not new_name or new_name == item.name:
            return

        old_name = item.name
        old_full_name = item.full_name
        new_full_name = item.name_prefix + new_name

        item.name = new_name
        item.full_name = new_full_name

        def success(out: OpChangesWithCount) -> None:
            if out.count:
                tooltip(tr.browsing_notes_updated(count=out.count),
                        parent=self)
            else:
                # revert renaming of sidebar item
                item.full_name = old_full_name
                item.name = old_name
                showInfo(tr.browsing_tag_rename_warning_empty(), parent=self)

        rename_tag(
            parent=self.browser,
            current_name=old_full_name,
            new_name=new_full_name,
        ).success(success).run_in_background()
Esempio n. 4
0
File: tree.py Progetto: rye761/anki
    def _deck_tree(self, root: SidebarItem) -> None:
        icon = "icons:book-outline.svg"
        icon_current = "icons:book-clock-outline.svg"
        icon_filtered = "icons:book-cog-outline.svg"

        def render(
            root: SidebarItem, nodes: Iterable[DeckTreeNode], head: str = ""
        ) -> None:
            def toggle_expand(node: DeckTreeNode) -> Callable[[bool], None]:
                return lambda expanded: set_deck_collapsed(
                    parent=self,
                    deck_id=DeckId(node.deck_id),
                    collapsed=not expanded,
                    scope=DeckCollapseScope.BROWSER,
                ).run_in_background(
                    initiator=self,
                )

            for node in nodes:
                item = SidebarItem(
                    name=node.name,
                    icon=icon_filtered if node.filtered else icon,
                    search_node=SearchNode(deck=head + node.name),
                    on_expanded=toggle_expand(node),
                    expanded=not node.collapsed,
                    item_type=SidebarItemType.DECK,
                    id=node.deck_id,
                    name_prefix=head,
                )
                root.add_child(item)
                newhead = f"{head + node.name}::"
                render(item, node.children, newhead)

        tree = self.col.decks.deck_tree()
        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_decks(),
            icon=icon,
            collapse_key=Config.Bool.COLLAPSE_DECKS,
            type=SidebarItemType.DECK_ROOT,
        )
        root.search_node = SearchNode(deck="_*")
        current = root.add_simple(
            name=tr.browsing_current_deck(),
            icon=icon_current,
            type=SidebarItemType.DECK_CURRENT,
            search_node=SearchNode(deck="current"),
        )
        current.id = self.mw.col.decks.selected()

        render(root, tree.children)
Esempio n. 5
0
    def remove_tags(self, item: SidebarItem) -> None:
        tags = self.mw.col.tags.join(self._selected_tags())
        item.name = "..."

        remove_tags_from_all_notes(
            parent=self.browser,
            space_separated_tags=tags).run_in_background()
Esempio n. 6
0
    def rename_deck(self, item: SidebarItem, new_name: str) -> None:
        if not new_name:
            return

        # update UI immediately, to avoid redraw
        item.name = new_name

        full_name = item.name_prefix + new_name
        deck_id = DeckId(item.id)

        def after_fetch(deck: Deck) -> None:
            if full_name == deck.name:
                return

            rename_deck(
                parent=self,
                deck_id=deck_id,
                new_name=full_name,
            ).run_in_background()

        QueryOp(
            parent=self.browser,
            op=lambda col: col.get_deck(deck_id),
            success=after_fetch,
        ).run_in_background()
Esempio n. 7
0
 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
     self.browser._update_flag_labels()
     self.refresh()
Esempio n. 8
0
    def rename_tag(self, item: SidebarItem, new_name: str) -> None:
        if not new_name or new_name == item.name:
            return

        new_name_base = new_name

        old_name = item.full_name
        new_name = item.name_prefix + new_name

        item.name = new_name_base
        item.full_name = new_name

        rename_tag(
            parent=self.browser,
            current_name=old_name,
            new_name=new_name,
        ).run_in_background()
Esempio n. 9
0
    def _notetype_tree(self, root: SidebarItem) -> None:
        icon = ":/icons/notetype.svg"
        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_notetypes(),
            icon=icon,
            collapse_key=Config.Bool.COLLAPSE_NOTETYPES,
            type=SidebarItemType.NOTETYPE_ROOT,
        )

        for nt in sorted(self.col.models.all(), key=lambda nt: nt["name"].lower()):
            item = SidebarItem(
                nt["name"],
                icon,
                search_node=SearchNode(note=nt["name"]),
                item_type=SidebarItemType.NOTETYPE,
                id=nt["id"],
            )

            for c, tmpl in enumerate(nt["tmpls"]):
                child = SidebarItem(
                    tmpl["name"],
                    icon,
                    search_node=self.col.group_searches(
                        SearchNode(note=nt["name"]), SearchNode(template=c)
                    ),
                    item_type=SidebarItemType.NOTETYPE_TEMPLATE,
                    name_prefix=f"{nt['name']}::",
                    id=tmpl["ord"],
                )
                item.add_child(child)

            root.add_child(item)
Esempio n. 10
0
    def _card_state_tree(self, root: SidebarItem) -> None:
        icon = ":/icons/circle.svg"
        icon_outline = ":/icons/circle-outline.svg"

        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_card_state(),
            icon=icon_outline,
            collapse_key=Config.Bool.COLLAPSE_CARD_STATE,
            type=SidebarItemType.CARD_STATE_ROOT,
        )
        type = SidebarItemType.CARD_STATE
        colored_icon = ColoredIcon(path=icon, color=colors.DISABLED)

        root.add_simple(
            tr.actions_new(),
            icon=colored_icon.with_color(colors.NEW_COUNT),
            type=type,
            search_node=SearchNode(card_state=SearchNode.CARD_STATE_NEW),
        )

        root.add_simple(
            name=tr.scheduling_learning(),
            icon=colored_icon.with_color(colors.LEARN_COUNT),
            type=type,
            search_node=SearchNode(card_state=SearchNode.CARD_STATE_LEARN),
        )
        root.add_simple(
            name=tr.scheduling_review(),
            icon=colored_icon.with_color(colors.REVIEW_COUNT),
            type=type,
            search_node=SearchNode(card_state=SearchNode.CARD_STATE_REVIEW),
        )
        root.add_simple(
            name=tr.browsing_suspended(),
            icon=colored_icon.with_color(colors.SUSPENDED_FG),
            type=type,
            search_node=SearchNode(card_state=SearchNode.CARD_STATE_SUSPENDED),
        )
        root.add_simple(
            name=tr.browsing_buried(),
            icon=colored_icon.with_color(colors.BURIED_FG),
            type=type,
            search_node=SearchNode(card_state=SearchNode.CARD_STATE_BURIED),
        )
Esempio n. 11
0
    def _tag_tree(self, root: SidebarItem) -> None:
        icon = ":/icons/tag-outline.svg"
        icon_off = ":/icons/tag-off-outline.svg"

        def render(root: SidebarItem,
                   nodes: Iterable[TagTreeNode],
                   head: str = "") -> None:
            def toggle_expand(node: TagTreeNode) -> Callable[[bool], None]:
                full_name = head + node.name
                return lambda expanded: set_tag_collapsed(
                    parent=self, tag=full_name, collapsed=not expanded
                ).run_in_background(initiator=self)

            for node in nodes:
                item = SidebarItem(
                    name=node.name,
                    icon=icon,
                    search_node=SearchNode(tag=head + node.name),
                    on_expanded=toggle_expand(node),
                    expanded=not node.collapsed,
                    item_type=SidebarItemType.TAG,
                    name_prefix=head,
                )
                root.add_child(item)
                newhead = f"{head + node.name}::"
                render(item, node.children, newhead)

        tree = self.col.tags.tree()
        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_tags(),
            icon=icon,
            collapse_key=Config.Bool.COLLAPSE_TAGS,
            type=SidebarItemType.TAG_ROOT,
        )
        root.search_node = SearchNode(tag="_*")
        root.add_simple(
            name=tr.browsing_sidebar_untagged(),
            icon=icon_off,
            type=SidebarItemType.TAG_NONE,
            search_node=SearchNode(negated=SearchNode(tag="_*")),
        )

        render(root, tree.children)
Esempio n. 12
0
    def _saved_searches_tree(self, root: SidebarItem) -> None:
        icon = ":/icons/heart-outline.svg"
        saved = self._get_saved_searches()

        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_saved_searches(),
            icon=icon,
            collapse_key=Config.Bool.COLLAPSE_SAVED_SEARCHES,
            type=SidebarItemType.SAVED_SEARCH_ROOT,
        )

        for name, filt in sorted(saved.items()):
            item = SidebarItem(
                name,
                icon,
                search_node=SearchNode(parsable_text=filt),
                item_type=SidebarItemType.SAVED_SEARCH,
            )
            root.add_child(item)
Esempio n. 13
0
    def rename_deck(self, item: SidebarItem, new_name: str) -> None:
        if not new_name or new_name == item.name:
            return

        # update UI immediately, to avoid redraw
        item.name = new_name

        rename_deck(
            parent=self,
            deck_id=DeckId(item.id),
            new_name=item.name_prefix + new_name,
        ).run_in_background()
Esempio n. 14
0
    def _root_tree(self) -> SidebarItem:
        root: SidebarItem | None = None

        for stage in SidebarStage:
            if stage == SidebarStage.ROOT:
                root = SidebarItem("", "", item_type=SidebarItemType.ROOT)
            handled = gui_hooks.browser_will_build_tree(
                False, root, stage, self.browser)
            if not handled:
                self._build_stage(root, stage)

        return root
Esempio n. 15
0
File: tree.py Progetto: rye761/anki
 def _save_search(self, name: str, search: str, update: bool = False) -> None:
     conf = self._get_saved_searches()
     if not update and name in conf:
         if conf[name] == search:
             # nothing to do
             return
         if not askUser(tr.browsing_confirm_saved_search_overwrite(name=name)):
             # don't overwrite existing saved search
             return
     conf[name] = search
     self._set_saved_searches(conf)
     self.refresh(SidebarItem(name, "", item_type=SidebarItemType.SAVED_SEARCH))
Esempio n. 16
0
    def _flags_tree(self, root: SidebarItem) -> None:
        icon = ColoredIcon(path=":/icons/flag.svg", color=colors.DISABLED)
        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_flags(),
            icon=icon,
            collapse_key=Config.Bool.COLLAPSE_FLAGS,
            type=SidebarItemType.FLAG_ROOT,
        )
        root.search_node = SearchNode(flag=SearchNode.FLAG_ANY)

        for flag in load_flags(self.col):
            root.add_child(
                SidebarItem(
                    name=flag.label,
                    icon=flag.icon,
                    search_node=flag.search_node,
                    item_type=SidebarItemType.FLAG,
                    id=flag.index,
                ))

        root.add_simple(
            tr.browsing_no_flag(),
            icon=icon,
            type=SidebarItemType.FLAG,
            search_node=SearchNode(flag=SearchNode.FLAG_NONE),
        )
Esempio n. 17
0
    def _flags_tree(self, root: SidebarItem) -> None:
        icon = ":/icons/flag.svg"
        icon_outline = ":/icons/flag-outline.svg"

        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_flags(),
            icon=icon_outline,
            collapse_key=Config.Bool.COLLAPSE_FLAGS,
            type=SidebarItemType.FLAG_ROOT,
        )
        root.search_node = SearchNode(flag=SearchNode.FLAG_ANY)

        for flag in self.mw.flags.all():
            root.add_child(
                SidebarItem(
                    name=flag.label,
                    icon=flag.icon,
                    search_node=flag.search_node,
                    item_type=SidebarItemType.FLAG,
                    id=flag.index,
                ))

        root.add_simple(
            tr.browsing_no_flag(),
            icon=icon_outline,
            type=SidebarItemType.FLAG,
            search_node=SearchNode(flag=SearchNode.FLAG_NONE),
        )
Esempio n. 18
0
        def render(root: SidebarItem,
                   nodes: Iterable[TagTreeNode],
                   head: str = "") -> None:
            def toggle_expand(node: TagTreeNode) -> Callable[[bool], None]:
                full_name = head + node.name
                return lambda expanded: set_tag_collapsed(
                    parent=self, tag=full_name, collapsed=not expanded
                ).run_in_background(initiator=self)

            for node in nodes:
                item = SidebarItem(
                    name=node.name,
                    icon=icon,
                    search_node=SearchNode(tag=head + node.name),
                    on_expanded=toggle_expand(node),
                    expanded=not node.collapsed,
                    item_type=SidebarItemType.TAG,
                    name_prefix=head,
                )
                root.add_child(item)
                newhead = f"{head + node.name}::"
                render(item, node.children, newhead)
Esempio n. 19
0
    def _section_root(
        self,
        *,
        root: SidebarItem,
        name: str,
        icon: Union[str, ColoredIcon],
        collapse_key: Config.Bool.Key.V,
        type: Optional[SidebarItemType] = None,
    ) -> SidebarItem:
        def update(expanded: bool) -> None:
            self.col.set_config_bool(collapse_key, not expanded)

        top = SidebarItem(
            name,
            icon,
            on_expanded=update,
            expanded=not self.col.get_config_bool(collapse_key),
            item_type=type,
        )
        root.add_child(top)

        return top
Esempio n. 20
0
 def rename_saved_search(self, item: SidebarItem, new_name: str) -> None:
     old_name = item.name
     conf = self._get_saved_searches()
     try:
         filt = conf[old_name]
     except KeyError:
         return
     if new_name in conf and not askUser(
             tr.browsing_confirm_saved_search_overwrite(name=new_name)):
         return
     conf[new_name] = filt
     del conf[old_name]
     self._set_saved_searches(conf)
     item.name = new_name
     self.refresh()
Esempio n. 21
0
    def _notetype_tree(self, root: SidebarItem) -> None:
        notetype_icon = ":/icons/newspaper.svg"
        template_icon = ":/icons/iframe-braces-outline.svg"
        field_icon = ":/icons/form-textbox.svg"

        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_notetypes(),
            icon=notetype_icon,
            collapse_key=Config.Bool.COLLAPSE_NOTETYPES,
            type=SidebarItemType.NOTETYPE_ROOT,
        )
        root.search_node = SearchNode(note="_*")

        for nt in sorted(self.col.models.all(),
                         key=lambda nt: nt["name"].lower()):
            item = SidebarItem(
                nt["name"],
                notetype_icon,
                search_node=SearchNode(note=nt["name"]),
                item_type=SidebarItemType.NOTETYPE,
                id=nt["id"],
            )

            for c, tmpl in enumerate(nt["tmpls"]):
                child = SidebarItem(
                    tmpl["name"],
                    template_icon,
                    search_node=self.col.group_searches(
                        SearchNode(note=nt["name"]), SearchNode(template=c)),
                    item_type=SidebarItemType.NOTETYPE_TEMPLATE,
                    id=tmpl["ord"],
                )
                item.add_child(child)

            for c, fld in enumerate(nt["flds"]):
                child = SidebarItem(
                    fld["name"],
                    field_icon,
                    search_node=self.col.group_searches(
                        SearchNode(note=nt["name"]),
                        SearchNode(field_name=fld["name"])),
                    item_type=SidebarItemType.NOTETYPE_FIELD,
                    id=fld["ord"],
                )
                item.add_child(child)

            root.add_child(item)
Esempio n. 22
0
    def _flags_tree(self, root: SidebarItem) -> None:
        icon = ColoredIcon(path=":/icons/flag.svg", color=colors.DISABLED)
        root = self._section_root(
            root=root,
            name=tr.browsing_sidebar_flags(),
            icon=icon,
            collapse_key=Config.Bool.COLLAPSE_FLAGS,
            type=SidebarItemType.FLAG_ROOT,
        )
        root.search_node = SearchNode(flag=SearchNode.FLAG_ANY)

        type = SidebarItemType.FLAG
        root.add_simple(
            tr.actions_red_flag(),
            icon=icon.with_color(colors.FLAG1_FG),
            type=type,
            search_node=SearchNode(flag=SearchNode.FLAG_RED),
        )
        root.add_simple(
            tr.actions_orange_flag(),
            icon=icon.with_color(colors.FLAG2_FG),
            type=type,
            search_node=SearchNode(flag=SearchNode.FLAG_ORANGE),
        )
        root.add_simple(
            tr.actions_green_flag(),
            icon=icon.with_color(colors.FLAG3_FG),
            type=type,
            search_node=SearchNode(flag=SearchNode.FLAG_GREEN),
        )
        root.add_simple(
            tr.actions_blue_flag(),
            icon=icon.with_color(colors.FLAG4_FG),
            type=type,
            search_node=SearchNode(flag=SearchNode.FLAG_BLUE),
        )
        root.add_simple(
            tr.browsing_no_flag(),
            icon=icon.with_color(colors.DISABLED),
            type=type,
            search_node=SearchNode(flag=SearchNode.FLAG_NONE),
        )
Esempio n. 23
0
    def _today_tree(self, root: SidebarItem) -> None:
        icon = ":/icons/clock-outline.svg"
        root = self._section_root(
            root=root,
            name=tr.browsing_today(),
            icon=icon,
            collapse_key=Config.Bool.COLLAPSE_TODAY,
            type=SidebarItemType.TODAY_ROOT,
        )
        type = SidebarItemType.TODAY

        root.add_simple(
            name=tr.browsing_sidebar_due_today(),
            icon=icon,
            type=type,
            search_node=SearchNode(due_on_day=0),
        )
        root.add_simple(
            name=tr.browsing_added_today(),
            icon=icon,
            type=type,
            search_node=SearchNode(added_in_days=1),
        )
        root.add_simple(
            name=tr.browsing_edited_today(),
            icon=icon,
            type=type,
            search_node=SearchNode(edited_in_days=1),
        )
        root.add_simple(
            name=tr.browsing_studied_today(),
            icon=icon,
            type=type,
            search_node=SearchNode(rated=SearchNode.Rated(days=1)),
        )
        root.add_simple(
            name=tr.browsing_sidebar_first_review(),
            icon=icon,
            type=type,
            search_node=SearchNode(introduced_in_days=1),
        )
        root.add_simple(
            name=tr.browsing_sidebar_rescheduled(),
            icon=icon,
            type=type,
            search_node=SearchNode(rated=SearchNode.Rated(
                days=1, rating=SearchNode.RATING_BY_RESCHEDULE)),
        )
        root.add_simple(
            name=tr.browsing_again_today(),
            icon=icon,
            type=type,
            search_node=SearchNode(rated=SearchNode.Rated(
                days=1, rating=SearchNode.RATING_AGAIN)),
        )
        root.add_simple(
            name=tr.browsing_sidebar_overdue(),
            icon=icon,
            type=type,
            search_node=self.col.group_searches(
                SearchNode(card_state=SearchNode.CARD_STATE_DUE),
                SearchNode(negated=SearchNode(due_on_day=0)),
            ),
        )
Esempio n. 24
0
 def rename_flag(self, item: SidebarItem, new_name: str) -> None:
     item.name = new_name
     self.mw.flags.rename_flag(item.id, new_name)