mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add a count of how many books on the device matched a particular copy in the library. Useful because books on the device can accumulate when sent after changing metadata used in the file path. The UUID doesn't change, so we can detect that they are copies of the same book.
searching for 'ondevice:books' will find instances of more than one copy.
This commit is contained in:
parent
563b6d0b2e
commit
d9d1981fbe
@ -1306,16 +1306,26 @@ class DeviceMixin(object): # {{{
|
|||||||
self.library_view.model().refresh_ids(list(changed))
|
self.library_view.model().refresh_ids(list(changed))
|
||||||
|
|
||||||
def book_on_device(self, id, format=None, reset=False):
|
def book_on_device(self, id, format=None, reset=False):
|
||||||
loc = [None, None, None]
|
'''
|
||||||
|
Return an indication of whether the given book represented by its db id
|
||||||
|
is on the currently connected device. It returns a 4 element list. The
|
||||||
|
first three elements represent memory locations main, carda, and cardb,
|
||||||
|
and are true if the book is identifiably in that memory. The fourth
|
||||||
|
is the a count of how many instances of the book were found across all
|
||||||
|
the memory locations.
|
||||||
|
'''
|
||||||
|
loc = [None, None, None, 0]
|
||||||
|
|
||||||
if reset:
|
if reset:
|
||||||
self.book_db_title_cache = None
|
self.book_db_title_cache = None
|
||||||
self.book_db_uuid_cache = None
|
self.book_db_uuid_cache = None
|
||||||
|
self.book_db_id_counts = None
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.book_db_title_cache is None:
|
if self.book_db_title_cache is None:
|
||||||
self.book_db_title_cache = []
|
self.book_db_title_cache = []
|
||||||
self.book_db_uuid_cache = []
|
self.book_db_uuid_cache = []
|
||||||
|
self.book_db_id_counts = {}
|
||||||
for i, l in enumerate(self.booklists()):
|
for i, l in enumerate(self.booklists()):
|
||||||
self.book_db_title_cache.append({})
|
self.book_db_title_cache.append({})
|
||||||
self.book_db_uuid_cache.append(set())
|
self.book_db_uuid_cache.append(set())
|
||||||
@ -1333,6 +1343,10 @@ class DeviceMixin(object): # {{{
|
|||||||
db_id = book.db_id
|
db_id = book.db_id
|
||||||
if db_id is not None:
|
if db_id is not None:
|
||||||
self.book_db_title_cache[i][book_title]['db_ids'].add(db_id)
|
self.book_db_title_cache[i][book_title]['db_ids'].add(db_id)
|
||||||
|
# increment the count of books on the device with this
|
||||||
|
# db_id.
|
||||||
|
c = self.book_db_id_counts.get(db_id, 0)
|
||||||
|
self.book_db_id_counts[db_id] = c + 1
|
||||||
uuid = getattr(book, 'uuid', None)
|
uuid = getattr(book, 'uuid', None)
|
||||||
if uuid is not None:
|
if uuid is not None:
|
||||||
self.book_db_uuid_cache[i].add(uuid)
|
self.book_db_uuid_cache[i].add(uuid)
|
||||||
@ -1351,7 +1365,13 @@ class DeviceMixin(object): # {{{
|
|||||||
if mi.authors and \
|
if mi.authors and \
|
||||||
re.sub('(?u)\W|[_]', '', authors_to_string(mi.authors).lower()) \
|
re.sub('(?u)\W|[_]', '', authors_to_string(mi.authors).lower()) \
|
||||||
in cache['authors']:
|
in cache['authors']:
|
||||||
|
# We really shouldn't get here, because set_books_in_library
|
||||||
|
# should have set the db_ids for the books, and therefore
|
||||||
|
# the if just above should have found them. Mark the book
|
||||||
|
# anyway, and print a message about the situation
|
||||||
loc[i] = True
|
loc[i] = True
|
||||||
|
print 'book_on_device: matched title/author but not db_id!', \
|
||||||
|
mi.title, authors_to_string(mi.authors)
|
||||||
continue
|
continue
|
||||||
# Also check author sort, because it can be used as author in
|
# Also check author sort, because it can be used as author in
|
||||||
# some formats
|
# some formats
|
||||||
@ -1360,9 +1380,16 @@ class DeviceMixin(object): # {{{
|
|||||||
in cache['authors']:
|
in cache['authors']:
|
||||||
loc[i] = True
|
loc[i] = True
|
||||||
continue
|
continue
|
||||||
|
loc[3] = self.book_db_id_counts.get(id, 0)
|
||||||
return loc
|
return loc
|
||||||
|
|
||||||
def set_books_in_library(self, booklists, reset=False):
|
def set_books_in_library(self, booklists, reset=False):
|
||||||
|
'''
|
||||||
|
Set the ondevice indications in the device database.
|
||||||
|
This method should be called before book_on_device is called, because
|
||||||
|
it sets the application_id for matched books. Book_on_device uses that
|
||||||
|
to both speed up matching and to count matches.
|
||||||
|
'''
|
||||||
# Force a reset if the caches are not initialized
|
# Force a reset if the caches are not initialized
|
||||||
if reset or not hasattr(self, 'db_book_title_cache'):
|
if reset or not hasattr(self, 'db_book_title_cache'):
|
||||||
# It might be possible to get here without having initialized the
|
# It might be possible to get here without having initialized the
|
||||||
@ -1428,7 +1455,7 @@ class DeviceMixin(object): # {{{
|
|||||||
if book.db_id in d['db_ids']:
|
if book.db_id in d['db_ids']:
|
||||||
book.in_library = True
|
book.in_library = True
|
||||||
book.application_id = \
|
book.application_id = \
|
||||||
d['db_ids'][book.db_id].application_id
|
d['db_ids'][book.db_id].application_id
|
||||||
if update_metadata:
|
if update_metadata:
|
||||||
book.smart_update(d['db_ids'][book.db_id],
|
book.smart_update(d['db_ids'][book.db_id],
|
||||||
replace_metadata=True)
|
replace_metadata=True)
|
||||||
@ -1441,7 +1468,7 @@ class DeviceMixin(object): # {{{
|
|||||||
if book_authors in d['authors']:
|
if book_authors in d['authors']:
|
||||||
book.in_library = True
|
book.in_library = True
|
||||||
book.application_id = \
|
book.application_id = \
|
||||||
d['authors'][book_authors].application_id
|
d['authors'][book_authors].application_id
|
||||||
if update_metadata:
|
if update_metadata:
|
||||||
book.smart_update(d['authors'][book_authors],
|
book.smart_update(d['authors'][book_authors],
|
||||||
replace_metadata=True)
|
replace_metadata=True)
|
||||||
|
@ -640,16 +640,17 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
|
|
||||||
def book_on_device_string(self, id):
|
def book_on_device_string(self, id):
|
||||||
loc = []
|
loc = []
|
||||||
|
count = 0
|
||||||
on = self.book_on_device(id)
|
on = self.book_on_device(id)
|
||||||
if on is not None:
|
if on is not None:
|
||||||
m, a, b = on
|
m, a, b, count = on
|
||||||
if m is not None:
|
if m is not None:
|
||||||
loc.append(_('Main'))
|
loc.append(_('Main'))
|
||||||
if a is not None:
|
if a is not None:
|
||||||
loc.append(_('Card A'))
|
loc.append(_('Card A'))
|
||||||
if b is not None:
|
if b is not None:
|
||||||
loc.append(_('Card B'))
|
loc.append(_('Card B'))
|
||||||
return ', '.join(loc)
|
return ', '.join(loc) + ((' (%s books)'%count) if count > 1 else '')
|
||||||
|
|
||||||
def set_book_on_device_func(self, func):
|
def set_book_on_device_func(self, func):
|
||||||
self.book_on_device_func = func
|
self.book_on_device_func = func
|
||||||
|
Loading…
x
Reference in New Issue
Block a user