Last changes for book matching. Make both book on device and book in library respect the exact-match semantics that Kovid implemented.

This commit is contained in:
Charles Haley 2010-09-10 14:07:11 +01:00
parent 98bc0e53ec
commit 0b6b78713a
2 changed files with 46 additions and 11 deletions

View File

@ -760,8 +760,8 @@ class DeviceMixin(object): # {{{
def refresh_ondevice_info(self, device_connected, reset_only = False): def refresh_ondevice_info(self, device_connected, reset_only = False):
''' '''
Force the library view to refresh, taking into consideration Force the library view to refresh, taking into consideration new
books information device books information
''' '''
self.book_on_device(None, reset=True) self.book_on_device(None, reset=True)
if reset_only: if reset_only:
@ -791,9 +791,10 @@ class DeviceMixin(object): # {{{
self.booklists()) self.booklists())
model.paths_deleted(paths) model.paths_deleted(paths)
self.upload_booklists() self.upload_booklists()
# Force recomputation the library's ondevice info. We don't need to call # Force recomputation the library's ondevice info. We need to call
# set_books_in_library, because no books were added to the device and # set_books_in_library even though books were not added because
# the deleted book is no longer displayed. # the deleted book might have been an exact match.
self.set_books_in_library(self.booklists(), reset=True)
self.book_on_device(None, None, reset=True) self.book_on_device(None, None, reset=True)
# We need to reset the ondevice flags in the library. Use a big hammer, # We need to reset the ondevice flags in the library. Use a big hammer,
# so we don't need to worry about whether some succeeded or not. # so we don't need to worry about whether some succeeded or not.
@ -1366,6 +1367,9 @@ class DeviceMixin(object): # {{{
self.book_db_uuid_cache[i].add(uuid) self.book_db_uuid_cache[i].add(uuid)
self.book_db_uuid_path_map[uuid] = book.path self.book_db_uuid_path_map[uuid] = book.path
if uuid in self.db_book_uuid_cache: if uuid in self.db_book_uuid_cache:
# This book exactly matches a book on the device.
# Set the flag that prevents the book from
# participating in metadata matching
self.book_db_title_cache[i][book_title]\ self.book_db_title_cache[i][book_title]\
['uuid_in_library'] = True ['uuid_in_library'] = True
self.book_db_title_cache[i][book_title]['paths'].add(book.path) self.book_db_title_cache[i][book_title]['paths'].add(book.path)
@ -1380,6 +1384,12 @@ class DeviceMixin(object): # {{{
db_title = clean_string(mi.title) db_title = clean_string(mi.title)
cache = self.book_db_title_cache[i].get(db_title, None) cache = self.book_db_title_cache[i].get(db_title, None)
if cache and not cache['uuid_in_library']: if cache and not cache['uuid_in_library']:
# We really shouldn't get here, because set_books_in_library
# should have set the db_ids for the books, the cache-builder
# will add the uuid for those matched books to the cache, and
# therefore the if just above should have found them. Check
# anyway, just in case. Also print that we got here...
prints('checking metadata matches:', mi.title)
if id in cache['db_ids']: if id in cache['db_ids']:
loc[i] = True loc[i] = True
loc[4] = 'db_id' loc[4] = 'db_id'
@ -1390,10 +1400,6 @@ class DeviceMixin(object): # {{{
if (mi.authors and clean_string(authors_to_string(mi.authors)) if (mi.authors and clean_string(authors_to_string(mi.authors))
in cache['authors']) or (mi.author_sort and in cache['authors']) or (mi.author_sort and
clean_string(mi.author_sort) in cache['authors']): clean_string(mi.author_sort) 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, just in case.
loc[i] = True loc[i] = True
loc[4] = 'metadata' loc[4] = 'metadata'
loc[5] = cache['paths'] loc[5] = cache['paths']
@ -1454,6 +1460,7 @@ class DeviceMixin(object): # {{{
update_metadata = prefs['manage_device_metadata'] == 'on_connect' update_metadata = prefs['manage_device_metadata'] == 'on_connect'
for booklist in booklists: for booklist in booklists:
for book in booklist: for book in booklist:
book.in_library = None
if getattr(book, 'uuid', None) in self.db_book_uuid_cache: if getattr(book, 'uuid', None) in self.db_book_uuid_cache:
if update_metadata: if update_metadata:
book.smart_update(self.db_book_uuid_cache[book.uuid], book.smart_update(self.db_book_uuid_cache[book.uuid],
@ -1462,19 +1469,38 @@ class DeviceMixin(object): # {{{
# ensure that the correct application_id is set # ensure that the correct application_id is set
book.application_id = \ book.application_id = \
self.db_book_uuid_cache[book.uuid].application_id self.db_book_uuid_cache[book.uuid].application_id
# We had an exact UUID match. The rules are that once the
# uuid of a book on the device exactly matches the uuid of a
# book in the database, don't do metadata matching for that
# book. This prevents the device-book from matching other
# instances of library-books that happen to have the same
# metadata. Of course, this means that if there are more
# copies of the book on the device, then they must also
# exactly match.
book_title = clean_string(book.title)
if book_title in self.db_book_title_cache:
del self.db_book_title_cache[book_title]
continue continue
for booklist in booklists:
for book in booklist:
if book.in_library:
continue
book_title = clean_string(book.title) book_title = clean_string(book.title)
book.in_library = None
d = self.db_book_title_cache.get(book_title, None) d = self.db_book_title_cache.get(book_title, None)
if d is not None: if d is not None:
# At this point we know that the title matches. The book
# will match if any of the db_id, author, or author_sort
# also match.
if getattr(book, 'application_id', None) in d['db_ids']: if getattr(book, 'application_id', None) in d['db_ids']:
book.in_library = True book.in_library = True
# application already matches a db_id. No need to set it # app_id already matches a db_id. No need to set it.
if update_metadata: if update_metadata:
book.smart_update(d['db_ids'][book.application_id], book.smart_update(d['db_ids'][book.application_id],
replace_metadata=True) replace_metadata=True)
continue continue
# Sonys know their db_id independent of the application_id
# in the metadata cache. Check that as well.
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 = \
@ -1483,6 +1509,11 @@ class DeviceMixin(object): # {{{
book.smart_update(d['db_ids'][book.db_id], book.smart_update(d['db_ids'][book.db_id],
replace_metadata=True) replace_metadata=True)
continue continue
# We now know that the application_id is not right. Set it
# to None to prevent book_on_device from accidentally
# matching on it. It will be set to a correct value below if
# the book is matched with one in the library
book.application_id = None
if book.authors: if book.authors:
# Compare against both author and author sort, because # Compare against both author and author sort, because
# either can appear as the author # either can appear as the author
@ -1501,6 +1532,9 @@ class DeviceMixin(object): # {{{
if update_metadata: if update_metadata:
book.smart_update(d['author_sort'][book_authors], book.smart_update(d['author_sort'][book_authors],
replace_metadata=True) replace_metadata=True)
else:
# Book definitely not matched. Clear its application ID
book.application_id = None
# Set author_sort if it isn't already # Set author_sort if it isn't already
asort = getattr(book, 'author_sort', None) asort = getattr(book, 'author_sort', None)
if not asort and book.authors: if not asort and book.authors:

View File

@ -122,6 +122,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.device_connected = is_connected self.device_connected = is_connected
self.db.refresh_ondevice() self.db.refresh_ondevice()
self.refresh() self.refresh()
self.research()
if is_connected and self.sorted_on[0] == 'ondevice': if is_connected and self.sorted_on[0] == 'ondevice':
self.resort() self.resort()