From 94598bd8441bf7c2349b89dfb5c1db858b7174e9 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 16 Jun 2010 14:30:50 +0100 Subject: [PATCH] Mark matching books for deletion feature. The changes to device.py fix a bug that is independent of the feature. --- src/calibre/gui2/actions.py | 15 +++++++++++++++ src/calibre/gui2/device.py | 8 +++++--- src/calibre/gui2/init.py | 3 +++ src/calibre/gui2/library/models.py | 16 ++++++++++++++-- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/calibre/gui2/actions.py b/src/calibre/gui2/actions.py index 6da04a41be..fc3d12e29a 100644 --- a/src/calibre/gui2/actions.py +++ b/src/calibre/gui2/actions.py @@ -471,6 +471,21 @@ class DeleteAction(object): # {{{ if ids: self.tags_view.recount() + def mark_matching_for_removal(self, *args): + ids = self._get_selected_ids() + if not ids: + return + db = self.library_view.model().db + for model in (self.memory_view.model(), self.card_a_view.model(), + self.card_b_view.model()): + ids_to_mark = [] + for id in ids: + uuid = db.uuid(id, index_is_id=True) + for book in model.db: + if getattr(book, 'uuid', None) == uuid: + ids_to_mark.append(id) + break + model.clear_ondevice(ids_to_mark, to_what=False) def delete_covers(self, *args): ids = self._get_selected_ids() diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index b3a7196b20..d00dd2782c 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -1347,7 +1347,7 @@ class DeviceMixin(object): # {{{ if reset: # First build a cache of the library, so the search isn't On**2 self.db_book_title_cache = {} - self.db_book_uuid_cache = set() + self.db_book_uuid_cache = {} db = self.library_view.model().db for id in db.data.iterallids(): mi = db.get_metadata(id, index_is_id=True) @@ -1364,7 +1364,7 @@ class DeviceMixin(object): # {{{ aus = re.sub('(?u)\W|[_]', '', aus) self.db_book_title_cache[title]['author_sort'][aus] = mi self.db_book_title_cache[title]['db_ids'][mi.application_id] = mi - self.db_book_uuid_cache.add(mi.uuid) + self.db_book_uuid_cache[mi.uuid] = mi.application_id # Now iterate through all the books on the device, setting the # in_library field Fastest and most accurate key is the uuid. Second is @@ -1376,11 +1376,13 @@ class DeviceMixin(object): # {{{ for book in booklist: if getattr(book, 'uuid', None) in self.db_book_uuid_cache: book.in_library = True + # ensure that the correct application_id is set + book.application_id = self.db_book_uuid_cache[book.uuid] continue book_title = book.title.lower() if book.title else '' book_title = re.sub('(?u)\W|[_]', '', book_title) - book.in_library = False + book.in_library = None d = self.db_book_title_cache.get(book_title, None) if d is not None: if getattr(book, 'application_id', None) in d['db_ids']: diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 0a82d3b75b..cce7731004 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -131,6 +131,9 @@ class ToolbarMixin(object): # {{{ self.delete_all_but_selected_formats) self.delete_menu.addAction( _('Remove covers from selected books'), self.delete_covers) + self.delete_menu.addAction( + _('Mark matching books on device for removal'), + self.mark_matching_for_removal) self.action_del.setMenu(self.delete_menu) self.action_open_containing_folder.setShortcut(Qt.Key_O) diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 8080769377..a1bab24788 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -769,6 +769,7 @@ class OnDeviceSearch(SearchQueryParser): # {{{ 'format', 'formats', 'title', + 'inlibrary' ] @@ -807,12 +808,21 @@ class OnDeviceSearch(SearchQueryParser): # {{{ 'author': lambda x: ' & '.join(getattr(x, 'authors')).lower(), 'collections':lambda x: ','.join(getattr(x, 'device_collections')).lower(), 'format':lambda x: os.path.splitext(x.path)[1].lower(), + 'inlibrary':lambda x : getattr(x, 'in_library') } for x in ('author', 'format'): q[x+'s'] = q[x] for index, row in enumerate(self.model.db): for locvalue in locations: accessor = q[locvalue] + if query == 'true': + if accessor(row) is not None: + matches.add(index) + continue + if query == 'false': + if accessor(row) is None: + matches.add(index) + continue try: ### Can't separate authors because comma is used for name sep and author sep ### Exact match might not get what you want. For that reason, turn author @@ -888,13 +898,13 @@ class DeviceBooksModel(BooksModel): # {{{ ans.extend(v) return ans - def clear_ondevice(self, db_ids): + def clear_ondevice(self, db_ids, to_what=None): for data in self.db: if data is None: continue app_id = getattr(data, 'application_id', None) if app_id is not None and app_id in db_ids: - data.in_library = False + data.in_library = to_what self.reset() def flags(self, index): @@ -1089,6 +1099,8 @@ class DeviceBooksModel(BooksModel): # {{{ elif role == Qt.DecorationRole and cname == 'inlibrary': if self.db[self.map[row]].in_library: return QVariant(self.bool_yes_icon) + elif self.db[self.map[row]].in_library is not None: + return QVariant(self.bool_no_icon) elif role == Qt.TextAlignmentRole: cname = self.column_map[index.column()] ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname,