diff --git a/src/calibre/devices/sne/driver.py b/src/calibre/devices/sne/driver.py index bb8d34c59c..04e5cd0d76 100644 --- a/src/calibre/devices/sne/driver.py +++ b/src/calibre/devices/sne/driver.py @@ -33,6 +33,6 @@ class SNE(USBMS): STORAGE_CARD_VOLUME_LABEL = 'SNE Storage Card' EBOOK_DIR_MAIN = EBOOK_DIR_CARD_A = 'Books' - SUPPORTS_SUB_DIRS = True + SUPPORTS_SUB_DIRS = False diff --git a/src/calibre/ebooks/rtf2xml/default_encoding.py b/src/calibre/ebooks/rtf2xml/default_encoding.py index 31122318b6..3ddfbcd321 100755 --- a/src/calibre/ebooks/rtf2xml/default_encoding.py +++ b/src/calibre/ebooks/rtf2xml/default_encoding.py @@ -121,7 +121,7 @@ class DefaultEncoding: else: fenc = re.compile(r'\\(mac|pc|ansi|pca)[\\ \{\}\t\n]+') fenccp = re.compile(r'\\ansicpg(\d+)[\\ \{\}\t\n]+') - + for line in read_obj: if fenc.search(line): enc = fenc.search(line).group(1) @@ -141,6 +141,7 @@ class DefaultEncoding: self.__code_page = '850' if __name__ == '__main__': + import sys encode_obj = DefaultEncoding( in_file = sys.argv[1], bug_handler = Exception, diff --git a/src/calibre/ebooks/rtf2xml/delete_info.py b/src/calibre/ebooks/rtf2xml/delete_info.py index 80d2a2b2bd..823b50741e 100755 --- a/src/calibre/ebooks/rtf2xml/delete_info.py +++ b/src/calibre/ebooks/rtf2xml/delete_info.py @@ -199,7 +199,8 @@ class DeleteInfo: # Get action to perform action = self.__state_dict.get(self.__state) if not action: - sys.stderr.write('No action in dictionary state is "%s" \n' % self.__state) + sys.stderr.write('No action in dictionary state is "%s" \n' + % self.__state) # Print if allowed by action if action(line): self.__write_obj.write(line) 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 diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index 2c0d2a6173..0e8c101620 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -437,6 +437,15 @@ My antivirus program claims |app| is a virus/trojan? Your antivirus program is wrong. |app| is a completely open source product. You can actually browse the source code yourself (or hire someone to do it for you) to verify that it is not a virus. Please report the false identification to whatever company you buy your antivirus software from. If the antivirus program is preventing you from downloading/installing |app|, disable it temporarily, install |app| and then re-enable it. +How do I backup |app|? +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The most important thing to backup is the |app| library folder, that contains all your books and metadata. This is the folder you chose for your |app| library when you ran |app| for the first time. You can get the path to the library folder by clicking the |app| icon on the main toolbar. You must backup this complete folder with all its files and sub-folders. + +You can switch |app| to using a backed up library folder by simply clicking the |app| icon on the toolbar and choosing your backup library folder. + +If you want to backup the |app| configuration/plugins, you have to backup the config directory. You can find this config directory via :guilabel:`Preferences->Miscellaneous`. Note that restoring configuration directories is not officially supported, but should work in most cases. Just copy the contents of the backup directory into the current configuration directory to restore. + How do I use purchased EPUB books with |app|? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Most purchased EPUB books have `DRM `_. This prevents |app| from opening them. You can still use |app| to store and transfer them to your e-book reader. First, you must authorize your reader on a windows machine with Adobe Digital Editions. Once this is done, EPUB books transferred with |app| will work fine on your reader. When you purchase an epub book from a website, you will get an ".acsm" file. This file should be opened with Adobe Digital Editions, which will then download the actual ".epub" e-book. The e-book file will be stored in the folder "My Digital Editions", from where you can add it to |app|.