diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index b61c3527a8..e572fd6784 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -847,6 +847,11 @@ class ActionQuickview(InterfaceActionBase): actual_plugin = 'calibre.gui2.actions.show_quickview:ShowQuickviewAction' description = _('Show a list of related books quickly') +class ActionTagMapper(InterfaceActionBase): + name = 'Tag Mapper' + actual_plugin = 'calibre.gui2.actions.tag_mapper:TagMapAction' + description = _('Filter/transform the tags for books in the library') + class ActionTemplateTester(InterfaceActionBase): name = 'Template Tester' actual_plugin = 'calibre.gui2.actions.show_template_tester:ShowTemplateTesterAction' @@ -987,7 +992,7 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionAddToLibrary, ActionEditCollections, ActionMatchBooks, ActionChooseLibrary, ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore, ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy, - ActionMarkBooks, ActionEmbed, ActionTemplateTester] + ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper] # }}} diff --git a/src/calibre/gui2/actions/tag_mapper.py b/src/calibre/gui2/actions/tag_mapper.py new file mode 100644 index 0000000000..a0e5e5891a --- /dev/null +++ b/src/calibre/gui2/actions/tag_mapper.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2015, Kovid Goyal + +from __future__ import (unicode_literals, division, absolute_import, + print_function) +from future_builtins import map + +from calibre.gui2 import gprefs +from calibre.gui2.actions import InterfaceAction + +class TagMapAction(InterfaceAction): + + name = 'Tag Mapper' + action_spec = (_('Tag Mapper'), 'tags.png', _('Filter/transform the tags for books in the library'), None) + action_type = 'current' + + def genesis(self): + self.qaction.triggered.connect(self.start_map) + + def start_map(self): + rows = self.gui.library_view.selectionModel().selectedRows() + selected = True + if not rows or len(rows) < 2: + selected = False + rows = xrange(self.gui.library_view.model().rowCount(None)) + ids = set(map(self.gui.library_view.model().id, rows)) + self.do_map(ids, selected) + + def do_map(self, book_ids, selected): + from calibre.ebooks.metadata.tag_mapper import map_tags + from calibre.gui2.tag_mapper import RulesDialog + from calibre.gui2.device import BusyCursor + d = RulesDialog(self.gui) + d.setWindowTitle(_('Map tags for %d books in the library') % len(book_ids)) + d.rules = gprefs.get('library-tag-mapper-ruleset', ()) + txt = _('The changes will be applied to the %d selected books') if selected else _( + 'The changes will be applied to %d books in the library') + d.edit_widget.msg_label.setText(d.edit_widget.msg_label.text() + '

' + txt % len(book_ids)) + if d.exec_() != d.Accepted: + return + with BusyCursor(): + rules = d.rules + gprefs.set('library-tag-mapper-ruleset', rules) + db = self.gui.current_db.new_api + tag_map = db.all_field_for('tags', book_ids) + changed_tag_map = {} + for book_id, tags in tag_map.iteritems(): + tags = list(tags) + new_tags = map_tags(tags, rules) + if tags != new_tags: + changed_tag_map[book_id] = new_tags + if changed_tag_map: + db.set_field('tags', changed_tag_map) + self.gui.library_view.model().refresh_ids(tuple(changed_tag_map), current_row=self.gui.library_view.currentIndex().row()) diff --git a/src/calibre/gui2/tag_mapper.py b/src/calibre/gui2/tag_mapper.py index 97384b7fec..0e6e70981e 100644 --- a/src/calibre/gui2/tag_mapper.py +++ b/src/calibre/gui2/tag_mapper.py @@ -178,7 +178,7 @@ class Rules(QWidget): QWidget.__init__(self, parent) self.l = l = QVBoxLayout(self) - self.la = la = QLabel( + self.msg_label = la = QLabel( '

' + _('You can specify rules to filter/transform tags here. Click the "Add Rule" button' ' below to get started. The rules will be processed in order for every tag until either a' ' "remove" or a "keep" rule matches.') + '

' + _(