def update_search( self, *terms: Union[str, SearchNode], joiner: SearchJoiner = "AND", ) -> None: """Modify the current search string based on modifier keys, then refresh.""" mods = KeyboardModifiersPressed() previous = SearchNode(parsable_text=self.browser.current_search()) current = self.mw.col.group_searches(*terms, joiner=joiner) # if Alt pressed, invert if mods.alt: current = SearchNode(negated=current) try: if mods.control and mods.shift: # If Ctrl+Shift, replace searches nodes of the same type. search = self.col.replace_in_search_node(previous, current) elif mods.control: # If Ctrl, AND with previous search = self.col.join_searches(previous, current, "AND") elif mods.shift: # If Shift, OR with previous search = self.col.join_searches(previous, current, "OR") else: search = self.col.build_search_string(current) except Exception as e: showWarning(str(e)) else: self.browser.search_for(search)
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)
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), )
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, self._filter_func(SearchNode(note=nt["name"])), item_type=SidebarItemType.NOTETYPE, id=nt["id"], ) for c, tmpl in enumerate(nt["tmpls"]): child = SidebarItem( tmpl["name"], icon, self._filter_func(SearchNode(note=nt["name"]), SearchNode(template=c)), item_type=SidebarItemType.NOTETYPE_TEMPLATE, full_name=f"{nt['name']}::{tmpl['name']}", ) item.add_child(child) root.add_child(item)
def show_duplicates_report(self, dupes: list[tuple[str, list[NoteId]]]) -> None: self._dupes = dupes if not self._dupesButton: self._dupesButton = b = self.form.buttonBox.addButton( tr.browsing_tag_duplicates(), QDialogButtonBox.ButtonRole.ActionRole) qconnect(b.clicked, self._tag_duplicates) text = "" groups = len(dupes) notes = sum(len(r[1]) for r in dupes) part1 = tr.browsing_group(count=groups) part2 = tr.browsing_note_count(count=notes) text += tr.browsing_found_as_across_bs(part=part1, whole=part2) text += "<p><ol>" for val, nids in dupes: text += ( """<li><a href=# onclick="pycmd('%s');return false;">%s</a>: %s</a>""" % ( html.escape( self.mw.col.build_search_string( SearchNode(nids=SearchNode.IdList(ids=nids)))), tr.browsing_note_count(count=len(nids)), html.escape(val), )) text += "</ol>" self.form.webView.stdHtml(text, context=self)
def update_search(self, *terms: Union[str, SearchNode]) -> None: """Modify the current search string based on modifier keys, then refresh.""" mods = self.mw.app.keyboardModifiers() previous = SearchNode(parsable_text=self.browser.current_search()) current = self.mw.col.group_searches(*terms) # if Alt pressed, invert if mods & Qt.AltModifier: current = SearchNode(negated=current) try: if mods & Qt.ControlModifier and mods & Qt.ShiftModifier: # If Ctrl+Shift, replace searches nodes of the same type. search = self.col.replace_in_search_node(previous, current) elif mods & Qt.ControlModifier: # If Ctrl, AND with previous search = self.col.join_searches(previous, current, "AND") elif mods & Qt.ShiftModifier: # If Shift, OR with previous search = self.col.join_searches(previous, current, "OR") else: search = self.col.build_search_string(current) except InvalidInput as e: show_invalid_search_error(e) else: self.browser.search_for(search)
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), )
def selectNotes(self) -> None: nids = self.selected_notes() # clear the selection so we don't waste energy preserving it self.table.clear_selection() search = self.col.build_search_string( SearchNode(nids=SearchNode.IdList(ids=nids))) self.search_for(search) self.table.select_all()
def showDupes(self) -> None: aqt.dialogs.open( "Browser", self.mw, search=(SearchNode(dupe=SearchNode.Dupe( notetype_id=self.note.note_type()["id"], first_field=self.note.fields[0], )), ), )
def _filtered_search_node(self) -> tuple[SearchNode]: """Return a search node that matches cards in filtered decks, if applicable excluding those in the deck being rebuild.""" if self.deck.id: return (self.col.group_searches( SearchNode(deck="filtered"), SearchNode(negated=SearchNode(deck=self.deck.name)), ), ) return (SearchNode(deck="filtered"), )
def _today_tree(self, root: SidebarItem) -> None: icon = ":/icons/clock.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 search = self._filter_func root.add_simple( name=TR.BROWSING_SIDEBAR_DUE_TODAY, icon=icon, type=type, on_click=search(SearchNode(due_on_day=0)), ) root.add_simple( name=TR.BROWSING_ADDED_TODAY, icon=icon, type=type, on_click=search(SearchNode(added_in_days=1)), ) root.add_simple( name=TR.BROWSING_EDITED_TODAY, icon=icon, type=type, on_click=search(SearchNode(edited_in_days=1)), ) root.add_simple( name=TR.BROWSING_STUDIED_TODAY, icon=icon, type=type, on_click=search(SearchNode(rated=SearchNode.Rated(days=1))), ) root.add_simple( name=TR.BROWSING_AGAIN_TODAY, icon=icon, type=type, on_click=search( SearchNode( rated=SearchNode.Rated(days=1, rating=SearchNode.RATING_AGAIN) ) ), ) root.add_simple( name=TR.BROWSING_SIDEBAR_OVERDUE, icon=icon, type=type, on_click=search( SearchNode(card_state=SearchNode.CARD_STATE_DUE), SearchNode(negated=SearchNode(due_on_day=0)), ), )
def set_default_searches(self, deck_name: str) -> None: self.form.search.setText( self.mw.col.build_search_string( SearchNode(deck=deck_name), SearchNode(card_state=SearchNode.CARD_STATE_DUE), )) self.form.search_2.setText( self.mw.col.build_search_string( SearchNode(deck=deck_name), SearchNode(card_state=SearchNode.CARD_STATE_NEW), ))
def _learning_search_node(self) -> tuple[SearchNode, ...]: """Return a search node that matches learning cards if the old scheduler is enabled. If it's a rebuild, exclude cards from this filtered deck as those will be reset. """ if self.col.sched_ver() == 1: if self.deck.id: return (self.col.group_searches( SearchNode(card_state=SearchNode.CARD_STATE_LEARN), SearchNode(negated=SearchNode(deck=self.deck.name)), ), ) return (SearchNode(card_state=SearchNode.CARD_STATE_LEARN), ) return ()
def _today_tree(self, root: SidebarItem) -> None: icon = ":/icons/clock.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_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)), ), )
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)
def _card_state_tree(self, root: SidebarItem) -> None: icon = ColoredIcon(path=":/icons/card-state.svg", color=colors.DISABLED) root = self._section_root( root=root, name=TR.BROWSING_SIDEBAR_CARD_STATE, icon=icon, collapse_key=Config.Bool.COLLAPSE_CARD_STATE, type=SidebarItemType.CARD_STATE_ROOT, ) type = SidebarItemType.CARD_STATE search = self._filter_func root.add_simple( TR.ACTIONS_NEW, icon=icon.with_color(colors.NEW_COUNT), type=type, on_click=search(SearchNode(card_state=SearchNode.CARD_STATE_NEW)), ) root.add_simple( name=TR.SCHEDULING_LEARNING, icon=icon.with_color(colors.LEARN_COUNT), type=type, on_click=search( SearchNode(card_state=SearchNode.CARD_STATE_LEARN)), ) root.add_simple( name=TR.SCHEDULING_REVIEW, icon=icon.with_color(colors.REVIEW_COUNT), type=type, on_click=search( SearchNode(card_state=SearchNode.CARD_STATE_REVIEW)), ) root.add_simple( name=TR.BROWSING_SUSPENDED, icon=icon.with_color(colors.SUSPENDED_FG), type=type, on_click=search( SearchNode(card_state=SearchNode.CARD_STATE_SUSPENDED)), ) root.add_simple( name=TR.BROWSING_BURIED, icon=icon.with_color(colors.BURIED_FG), type=type, on_click=search( SearchNode(card_state=SearchNode.CARD_STATE_BURIED)), )
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)
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), )
def browse_to_nid(note_id: Union["NoteId", int]): """Open browser and find cards by nid""" if NEW_SEARCH_SUPPORT: aqt.dialogs.open("Browser", mw, search=(SearchNode(nid=note_id), )) else: browser: Browser = aqt.dialogs.open("Browser", mw) browser.form.searchEdit.lineEdit().setText(f"nid:{note_id}") browser.onSearchActivated()
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)
def _deck_tree(self, root: SidebarItem) -> None: icon = ":/icons/deck.svg" def render(root: SidebarItem, nodes: Iterable[DeckTreeNode], head: str = "") -> None: for node in nodes: def toggle_expand() -> Callable[[bool], None]: did = node.deck_id # pylint: disable=cell-var-from-loop return lambda _: self.mw.col.decks.collapseBrowser(did) item = SidebarItem( node.name, icon, self._filter_func(SearchNode(deck=head + node.name)), toggle_expand(), not node.collapsed, item_type=SidebarItemType.DECK, id=node.deck_id, full_name=head + node.name, ) 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.on_click = self._filter_func(SearchNode(deck="*")) current = root.add_simple( name=tr(TR.BROWSING_CURRENT_DECK), icon=icon, type=SidebarItemType.DECK, on_click=self._filter_func(SearchNode(deck="current")), ) current.id = self.mw.col.decks.selected() render(root, tree.children)
def _tag_tree(self, root: SidebarItem) -> None: icon = ":/icons/tag.svg" def render(root: SidebarItem, nodes: Iterable[TagTreeNode], head: str = "") -> None: for node in nodes: def toggle_expand() -> Callable[[bool], None]: full_name = head + node.name # pylint: disable=cell-var-from-loop return lambda expanded: self.mw.col.tags.set_expanded( full_name, expanded) item = SidebarItem( node.name, icon, self._filter_func(SearchNode(tag=head + node.name)), toggle_expand(), node.expanded, item_type=SidebarItemType.TAG, full_name=head + node.name, ) 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.on_click = self._filter_func( SearchNode(negated=SearchNode(tag="none"))) root.add_simple( name=tr(TR.BROWSING_SIDEBAR_UNTAGGED), icon=icon, type=SidebarItemType.TAG_NONE, on_click=self._filter_func(SearchNode(tag="none")), ) render(root, tree.children)
def duplicatesReport( self, web: AnkiWebView, fname: str, search: str, frm: aqt.forms.finddupes.Ui_Dialog, web_context: FindDupesDialog, ) -> None: self.mw.progress.start() try: res = self.mw.col.findDupes(fname, search) except Exception as e: self.mw.progress.finish() showWarning(str(e)) return if not self._dupesButton: self._dupesButton = b = frm.buttonBox.addButton( tr.browsing_tag_duplicates(), QDialogButtonBox.ActionRole ) qconnect(b.clicked, lambda: self._onTagDupes(res)) t = "" groups = len(res) notes = sum(len(r[1]) for r in res) part1 = tr.browsing_group(count=groups) part2 = tr.browsing_note_count(count=notes) t += tr.browsing_found_as_across_bs(part=part1, whole=part2) t += "<p><ol>" for val, nids in res: t += ( """<li><a href=# onclick="pycmd('%s');return false;">%s</a>: %s</a>""" % ( html.escape( self.col.build_search_string( SearchNode(nids=SearchNode.IdList(ids=nids)) ) ), tr.browsing_note_count(count=len(nids)), html.escape(val), ) ) t += "</ol>" web.stdHtml(t, context=web_context) self.mw.progress.finish()
def on_hint_button(self) -> None: """Open the browser to show cards that match the typed-in filters but cannot be included due to internal limitations. """ manual_filters = (self.form.search.text(), *self._second_filter()) implicit_filters = ( SearchNode(card_state=SearchNode.CARD_STATE_SUSPENDED), SearchNode(card_state=SearchNode.CARD_STATE_BURIED), *self._learning_search_node(), *self._filtered_search_node(), ) manual_filter = self.col.group_searches(*manual_filters, joiner="OR") implicit_filter = self.col.group_searches(*implicit_filters, joiner="OR") try: search = self.col.build_search_string(manual_filter, implicit_filter) except Exception as err: showWarning(str(err)) else: aqt.dialogs.open("Browser", self.mw, search=(search,))
def load_flags(col: Collection) -> List[Flag]: """Return a list of all flags, reloading labels from the config.""" labels = cast(Dict[str, str], col.get_config("flagLabels", {})) icon = ColoredIcon(path=":/icons/flag.svg", color=colors.DISABLED) return [ Flag( 1, labels["1"] if "1" in labels else tr.actions_flag_red(), icon.with_color(colors.FLAG1_FG), SearchNode(flag=SearchNode.FLAG_RED), "actionRed_Flag", ), Flag( 2, labels["2"] if "2" in labels else tr.actions_flag_orange(), icon.with_color(colors.FLAG2_FG), SearchNode(flag=SearchNode.FLAG_ORANGE), "actionOrange_Flag", ), Flag( 3, labels["3"] if "3" in labels else tr.actions_flag_green(), icon.with_color(colors.FLAG3_FG), SearchNode(flag=SearchNode.FLAG_GREEN), "actionGreen_Flag", ), Flag( 4, labels["4"] if "4" in labels else tr.actions_flag_blue(), icon.with_color(colors.FLAG4_FG), SearchNode(flag=SearchNode.FLAG_BLUE), "actionBlue_Flag", ), Flag( 5, 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", ), ]
def _default_search(self, card: Card | None = None) -> None: default = self.col.get_config_string(Config.String.DEFAULT_SEARCH_TEXT) if default.strip(): search = default prompt = default else: search = self.col.build_search_string(SearchNode(deck="current")) prompt = "" if card is not None: search = gui_hooks.default_search(search, card) self.search_for(search, prompt)
def _load_flags(self) -> None: labels = cast(dict[str, str], self.mw.col.get_config("flagLabels", {})) icon = ColoredIcon(path=":/icons/flag.svg", color=colors.DISABLED) self._flags = [ Flag( 1, labels["1"] if "1" in labels else tr.actions_flag_red(), icon.with_color(colors.FLAG1_FG), SearchNode(flag=SearchNode.FLAG_RED), "actionRed_Flag", ), Flag( 2, labels["2"] if "2" in labels else tr.actions_flag_orange(), icon.with_color(colors.FLAG2_FG), SearchNode(flag=SearchNode.FLAG_ORANGE), "actionOrange_Flag", ), Flag( 3, labels["3"] if "3" in labels else tr.actions_flag_green(), icon.with_color(colors.FLAG3_FG), SearchNode(flag=SearchNode.FLAG_GREEN), "actionGreen_Flag", ), Flag( 4, labels["4"] if "4" in labels else tr.actions_flag_blue(), icon.with_color(colors.FLAG4_FG), SearchNode(flag=SearchNode.FLAG_BLUE), "actionBlue_Flag", ), Flag( 5, 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", ), ]
def onHistory(self) -> None: m = QMenu(self) for nid in self.history: if self.mw.col.findNotes(SearchNode(nid=nid)): note = self.mw.col.get_note(nid) fields = note.fields txt = htmlToTextLine(", ".join(fields)) if len(txt) > 30: txt = f"{txt[:30]}..." line = tr(TR.ADDING_EDIT, val=txt) line = gui_hooks.addcards_will_add_history_entry(line, note) a = m.addAction(line) qconnect(a.triggered, lambda b, nid=nid: self.editHistory(nid)) else: a = m.addAction(tr(TR.ADDING_NOTE_DELETED)) a.setEnabled(False) gui_hooks.add_cards_will_show_history_menu(self, m) m.exec_(self.historyButton.mapToGlobal(QPoint(0, 0)))
def setupSearch( self, card: Optional[Card] = None, search: Optional[Tuple[Union[str, SearchNode]]] = None, ) -> None: qconnect(self.form.searchEdit.lineEdit().returnPressed, self.onSearchActivated) self.form.searchEdit.setCompleter(None) self.form.searchEdit.lineEdit().setPlaceholderText( tr.browsing_search_bar_hint()) self.form.searchEdit.addItems(self.mw.pm.profile["searchHistory"]) if search is not None: self.search_for_terms(*search) elif card: self.show_single_card(card) else: self.search_for( self.col.build_search_string(SearchNode(deck="current")), "") self.form.searchEdit.setFocus()
def _on_render_latex(self) -> None: self.progress_dialog = self.mw.progress.start() try: out = self.mw.col.media.render_all_latex( self._on_render_latex_progress) if self.progress_dialog.wantCancel: return finally: self.mw.progress.finish() self.progress_dialog = None if out is not None: nid, err = out aqt.dialogs.open("Browser", self.mw, search=(SearchNode(nid=nid), )) showText(err, type="html") else: tooltip(tr.media_check_all_latex_rendered())