From 041f4645fae00cce5435ef82ac9db5169c510819 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 21 Dec 2010 19:54:00 +0000 Subject: [PATCH 1/6] Tweak to build collections of all books by title and by author --- resources/default_tweaks.py | 17 ++++++++++++ src/calibre/devices/prs505/sony_cache.py | 3 +++ src/calibre/devices/usbms/books.py | 34 ++++++++++++++++-------- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index a420cd7d44..d15ffd4339 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -180,6 +180,23 @@ sony_collection_renaming_rules={} # Default: empty (no rules), so no collection attributes are named. sony_collection_sorting_rules = [] +# Specify whether special collections are to be made. The two available are +# all_by_author and all_by_title. These collections work around various device +# idiosyncrasies regarding sorting of lists. The all by author collection is +# sorted by author(s) then title. The by title collection is sorted by title +# then authors(s) +# Enable a collection by entering a collection name in the variable. That +# collection name must be unique. +# Examples: +# sony_all_books_by_author_collection = '%All by author' +# create a collection of all books sorted by author +# sony_all_books_by_title_collection = '%All by title' +# create a collection of books sorted by title, respecting the order tweaks +# sony_all_books_by_author_collection = '' +# disable the collection +sony_all_books_by_author_collection = '' +sony_all_books_by_title_collection = '' + # Create search terms to apply a query across several built-in search terms. # Syntax: {'new term':['existing term 1', 'term 2', ...], 'new':['old'...] ...} diff --git a/src/calibre/devices/prs505/sony_cache.py b/src/calibre/devices/prs505/sony_cache.py index f271329fc8..841f6bc346 100644 --- a/src/calibre/devices/prs505/sony_cache.py +++ b/src/calibre/devices/prs505/sony_cache.py @@ -410,6 +410,9 @@ class XMLCache(object): newmi = book.deepcopy_metadata() newmi.template_to_attribute(book, plugboard) newmi.set('_new_book', getattr(book, '_new_book', False)) + book.set('_pb_title_sort', + newmi.get('title_sort', newmi.get('title', None))) + book.set('_pb_author_sort', newmi.get('author_sort', '')) else: newmi = book (gtz_count, ltz_count, use_tz_var) = \ diff --git a/src/calibre/devices/usbms/books.py b/src/calibre/devices/usbms/books.py index 3372f5c8a5..0f78b85a57 100644 --- a/src/calibre/devices/usbms/books.py +++ b/src/calibre/devices/usbms/books.py @@ -132,9 +132,14 @@ class CollectionsBookList(BookList): use_renaming_rules = prefs['manage_device_metadata'] == 'on_connect' collections = {} - # This map of sets is used to avoid linear searches when testing for - # book equality + + all_by_author = tweaks['sony_all_books_by_author_collection'] + all_by_title = tweaks['sony_all_books_by_title_collection'] + for book in self: + tsval = book.get('_pb_title_sort', + book.get('title_sort', book.get('title', 'zzzz'))) + asval = book.get('_pb_author_sort', book.get('author_sort', '')) # Make sure we can identify this book via the lpath lpath = getattr(book, 'lpath', None) if lpath is None: @@ -211,22 +216,29 @@ class CollectionsBookList(BookList): collections[cat_name] = {} if use_renaming_rules and sort_attr: sort_val = book.get(sort_attr, None) - collections[cat_name][lpath] = \ - (book, sort_val, book.get('title_sort', 'zzzz')) + collections[cat_name][lpath] = (book, sort_val, tsval) elif is_series: if doing_dc: collections[cat_name][lpath] = \ - (book, book.get('series_index', sys.maxint), - book.get('title_sort', 'zzzz')) + (book, book.get('series_index', sys.maxint), tsval) else: collections[cat_name][lpath] = \ - (book, book.get(attr+'_index', sys.maxint), - book.get('title_sort', 'zzzz')) + (book, book.get(attr+'_index', sys.maxint), tsval) else: if lpath not in collections[cat_name]: - collections[cat_name][lpath] = \ - (book, book.get('title_sort', 'zzzz'), - book.get('title_sort', 'zzzz')) + collections[cat_name][lpath] = (book, tsval, tsval) + + # All books by author + if all_by_author: + if all_by_author not in collections: + collections[all_by_author] = {} + collections[all_by_author][lpath] = (book, asval, tsval) + # All books by title + if all_by_title: + if all_by_title not in collections: + collections[all_by_title] = {} + collections[all_by_title][lpath] = (book, tsval, asval) + # Sort collections result = {} From d7986e12baff8b98ec6fd8c280ced9385c6bd626 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 21 Dec 2010 20:37:19 +0000 Subject: [PATCH 2/6] Changes to the sony auto-collections tweak requested by Kovid. Also take the author_sort from the device_db plugboard, if it is available. --- resources/default_tweaks.py | 24 ++++++++++++------------ src/calibre/devices/usbms/books.py | 11 +++++++++-- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index d15ffd4339..3835bcd656 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -180,22 +180,22 @@ sony_collection_renaming_rules={} # Default: empty (no rules), so no collection attributes are named. sony_collection_sorting_rules = [] -# Specify whether special collections are to be made. The two available are -# all_by_author and all_by_title. These collections work around various device -# idiosyncrasies regarding sorting of lists. The all by author collection is -# sorted by author(s) then title. The by title collection is sorted by title -# then authors(s) +# Specify whether special collections are to be made. This option is primarily +# of use on a Sony. The two available are all_by_author and all_by_title. These +# collections work around various device idiosyncrasies regarding sorting of +# lists, especially the sony *50 models. The author collection is sorted by +# author(s) then title. The title collection is sorted by title then authors(s) # Enable a collection by entering a collection name in the variable. That # collection name must be unique. # Examples: -# sony_all_books_by_author_collection = '%All by author' -# create a collection of all books sorted by author -# sony_all_books_by_title_collection = '%All by title' -# create a collection of books sorted by title, respecting the order tweaks -# sony_all_books_by_author_collection = '' +# device_special_collections = {'title':'', 'author':'%All by author'} +# create a collection named '%All by author' of all books sorted by author +# device_special_collections = {'title':'%All by title', 'author':''} +# create a collection named '%All by title' of books sorted by title, +# respecting the order tweaks +# sony_all_books_by_author_collection = {'title':'', 'author':''} # disable the collection -sony_all_books_by_author_collection = '' -sony_all_books_by_title_collection = '' +device_special_collections = {'title':'', 'author':''} # Create search terms to apply a query across several built-in search terms. diff --git a/src/calibre/devices/usbms/books.py b/src/calibre/devices/usbms/books.py index 0f78b85a57..84b8585d5c 100644 --- a/src/calibre/devices/usbms/books.py +++ b/src/calibre/devices/usbms/books.py @@ -133,8 +133,15 @@ class CollectionsBookList(BookList): collections = {} - all_by_author = tweaks['sony_all_books_by_author_collection'] - all_by_title = tweaks['sony_all_books_by_title_collection'] + # get the special collection names + try: + all_by_author = tweaks['device_special_collections']['author'] + except: + all_by_author = '' + try: + all_by_title = tweaks['device_special_collections']['title'] + except: + all_by_title = '' for book in self: tsval = book.get('_pb_title_sort', From 5fe71e5c3f5aff91e148e6287ef652e341bcc0e4 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 21 Dec 2010 20:38:41 +0000 Subject: [PATCH 3/6] Clean up tweaks comments --- resources/default_tweaks.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index 3835bcd656..d2e4758ba6 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -192,9 +192,11 @@ sony_collection_sorting_rules = [] # create a collection named '%All by author' of all books sorted by author # device_special_collections = {'title':'%All by title', 'author':''} # create a collection named '%All by title' of books sorted by title, -# respecting the order tweaks +# respecting the order tweaks +# device_special_collections = {'title':'%All by title', 'author':'%All by author'} +# make both collections # sony_all_books_by_author_collection = {'title':'', 'author':''} -# disable the collection +# disable both collections device_special_collections = {'title':'', 'author':''} From f78767db15e4410a1393a954ec126dcf26db5b38 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 22 Dec 2010 13:24:39 +0000 Subject: [PATCH 4/6] Try harder to keep the tags view positioned after an item edit --- src/calibre/gui2/tag_view.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py index 478f6b042f..3d43d49a75 100644 --- a/src/calibre/gui2/tag_view.py +++ b/src/calibre/gui2/tag_view.py @@ -695,8 +695,10 @@ class TagsModel(QAbstractItemModel): # {{{ def setData(self, index, value, role=Qt.EditRole): if not index.isValid(): return NONE - # set up to position at the category label - path = self.path_for_index(self.parent(index)) + # set up to reposition at the same item. We can do this except if + # working with the last item and that item is deleted, in which case + # we position at the parent label + path = index.model().path_for_index(index) val = unicode(value.toString()) if not val: error_dialog(self.tags_view, _('Item is blank'), @@ -947,18 +949,22 @@ class TagBrowserMixin(object): # {{{ for old_id in to_rename[text]: rename_func(old_id, new_name=unicode(text)) - # Clean up everything, as information could have changed for many books. - self.library_view.model().refresh() - self.tags_view.set_new_model() - self.tags_view.recount() - self.saved_search.clear() - self.search.clear() + # Clean up the library view + self.do_tag_item_renamed() + self.tags_view.set_new_model() # does a refresh for free def do_tag_item_renamed(self): # Clean up library view and search - self.library_view.model().refresh() - self.saved_search.clear() - self.search.clear() + # get information to redo the selection + rows = [r.row() for r in \ + self.library_view.selectionModel().selectedRows()] + m = self.library_view.model() + ids = [m.id(r) for r in rows] + + m.refresh(reset=False) + m.research() + self.library_view.select_rows(ids) + # refreshing the tags view happens at the emit()/call() site def do_author_sort_edit(self, parent, id): db = self.library_view.model().db From 2afb62c9f7b46c83b836f030e6a60414c5d8a8ba Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 22 Dec 2010 18:11:11 +0000 Subject: [PATCH 5/6] Another try at the special collection stuff --- src/calibre/devices/prs505/driver.py | 11 +++++++++-- src/calibre/devices/usbms/books.py | 19 +++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/calibre/devices/prs505/driver.py b/src/calibre/devices/prs505/driver.py index 23f59e4737..6652d581d4 100644 --- a/src/calibre/devices/prs505/driver.py +++ b/src/calibre/devices/prs505/driver.py @@ -58,9 +58,16 @@ class PRS505(USBMS): SUPPORTS_USE_AUTHOR_SORT = True EBOOK_DIR_MAIN = 'database/media/books' + ALL_BY_TITLE = _('All by title') + ALL_BY_AUTHOR = _('All by author') + EXTRA_CUSTOMIZATION_MESSAGE = _('Comma separated list of metadata fields ' 'to turn into collections on the device. Possibilities include: ')+\ - 'series, tags, authors' + 'series, tags, authors' +\ + _('. Two special collections are available: %s:%s and %s:%s. Add ' + 'these values to the list to enable them. The collections will be ' + 'given the name provided after the ":" character.')%( + 'abt', ALL_BY_TITLE, 'aba', ALL_BY_AUTHOR) EXTRA_CUSTOMIZATION_DEFAULT = ', '.join(['series', 'tags']) plugboard = None @@ -151,7 +158,7 @@ class PRS505(USBMS): blists[i] = booklists[i] opts = self.settings() if opts.extra_customization: - collections = [x.lower().strip() for x in + collections = [x.strip() for x in opts.extra_customization.split(',')] else: collections = [] diff --git a/src/calibre/devices/usbms/books.py b/src/calibre/devices/usbms/books.py index 84b8585d5c..a9c980c31b 100644 --- a/src/calibre/devices/usbms/books.py +++ b/src/calibre/devices/usbms/books.py @@ -134,14 +134,17 @@ class CollectionsBookList(BookList): collections = {} # get the special collection names - try: - all_by_author = tweaks['device_special_collections']['author'] - except: - all_by_author = '' - try: - all_by_title = tweaks['device_special_collections']['title'] - except: - all_by_title = '' + all_by_author = '' + all_by_title = '' + ca = [] + for c in collection_attributes: + if c.startswith('aba:') and c[4:]: + all_by_author = c[4:] + elif c.startswith('abt:') and c[4:]: + all_by_title = c[4:] + else: + ca.append(c.lower()) + collection_attributes = ca for book in self: tsval = book.get('_pb_title_sort', From 252488739fa70e354ee9f98b0b6908c0cc809b64 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 22 Dec 2010 18:16:02 +0000 Subject: [PATCH 6/6] Remove special collections tweak --- resources/default_tweaks.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index d2e4758ba6..a420cd7d44 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -180,25 +180,6 @@ sony_collection_renaming_rules={} # Default: empty (no rules), so no collection attributes are named. sony_collection_sorting_rules = [] -# Specify whether special collections are to be made. This option is primarily -# of use on a Sony. The two available are all_by_author and all_by_title. These -# collections work around various device idiosyncrasies regarding sorting of -# lists, especially the sony *50 models. The author collection is sorted by -# author(s) then title. The title collection is sorted by title then authors(s) -# Enable a collection by entering a collection name in the variable. That -# collection name must be unique. -# Examples: -# device_special_collections = {'title':'', 'author':'%All by author'} -# create a collection named '%All by author' of all books sorted by author -# device_special_collections = {'title':'%All by title', 'author':''} -# create a collection named '%All by title' of books sorted by title, -# respecting the order tweaks -# device_special_collections = {'title':'%All by title', 'author':'%All by author'} -# make both collections -# sony_all_books_by_author_collection = {'title':'', 'author':''} -# disable both collections -device_special_collections = {'title':'', 'author':''} - # Create search terms to apply a query across several built-in search terms. # Syntax: {'new term':['existing term 1', 'term 2', ...], 'new':['old'...] ...}