diff --git a/src/calibre/gui2/actions/catalog.py b/src/calibre/gui2/actions/catalog.py index d75b0dfa5a..6d3bb539a2 100644 --- a/src/calibre/gui2/actions/catalog.py +++ b/src/calibre/gui2/actions/catalog.py @@ -28,7 +28,7 @@ class GenerateCatalogAction(InterfaceAction): if not ids: return error_dialog(self.gui, _('No books selected'), - _('No books selected to generate catalog for'), + _('No books selected for catalog generation'), show=True) db = self.gui.library_view.model().db @@ -55,9 +55,9 @@ class GenerateCatalogAction(InterfaceAction): def catalog_generated(self, job): if job.result: - # Search terms nulled catalog results - return error_dialog(self.gui, _('No books found'), - _("No books to catalog\nCheck job details"), + # Error during catalog generation + return error_dialog(self.gui, _('Catalog generation terminated'), + job.result, show=True) if job.failed: return self.gui.job_exception(job) diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index c045ccf686..087d40c4eb 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -1144,7 +1144,9 @@ class EPUB_MOBI(CatalogPlugin): def error(self): def fget(self): return self.__error - return property(fget=fget) + def fset(self, val): + self.__error = val + return property(fget=fget,fset=fset) @dynamic_property def generateForKindle(self): def fget(self): @@ -1411,6 +1413,88 @@ class EPUB_MOBI(CatalogPlugin): except: pass + def fetchBooksByAuthor(self): + ''' + Generate a list of titles sorted by author from the database + return = Success + ''' + + self.updateProgressFullStep("Sorting database") + + ''' + # Sort titles case-insensitive, by author + self.booksByAuthor = sorted(self.booksByTitle, + key=lambda x:(x['author_sort'].upper(), x['author_sort'].upper())) + ''' + + self.booksByAuthor = list(self.booksByTitle) + self.booksByAuthor.sort(self.author_compare) + + if False and self.verbose: + self.opts.log.info("fetchBooksByAuthor(): %d books" % len(self.booksByAuthor)) + self.opts.log.info(" %-30s %-20s %s" % ('title', 'series', 'series_index')) + for title in self.booksByAuthor: + self.opts.log.info((u" %-30s %-20s%5s " % \ + (title['title'][:30], + title['series'][:20] if title['series'] else '', + title['series_index'], + )).encode('utf-8')) + raise SystemExit + + # Build the unique_authors set from existing data + authors = [(record['author'], record['author_sort'].capitalize()) for record in self.booksByAuthor] + + # authors[] contains a list of all book authors, with multiple entries for multiple books by author + # authors[]: (([0]:friendly [1]:sort)) + # unique_authors[]: (([0]:friendly [1]:sort [2]:book_count)) + books_by_current_author = 0 + current_author = authors[0] + multiple_authors = False + unique_authors = [] + for (i,author) in enumerate(authors): + if author != current_author: + # Note that current_author and author are tuples: (friendly, sort) + multiple_authors = True + + if author != current_author and i: + # Warn, exit if friendly matches previous, but sort doesn't + if author[0] == current_author[0]: + error_msg = _(''' +\n*** Metadata error *** +Inconsistent Author Sort values for Author '{0}', unable to continue building catalog. +Select all books by '{0}', apply correct Author Sort value in Edit Metadata dialog, +then rebuild the catalog.\n''').format(author[0]) + + self.opts.log.warn(error_msg) + self.error = error_msg + return False + + # New author, save the previous author/sort/count + unique_authors.append((current_author[0], icu_title(current_author[1]), + books_by_current_author)) + current_author = author + books_by_current_author = 1 + elif i==0 and len(authors) == 1: + # Allow for single-book lists + unique_authors.append((current_author[0], icu_title(current_author[1]), + books_by_current_author)) + else: + books_by_current_author += 1 + else: + # Add final author to list or single-author dataset + if (current_author == author and len(authors) > 1) or not multiple_authors: + unique_authors.append((current_author[0], icu_title(current_author[1]), + books_by_current_author)) + + if False and self.verbose: + self.opts.log.info("\nfetchBooksByauthor(): %d unique authors" % len(unique_authors)) + for author in unique_authors: + self.opts.log.info((u" %-50s %-25s %2d" % (author[0][0:45], author[1][0:20], + author[2])).encode('utf-8')) + + self.authors = unique_authors + return True + def fetchBooksByTitle(self): self.updateProgressFullStep("Fetching database") @@ -1562,90 +1646,9 @@ class EPUB_MOBI(CatalogPlugin): title['title_sort'][0:40])).decode('mac-roman')) return True else: + self.error = _("No books found to catalog.\nCheck 'Excluded books' criteria in E-book options.") return False - def fetchBooksByAuthor(self): - ''' - Generate a list of titles sorted by author from the database - return = Success - ''' - - self.updateProgressFullStep("Sorting database") - - ''' - # Sort titles case-insensitive, by author - self.booksByAuthor = sorted(self.booksByTitle, - key=lambda x:(x['author_sort'].upper(), x['author_sort'].upper())) - ''' - - self.booksByAuthor = list(self.booksByTitle) - self.booksByAuthor.sort(self.author_compare) - - if False and self.verbose: - self.opts.log.info("fetchBooksByAuthor(): %d books" % len(self.booksByAuthor)) - self.opts.log.info(" %-30s %-20s %s" % ('title', 'series', 'series_index')) - for title in self.booksByAuthor: - self.opts.log.info((u" %-30s %-20s%5s " % \ - (title['title'][:30], - title['series'][:20] if title['series'] else '', - title['series_index'], - )).encode('utf-8')) - raise SystemExit - - # Build the unique_authors set from existing data - authors = [(record['author'], record['author_sort'].capitalize()) for record in self.booksByAuthor] - - # authors[] contains a list of all book authors, with multiple entries for multiple books by author - # authors[]: (([0]:friendly [1]:sort)) - # unique_authors[]: (([0]:friendly [1]:sort [2]:book_count)) - books_by_current_author = 0 - current_author = authors[0] - multiple_authors = False - unique_authors = [] - for (i,author) in enumerate(authors): - if author != current_author: - # Note that current_author and author are tuples: (friendly, sort) - multiple_authors = True - - if author != current_author and i: - # Warn, exit if friendly matches previous, but sort doesn't - if author[0] == current_author[0]: - error_msg = _(''' -\n*** Metadata error *** -Inconsistent Author Sort values for Author '{0}', unable to continue building catalog. -Select all books by '{0}', apply correct Author Sort value in Edit Metadata dialog, -then rebuild the catalog. -*** Terminating catalog generation ***\n''').format(author[0]) - - self.opts.log.warn(error_msg) - return False - - # New author, save the previous author/sort/count - unique_authors.append((current_author[0], icu_title(current_author[1]), - books_by_current_author)) - current_author = author - books_by_current_author = 1 - elif i==0 and len(authors) == 1: - # Allow for single-book lists - unique_authors.append((current_author[0], icu_title(current_author[1]), - books_by_current_author)) - else: - books_by_current_author += 1 - else: - # Add final author to list or single-author dataset - if (current_author == author and len(authors) > 1) or not multiple_authors: - unique_authors.append((current_author[0], icu_title(current_author[1]), - books_by_current_author)) - - if False and self.verbose: - self.opts.log.info("\nfetchBooksByauthor(): %d unique authors" % len(unique_authors)) - for author in unique_authors: - self.opts.log.info((u" %-50s %-25s %2d" % (author[0][0:45], author[1][0:20], - author[2])).encode('utf-8')) - - self.authors = unique_authors - return True - def fetchBookmarks(self): ''' Collect bookmarks for catalog entries @@ -5069,6 +5072,8 @@ then rebuild the catalog. abort_after_input_dump=False) plumber.merge_ui_recommendations(recommendations) plumber.run() - return 0 + # returns to gui2.actions.catalog:catalog_generated() + return None else: - return 1 + # returns to gui2.actions.catalog:catalog_generated() + return catalog.error diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index 43891a64c4..31f5e73689 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -693,8 +693,12 @@ def command_catalog(args, dbpath): } with plugin: - plugin.run(args[1], opts, get_db(dbpath, opts)) - return 0 + ret = plugin.run(args[1], opts, get_db(dbpath, opts)) + if ret is None: + ret = 0 + else: + ret = 1 + return ret # end of GR additions