diff --git a/src/calibre/db/backend.py b/src/calibre/db/backend.py index 851b9df1d6..1b87da8548 100644 --- a/src/calibre/db/backend.py +++ b/src/calibre/db/backend.py @@ -1199,14 +1199,18 @@ class DB(object): def has_format(self, book_id, fmt, fname, path): return self.format_abspath(book_id, fmt, fname, path) is not None - def remove_format(self, book_id, fmt, fname, path): - path = self.format_abspath(book_id, fmt, fname, path) - if path is not None: - try: - delete_service().delete_files((path,), self.library_path) - except: - import traceback - traceback.print_exc() + def remove_formats(self, remove_map): + paths = [] + for book_id, removals in remove_map.iteritems(): + for fmt, fname, path in removals: + path = self.format_abspath(book_id, fmt, fname, path) + if path is not None: + paths.append(path) + try: + delete_service().delete_files(paths, self.library_path) + except: + import traceback + traceback.print_exc() def cover_last_modified(self, path): path = os.path.abspath(os.path.join(self.library_path, path, 'cover.jpg')) diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index 0313e6ffe6..bf3a807984 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -1280,6 +1280,7 @@ class Cache(object): self.format_metadata_cache[book_id].pop(fmt, None) if not db_only: + removes = defaultdict(set) for book_id, fmts in formats_map.iteritems(): try: path = self._field_for('path', book_id).replace('/', os.sep) @@ -1291,7 +1292,9 @@ class Cache(object): except: continue if name and path: - self.backend.remove_format(book_id, fmt, name, path) + removes[book_id].add((fmt, name, path)) + if removes: + self.backend.remove_formats(removes) size_map = table.remove_formats(formats_map, self.backend) self.fields['size'].table.update_sizes(size_map) diff --git a/src/calibre/gui2/actions/delete.py b/src/calibre/gui2/actions/delete.py index ddd71ee18f..654da7d6a3 100644 --- a/src/calibre/gui2/actions/delete.py +++ b/src/calibre/gui2/actions/delete.py @@ -196,12 +196,10 @@ class DeleteAction(InterfaceAction): _('Choose formats to be deleted'), ids) if not fmts: return - for id in ids: - for fmt in fmts: - self.gui.library_view.model().db.remove_format(id, fmt, - index_is_id=True, notify=False) - self.gui.library_view.model().refresh_ids(ids) - self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), + m = self.gui.library_view.model() + m.db.new_api.remove_formats({book_id:fmts for book_id in ids}) + m.refresh_ids(ids) + m.current_changed(self.gui.library_view.currentIndex(), self.gui.library_view.currentIndex()) if ids: self.gui.tags_view.recount() @@ -216,8 +214,10 @@ class DeleteAction(InterfaceAction): exclude=True) if fmts is None: return + m = self.gui.library_view.model() + removals = {} for id in ids: - bfmts = self.gui.library_view.model().db.formats(id, index_is_id=True) + bfmts = m.db.formats(id, index_is_id=True) if bfmts is None: continue bfmts = set([x.lower() for x in bfmts.split(',')]) @@ -225,14 +225,14 @@ class DeleteAction(InterfaceAction): if bfmts - rfmts: # Do not delete if it will leave the book with no # formats - for fmt in rfmts: - self.gui.library_view.model().db.remove_format(id, fmt, - index_is_id=True, notify=False) - self.gui.library_view.model().refresh_ids(ids) - self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), - self.gui.library_view.currentIndex()) - if ids: - self.gui.tags_view.recount() + removals[id] = rfmts + if removals: + m.db.new_api.remove_formats(removals) + m.refresh_ids(ids) + m.current_changed(self.gui.library_view.currentIndex(), + self.gui.library_view.currentIndex()) + if ids: + self.gui.tags_view.recount() def delete_all_formats(self, *args): ids = self._get_selected_ids() @@ -244,17 +244,18 @@ class DeleteAction(InterfaceAction): +'

', 'delete_all_formats', self.gui): return db = self.gui.library_view.model().db + removals = {} for id in ids: fmts = db.formats(id, index_is_id=True, verify_formats=False) if fmts: - for fmt in fmts.split(','): - self.gui.library_view.model().db.remove_format(id, fmt, - index_is_id=True, notify=False) - self.gui.library_view.model().refresh_ids(ids) - self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), - self.gui.library_view.currentIndex()) - if ids: - self.gui.tags_view.recount() + removals[id] = fmts.split(',') + if removals: + db.new_api.remove_formats(removals) + self.gui.library_view.model().refresh_ids(ids) + self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), + self.gui.library_view.currentIndex()) + if ids: + self.gui.tags_view.recount() def remove_matching_books_from_device(self, *args): if not self.gui.device_manager.is_device_present: diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index f0760e7439..e52525be9f 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -398,13 +398,14 @@ def command_add(args, dbpath): return 0 def do_remove(db, ids): + book_ids = set() for x in ids: if isinstance(x, int): - db.delete_book(x) + book_ids.add(x) else: - for y in x: - db.delete_book(y) + book_ids |= set(x) + db.new_api.remove_books(book_ids) db.clean() send_message()