diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py index 72f0efd9bf..a64eb2eb9a 100644 --- a/src/calibre/gui2/tag_view.py +++ b/src/calibre/gui2/tag_view.py @@ -424,10 +424,8 @@ class TagsModel(QAbstractItemModel): # {{{ self.categories = [] # Reconstruct the user categories, putting them into metadata + self.db.field_metadata.remove_dynamic_categories() tb_cats = self.db.field_metadata - for k in tb_cats.keys(): - if tb_cats[k]['kind'] in ['user', 'search']: - del tb_cats[k] for user_cat in sorted(self.db.prefs.get('user_categories', {}).keys()): cat_name = user_cat+':' # add the ':' to avoid name collision tb_cats.add_user_category(label=cat_name, name=user_cat) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 624935f279..f40eed1fcd 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -523,11 +523,15 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ def shutdown(self, write_settings=True): try: - cf = self.library_view.model().db.clean + db = self.library_view.model().db + cf = db.clean except: pass else: cf() + # Save the current field_metadata for applications like calibre2opds + # Goes here, because if cf is valid, db is valid. + db.prefs['field_metadata'] = db.field_metadata.all_metadata() for action in self.iactions.values(): if not action.shutting_down(): return diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index 0bd0610ab0..9a2d0b0a62 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -576,6 +576,9 @@ def command_add_custom_column(args, dbpath): return 1 do_add_custom_column(get_db(dbpath, opts), args[0], args[1], args[2], opts.is_multiple, json.loads(opts.display)) + # Re-open the DB so that field_metadata is reflects the column changes + db = get_db(dbpath, opts) + db.prefs['field_metadata'] = db.field_metadata.all_metadata() return 0 def catalog_option_parser(args): @@ -806,6 +809,9 @@ def command_remove_custom_column(args, dbpath): return 1 do_remove_custom_column(get_db(dbpath, opts), args[0], opts.force) + # Re-open the DB so that field_metadata is reflects the column changes + db = get_db(dbpath, opts) + db.prefs['field_metadata'] = db.field_metadata.all_metadata() return 0 def saved_searches_option_parser(): diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 52b5f2d4e6..cc4ddb1c17 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -290,10 +290,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): # Reconstruct the user categories, putting them into field_metadata # Assumption is that someone else will fix them if they change. + self.field_metadata.remove_dynamic_categories() tb_cats = self.field_metadata - for k in tb_cats.keys(): - if tb_cats[k]['kind'] in ['user', 'search']: - del tb_cats[k] for user_cat in sorted(self.prefs.get('user_categories', {}).keys()): cat_name = user_cat+':' # add the ':' to avoid name collision tb_cats.add_user_category(label=cat_name, name=user_cat) diff --git a/src/calibre/library/field_metadata.py b/src/calibre/library/field_metadata.py index 09dd024b66..66cdee51f0 100644 --- a/src/calibre/library/field_metadata.py +++ b/src/calibre/library/field_metadata.py @@ -371,6 +371,12 @@ class FieldMetadata(dict): def get_custom_fields(self): return [l for l in self._tb_cats if self._tb_cats[l]['is_custom']] + def all_metadata(self): + l = {} + for k in self._tb_cats: + l[k] = self._tb_cats[k] + return l + def get_custom_field_metadata(self): l = {} for k in self._tb_cats: @@ -408,6 +414,12 @@ class FieldMetadata(dict): self._add_search_terms_to_map(key, [key]) self.custom_label_to_key_map[label+'_index'] = key + def remove_dynamic_categories(self): + for key in list(self._tb_cats.keys()): + val = self._tb_cats[key] + if val['is_category'] and val['kind'] in ('user', 'search'): + del self._tb_cats[key] + def cc_series_index_column_for(self, key): return self._tb_cats[key]['rec_index'] + 1