diff --git a/src/calibre/devices/prs505/sony_cache.py b/src/calibre/devices/prs505/sony_cache.py index e7d0e4686c..a704824a3f 100644 --- a/src/calibre/devices/prs505/sony_cache.py +++ b/src/calibre/devices/prs505/sony_cache.py @@ -9,7 +9,6 @@ import os, time from pprint import pprint from base64 import b64decode from uuid import uuid4 - from lxml import etree from calibre import prints, guess_type @@ -151,15 +150,14 @@ class XMLCache(object): else: seen.add(title) - def get_playlist_map(self): - debug_print('Start get_playlist_map') + def build_playlist_id_map(self): + debug_print('Start build_playlist_id_map') ans = {} self.ensure_unique_playlist_titles() debug_print('after ensure_unique_playlist_titles') self.prune_empty_playlists() - debug_print('get_playlist_map loop') for i, root in self.record_roots.items(): - debug_print('get_playlist_map loop', i) + debug_print('build_playlist_id_map loop', i) id_map = self.build_id_map(root) ans[i] = [] for playlist in root.xpath('//*[local-name()="playlist"]'): @@ -170,9 +168,23 @@ class XMLCache(object): if record is not None: items.append(record) ans[i].append((playlist.get('title'), items)) - debug_print('end get_playlist_map') + debug_print('end build_playlist_id_map') return ans + def build_id_playlist_map(self, bl_index): + debug_print('Start build_id_playlist_map') + pmap = self.build_playlist_id_map()[bl_index] + playlist_map = {} + for title, records in pmap: + for record in records: + path = record.get('path', None) + if path: + if path not in playlist_map: + playlist_map[path] = set() + playlist_map[path].add(title) + debug_print('Finish build_id_playlist_map. Found', len(playlist_map)) + return playlist_map + def get_or_create_playlist(self, bl_idx, title): root = self.record_roots[bl_idx] for playlist in root.xpath('//*[local-name()="playlist"]'): @@ -192,8 +204,7 @@ class XMLCache(object): # }}} def fix_ids(self): # {{{ - if DEBUG: - debug_print('Running fix_ids()') + debug_print('Running fix_ids()') def ensure_numeric_ids(root): idmap = {} @@ -276,38 +287,19 @@ class XMLCache(object): def update_booklist(self, bl, bl_index): if bl_index not in self.record_roots: return - if DEBUG: - debug_print('Updating JSON cache:', bl_index) + debug_print('Updating JSON cache:', bl_index) + playlist_map = self.build_id_playlist_map(bl_index) root = self.record_roots[bl_index] - pmap = self.get_playlist_map()[bl_index] - playlist_map = {} - for title, records in pmap: - for record in records: - path = record.get('path', None) - if path: - if path not in playlist_map: - playlist_map[path] = [] - playlist_map[path].append(title) - lpath_map = self.build_lpath_map(root) for book in bl: record = lpath_map.get(book.lpath, None) if record is not None: title = record.get('title', None) if title is not None and title != book.title: - if DEBUG: - debug_print('Renaming title', book.title, 'to', title) + debug_print('Renaming title', book.title, 'to', title) book.title = title -# We shouldn't do this for Sonys, because the reader strips -# all but the first author. -# authors = record.get('author', None) -# if authors is not None: -# authors = string_to_authors(authors) -# if authors != book.authors: -# if DEBUG: -# prints('Renaming authors', book.authors, 'to', -# authors) -# book.authors = authors + # Don't set the author, because the reader strips all but + # the first author. for thumbnail in record.xpath( 'descendant::*[local-name()="thumbnail"]'): for img in thumbnail.xpath( @@ -318,45 +310,45 @@ class XMLCache(object): book.thumbnail = raw break break - if book.lpath in playlist_map: - tags = playlist_map[book.lpath] - book.device_collections = tags + book.device_collections = list(playlist_map.get(book.lpath, set())) debug_print('Finished updating JSON cache:', bl_index) # }}} # Update XML from JSON {{{ def update(self, booklists, collections_attributes): - debug_print('Starting update XML from JSON') - playlist_map = self.get_playlist_map() - + debug_print('In update. Starting update XML from JSON') for i, booklist in booklists.items(): - if DEBUG: - debug_print('Updating XML Cache:', i) + playlist_map = self.build_id_playlist_map(i) + debug_print('Updating XML Cache:', i) root = self.record_roots[i] lpath_map = self.build_lpath_map(root) for book in booklist: path = os.path.join(self.prefixes[i], *(book.lpath.split('/'))) -# record = self.book_by_lpath(book.lpath, root) record = lpath_map.get(book.lpath, None) if record is None: record = self.create_text_record(root, i, book.lpath) self.update_text_record(record, book, path, i) - - bl_pmap = playlist_map[i] - self.update_playlists(i, root, booklist, bl_pmap, - collections_attributes) - - self.fix_ids() - - # This is needed to update device_collections + # Ensure the collections in the XML database are recorded for + # this book + if book.device_collections is None: + book.device_collections = [] + book.device_collections = list(set(book.device_collections) | + playlist_map.get(book.lpath, set())) + self.update_playlists(i, root, booklist, collections_attributes) + # Update the device collections because update playlist could have added + # some new ones. + debug_print('In update/ Starting refresh of device_collections') for i, booklist in booklists.items(): - self.update_booklist(booklist, i) + playlist_map = self.build_id_playlist_map(i) + for book in booklist: + book.device_collections = list(set(book.device_collections) | + playlist_map.get(book.lpath, set())) + self.fix_ids() debug_print('Finished update XML from JSON') - def update_playlists(self, bl_index, root, booklist, playlist_map, - collections_attributes): - debug_print('Starting update_playlists') + def update_playlists(self, bl_index, root, booklist, collections_attributes): + debug_print('Starting update_playlists', collections_attributes) collections = booklist.get_collections(collections_attributes) lpath_map = self.build_lpath_map(root) for category, books in collections.items(): @@ -372,10 +364,8 @@ class XMLCache(object): rec.set('id', str(self.max_id(root)+1)) ids = [x.get('id', None) for x in records] if None in ids: - if DEBUG: - debug_print('WARNING: Some elements do not have ids') - ids = [x for x in ids if x is not None] - + debug_print('WARNING: Some elements do not have ids') + ids = [x for x in ids if x is not None] playlist = self.get_or_create_playlist(bl_index, category) playlist_ids = [] for item in playlist: @@ -544,10 +534,5 @@ class XMLCache(object): break self.namespaces[i] = ns -# if DEBUG: -# debug_print('Found nsmaps:') -# pprint(self.nsmaps) -# debug_print('Found namespaces:') -# pprint(self.namespaces) # }}} diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 850396bc5d..836105aba9 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -1228,6 +1228,11 @@ class DeviceMixin(object): # {{{ return cp, fs = job.result self.location_view.model().update_devices(cp, fs) + # reset the views so that up-to-date info is shown. These need to be + # here because the sony driver updates collections in sync_booklists + self.memory_view.reset() + self.card_a_view.reset() + self.card_b_view.reset() def upload_books(self, files, names, metadata, on_card=None, memory=None): ''' diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 435b5c4c07..a85462e22d 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -1118,7 +1118,7 @@ class DeviceBooksModel(BooksModel): # {{{ elif cname == 'collections': tags = self.db[self.map[row]].device_collections if tags: - return QVariant(', '.join(tags)) + return QVariant(', '.join(sorted(tags, key=str.lower))) elif role == Qt.ToolTipRole and index.isValid(): if self.map[row] in self.indices_to_be_deleted(): return QVariant(_('Marked for deletion'))