Add a "Show items in selected books" choice to manage tags and manage authors.

Radio buttons are more visually intuitive than checkboxes, but it is a little strange not having a "Use all" radio button. You click the radio button again to turn it off. Adding the third button takes up more vertical space than it is worth. Switching back to checkboxes is trivial.
This commit is contained in:
Charles Haley 2023-11-05 15:32:51 +00:00 committed by Kovid Goyal
parent b43a3295fb
commit f176c4ac36
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 97 additions and 14 deletions

View File

@ -108,7 +108,10 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(_('&Cancel')) self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(_('&Cancel'))
self.buttonBox.accepted.connect(self.accepted) self.buttonBox.accepted.connect(self.accepted)
self.buttonBox.rejected.connect(self.rejected) self.buttonBox.rejected.connect(self.rejected)
self.apply_vl_checkbox.stateChanged.connect(self.use_vl_changed) self.apply_vl_checkbox.setAutoExclusive(False)
self.apply_vl_checkbox.toggled.connect(self.use_vl_changed)
self.apply_selection_checkbox.setAutoExclusive(False)
self.apply_selection_checkbox.toggled.connect(self.apply_selection_box_changed)
self.table.setAlternatingRowColors(True) self.table.setAlternatingRowColors(True)
self.table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
@ -211,8 +214,22 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.ignore_cell_changed = orig self.ignore_cell_changed = orig
def use_vl_changed(self, x): def use_vl_changed(self, x):
if self.apply_vl_checkbox.isChecked():
self.apply_selection_checkbox.setChecked(False)
self.show_table(None, None, None, False) self.show_table(None, None, None, False)
def apply_selection_box_changed(self, x):
if self.apply_selection_checkbox.isChecked():
self.apply_vl_checkbox.setChecked(False)
self.show_table(None, None, None, False)
def selection_to_apply(self):
if self.apply_selection_checkbox.isChecked():
return 'selection'
if self.apply_vl_checkbox.isChecked():
return 'virtual_library'
return None
def clear_filter(self): def clear_filter(self):
self.filter_box.setText('') self.filter_box.setText('')
self.show_table(None, None, None, False) self.show_table(None, None, None, False)
@ -221,8 +238,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.show_table(None, None, None, False) self.show_table(None, None, None, False)
def show_table(self, id_to_select, select_sort, select_link, is_first_letter): def show_table(self, id_to_select, select_sort, select_link, is_first_letter):
auts_to_show = {t[0] for t in auts_to_show = {t[0] for t in self.find_aut_func(self.selection_to_apply())}
self.find_aut_func(use_virtual_library=self.apply_vl_checkbox.isChecked())}
filter_text = icu_lower(str(self.filter_box.text())) filter_text = icu_lower(str(self.filter_box.text()))
if filter_text: if filter_text:
auts_to_show = {id_ for id_ in auts_to_show auts_to_show = {id_ for id_ in auts_to_show

View File

@ -66,17 +66,37 @@
</spacer> </spacer>
</item> </item>
<item row="0" column="4"> <item row="0" column="4">
<widget class="QCheckBox" name="apply_vl_checkbox"> <widget class="QRadioButton" name="apply_vl_checkbox">
<property name="toolTip"> <property name="toolTip">
<string>&lt;p&gt;Only show authors in the <string>&lt;p&gt;Show authors only if they appear in the
current Virtual library. Edits already done may be hidden but will current Virtual library. Edits already done may be hidden but will
not be forgotten.&lt;/p&gt;</string> not be forgotten.
&lt;/p&gt;&lt;p&gt;
Note that this box affects only what is displayed. Changes
will affect all books in your library even if this box
is checked.&lt;/p&gt;&lt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Only show authors in the current &amp;Virtual library</string> <string>Only show authors in the current &amp;Virtual library</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="4">
<widget class="QRadioButton" name="apply_selection_checkbox">
<property name="toolTip">
<string>&lt;p&gt;Show items only if they appear in the
currently selected books. Edits already done may be hidden but will
not be forgotten.
&lt;/p&gt;&lt;p&gt;
Note that this box affects only what is displayed. Changes
will affect all books in your library even if this box
is checked.&lt;/p&gt;&lt;</string>
</property>
<property name="text">
<string>O&amp;nly show authors in the currently selected books</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel"> <widget class="QLabel">
<property name="text"> <property name="text">

View File

@ -372,7 +372,10 @@ class TagListEditor(QDialog, Ui_TagListEditor):
ac.triggered.connect(self.clear_filter) ac.triggered.connect(self.clear_filter)
le.returnPressed.connect(self.do_filter) le.returnPressed.connect(self.do_filter)
self.filter_button.clicked.connect(self.do_filter) self.filter_button.clicked.connect(self.do_filter)
self.apply_vl_checkbox.clicked.connect(self.vl_box_changed) self.apply_vl_checkbox.setAutoExclusive(False)
self.apply_vl_checkbox.toggled.connect(self.vl_box_changed)
self.apply_selection_checkbox.setAutoExclusive(False)
self.apply_selection_checkbox.toggled.connect(self.apply_selection_box_changed)
self.is_enumerated = False self.is_enumerated = False
if fm: if fm:
@ -537,9 +540,24 @@ class TagListEditor(QDialog, Ui_TagListEditor):
return txt.swapcase() return txt.swapcase()
def vl_box_changed(self): def vl_box_changed(self):
if self.apply_vl_checkbox.isChecked():
self.apply_selection_checkbox.setChecked(False)
self.search_item_row = -1 self.search_item_row = -1
self.fill_in_table(None, None, False) self.fill_in_table(None, None, False)
def apply_selection_box_changed(self):
if self.apply_selection_checkbox.isChecked():
self.apply_vl_checkbox.setChecked(False)
self.search_item_row = -1
self.fill_in_table(None, None, False)
def selection_to_apply(self):
if self.apply_selection_checkbox.isChecked():
return 'selection'
if self.apply_vl_checkbox.isChecked():
return 'virtual_library'
return None
def do_search(self): def do_search(self):
self.not_found_label.setVisible(False) self.not_found_label.setVisible(False)
find_text = str(self.search_box.currentText()) find_text = str(self.search_box.currentText())
@ -653,7 +671,7 @@ class TagListEditor(QDialog, Ui_TagListEditor):
def fill_in_table(self, tags, tag_to_match, ttm_is_first_letter): def fill_in_table(self, tags, tag_to_match, ttm_is_first_letter):
self.create_table() self.create_table()
data = self.get_book_ids(self.apply_vl_checkbox.isChecked()) data = self.get_book_ids(self.selection_to_apply())
self.all_tags = {} self.all_tags = {}
filter_text = icu_lower(str(self.filter_box.text())) filter_text = icu_lower(str(self.filter_box.text()))
for k,v,count in data: for k,v,count in data:

View File

@ -72,7 +72,7 @@
</spacer> </spacer>
</item> </item>
<item row="0" column="4"> <item row="0" column="4">
<widget class="QCheckBox" name="apply_vl_checkbox"> <widget class="QRadioButton" name="apply_vl_checkbox">
<property name="toolTip"> <property name="toolTip">
<string>&lt;p&gt;Show items only if they appear in the <string>&lt;p&gt;Show items only if they appear in the
current Virtual library. Edits already done may be hidden but will current Virtual library. Edits already done may be hidden but will
@ -87,6 +87,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="4">
<widget class="QRadioButton" name="apply_selection_checkbox">
<property name="toolTip">
<string>&lt;p&gt;Show items only if they appear in the
currently selected books. Edits already done may be hidden but will
not be forgotten.
&lt;/p&gt;&lt;p&gt;
Note that this box affects only what is displayed. Changes
will affect all books in your library even if this box
is checked.&lt;/p&gt;</string>
</property>
<property name="text">
<string>O&amp;nly show items in the currently selected books</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">

View File

@ -15,7 +15,7 @@ from qt.core import (
) )
from calibre.ebooks.metadata import title_sort from calibre.ebooks.metadata import title_sort
from calibre.gui2 import config, error_dialog, gprefs, question_dialog from calibre.gui2 import config, error_dialog, gprefs, question_dialog, warning_dialog
from calibre.gui2.dialogs.edit_authors_dialog import EditAuthorsDialog from calibre.gui2.dialogs.edit_authors_dialog import EditAuthorsDialog
from calibre.gui2.dialogs.tag_categories import TagCategories from calibre.gui2.dialogs.tag_categories import TagCategories
from calibre.gui2.dialogs.tag_list_editor import TagListEditor from calibre.gui2.dialogs.tag_list_editor import TagListEditor
@ -157,7 +157,6 @@ class TagBrowserMixin: # {{{
self.library_view.model().research(reset=False) self.library_view.model().research(reset=False)
self.library_view.current_id = current_row_id # the setter checks for None self.library_view.current_id = current_row_id # the setter checks for None
def do_restriction_error(self, e): def do_restriction_error(self, e):
error_dialog(self.tags_view, _('Invalid search restriction'), error_dialog(self.tags_view, _('Invalid search restriction'),
_('The current search restriction is invalid'), _('The current search restriction is invalid'),
@ -312,8 +311,22 @@ class TagBrowserMixin: # {{{
db.new_api.clear_search_caches() db.new_api.clear_search_caches()
self.user_categories_edited() self.user_categories_edited()
# Keep this for compatibility. It isn't used here but could be used in a plugin
def get_book_ids(self, use_virtual_library, db, category): def get_book_ids(self, use_virtual_library, db, category):
book_ids = None if not use_virtual_library else self.tags_view.model().get_book_ids_to_use() return self.get_book_ids_in_vl_or_selection(
('virtual_library' if use_virtual_library else None), db, category)
def get_book_ids_in_vl_or_selection(self, use_what, db, category):
if use_what is None:
book_ids = None
elif use_what == 'virtual_library':
book_ids = self.tags_view.model().get_book_ids_to_use()
else:
book_ids = self.library_view.get_selected_ids()
if not book_ids:
warning_dialog(self.tags_view, _('No books selected'),
_('No books are selected. Showing all items.'), show=True)
book_ids = None
data = db.new_api.get_categories(book_ids=book_ids) data = db.new_api.get_categories(book_ids=book_ids)
if category in data: if category in data:
result = [(t.id, t.original_name, t.count) for t in data[category] if t.count > 0] result = [(t.id, t.original_name, t.count) for t in data[category] if t.count > 0]
@ -337,7 +350,7 @@ class TagBrowserMixin: # {{{
d = TagListEditor(self, category=category, d = TagListEditor(self, category=category,
cat_name=db.field_metadata[category]['name'], cat_name=db.field_metadata[category]['name'],
tag_to_match=tag, tag_to_match=tag,
get_book_ids=partial(self.get_book_ids, db=db, category=category), get_book_ids=partial(self.get_book_ids_in_vl_or_selection, db=db, category=category),
sorter=key, ttm_is_first_letter=is_first_letter, sorter=key, ttm_is_first_letter=is_first_letter,
fm=db.field_metadata[category], fm=db.field_metadata[category],
link_map=db.new_api.get_link_map(category)) link_map=db.new_api.get_link_map(category))
@ -514,7 +527,7 @@ class TagBrowserMixin: # {{{
Open the manage authors dialog Open the manage authors dialog
''' '''
db = self.library_view.model().db db = self.library_view.model().db
get_authors_func = partial(self.get_book_ids, db=db, category='authors') get_authors_func = partial(self.get_book_ids_in_vl_or_selection, db=db, category='authors')
if lookup_author: if lookup_author:
for t in get_authors_func(use_virtual_library=False): for t in get_authors_func(use_virtual_library=False):
if t[1] == id_: if t[1] == id_: