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:
Charles Haley 2010-09-07 14:18:14 +01:00
parent 563b6d0b2e
commit d9d1981fbe
2 changed files with 33 additions and 5 deletions

View File

@ -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)

View File

@ -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