diff --git a/src/calibre/gui2/dialogs/edit_authors_dialog.py b/src/calibre/gui2/dialogs/edit_authors_dialog.py
index f7002ef781..159dd86230 100644
--- a/src/calibre/gui2/dialogs/edit_authors_dialog.py
+++ b/src/calibre/gui2/dialogs/edit_authors_dialog.py
@@ -185,8 +185,9 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
ac.triggered.connect(self.clear_find)
le.returnPressed.connect(self.do_find)
self.find_box.editTextChanged.connect(self.find_text_changed)
- self.find_button.clicked.connect(self.do_find)
+ self.find_button.clicked.connect(partial(self.do_find, inverted=False))
self.find_button.setDefault(True)
+ self.find_inverted_button.clicked.connect(partial(self.do_find, inverted=True))
self.filter_box.initialize('manage_authors_filter')
le = self.filter_box.lineEdit()
@@ -194,7 +195,8 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
if ac is not None:
ac.triggered.connect(self.clear_filter)
self.filter_box.lineEdit().returnPressed.connect(self.do_filter)
- self.filter_button.clicked.connect(self.do_filter)
+ self.filter_button.clicked.connect(partial(self.do_filter, inverted=False))
+ self.filter_inverted_button.clicked.connect(partial(self.do_filter, inverted=True))
self.not_found_label = l = QLabel(self.table)
l.setFrameStyle(QFrame.Shape.StyledPanel)
@@ -212,6 +214,8 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.table.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.table.customContextMenuRequested.connect(self.show_context_menu)
+ self.inverted_filter = False
+
# Fetch the data
self.authors = {}
self.original_authors = {}
@@ -274,7 +278,8 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.filter_box.setText('')
self.show_table(None, None, None, False)
- def do_filter(self):
+ def do_filter(self, inverted):
+ self.inverted_filter = inverted
self.show_table(None, None, None, False)
def show_table(self, id_to_select, select_sort, select_link, is_first_letter):
@@ -282,7 +287,8 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
filter_text = icu_lower(str(self.filter_box.text()))
if filter_text:
auts_to_show = {id_ for id_ in auts_to_show
- if self.string_contains(filter_text, icu_lower(self.authors[id_]['name']))}
+ if self.string_contains(filter_text,
+ icu_lower(self.authors[id_]['name'])) != self.inverted_filter}
self.table.blockSignals(True)
self.table.clear()
@@ -530,7 +536,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
def find_text_changed(self):
self.start_find_pos = -1
- def do_find(self):
+ def do_find(self, inverted=False):
self.not_found_label.setVisible(False)
# For some reason the button box keeps stealing the RETURN shortcut.
# Steal it back
@@ -548,7 +554,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
c = self.start_find_pos % 2
item = self.table.item(r, c)
text = icu_lower(str(item.text()))
- if st in text:
+ if (st in text) != inverted:
self.table.setCurrentItem(item)
self.table.setFocus(Qt.FocusReason.OtherFocusReason)
return
diff --git a/src/calibre/gui2/dialogs/edit_authors_dialog.ui b/src/calibre/gui2/dialogs/edit_authors_dialog.ui
index 5746456f99..1f308cb70e 100644
--- a/src/calibre/gui2/dialogs/edit_authors_dialog.ui
+++ b/src/calibre/gui2/dialogs/edit_authors_dialog.ui
@@ -37,10 +37,9 @@
- <p>Only show authors that contain the text in this box.
- The match ignores case.</p>
+ Filter names in the Authors column using the text in this box. The search ignores case.
-
+
true
@@ -63,13 +62,16 @@
0
+
+ Search for names in the Authors column using the text in this box. The search ignores case.
+
200
0
-
+
true
@@ -89,6 +91,19 @@
Fi<er
+
+ Show all authors containing the filter text
+
+
+
+ -
+
+
+ Filter "not in"
+
+
+ Show all authors that do not contain the filter text
+
-
@@ -96,9 +111,22 @@
S&earch
+
+ Search for authors containing the search text
+
- -
+
-
+
+
+ Search "not in"
+
+
+ Search for authors that do not contain the search text
+
+
+
+ -
-
@@ -126,7 +154,7 @@
-
- <p>Show items only if they appear in the
+ <p>Show authors only if they appear in the
currently selected books. Edits already done may be hidden but will
not be forgotten.
</p><p>
diff --git a/src/calibre/gui2/dialogs/tag_list_editor.py b/src/calibre/gui2/dialogs/tag_list_editor.py
index ef3458de1f..80c09876af 100644
--- a/src/calibre/gui2/dialogs/tag_list_editor.py
+++ b/src/calibre/gui2/dialogs/tag_list_editor.py
@@ -405,8 +405,9 @@ class TagListEditor(QDialog, Ui_TagListEditor):
if ac is not None:
ac.triggered.connect(self.clear_search)
self.search_box.textChanged.connect(self.search_text_changed)
- self.search_button.clicked.connect(self.do_search)
+ self.search_button.clicked.connect(partial(self.do_search, inverted=False))
self.search_button.setDefault(True)
+ self.search_inverted_button.clicked.connect(partial(self.do_search, inverted=True))
self.filter_box.initialize('tag_list_filter_box_' + cat_name)
le = self.filter_box.lineEdit()
@@ -414,7 +415,9 @@ class TagListEditor(QDialog, Ui_TagListEditor):
if ac is not None:
ac.triggered.connect(self.clear_filter)
le.returnPressed.connect(self.do_filter)
- self.filter_button.clicked.connect(self.do_filter)
+ self.filter_button.clicked.connect(partial(self.do_filter, inverted=False))
+ self.filter_inverted_button.clicked.connect(partial(self.do_filter, inverted=True))
+ self.filter_inverted = False
self.show_button_layout.setSpacing(0)
self.show_button_layout.setContentsMargins(0, 0, 0, 0)
self.apply_all_checkbox.setContentsMargins(0, 0, 0, 0)
@@ -600,14 +603,14 @@ class TagListEditor(QDialog, Ui_TagListEditor):
return 'virtual_library'
return None
- def do_search(self):
+ def do_search(self, inverted=False):
self.not_found_label.setVisible(False)
find_text = str(self.search_box.currentText())
if not find_text:
return
for _ in range(self.table.rowCount()):
r = self.search_item_row = (self.search_item_row + 1) % self.table.rowCount()
- if self.string_contains(find_text, self.table.item(r, VALUE_COLUMN).text()):
+ if self.string_contains(find_text, self.table.item(r, VALUE_COLUMN).text()) != inverted:
self.table.setCurrentItem(self.table.item(r, VALUE_COLUMN))
self.table.setFocus(Qt.FocusReason.OtherFocusReason)
return
@@ -717,7 +720,7 @@ class TagListEditor(QDialog, Ui_TagListEditor):
self.all_tags = {}
filter_text = icu_lower(str(self.filter_box.text()))
for k,v,count in data:
- if not filter_text or self.string_contains(filter_text, icu_lower(v)):
+ if not filter_text or self.string_contains(filter_text, icu_lower(v)) != self.filter_inverted:
self.all_tags[v] = {'key': k, 'count': count, 'cur_name': v,
'is_deleted': k in self.to_delete}
self.original_names[k] = v
@@ -844,7 +847,8 @@ class TagListEditor(QDialog, Ui_TagListEditor):
self.filter_box.setText(txt)
self.do_filter()
- def do_filter(self):
+ def do_filter(self, inverted=False):
+ self.filter_inverted = inverted
self.fill_in_table(None, None, False)
def table_column_resized(self, *args):
diff --git a/src/calibre/gui2/dialogs/tag_list_editor.ui b/src/calibre/gui2/dialogs/tag_list_editor.ui
index 5fabb9fa94..bb84d4cc9b 100644
--- a/src/calibre/gui2/dialogs/tag_list_editor.ui
+++ b/src/calibre/gui2/dialogs/tag_list_editor.ui
@@ -65,7 +65,7 @@
- Search for an item in the first column
+ Search for an item in the first column using the text in this box. The search ignores case.
true
@@ -81,7 +81,7 @@
- Find items containing the search string
+ Search for items that contain the search text
S&earch
@@ -92,6 +92,26 @@
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Search "not in"
+
+
+ Search for items that do not contain the search text
+
+
+
+ :/images/search.png:/images/search.png
+
+
+
@@ -135,7 +155,7 @@
- Filter items using the text in this box
+ Filter items in the first column using the text in this box. The search ignores case.
true
@@ -151,7 +171,7 @@
- Show only items containing this text
+ Show all items that contain the filter text
F&ilter
@@ -162,6 +182,26 @@
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Filter "not in"
+
+
+ Show all items that do not contain the filter text
+
+
+
+ :/images/filter.png:/images/filter.png
+
+
+