Merge pull request #1151 from RumovZ/no-sel-dec

Fix some problems with browser actions while selection is empty
This commit is contained in:
Damien Elmes 2021-04-25 20:48:40 +10:00 committed by GitHub
commit b7b329cf90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 17 deletions

View file

@ -65,6 +65,7 @@ browsing-nd-names = { $num }: { $name }
browsing-new = (new) browsing-new = (new)
browsing-new-note-type = New note type: browsing-new-note-type = New note type:
browsing-no-flag = No Flag browsing-no-flag = No Flag
browsing-no-selection = No cards or notes selected.
browsing-note = Note browsing-note = Note
# Exactly one character representing 'Notes'; should differ from browsing-card-initial. # Exactly one character representing 'Notes'; should differ from browsing-card-initial.
browsing-note-initial = N browsing-note-initial = N

View file

@ -71,6 +71,7 @@ from aqt.utils import (
shortcut, shortcut,
showInfo, showInfo,
showWarning, showWarning,
skip_if_selection_is_empty,
tooltip, tooltip,
tr, tr,
) )
@ -573,11 +574,10 @@ where id in %s"""
# Misc menu options # Misc menu options
###################################################################### ######################################################################
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def onChangeModel(self) -> None: def onChangeModel(self) -> None:
nids = self.oneModelNotes() ChangeModel(self, self.oneModelNotes())
if nids:
ChangeModel(self, nids)
def createFilteredDeck(self) -> None: def createFilteredDeck(self) -> None:
search = self.current_search() search = self.current_search()
@ -619,6 +619,7 @@ where id in %s"""
# Card deletion # Card deletion
###################################################################### ######################################################################
@skip_if_selection_is_empty
def delete_selected_notes(self) -> None: def delete_selected_notes(self) -> None:
# ensure deletion is not accidentally triggered when the user is focused # ensure deletion is not accidentally triggered when the user is focused
# in the editing screen or search bar # in the editing screen or search bar
@ -626,11 +627,7 @@ where id in %s"""
if focus != self.form.tableView: if focus != self.form.tableView:
return return
# nothing selected?
nids = self.table.get_selected_note_ids() nids = self.table.get_selected_note_ids()
if not nids:
return
# select the next card if there is one # select the next card if there is one
self.focusTo = self.editor.currentField self.focusTo = self.editor.currentField
self.table.to_next_row() self.table.to_next_row()
@ -644,14 +641,12 @@ where id in %s"""
# Deck change # Deck change
###################################################################### ######################################################################
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def set_deck_of_selected_cards(self) -> None: def set_deck_of_selected_cards(self) -> None:
from aqt.studydeck import StudyDeck from aqt.studydeck import StudyDeck
cids = self.table.get_selected_card_ids() cids = self.table.get_selected_card_ids()
if not cids:
return
did = self.mw.col.db.scalar("select did from cards where id = ?", cids[0]) did = self.mw.col.db.scalar("select did from cards where id = ?", cids[0])
current = self.mw.col.decks.get(did)["name"] current = self.mw.col.decks.get(did)["name"]
ret = StudyDeck( ret = StudyDeck(
@ -675,6 +670,7 @@ where id in %s"""
# Tags # Tags
###################################################################### ######################################################################
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def add_tags_to_selected_notes( def add_tags_to_selected_notes(
self, self,
@ -687,6 +683,7 @@ where id in %s"""
parent=self, note_ids=self.selected_notes(), space_separated_tags=tags parent=self, note_ids=self.selected_notes(), space_separated_tags=tags
).run_in_background(initiator=self) ).run_in_background(initiator=self)
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def remove_tags_from_selected_notes(self, tags: Optional[str] = None) -> None: def remove_tags_from_selected_notes(self, tags: Optional[str] = None) -> None:
"Shows prompt if tags not provided." "Shows prompt if tags not provided."
@ -721,6 +718,7 @@ where id in %s"""
is_suspended = bool(self.card and self.card.queue == QUEUE_TYPE_SUSPENDED) is_suspended = bool(self.card and self.card.queue == QUEUE_TYPE_SUSPENDED)
self.form.actionToggle_Suspend.setChecked(is_suspended) self.form.actionToggle_Suspend.setChecked(is_suspended)
@skip_if_selection_is_empty
@ensure_editor_saved @ensure_editor_saved
def suspend_selected_cards(self, checked: bool) -> None: def suspend_selected_cards(self, checked: bool) -> None:
cids = self.selected_cards() cids = self.selected_cards()
@ -732,14 +730,15 @@ where id in %s"""
# Exporting # Exporting
###################################################################### ######################################################################
@skip_if_selection_is_empty
def _on_export_notes(self) -> None: def _on_export_notes(self) -> None:
cids = self.selectedNotesAsCards() cids = self.selectedNotesAsCards()
if cids:
ExportDialog(self.mw, cids=list(cids)) ExportDialog(self.mw, cids=list(cids))
# Flags & Marking # Flags & Marking
###################################################################### ######################################################################
@skip_if_selection_is_empty
@ensure_editor_saved @ensure_editor_saved
def set_flag_of_selected_cards(self, flag: int) -> None: def set_flag_of_selected_cards(self, flag: int) -> None:
if not self.card: if not self.card:
@ -782,6 +781,7 @@ where id in %s"""
# Scheduling # Scheduling
###################################################################### ######################################################################
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def reposition(self) -> None: def reposition(self) -> None:
if self.card and self.card.queue != QUEUE_TYPE_NEW: if self.card and self.card.queue != QUEUE_TYPE_NEW:
@ -793,6 +793,7 @@ where id in %s"""
): ):
op.run_in_background() op.run_in_background()
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def set_due_date(self) -> None: def set_due_date(self) -> None:
if op := set_due_date_dialog( if op := set_due_date_dialog(
@ -802,6 +803,7 @@ where id in %s"""
): ):
op.run_in_background() op.run_in_background()
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def forget_cards(self) -> None: def forget_cards(self) -> None:
forget_cards( forget_cards(
@ -812,6 +814,7 @@ where id in %s"""
# Edit: selection # Edit: selection
###################################################################### ######################################################################
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def selectNotes(self) -> None: def selectNotes(self) -> None:
nids = self.selected_notes() nids = self.selected_notes()
@ -860,13 +863,10 @@ where id in %s"""
# Edit: replacing # Edit: replacing
###################################################################### ######################################################################
@skip_if_selection_is_empty
@ensure_editor_saved_on_trigger @ensure_editor_saved_on_trigger
def onFindReplace(self) -> None: def onFindReplace(self) -> None:
nids = self.selected_notes() FindAndReplaceDialog(self, mw=self.mw, note_ids=self.selected_notes())
if not nids:
return
FindAndReplaceDialog(self, mw=self.mw, note_ids=nids)
# Edit: finding dupes # Edit: finding dupes
###################################################################### ######################################################################

View file

@ -1009,6 +1009,19 @@ def ensure_editor_saved_on_trigger(func: Callable) -> Callable:
return pyqtSlot()(ensure_editor_saved(func)) # type: ignore return pyqtSlot()(ensure_editor_saved(func)) # type: ignore
def skip_if_selection_is_empty(func: Callable) -> Callable:
"""Make the wrapped method a no-op and show a hint if the table selection is empty."""
@wraps(func)
def decorated(self: Any, *args: Any, **kwargs: Any) -> None:
if self.table.len_selection() > 0:
func(self, *args, **kwargs)
else:
tooltip(tr.browsing_no_selection())
return decorated
class KeyboardModifiersPressed: class KeyboardModifiersPressed:
"Util for type-safe checks of currently-pressed modifier keys." "Util for type-safe checks of currently-pressed modifier keys."