diff --git a/resources/catalog/help/epub_mobi/help.html b/resources/catalog/help/epub_mobi/help.html
new file mode 100644
index 0000000000..8244b1a4d9
--- /dev/null
+++ b/resources/catalog/help/epub_mobi/help.html
@@ -0,0 +1,151 @@
+
+
+
+
+Creating AZW3 • EPUB • MOBI Catalogs
+
+
+
+
+Creating AZW3 • EPUB • MOBI Catalogs
+
+
+
+
+
+
+
+
+Calibre's Create catalog feature enables you to create a catalog of your library in a variety of formats. This help file describes cataloging options when generating a catalog in AZW3, EPUB and MOBI formats.
+
+
+If you want
all of your library cataloged, remove any search or filtering criteria in the main window. With a single book selected, all books in your library will be candidates for inclusion in the generated catalog. Individual books may be excluded by various criteria; see the
Excluded genres section below for more information.
+
If you want only some of your library cataloged, you have two options:
+
+ - Create a multiple selection of the books you want cataloged. With more than one book selected in calibre's main window, only the selected books will be cataloged.
+ - Use the Search field or the Tag Browser to filter the displayed books. Only the displayed books will be cataloged.
+
+
To begin catalog generation, select the menu item Convert books|Create a catalog of the books in your calibre library. You may also add a Create Catalog button to a toolbar in Preferences|Interface|Toolbar for easier access to the Generate catalog dialog.
+

+
In Catalog options, select AZW3, EPUB or MOBI as the Catalog format. In the Catalog title field, provide a name that will be used for the generated catalog. If a catalog of the same name and format already exists, it will be replaced with the newly-generated catalog.
+

