From 8ee99309e1ade422148370fcf5fa301422e55b53 Mon Sep 17 00:00:00 2001 From: Starson17 Date: Sat, 27 Feb 2010 16:06:58 -0500 Subject: [PATCH] Add formats to existing records --- src/calibre/gui2/add.py | 64 +++++++++++++++++---- src/calibre/gui2/dialogs/config/add_save.py | 2 + src/calibre/gui2/dialogs/config/add_save.ui | 10 ++++ src/calibre/utils/config.py | 2 + 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py index 0b37fe2515..1539443bcf 100644 --- a/src/calibre/gui2/add.py +++ b/src/calibre/gui2/add.py @@ -13,9 +13,11 @@ from calibre.gui2 import question_dialog, error_dialog, info_dialog from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata import MetaInformation from calibre.constants import preferred_encoding, filesystem_encoding +from calibre.library.database2 import LibraryDatabase2 +from calibre.utils.config import prefs class DuplicatesAdder(QThread): - + # Add duplicate books def __init__(self, parent, db, duplicates, db_adder): QThread.__init__(self, parent) self.db, self.db_adder = db, db_adder @@ -27,6 +29,7 @@ class DuplicatesAdder(QThread): formats = [f for f in formats if not f.lower().endswith('.opf')] id = self.db.create_book_entry(mi, cover=cover, add_duplicates=True) + # here we add all the formats for dupe book record created above self.db_adder.add_formats(id, formats) self.db_adder.number_of_books_added += 1 self.emit(SIGNAL('added(PyQt_PyObject)'), count) @@ -52,7 +55,7 @@ class RecursiveFind(QThread): _('Searching in')+' '+dirpath[0]) self.books += list(self.db.find_books_in_directory(dirpath[0], self.single_book_per_directory)) - + def run(self): root = os.path.abspath(self.path) try: @@ -73,7 +76,7 @@ class RecursiveFind(QThread): return self.books = [formats for formats in self.books if formats] - + if not self.canceled: self.emit(SIGNAL('found(PyQt_PyObject)'), self.books) @@ -125,6 +128,33 @@ class DBAdder(Thread): fmts[-1] = fmt return fmts + def fuzzy_title(self, title): + indefinites = ['the', 'a', 'an'] + removals = [';', ':', ',', '\'', '[', ']', '(', ')', '{', '}', '<', '>'] + replacements = ['.', '_', '-'] + title = title.strip().lower() + for removal in removals: + title = title.replace(removal, '') + for replacement in replacements: + title = title.replace(replacement, ' ') + title_split = title.split() + for indefinite in indefinites: + if title_split[0] == indefinite: + title = ' '.join(title_split[1:]) + return title + + def find_identical_books(self, mi): + author_id = [unicode(self.db.conn.get('SELECT id FROM authors WHERE name = ?;', ([mi.author[0]]), all=False))] + identical_book_ids = [] + book_ids = self.db.conn.get('SELECT book FROM books_authors_link WHERE author = ?;', (author_id), all=True) + for book_id in book_ids: + fbook_title = self.db.conn.get('SELECT title FROM books WHERE id = ?;', (book_id), all=False) + fbook_title = self.fuzzy_title(fbook_title) + mbook_title = self.fuzzy_title(mi.title) + if fbook_title == mbook_title: + identical_book_ids.append(book_id) + return identical_book_ids + def add(self, id, opf, cover, name): formats = self.ids.pop(id) if opf.endswith('.error'): @@ -145,16 +175,30 @@ class DBAdder(Thread): if self.db is not None: if cover: cover = open(cover, 'rb').read() - id = self.db.create_book_entry(mi, cover=cover, add_duplicates=False) - self.number_of_books_added += 1 - if id is None: - self.duplicates.append((mi, cover, formats)) + if prefs['add_formats_to_existing']: + identical_book_list = self.find_identical_books(mi) + if (identical_book_list): # books with same author and nearly same title exist in db + for identical_book in identical_book_list: + formats = [f for f in formats if not f.lower().endswith('.opf')] + self.add_formats(identical_book[0], formats) + else: + id = self.db.create_book_entry(mi, cover=cover, add_duplicates=True) + self.number_of_books_added += 1 # what does this do? + formats = [f for f in formats if not f.lower().endswith('.opf')] + self.add_formats(id, formats) else: - formats = [f for f in formats if not f.lower().endswith('.opf')] - self.add_formats(id, formats) + if cover: + cover = open(cover, 'rb').read() + id = self.db.create_book_entry(mi, cover=cover, add_duplicates=False) + self.number_of_books_added += 1 + if id is None: + self.duplicates.append((mi, cover, formats)) + else: + formats = [f for f in formats if not f.lower().endswith('.opf')] + self.add_formats(id, formats) else: self.names.append(name) - self.paths.append(formats[0]) + self.path.append(formats[0]) self.infos.append(mi) return mi.title diff --git a/src/calibre/gui2/dialogs/config/add_save.py b/src/calibre/gui2/dialogs/config/add_save.py index 3c1e30ff01..aff995d84f 100644 --- a/src/calibre/gui2/dialogs/config/add_save.py +++ b/src/calibre/gui2/dialogs/config/add_save.py @@ -44,6 +44,7 @@ class AddSave(QTabWidget, Ui_TabWidget): self.filename_pattern = FilenamePattern(self) self.metadata_box.layout().insertWidget(0, self.filename_pattern) self.opt_swap_author_names.setChecked(prefs['swap_author_names']) + self.opt_add_formats_to_existing.setChecked(prefs['add_formats_to_existing']) help = '\n'.join(textwrap.wrap(c.get_option('template').help, 75)) self.save_template.initialize('save_to_disk', opts.template, help) self.send_template.initialize('send_to_device', opts.send_template, help) @@ -69,6 +70,7 @@ class AddSave(QTabWidget, Ui_TabWidget): pattern = self.filename_pattern.commit() prefs['filename_pattern'] = pattern prefs['swap_author_names'] = bool(self.opt_swap_author_names.isChecked()) + prefs['add_formats_to_existing'] = bool(self.opt_add_formats_to_existing.isChecked()) return True diff --git a/src/calibre/gui2/dialogs/config/add_save.ui b/src/calibre/gui2/dialogs/config/add_save.ui index fbf9ceaf2a..1e7450ba90 100644 --- a/src/calibre/gui2/dialogs/config/add_save.ui +++ b/src/calibre/gui2/dialogs/config/add_save.ui @@ -49,6 +49,16 @@ + + + Use with caution, this option will overwrite old copies of book with new copies in same format. Title match ignores leading indefinite articles ("the", "a", "an"), punctuation, case, etc. + + + &Add new formats to existing record of same book. (Caution: overwrites previous same format with new - matches author exactly, fuzzy matches title.) + + + + &Configure metadata from file name diff --git a/src/calibre/utils/config.py b/src/calibre/utils/config.py index 4bde124c40..316fc1de64 100644 --- a/src/calibre/utils/config.py +++ b/src/calibre/utils/config.py @@ -670,6 +670,8 @@ def _prefs(): help=_('The priority of worker processes')) c.add_opt('swap_author_names', default=False, help=_('Swap author first and last names when reading metadata')) + c.add_opt('add_formats_to_existing', default=False, + help=_('Add new formats to existing book records')) c.add_opt('migrated', default=False, help='For Internal use. Don\'t modify.') return c