diff --git a/src/calibre/gui2/dialogs/tag_list_editor.ui b/src/calibre/gui2/dialogs/tag_list_editor.ui
index 3123316e9b..d8dadb9047 100644
--- a/src/calibre/gui2/dialogs/tag_list_editor.ui
+++ b/src/calibre/gui2/dialogs/tag_list_editor.ui
@@ -76,7 +76,11 @@
<p>Show items only if they appear in the
current Virtual library. Edits already done may be hidden but will
- not be forgotten.</p>
+ not be forgotten.
+ </p><p>
+ Note that this box affects only what is displayed. Changes
+ will affect all books in your library even if this box
+ is checked.</p>
Only show items in the current &Virtual library
diff --git a/src/calibre/gui2/tag_browser/model.py b/src/calibre/gui2/tag_browser/model.py
index beee2621fc..5475239e25 100644
--- a/src/calibre/gui2/tag_browser/model.py
+++ b/src/calibre/gui2/tag_browser/model.py
@@ -968,7 +968,6 @@ class TagsModel(QAbstractItemModel): # {{{
self.db.new_api.set_pref('user_categories', user_cats)
self.refresh_required.emit()
self.user_category_added.emit()
-
return True
def do_drop_from_library(self, md, action, row, column, parent):
@@ -1315,9 +1314,7 @@ class TagsModel(QAbstractItemModel): # {{{
an_item.tag.name = new_name
an_item.tag.state = TAG_SEARCH_STATES['clear']
self.use_position_based_index_on_next_recount = True
- if not restrict_to_books:
- self.rename_item_in_all_user_categories(original_name,
- lookup_key, new_name)
+ self.add_renamed_item_to_user_categories(lookup_key, original_name, new_name)
children = item.all_children()
restrict_to_book_ids=self.get_book_ids_to_use() if item.use_vl else None
@@ -1341,6 +1338,7 @@ class TagsModel(QAbstractItemModel): # {{{
new_name = to_what + child_item.tag.original_name[len(search_name):]
do_one_item(key, child_item, child_item.tag.original_name,
new_name, restrict_to_book_ids)
+ self.clean_items_from_user_categories()
self.refresh_required.emit()
def rename_item_in_all_user_categories(self, item_name, item_category, new_name):
@@ -1386,6 +1384,53 @@ class TagsModel(QAbstractItemModel): # {{{
if user_categories is None:
self.db.new_api.set_pref('user_categories', user_cats)
+ def add_renamed_item_to_user_categories(self, lookup_key, original_name, new_name):
+ '''
+ Add new_name to any user category that contains original name if new_name
+ isn't already there. The original name isn't deleted. This is the first
+ step when renaming user categories that might be in virtual libraries
+ because when finished both names may still exist. You should call
+ clean_items_from_user_categories() when done to remove any keys that no
+ longer exist from all user categories. The caller must arrange to
+ redisplay the tree as appropriate.
+ '''
+ user_cats = self.db.new_api.pref('user_categories', {})
+ for cat in user_cats.keys():
+ found_original = False
+ found_new = False
+ for name,key,_ in user_cats[cat]:
+ if key == lookup_key:
+ if name == original_name:
+ found_original = True
+ if name == new_name:
+ found_new = True
+ if found_original and not found_new:
+ user_cats[cat].append([new_name, lookup_key, 0])
+ self.db.new_api.set_pref('user_categories', user_cats)
+
+ def clean_items_from_user_categories(self):
+ '''
+ Remove any items that no longer exist from user categories. This can
+ happen when renaming items in virtual libraries, where sometimes the
+ old name still exists on some book not in the VL and sometimes it
+ doesn't. The caller must arrange to redisplay the tree as appropriate.
+ '''
+ user_cats = self.db.new_api.pref('user_categories', {})
+ cache = self.db.new_api
+ all_cats = {}
+ for cat in user_cats.keys():
+ new_cat = []
+ for val, key, _ in user_cats[cat]:
+ datatype = cache.field_metadata.get(key, {}).get('datatype', '*****')
+ if datatype != 'composite':
+ id_ = cache.get_item_id(key, val)
+ v = cache.books_for_field(key, id_)
+ if v:
+ new_cat.append([val, key, 0])
+ if new_cat:
+ all_cats[cat] = new_cat
+ self.db.new_api.set_pref('user_categories', all_cats)
+
def headerData(self, *args):
return None