Enhancement to manage user categories: allow filtering the available items by the current virtual library

This commit is contained in:
Charles Haley 2015-04-06 11:19:05 +02:00
parent c9cf3066e8
commit 13c34447aa
3 changed files with 72 additions and 45 deletions

View File

@ -35,7 +35,7 @@ class TagCategories(QDialog, Ui_TagCategories):
''' '''
category_labels_orig = ['', 'authors', 'series', 'publisher', 'tags'] category_labels_orig = ['', 'authors', 'series', 'publisher', 'tags']
def __init__(self, window, db, on_category=None): def __init__(self, window, db, on_category=None, book_ids = None):
QDialog.__init__(self, window) QDialog.__init__(self, window)
Ui_TagCategories.__init__(self) Ui_TagCategories.__init__(self)
self.setupUi(self) self.setupUi(self)
@ -47,69 +47,41 @@ class TagCategories(QDialog, Ui_TagCategories):
self.db = db self.db = db
self.applied_items = [] self.applied_items = []
self.book_ids = book_ids
if self.book_ids is None:
self.apply_vl_checkbox.setEnabled(False)
cc_icon = QIcon(I('column.png')) cc_icon = QIcon(I('column.png'))
self.category_labels = self.category_labels_orig[:] self.category_labels = self.category_labels_orig[:]
category_icons = [None, QIcon(I('user_profile.png')), QIcon(I('series.png')), self.category_icons = [None, QIcon(I('user_profile.png')), QIcon(I('series.png')),
QIcon(I('publisher.png')), QIcon(I('tags.png'))] QIcon(I('publisher.png')), QIcon(I('tags.png'))]
category_values = [None, self.category_values = [None,
lambda: [n.replace('|', ',') for (id, n) in self.db.all_authors()], lambda: [t.original_name.replace('|', ',') for t in self.db_categories['authors']],
lambda: [n for (id, n) in self.db.all_series()], lambda: [t.original_name for t in self.db_categories['series']],
lambda: [n for (id, n) in self.db.all_publishers()], lambda: [t.original_name for t in self.db_categories['publisher']],
lambda: self.db.all_tags() lambda: [t.original_name for t in self.db_categories['tags']]
] ]
category_names = ['', _('Authors'), ngettext('Series', 'Series', 2), _('Publishers'), _('Tags')] category_names = ['', _('Authors'), ngettext('Series', 'Series', 2), _('Publishers'), _('Tags')]
cvals = {}
for key,cc in self.db.custom_field_metadata().iteritems(): for key,cc in self.db.custom_field_metadata().iteritems():
if cc['datatype'] in ['text', 'series', 'enumeration']: if cc['datatype'] in ['text', 'series', 'enumeration']:
self.category_labels.append(key) self.category_labels.append(key)
category_icons.append(cc_icon) self.category_icons.append(cc_icon)
category_values.append(lambda col=cc['label']: self.db.all_custom(label=col)) self.category_values.append(lambda col=key: [t.original_name for t in self.db_categories[col]])
category_names.append(cc['name']) category_names.append(cc['name'])
elif cc['datatype'] == 'composite' and \ elif cc['datatype'] == 'composite' and \
cc['display'].get('make_category', False): cc['display'].get('make_category', False):
self.category_labels.append(key) self.category_labels.append(key)
category_icons.append(cc_icon) self.category_icons.append(cc_icon)
category_names.append(cc['name']) category_names.append(cc['name'])
dex = cc['rec_index'] self.category_values.append(lambda col=key: [t.original_name for t in self.db_categories[col]])
cvals = set()
for book in db.data.iterall():
if book[dex]:
cvals.add(book[dex])
category_values.append(lambda s=list(cvals): s)
self.all_items = []
self.all_items_dict = {}
for idx,label in enumerate(self.category_labels):
if idx == 0:
continue
for n in category_values[idx]():
t = Item(name=n, label=label, index=len(self.all_items),
icon=category_icons[idx], exists=True)
self.all_items.append(t)
self.all_items_dict[icu_lower(label+':'+n)] = t
self.categories = dict.copy(db.prefs.get('user_categories', {})) self.categories = dict.copy(db.prefs.get('user_categories', {}))
if self.categories is None: if self.categories is None:
self.categories = {} self.categories = {}
for cat in self.categories: self.initialize_category_lists(book_ids=None)
for item,l in enumerate(self.categories[cat]):
key = icu_lower(':'.join([l[1], l[0]]))
t = self.all_items_dict.get(key, None)
if l[1] in self.category_labels:
if t is None:
t = Item(name=l[0], label=l[1], index=len(self.all_items),
icon=category_icons[self.category_labels.index(l[1])],
exists=False)
self.all_items.append(t)
self.all_items_dict[key] = t
l[2] = t.index
else:
# remove any references to a category that no longer exists
del self.categories[cat][item]
self.all_items_sorted = sorted(self.all_items, key=lambda x: sort_key(x.name))
self.display_filtered_categories(0) self.display_filtered_categories(0)
for v in category_names: for v in category_names:
@ -129,6 +101,7 @@ class TagCategories(QDialog, Ui_TagCategories):
else: else:
self.available_items_box.itemActivated.connect(self.apply_tags) self.available_items_box.itemActivated.connect(self.apply_tags)
self.applied_items_box.itemActivated.connect(self.unapply_tags) self.applied_items_box.itemActivated.connect(self.unapply_tags)
self.apply_vl_checkbox.clicked.connect(self.apply_vl)
self.populate_category_list() self.populate_category_list()
if on_category is not None: if on_category is not None:
@ -139,6 +112,44 @@ class TagCategories(QDialog, Ui_TagCategories):
self.category_box.setCurrentIndex(0) self.category_box.setCurrentIndex(0)
self.select_category(0) self.select_category(0)
def initialize_category_lists(self, book_ids):
self.db_categories = self.db.new_api.get_categories(book_ids=book_ids)
self.all_items = []
self.all_items_dict = {}
for idx,label in enumerate(self.category_labels):
if idx == 0:
continue
for n in self.category_values[idx]():
t = Item(name=n, label=label, index=len(self.all_items),
icon=self.category_icons[idx], exists=True)
self.all_items.append(t)
self.all_items_dict[icu_lower(label+':'+n)] = t
for cat in self.categories:
for item,l in enumerate(self.categories[cat]):
key = icu_lower(':'.join([l[1], l[0]]))
t = self.all_items_dict.get(key, None)
if l[1] in self.category_labels:
if t is None:
t = Item(name=l[0], label=l[1], index=len(self.all_items),
icon=self.category_icons[self.category_labels.index(l[1])],
exists=False)
self.all_items.append(t)
self.all_items_dict[key] = t
l[2] = t.index
else:
# remove any references to a category that no longer exists
del self.categories[cat][item]
self.all_items_sorted = sorted(self.all_items, key=lambda x: sort_key(x.name))
def apply_vl(self, checked):
if checked:
self.initialize_category_lists(self.book_ids)
else:
self.initialize_category_lists(None)
self.fill_applied_items()
def make_list_widget(self, item): def make_list_widget(self, item):
n = item.name if item.exists else item.name + _(' (not on any book)') n = item.name if item.exists else item.name + _(' (not on any book)')
w = QListWidgetItem(item.icon, n) w = QListWidgetItem(item.icon, n)
@ -256,6 +267,9 @@ class TagCategories(QDialog, Ui_TagCategories):
self.current_cat_name = unicode(s) self.current_cat_name = unicode(s)
else: else:
self.current_cat_name = None self.current_cat_name = None
self.fill_applied_items()
def fill_applied_items(self):
if self.current_cat_name: if self.current_cat_name:
self.applied_items = [cat[2] for cat in self.categories.get(self.current_cat_name, [])] self.applied_items = [cat[2] for cat in self.categories.get(self.current_cat_name, [])]
else: else:

View File

@ -150,6 +150,18 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="1" colspan="2">
<widget class="QCheckBox" name="apply_vl_checkbox">
<property name="toolTip">
<string>&lt;p&gt;Show items in the Available items box only if they appear in the
current virtual library. Applied items not in the VL will be marked
"not on any book".&lt;/p&gt;</string>
</property>
<property name="text">
<string>Show only available items in current virtual library</string>
</property>
</widget>
</item>
<item row="2" column="0"> <item row="2" column="0">
<layout class="QVBoxLayout"> <layout class="QVBoxLayout">
<item> <item>

View File

@ -108,7 +108,8 @@ class TagBrowserMixin(object): # {{{
Open the user categories editor. Open the user categories editor.
''' '''
db = self.library_view.model().db db = self.library_view.model().db
d = TagCategories(self, db, on_category) d = TagCategories(self, db, on_category,
book_ids=self.tags_view.model().get_book_ids_to_use())
if d.exec_() == d.Accepted: if d.exec_() == d.Accepted:
db.new_api.set_pref('user_categories', d.categories) db.new_api.set_pref('user_categories', d.categories)
db.field_metadata.remove_user_categories() db.field_metadata.remove_user_categories()