diff --git a/src/calibre/ebooks/metadata/sources/prefs.py b/src/calibre/ebooks/metadata/sources/prefs.py index 39e0933b3b..0b353f4f81 100644 --- a/src/calibre/ebooks/metadata/sources/prefs.py +++ b/src/calibre/ebooks/metadata/sources/prefs.py @@ -18,6 +18,7 @@ msprefs.defaults['wait_after_first_cover_result'] = 60 # seconds msprefs.defaults['swap_author_names'] = False msprefs.defaults['fewer_tags'] = True msprefs.defaults['find_first_edition_date'] = False +msprefs.defaults['append_comments'] = False # Google covers are often poor quality (scans/errors) but they have high # resolution, so they trump covers from better sources. So make sure they diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index 0b0da2e85b..253b9ff6cb 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -20,6 +20,9 @@ from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.opf2 import OPF, metadata_to_opf from calibre.utils.icu import sort_key from calibre.db.errors import NoSuchFormat +from calibre.library.comments import merge_comments +from calibre.ebooks.metadata.sources.prefs import msprefs + class EditMetadataAction(InterfaceAction): @@ -261,9 +264,9 @@ class EditMetadataAction(InterfaceAction): if restrict_to_failed: db.data.set_marked_ids(failed_ids) - self.apply_metadata_changes(id_map, - callback=partial(self.downloaded_metadata_applied, tdir, - restrict_to_failed)) + self.apply_metadata_changes( + id_map, merge_comments=msprefs['append_comments'], + callback=partial(self.downloaded_metadata_applied, tdir, restrict_to_failed)) def downloaded_metadata_applied(self, tdir, restrict_to_failed, *args): if restrict_to_failed: @@ -607,7 +610,7 @@ class EditMetadataAction(InterfaceAction): # Apply bulk metadata changes {{{ def apply_metadata_changes(self, id_map, title=None, msg='', callback=None, - merge_tags=True): + merge_tags=True, merge_comments=False): ''' Apply the metadata changes in id_map to the database synchronously id_map must be a mapping of ids to Metadata objects. Set any fields you @@ -640,6 +643,7 @@ class EditMetadataAction(InterfaceAction): self.apply_pd.setModal(True) self.apply_pd.show() self._am_merge_tags = merge_tags + self._am_merge_comments = merge_comments self.do_one_apply() def do_one_apply(self): @@ -684,6 +688,10 @@ class EditMetadataAction(InterfaceAction): tags = [x.strip() for x in old_tags.split(',')] + ( mi.tags if mi.tags else []) mi.tags = list(set(tags)) + if self._am_merge_comments: + old_comments = db.new_api.field_for('comments', book_id) + if old_comments and mi.comments and old_comments != mi.comments: + mi.comments = merge_comments(old_comments, mi.comments) db.set_metadata(book_id, mi, commit=False, set_title=set_title, set_authors=set_authors, notify=False) self.applied_ids.add(book_id) diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py index 908275ebcc..075c86cea7 100644 --- a/src/calibre/gui2/metadata/single.py +++ b/src/calibre/gui2/metadata/single.py @@ -27,6 +27,7 @@ from calibre.utils.config import tweaks from calibre.ebooks.metadata.book.base import Metadata from calibre.utils.localization import canonicalize_lang from calibre.utils.date import local_tz +from calibre.library.comments import merge_comments as merge_two_comments BASE_TITLE = _('Edit Metadata') @@ -372,7 +373,7 @@ class MetadataSingleDialogBase(ResizableDialog): show=True) return - def update_from_mi(self, mi, update_sorts=True, merge_tags=True): + def update_from_mi(self, mi, update_sorts=True, merge_tags=True, merge_comments=False): if not mi.is_null('title'): self.title.current_val = mi.title if update_sorts: @@ -415,7 +416,12 @@ class MetadataSingleDialogBase(ResizableDialog): if langs: self.languages.current_val = langs if mi.comments and mi.comments.strip(): - self.comments.current_val = mi.comments + val = mi.comments + if val and merge_comments: + cval = self.comments.current_val + if cval: + val = merge_two_comments(cval, val) + self.comments.current_val = val def fetch_metadata(self, *args): d = FullFetch(self.cover.pixmap(), self) @@ -437,7 +443,7 @@ class MetadataSingleDialogBase(ResizableDialog): # update_from_mi from changing the pubdate mi.pubdate = datetime(pd.year, pd.month, pd.day, tzinfo=local_tz) - self.update_from_mi(mi) + self.update_from_mi(mi, merge_comments=msprefs['append_comments']) if d.cover_pixmap is not None: self.cover.current_val = pixmap_to_data(d.cover_pixmap) diff --git a/src/calibre/gui2/preferences/metadata_sources.py b/src/calibre/gui2/preferences/metadata_sources.py index 5c4a7decd0..189c34907d 100644 --- a/src/calibre/gui2/preferences/metadata_sources.py +++ b/src/calibre/gui2/preferences/metadata_sources.py @@ -297,6 +297,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): r('swap_author_names', msprefs) r('fewer_tags', msprefs) r('find_first_edition_date', msprefs) + r('append_comments', msprefs) self.configure_plugin_button.clicked.connect(self.configure_plugin) self.sources_model = SourcesModel(self) diff --git a/src/calibre/gui2/preferences/metadata_sources.ui b/src/calibre/gui2/preferences/metadata_sources.ui index cfbdb51571..7ae0915854 100644 --- a/src/calibre/gui2/preferences/metadata_sources.ui +++ b/src/calibre/gui2/preferences/metadata_sources.ui @@ -21,55 +21,49 @@ - - - - Metadata sources + + + + Use published date of "first edition" (from worldcat.org) + + + + + + + Max. &time to wait after first match is found: + + + opt_wait_after_first_identify_result + + + + + + + Max. time to wait after first &cover is found: + + + opt_wait_after_first_cover_result + + + + + + + secs + + + + + + + <p>Different metadata sources have different sets of tags for the same book. If this option is checked, then calibre will use the smaller tag sets. These tend to be more like genres, while the larger tag sets tend to describe the books content. +<p>Note that this option will only make a practical difference if one of the metadata sources has a genre like tag set for the book you are searching for. Most often, they all have large tag sets. + + + Prefer &fewer tags - - - - - Disable any metadata sources you do not want by unchecking them. You can also set the cover priority. Covers from sources that have a higher (smaller) priority will be preferred when bulk downloading metadata. - - - - true - - - - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - - - - - Sources with a red X next to their names must be configured before they will be used. - - - true - - - - - - - Configure selected source - - - - :/images/plugins.png:/images/plugins.png - - - - @@ -139,7 +133,7 @@ - + Max. number of &tags to download: @@ -149,58 +143,74 @@ - + - - - - Max. &time to wait after first match is found: - - - opt_wait_after_first_identify_result - - - - + secs - - - - Max. time to wait after first &cover is found: - - - opt_wait_after_first_cover_result + + + + Metadata sources + + + + + Disable any metadata sources you do not want by unchecking them. You can also set the cover priority. Covers from sources that have a higher (smaller) priority will be preferred when bulk downloading metadata. + + + + true + + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + + + + Sources with a red X next to their names must be configured before they will be used. + + + true + + + + + + + Configure selected source + + + + :/images/plugins.png:/images/plugins.png + + + + - - - - secs - - - - - + + - <p>Different metadata sources have different sets of tags for the same book. If this option is checked, then calibre will use the smaller tag sets. These tend to be more like genres, while the larger tag sets tend to describe the books content. -<p>Note that this option will only make a practical difference if one of the metadata sources has a genre like tag set for the book you are searching for. Most often, they all have large tag sets. + <p>When downloading comments, append the downloaded comments to any existing comment, instead of overwriting them. - Prefer &fewer tags - - - - - - - Use published date of "first edition" (from worldcat.org) + Append &comments to existing diff --git a/src/calibre/library/comments.py b/src/calibre/library/comments.py index 5ff4977045..1416be14b6 100644 --- a/src/calibre/library/comments.py +++ b/src/calibre/library/comments.py @@ -131,6 +131,9 @@ def comments_to_html(comments): return result.renderContents(encoding=None) +def merge_comments(one, two): + return comments_to_html(one) + '\n\n' + comments_to_html(two) + def sanitize_comments_html(html): text = html2text(html) md = Markdown(safe_mode='remove')