+
Enabling Send catalog to device automatically will download the generated catalog to a connected device upon completion.
+
+
+
+
Sections enabled by a checkmark will be included in the generated catalog:
+
+ - Authors - all books, sorted by author, presented in a list format. Non-series books are listed before series books.
+ - Titles - all books, sorted by title, presented in a list format.
+ - Series - all books that are part of a series, sorted by series, presented in a list format.
+ - Genres - individual genres presented in a list, sorted by Author and Series.
+ - Recently Added - all books, sorted in reverse chronological order. List includes books added in the last 30 days, then a month-by-month listing of added books.
+ - Descriptions - detailed description page for each book, including a cover thumbnail and comments. Sorted by author, with non-series books listed before series books.
+
+
+
+
+
+
Prefix rules allow you to add a prefix to book listings when certain criteria are met. For example, you might want to mark books you've read with a checkmark, or books on your wishlist with an X.
+
The checkbox in the first column enables the rule. Name is a rule name that you provide. Field is either Tags or a custom column from your library. Value is the content of Field to match. When a prefix rule is satisfied, the book will be marked with the selected Prefix.
+
Three prefix rules have been specified in the example above:
+
+ - Read book specifies that a book with any date in a custom column named Last read will be prefixed with a checkmark symbol.
+ - Wishlist item specifies that any book with a Wishlist tag will be prefixed with an X symbol.
+ - Library books specifies that any book with a value of True (or Yes) in a custom column Available in Library will be prefixed with a double arrow symbol.
+
+
The first matching rule supplies the prefix. Disabled or incomplete rules are ignored.
+
+
+
+
+
Exclusion rules allow you to specify books that will not be cataloged.
+
The checkbox in the first column enables the rule. Name is a rule name that you provide. Field is either Tags or a custom column in your library. Value is the content of Field to match. When an exclusion rule is satisfied, the book will be excluded from the generated catalog.
+
Two exclusion rules have been specified in the example above:
+
+ - The Catalogs rule specifies that any book with a Catalog tag will be excluded from the generated catalog.
+ - The Archived Books rule specifies that any book with a value of Archived in the custom column Status will be excluded from the generated catalog.
+
+
All rules are evaluated for every book. Disabled or incomplete rules are ignored.
+
+
+
+
+
When the catalog is generated, tags in your database are used as genres. For example, you may use the tags Fiction and Nonfiction. These tags become genres in the generated catalog, with books listed under their respective genre lists based on their assigned tags. A book will be listed in every genre section for which it has a corresponding tag.
+
You may be using certain tags for other purposes, perhaps a + to indicate a read book, or a bracketed tag like [Amazon Freebie] to indicate a book's source. The Excluded genres regex allows you to specify tags that you don't want used as genres in the generated catalog. The default exclusion regex pattern \[.+\]\+ excludes any tags of the form [tag], as well as excluding +, the default tag for read books, from being used as genres in the generated catalog.
+
You can also use an exact tag name in a regex. For example, [Amazon Freebie] or [Project Gutenberg]. If you want to list multiple exact tags for exclusion, put a pipe (vertical bar) character between them: [Amazon Freebie]|[Project Gutenberg].
+
Results of regex shows you which tags will be excluded when the catalog is built, based on the tags in your database and the regex pattern you enter. The results are updated as you modify the regex pattern.
+
+
+
+
+
Catalog cover specifies whether to generate a new cover or use an existing cover. It is possible to create a custom cover for your catalogs - see Custom catalog covers for more information. If you have created a custom cover that you want to reuse, select Use existing cover. Otherwise, select Generate new cover.
+
Extra Description note specifies a custom column's contents to be inserted into the Description page, next to the cover thumbnail. For example, you might want to display the date you last read a book using a Last Read custom column. For advanced use of the Description note feature, see this post in the calibre forum.
+
Thumb width specifies a width preference for cover thumbnails included with Descriptions pages. Thumbnails are cached to improve performance.To experiment with different widths, try generating a catalog with just a few books until you've determined your preferred width, then generate your full catalog. The first time a catalog is generated with a new thumbnail width, performance will be slower, but subsequent builds of the catalog will take advantage of the thumbnail cache.
+
Merge with Comments specifies a custom column whose content will be non-destructively merged with the Comments metadata during catalog generation. For example, you might have a custom column Author Bio that you'd like to append to the Comments metadata. You can choose to insert the custom column contents before or after the Comments section, and optionally separate the appended content with a horizontal rule separator. Eligible custom column types include text, comments, and composite.
+
+
+
+
+
With the Generate Cover plugin installed, you can create custom covers for your catalog.
+
To install the plugin, go to Preferences|Advanced|Plugins|Get new plugins.
+
+
+
+For more information on calibre's Catalog feature, see the MobileRead forum sticky Creating Catalogs - Start here, where you can find information on how to customize the catalog templates, and how to submit a bug report.
+
To ask questions or discuss calibre's Catalog feature with other users, visit the MobileRead forum Calibre Catalogs.
+
Calibre's online user manual can be found here.
+
+
+
diff --git a/resources/catalog/help/epub_mobi/images/catalog_options.png b/resources/catalog/help/epub_mobi/images/catalog_options.png
new file mode 100644
index 0000000000..44a97f8b12
Binary files /dev/null and b/resources/catalog/help/epub_mobi/images/catalog_options.png differ
diff --git a/resources/catalog/help/epub_mobi/images/custom_cover.png b/resources/catalog/help/epub_mobi/images/custom_cover.png
new file mode 100644
index 0000000000..0f5b05f50f
Binary files /dev/null and b/resources/catalog/help/epub_mobi/images/custom_cover.png differ
diff --git a/resources/catalog/help/epub_mobi/images/excluded_books.png b/resources/catalog/help/epub_mobi/images/excluded_books.png
new file mode 100644
index 0000000000..6666d79341
Binary files /dev/null and b/resources/catalog/help/epub_mobi/images/excluded_books.png differ
diff --git a/resources/catalog/help/epub_mobi/images/excluded_genres.png b/resources/catalog/help/epub_mobi/images/excluded_genres.png
new file mode 100644
index 0000000000..a7c681fc38
Binary files /dev/null and b/resources/catalog/help/epub_mobi/images/excluded_genres.png differ
diff --git a/resources/catalog/help/epub_mobi/images/included_sections.png b/resources/catalog/help/epub_mobi/images/included_sections.png
new file mode 100644
index 0000000000..8139169ef2
Binary files /dev/null and b/resources/catalog/help/epub_mobi/images/included_sections.png differ
diff --git a/resources/catalog/help/epub_mobi/images/other_options.png b/resources/catalog/help/epub_mobi/images/other_options.png
new file mode 100644
index 0000000000..5e1b7b85c9
Binary files /dev/null and b/resources/catalog/help/epub_mobi/images/other_options.png differ
diff --git a/resources/catalog/help/epub_mobi/images/prefix_rules.png b/resources/catalog/help/epub_mobi/images/prefix_rules.png
new file mode 100644
index 0000000000..41750c4117
Binary files /dev/null and b/resources/catalog/help/epub_mobi/images/prefix_rules.png differ
diff --git a/resources/catalog/help/epub_mobi/images/send_to_device.png b/resources/catalog/help/epub_mobi/images/send_to_device.png
new file mode 100644
index 0000000000..82068a43aa
Binary files /dev/null and b/resources/catalog/help/epub_mobi/images/send_to_device.png differ
diff --git a/resources/catalog/help_epub_mobi.html b/resources/catalog/help_epub_mobi.html
deleted file mode 100644
index fd03277af7..0000000000
--- a/resources/catalog/help_epub_mobi.html
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
-
-Untitled Document
-
-
-
-
-Creating AZW3 • EPUB • MOBI Catalogs
-
-
-
-
-
-
-
-
-
-If you want all of your library cataloged, remove any search or filtering criteria by clearing the Search: field in the main window. With a single book selected, all books in your library will be candidates for inclusion in the generated catalog. Individual books may be excluded by various criteria; see the Excluded genres section below for more information.
-If you want only some of your library cataloged, you have two options:
-
- - Create a multiple selection of the books you want cataloged. With more than one book selected in calibre's main window, only the selected books will be cataloged.
- - Use the Search: field or calibre's Tag Browser to filter the displayed books. With a single book selected, only the displayed books will be cataloged.
-
-
-
-<img>
-Sections enabled by a checkmark will be included in the generated catalog:
-
- - Authors - all books, sorted by author, presented in a list format.
- - Titles - all books, sorted by title, presented in a list format.
- - Series - all books in series, sorted by series, presented in a list format
- - Genres - individual genres presented in a list, sorted by Author and Series
- - Recently Added - all books, sorted in reverse chronological order. List includes books added in the last 30 days, then a month-by-month listing of added books.
- - Descriptions - detailed description page for each book, including a cover thumbnail and comments. Sorted by author, with non-series books listed before series books.
-
-
-
-<img>
-Prefix rules specify matching criteria and a prefix to use when the criteria is matched.
-The checkbox in the first column enables the rule. Name is a rule name that you provide. Field is either Tags or a custom column in your library. Value is the content of Field to match. When a prefix rule is satisfied, the book will be marked with the selected symbol in the Prefix column.
-Three prefix rules have been specified in the example above:
-
- - Read book specifies that a book with any date in a custom column named Last read will be prefixed with a checkmark symbol.
- - Wishlist item specifies that any book with a Wishlist tag will be prefixed with an X symbol.
- - Library books specifies that any book with a value of True (or Yes) in a custom column Available in Library will be prefixed with a double arrow symbol.
-
-The first matching rule supplies the prefix. Disabled or incomplete rules are ignored.
-
-
-<img>
-Exclusion rules specify matching criteria for books that will not be cataloged.
-The checkbox in the first column enables the rule. Name is a rule name that you provide. Field is either Tags or a custom column in your library. Value is the content of Field to match. When an exclusion rule is satisfied, the book will be excluded from the generated catalog.
-Two exclusion rules have been specified in the example above:
-
- - The Catalogs rule specifies that any book with a Catalog tag will be excluded from the generated catalog.
- - The Archived Books rule specifies that any book with a value of Archived in the custom column Status will be excluded from the generated catalog.
-
-All rules are evaluated for every book. Disabled or incomplete rules are ignored.
-
-
-<img>
-When the catalog is generated, tags in your database are used as genres. For example, you may have the tags Fiction and Nonfiction applied to books in your library. These tags become genres in the generated catalog, with all tagged books showing up in their respective genre lists.
-You may be using certain tags for other purposes, perhaps a + to indicate a read book, or a bracketed tag like [Amazon Freebie] to indicate a book's source. The Excluded genres regex allows you to specify tags that you don't want used as genres in the generated catalog. The default exclusion regex pattern \[.+\]\+ excludes any tags of the form [tag], as well as excluding +, the default tag for read books, from being used as genres in the generated catalog.
-You can also use the exact tag name in a regex. For example, [Amazon Freebie] will exclude that tag from the generated catalog. If you want to list multiple exact tags for exclusion, put a pipe character between them: [Amazon Freebie]|[Project Gutenberg].
-The Results field shows you which tags will be excluded when the catalog is built, based on the tags in your database and the regex you enter.
-
-
-Thumb width specifies a width preference for cover thumbnails included in the Descriptions section. Thumbnails are cached to improve performance. If you want to experiment with different widths, try generating a catalog with just a few books until you've found your optimal width, then generate your full catalog. The first time a catalog is generated with a new thumbnail width, performance will be slower, but subsequent runs will take advantage of the cache.
-Extra note specifies a custom column's contents to be inserted into the Description, opposite the cover. For example, you might want to display the date you last read a book using a Last Read custom column. For advanced use of the Description note feature, see this post in the calibre forum.
-Merge with Comments specifies a custom column whose content will be non-destructively merged with the Comments metadata during catalog generation. For example, you might have a custom column Author Bio that you'd like to append to the Comments metadata. You can choose to insert the custom column contents before or after the Comments section, and optionally separate the appended content with a horizontal rule. Eligible custom column types include text, comments, and composite.
-
-Additional help resources
-For more information on calibre's Catalog feature, see the MobileRead forum sticky Creating Catalogs - Start here, where you can also find information on how to submit a bug report.
-To ask questions or discuss calibre's Catalog feature with other users, visit the MobileRead forum Calibre Catalogs.
-
-
diff --git a/src/calibre/gui2/catalog/catalog_epub_mobi.py b/src/calibre/gui2/catalog/catalog_epub_mobi.py
index 6d83adb4a8..55ac91ea6b 100644
--- a/src/calibre/gui2/catalog/catalog_epub_mobi.py
+++ b/src/calibre/gui2/catalog/catalog_epub_mobi.py
@@ -131,13 +131,14 @@ class PluginWidget(QWidget,Ui_Form):
# Look up custom column friendly name
rule['field'] = self.eligible_custom_fields[rule['field']]['field']
if rule['pattern'] in [_('any value'),_('any date')]:
- rule_pattern = '.*'
+ rule['pattern'] = '.*'
elif rule['pattern'] == _('unspecified'):
rule['pattern'] = 'None'
if 'prefix' in rule:
pr = (rule['name'],rule['field'],rule['pattern'],rule['prefix'])
else:
pr = (rule['name'],rule['field'],rule['pattern'])
+
rule_set.append(pr)
opt_value = tuple(rule_set)
# Strip off the trailing '_tw'
@@ -155,12 +156,12 @@ class PluginWidget(QWidget,Ui_Form):
Output:
self.exclude_genre_results (QLabel): updated to show tags to be excluded as genres
"""
+ results = _('No genres will be excluded')
if not regex:
self.exclude_genre_results.clear()
- self.exclude_genre_results.setText(_('No genres will be excluded'))
+ self.exclude_genre_results.setText(results)
return
- results = _('Regex does not match any tags in database')
try:
pattern = re.compile((str(regex)))
except:
@@ -188,7 +189,7 @@ class PluginWidget(QWidget,Ui_Form):
self.exclude_genre.setText(default[1])
break
- def fetchEligibleCustomFields(self):
+ def fetch_eligible_custom_fields(self):
self.all_custom_fields = self.db.custom_field_keys()
custom_fields = {}
custom_fields['Tags'] = {'field':'tag', 'datatype':u'text'}
@@ -199,6 +200,17 @@ class PluginWidget(QWidget,Ui_Form):
'datatype':field_md['datatype']}
self.eligible_custom_fields = custom_fields
+ def generate_descriptions_changed(self, enabled):
+ '''
+ Toggle Description-related controls
+ '''
+ self.header_note_source_field.setEnabled(enabled)
+ self.thumb_width.setEnabled(enabled)
+ self.merge_source_field.setEnabled(enabled)
+ self.merge_before.setEnabled(enabled)
+ self.merge_after.setEnabled(enabled)
+ self.include_hr.setEnabled(enabled)
+
def initialize(self, name, db):
'''
@@ -223,7 +235,7 @@ class PluginWidget(QWidget,Ui_Form):
self.name = name
self.db = db
self.all_tags = db.all_tags()
- self.fetchEligibleCustomFields()
+ self.fetch_eligible_custom_fields()
self.populate_combo_boxes()
# Update dialog fields from stored options
@@ -263,6 +275,10 @@ class PluginWidget(QWidget,Ui_Form):
# Hook textChanged event for exclude_genre QLineEdit
self.exclude_genre.textChanged.connect(self.exclude_genre_changed)
+ # Hook Descriptions checkbox for related options, init
+ self.generate_descriptions.clicked.connect(self.generate_descriptions_changed)
+ self.generate_descriptions_changed(self.generate_descriptions.isChecked())
+
# Init self.merge_source_field_name
self.merge_source_field_name = ''
cs = unicode(self.merge_source_field.currentText())
@@ -448,7 +464,7 @@ class PluginWidget(QWidget,Ui_Form):
'''
Display help file
'''
- url = 'file:///' + P('catalog/help_epub_mobi.html')
+ url = 'file:///' + P('catalog/help/epub_mobi/help.html')
open_url(QUrl(url))
class CheckableTableWidgetItem(QTableWidgetItem):
diff --git a/src/calibre/gui2/catalog/catalog_epub_mobi.ui b/src/calibre/gui2/catalog/catalog_epub_mobi.ui
index 162a1cce73..5e3a195190 100644
--- a/src/calibre/gui2/catalog/catalog_epub_mobi.ui
+++ b/src/calibre/gui2/catalog/catalog_epub_mobi.ui
@@ -6,7 +6,7 @@
0
0
- 650
+ 658
603
@@ -304,142 +304,9 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
Other options
-
-
- QFormLayout::FieldsStayAtSizeHint
-
- -
-
-
-
-
-
-
- 175
- 0
-
-
-
-
- 200
- 16777215
-
-
-
- &Thumb width:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- merge_source_field
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 137
- 16777215
-
-
-
- Size hint for cover thumbnails included in Descriptions section.
-
-
- inch
-
-
- 2
-
-
- 1.000000000000000
-
-
- 2.000000000000000
-
-
- 0.100000000000000
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- -
-
-
- E&xtra note:
-
-
- header_note_source_field
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
- Custom column source for text to include in Description section.
-
-
-
-
-
- -
-
-
-
-
-
-
- 175
- 0
-
-
-
-
- 200
- 16777215
-
-
-
- &Merge with Comments:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- merge_source_field
-
-
-
+
+ -
+
-
@@ -468,6 +335,9 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
&Before
+
+ merge_options_bg
+
-
@@ -478,6 +348,9 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
&After
+
+ merge_options_bg
+
-
@@ -493,30 +366,55 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
Separate Comments metadata and additional content with a horizontal rule.
- &Separator
+ Include &Separator
-
+
+
+
+ 175
+ 0
+
+
+
+
+ 200
+ 16777215
+
+
+
+ &Merge with Comments:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ merge_source_field
+
+
+
+ -
+
+
+
+ 175
+ 20
+
+
+
+ Catalog cover:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
-
-
-
-
-
- 175
- 20
-
-
-
- Catalog cover:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
@@ -525,6 +423,9 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
true
+
+ cover_options_bg
+
-
@@ -532,6 +433,130 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
Use existing cover
+
+ cover_options_bg
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ E&xtra Description note:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ header_note_source_field
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Custom column source for text to include in Description section.
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ &Thumb width:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ merge_source_field
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Size hint for cover thumbnails included in Descriptions section.
+
+
+ inch
+
+
+ 2
+
+
+ 1.000000000000000
+
+
+ 2.000000000000000
+
+
+ 0.100000000000000
+
@@ -543,4 +568,8 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
+
+
+
+
diff --git a/src/calibre/library/catalogs/__init__.py b/src/calibre/library/catalogs/__init__.py
index 0fcf8266da..a5c98955e8 100644
--- a/src/calibre/library/catalogs/__init__.py
+++ b/src/calibre/library/catalogs/__init__.py
@@ -17,4 +17,6 @@ FIELDS = ['all', 'title', 'title_sort', 'author_sort', 'authors', 'comments',
TEMPLATE_ALLOWED_FIELDS = [ 'author_sort', 'authors', 'id', 'isbn', 'pubdate', 'title_sort',
'publisher', 'series_index', 'series', 'tags', 'timestamp', 'title', 'uuid' ]
+class AuthorSortMismatchException(Exception): pass
+class EmptyCatalogException(Exception): pass
diff --git a/src/calibre/library/catalogs/epub_mobi.py b/src/calibre/library/catalogs/epub_mobi.py
index f37f66f7c3..c92d178f6f 100644
--- a/src/calibre/library/catalogs/epub_mobi.py
+++ b/src/calibre/library/catalogs/epub_mobi.py
@@ -7,13 +7,14 @@ __license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal '
__docformat__ = 'restructuredtext en'
-import os, shutil, time
+import os, shutil, sys, time
from collections import namedtuple
from calibre import strftime
from calibre.customize import CatalogPlugin
from calibre.customize.conversion import OptionRecommendation, DummyReporter
from calibre.ebooks import calibre_cover
+from calibre.library.catalogs import AuthorSortMismatchException, EmptyCatalogException
from calibre.ptempfile import PersistentTemporaryFile
Option = namedtuple('Option', 'option, default, dest, action, help')
@@ -146,6 +147,13 @@ class EPUB_MOBI(CatalogPlugin):
"When multiple rules are defined, the first matching rule will be used.\n"
"Default:\n" + '"' + '%default' + '"' + "\n"
"Applies to AZW3, ePub, MOBI output formats")),
+ Option('--use-existing-cover',
+ default=False,
+ dest='use_existing_cover',
+ action = 'store_true',
+ help=_("Replace existing cover when generating the catalog.\n"
+ "Default: '%default'\n"
+ "Applies to: AZW3, ePub, MOBI output formats")),
Option('--thumb-width',
default='1.0',
dest='thumb_width',
@@ -311,7 +319,7 @@ class EPUB_MOBI(CatalogPlugin):
'header_note_source_field','merge_comments_rule',
'output_profile','prefix_rules','read_book_marker',
'search_text','sort_by','sort_descriptions_by_author','sync',
- 'thumb_width','wishlist_tag']:
+ 'thumb_width','use_existing_cover','wishlist_tag']:
build_log.append(" %s: %s" % (key, repr(opts_dict[key])))
if opts.verbose:
@@ -325,16 +333,17 @@ class EPUB_MOBI(CatalogPlugin):
if opts.verbose:
log.info(" Begin catalog source generation")
- # Returns False if nothing to catalog or author_sort mismatches while building MOBI
- catalog_source_built = catalog.build_sources()
-
- if opts.verbose:
- if catalog_source_built:
+ try:
+ catalog_source_built = catalog.build_sources()
+ if opts.verbose:
log.info(" Completed catalog source generation\n")
- else:
- log.error(" *** Terminated catalog generation, check log for details ***")
+ except (AuthorSortMismatchException, EmptyCatalogException), e:
+ log.error(" *** Terminated catalog generation: %s ***" % e)
+ except:
+ log.error(" unhandled exception in catalog generator")
+ raise
- if catalog_source_built:
+ else:
recommendations = []
recommendations.append(('remove_fake_margins', False,
OptionRecommendation.HIGH))
@@ -382,7 +391,7 @@ class EPUB_MOBI(CatalogPlugin):
recommendations.append(('cover', cpath, OptionRecommendation.HIGH))
log.info("using existing catalog cover")
else:
- log.info("generating new catalog cover")
+ log.info("replacing catalog cover")
new_cover_path = PersistentTemporaryFile(suffix='.jpg')
new_cover = calibre_cover(opts.catalog_title.replace('"', '\\"'), 'calibre')
new_cover_path.write(new_cover)
diff --git a/src/calibre/library/catalogs/epub_mobi_builder.py b/src/calibre/library/catalogs/epub_mobi_builder.py
index e1a0b8ffa0..3a90482667 100644
--- a/src/calibre/library/catalogs/epub_mobi_builder.py
+++ b/src/calibre/library/catalogs/epub_mobi_builder.py
@@ -12,6 +12,7 @@ from calibre.customize.conversion import DummyReporter
from calibre.customize.ui import output_profiles
from calibre.ebooks.BeautifulSoup import BeautifulSoup, BeautifulStoneSoup, Tag, NavigableString
from calibre.ebooks.chardet import substitute_entites
+from calibre.library.catalogs import AuthorSortMismatchException, EmptyCatalogException
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.utils.config import config_dir
from calibre.utils.date import format_date, is_date_undefined, now as nowf
@@ -20,9 +21,6 @@ from calibre.utils.icu import capitalize, collation_order, sort_key
from calibre.utils.magick.draw import thumbnail
from calibre.utils.zipfile import ZipFile
-class AuthorSortMismatchException(Exception): pass
-class EmptyCatalogException(Exception): pass
-
class CatalogBuilder(object):
'''
Generates catalog source files from calibre database
@@ -499,26 +497,18 @@ class CatalogBuilder(object):
Called from gui2.convert.gui_conversion:gui_catalog()
Args:
- (none)
- Touches:
+ Exceptions:
+ AuthorSortMismatchException
+ EmptyCatalogException
+
+ Results:
error: problems reported during build
- Return:
- (bool): True: successful build, possibly with warnings
- False: failed to build
"""
- try:
- self.fetch_books_by_title()
- except EmptyCatalogException:
- return False
-
- try:
- self.fetch_books_by_author()
- except AuthorSortMismatchException:
- return False
-
+ self.fetch_books_by_title()
+ self.fetch_books_by_author()
self.fetch_bookmarks()
if self.opts.generate_descriptions:
self.generate_thumbnails()
@@ -535,11 +525,11 @@ class CatalogBuilder(object):
if self.opts.section_list == ['Genres'] and not self.genres:
error_msg = _("No genres to catalog.\n")
if not self.opts.cli_environment:
- error_msg += "Check 'Excluded genres' regex in E-book options.\n"
+ error_msg += _("Check 'Excluded genres' regex in E-book options.\n")
self.opts.log.error(error_msg)
self.error.append(_('No books available to catalog'))
self.error.append(error_msg)
- return False
+ raise EmptyCatalogException, "No genres to catalog"
if self.opts.generate_recently_added:
self.generate_html_by_date_added()
if self.generate_recently_read:
@@ -561,9 +551,7 @@ class CatalogBuilder(object):
self.generate_ncx_by_date_read(_("Recently Read"))
if self.opts.generate_descriptions:
self.generate_ncx_descriptions(_("Descriptions"))
-
self.write_ncx()
- return True
def calculate_thumbnail_dimensions(self):
""" Calculate thumb dimensions based on device DPI.
@@ -799,7 +787,7 @@ class CatalogBuilder(object):
self.error.append('Author Sort mismatch')
self.error.append(error_msg)
- raise AuthorSortMismatchException
+ raise AuthorSortMismatchException, "author_sort mismatch while building MOBI"
else:
# Warning if building non-MOBI
if not self.error:
@@ -810,6 +798,7 @@ class CatalogBuilder(object):
self.opts.log.warn('\n*** Metadata warning ***')
self.opts.log.warn(error_msg)
self.error.append(error_msg)
+ continue
current_author = author
@@ -827,10 +816,9 @@ class CatalogBuilder(object):
None: no match
"""
def _log_prefix_rule_match_info(rule, record):
- self.opts.log.info(" %s %s by %s (Prefix rule '%s': %s:%s)" %
+ self.opts.log.info(" %s '%s' by %s (Prefix rule '%s')" %
(rule['prefix'],record['title'],
- record['authors'][0], rule['name'],
- rule['field'],rule['pattern']))
+ record['authors'][0], rule['name']))
# Compare the record to each rule looking for a match
for rule in self.prefix_rules:
@@ -1168,9 +1156,6 @@ class CatalogBuilder(object):
# Re-sort based on title_sort
if len(titles):
- #self.books_by_title = sorted(titles,
- # key=lambda x:(x['title_sort'].upper(), x['title_sort'].upper()))
-
self.books_by_title = sorted(titles, key=lambda x: sort_key(x['title_sort'].upper()))
if self.DEBUG and self.opts.verbose:
@@ -1184,7 +1169,7 @@ class CatalogBuilder(object):
self.opts.log.error('*** ' + error_msg + ' ***')
self.error.append(_('No books available to include in catalog'))
self.error.append(error_msg)
- raise EmptyCatalogException
+ raise EmptyCatalogException, error_msg
def fetch_bookmarks(self):
""" Interrogate connected Kindle for bookmarks.
@@ -2385,6 +2370,9 @@ class CatalogBuilder(object):
Output:
content/BySeries.html (file)
+
+ To do:
+ self.books_by_series = [i for i in self.books_by_title if i['series']]
"""
friendly_name = _("Series")
self.update_progress_full_step("%s HTML" % friendly_name)
@@ -2414,7 +2402,7 @@ class CatalogBuilder(object):
data = self.plugin.search_sort_db(self.db, self.opts)
# Remove exclusions
- self.books_by_series = self.process_exclusions(data)
+ self.books_by_series = self.process_exclusions(data, log_exclusion=False)
if not self.books_by_series:
self.opts.generate_series = False
@@ -4496,13 +4484,16 @@ class CatalogBuilder(object):
# Report excluded books
if self.opts.verbose and excluded_tags:
- self.opts.log.info(" Excluded books:")
+ self.opts.log.info(" Excluded books by Tags:")
data = self.db.get_data_as_dict(ids=self.opts.ids)
for record in data:
matched = list(set(record['tags']) & set(excluded_tags))
- if matched :
- self.opts.log.info(" - '%s' by %s (Exclusion rule Tags: '%s')" %
- (record['title'], record['authors'][0], str(matched[0])))
+ if matched:
+ for rule in self.opts.exclusion_rules:
+ if rule[1] == 'Tags' and rule[2] == str(matched[0]):
+ self.opts.log.info(" - '%s' by %s (Exclusion rule '%s')" %
+ (record['title'], record['authors'][0], rule[0]))
+
return excluded_tags
def get_friendly_genre_tag(self, genre):
@@ -4786,7 +4777,7 @@ class CatalogBuilder(object):
normalized += c
return normalized
- def process_exclusions(self, data_set):
+ def process_exclusions(self, data_set, log_exclusion=True):
""" Filter data_set based on exclusion_rules.
Compare each book in data_set to each exclusion_rule. Remove
@@ -4817,12 +4808,15 @@ class CatalogBuilder(object):
field,
index_is_id=True)
if field_contents:
- if re.search(pat, unicode(field_contents),
- re.IGNORECASE) is not None:
- if self.opts.verbose:
+ matched = re.search(pat, unicode(field_contents),
+ re.IGNORECASE)
+ if matched is not None:
+ if self.opts.verbose and log_exclusion:
field_md = self.db.metadata_for_field(field)
- self.opts.log.info(" - %s (Exclusion rule '%s': %s:%s)" %
- (record['title'], field_md['name'], field,pat))
+ for rule in self.opts.exclusion_rules:
+ if rule[1] == '#%s' % field_md['label']:
+ self.opts.log.info(" - '%s' by %s (Exclusion rule '%s')" %
+ (record['title'], record['authors'][0], rule[0]))
exclusion_set.append(record)
if record in filtered_data_set:
filtered_data_set.remove(record)