Catalogs: Generate cover for mobi/azw3 catalogs

This commit is contained in:
Kovid Goyal 2012-08-07 19:34:50 +05:30
commit 015845c7d3
3 changed files with 45 additions and 24 deletions

View File

@ -25,7 +25,7 @@ from PyQt4.Qt import (Qt, QAbstractItemView, QCheckBox, QComboBox, QDialog,
class PluginWidget(QWidget,Ui_Form): class PluginWidget(QWidget,Ui_Form):
TITLE = _('E-book options') TITLE = _('E-book options')
HELP = _('Options specific to')+' EPUB/MOBI '+_('output') HELP = _('Options specific to')+' AZW3/EPUB/MOBI '+_('output')
# Output synced to the connected device? # Output synced to the connected device?
sync_enabled = True sync_enabled = True
@ -402,7 +402,6 @@ class PluginWidget(QWidget,Ui_Form):
self.exclude_genre.setText(default[1]) self.exclude_genre.setText(default[1])
break break
class CheckableTableWidgetItem(QTableWidgetItem): class CheckableTableWidgetItem(QTableWidgetItem):
''' '''
Borrowed from kiwidude Borrowed from kiwidude
@ -637,8 +636,9 @@ class GenericRulesTable(QTableWidget):
pass pass
def resize_name(self, scale): def resize_name(self, scale):
current_width = self.columnWidth(1) #current_width = self.columnWidth(1)
self.setColumnWidth(1, min(225,int(current_width * scale))) #self.setColumnWidth(1, min(225,int(current_width * scale)))
self.setColumnWidth(1, 225)
def rule_name_edited(self): def rule_name_edited(self):
current_row = self.currentRow() current_row = self.currentRow()

View File

@ -13,6 +13,8 @@ from collections import namedtuple
from calibre import strftime from calibre import strftime
from calibre.customize import CatalogPlugin from calibre.customize import CatalogPlugin
from calibre.customize.conversion import OptionRecommendation, DummyReporter from calibre.customize.conversion import OptionRecommendation, DummyReporter
from calibre.ebooks import calibre_cover
from calibre.ptempfile import PersistentTemporaryFile
Option = namedtuple('Option', 'option, default, dest, action, help') Option = namedtuple('Option', 'option, default, dest, action, help')
@ -20,7 +22,7 @@ class EPUB_MOBI(CatalogPlugin):
'ePub catalog generator' 'ePub catalog generator'
name = 'Catalog_EPUB_MOBI' name = 'Catalog_EPUB_MOBI'
description = 'EPUB/MOBI catalog generator' description = 'AZW3/EPUB/MOBI catalog generator'
supported_platforms = ['windows', 'osx', 'linux'] supported_platforms = ['windows', 'osx', 'linux']
minimum_calibre_version = (0, 7, 40) minimum_calibre_version = (0, 7, 40)
author = 'Greg Riker' author = 'Greg Riker'
@ -36,7 +38,7 @@ class EPUB_MOBI(CatalogPlugin):
action = None, action = None,
help = _('Title of generated catalog used as title in metadata.\n' help = _('Title of generated catalog used as title in metadata.\n'
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--debug-pipeline', Option('--debug-pipeline',
default=None, default=None,
dest='debug_pipeline', dest='debug_pipeline',
@ -46,17 +48,17 @@ class EPUB_MOBI(CatalogPlugin):
"directory. Useful if you are unsure at which stage " "directory. Useful if you are unsure at which stage "
"of the conversion process a bug is occurring.\n" "of the conversion process a bug is occurring.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--exclude-genre', Option('--exclude-genre',
default='\[.+\]|\+', default='\[.+\]|\+',
dest='exclude_genre', dest='exclude_genre',
action = None, action = None,
help=_("Regex describing tags to exclude as genres.\n" help=_("Regex describing tags to exclude as genres.\n"
"Default: '%default' excludes bracketed tags, e.g. '[Project Gutenberg]', and '+', the default tag for read books.\n" "Default: '%default' excludes bracketed tags, e.g. '[Project Gutenberg]', and '+', the default tag for read books.\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--exclusion-rules', Option('--exclusion-rules',
default="(('Excluded tags','Tags','~,Catalog'),)", default="(('Excluded tags','Tags','Catalog'),)",
dest='exclusion_rules', dest='exclusion_rules',
action=None, action=None,
help=_("Specifies the rules used to exclude books from the generated catalog.\n" help=_("Specifies the rules used to exclude books from the generated catalog.\n"
@ -67,7 +69,7 @@ class EPUB_MOBI(CatalogPlugin):
"will exclude a book with a value of 'Archived' in the custom column 'status'.\n" "will exclude a book with a value of 'Archived' in the custom column 'status'.\n"
"When multiple rules are defined, all rules will be applied.\n" "When multiple rules are defined, all rules will be applied.\n"
"Default: \n" + '"' + '%default' + '"' + "\n" "Default: \n" + '"' + '%default' + '"' + "\n"
"Applies to ePub, MOBI output formats")), "Applies to AZW3, ePub, MOBI output formats")),
Option('--generate-authors', Option('--generate-authors',
default=False, default=False,
@ -75,49 +77,49 @@ class EPUB_MOBI(CatalogPlugin):
action = 'store_true', action = 'store_true',
help=_("Include 'Authors' section in catalog.\n" help=_("Include 'Authors' section in catalog.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--generate-descriptions', Option('--generate-descriptions',
default=False, default=False,
dest='generate_descriptions', dest='generate_descriptions',
action = 'store_true', action = 'store_true',
help=_("Include 'Descriptions' section in catalog.\n" help=_("Include 'Descriptions' section in catalog.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--generate-genres', Option('--generate-genres',
default=False, default=False,
dest='generate_genres', dest='generate_genres',
action = 'store_true', action = 'store_true',
help=_("Include 'Genres' section in catalog.\n" help=_("Include 'Genres' section in catalog.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--generate-titles', Option('--generate-titles',
default=False, default=False,
dest='generate_titles', dest='generate_titles',
action = 'store_true', action = 'store_true',
help=_("Include 'Titles' section in catalog.\n" help=_("Include 'Titles' section in catalog.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--generate-series', Option('--generate-series',
default=False, default=False,
dest='generate_series', dest='generate_series',
action = 'store_true', action = 'store_true',
help=_("Include 'Series' section in catalog.\n" help=_("Include 'Series' section in catalog.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--generate-recently-added', Option('--generate-recently-added',
default=False, default=False,
dest='generate_recently_added', dest='generate_recently_added',
action = 'store_true', action = 'store_true',
help=_("Include 'Recently Added' section in catalog.\n" help=_("Include 'Recently Added' section in catalog.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--header-note-source-field', Option('--header-note-source-field',
default='', default='',
dest='header_note_source_field', dest='header_note_source_field',
action = None, action = None,
help=_("Custom field containing note text to insert in Description header.\n" help=_("Custom field containing note text to insert in Description header.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--merge-comments', Option('--merge-comments',
default='::', default='::',
dest='merge_comments', dest='merge_comments',
@ -127,14 +129,14 @@ class EPUB_MOBI(CatalogPlugin):
" [before|after] Placement of notes with respect to Comments\n" " [before|after] Placement of notes with respect to Comments\n"
" [True|False] - A horizontal rule is inserted between notes and Comments\n" " [True|False] - A horizontal rule is inserted between notes and Comments\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to ePub, MOBI output formats")), "Applies to AZW3, ePub, MOBI output formats")),
Option('--output-profile', Option('--output-profile',
default=None, default=None,
dest='output_profile', dest='output_profile',
action = None, action = None,
help=_("Specifies the output profile. In some cases, an output profile is required to optimize the catalog for the device. For example, 'kindle' or 'kindle_dx' creates a structured Table of Contents with Sections and Articles.\n" help=_("Specifies the output profile. In some cases, an output profile is required to optimize the catalog for the device. For example, 'kindle' or 'kindle_dx' creates a structured Table of Contents with Sections and Articles.\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to: ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--prefix-rules', Option('--prefix-rules',
default="(('Read books','tags','+','\u2713'),('Wishlist items','tags','Wishlist','\u00d7'))", default="(('Read books','tags','+','\u2713'),('Wishlist items','tags','Wishlist','\u00d7'))",
dest='prefix_rules', dest='prefix_rules',
@ -143,7 +145,7 @@ class EPUB_MOBI(CatalogPlugin):
"The model for a prefix rule is ('<rule name>','<source field>','<pattern>','<prefix>').\n" "The model for a prefix rule is ('<rule name>','<source field>','<pattern>','<prefix>').\n"
"When multiple rules are defined, the first matching rule will be used.\n" "When multiple rules are defined, the first matching rule will be used.\n"
"Default:\n" + '"' + '%default' + '"' + "\n" "Default:\n" + '"' + '%default' + '"' + "\n"
"Applies to ePub, MOBI output formats")), "Applies to AZW3, ePub, MOBI output formats")),
Option('--thumb-width', Option('--thumb-width',
default='1.0', default='1.0',
dest='thumb_width', dest='thumb_width',
@ -151,7 +153,7 @@ class EPUB_MOBI(CatalogPlugin):
help=_("Size hint (in inches) for book covers in catalog.\n" help=_("Size hint (in inches) for book covers in catalog.\n"
"Range: 1.0 - 2.0\n" "Range: 1.0 - 2.0\n"
"Default: '%default'\n" "Default: '%default'\n"
"Applies to ePub, MOBI output formats")), "Applies to AZW3, ePub, MOBI output formats")),
] ]
# }}} # }}}
@ -172,7 +174,8 @@ class EPUB_MOBI(CatalogPlugin):
if op is None: if op is None:
op = 'default' op = 'default'
if opts.connected_device['name'] and 'kindle' in opts.connected_device['name'].lower(): if opts.connected_device['name'] and \
opts.connected_device['short_name'] in ['kindle','kindle dx']:
opts.connected_kindle = True opts.connected_kindle = True
if opts.connected_device['serial'] and \ if opts.connected_device['serial'] and \
opts.connected_device['serial'][:4] in ['B004','B005']: opts.connected_device['serial'][:4] in ['B004','B005']:
@ -337,7 +340,7 @@ class EPUB_MOBI(CatalogPlugin):
OptionRecommendation.HIGH)) OptionRecommendation.HIGH))
recommendations.append(('comments', '', OptionRecommendation.HIGH)) recommendations.append(('comments', '', OptionRecommendation.HIGH))
# Use to debug generated catalog code before conversion # >>> Use to debug generated catalog code before conversion <<<
#setattr(opts,'debug_pipeline',os.path.expanduser("~/Desktop/Catalog debug")) #setattr(opts,'debug_pipeline',os.path.expanduser("~/Desktop/Catalog debug"))
dp = getattr(opts, 'debug_pipeline', None) dp = getattr(opts, 'debug_pipeline', None)
@ -355,6 +358,7 @@ class EPUB_MOBI(CatalogPlugin):
# If cover exists, use it # If cover exists, use it
cpath = None cpath = None
generate_new_cover = False
try: try:
search_text = 'title:"%s" author:%s' % ( search_text = 'title:"%s" author:%s' % (
opts.catalog_title.replace('"', '\\"'), 'calibre') opts.catalog_title.replace('"', '\\"'), 'calibre')
@ -364,9 +368,26 @@ class EPUB_MOBI(CatalogPlugin):
if cpath and os.path.exists(cpath): if cpath and os.path.exists(cpath):
recommendations.append(('cover', cpath, recommendations.append(('cover', cpath,
OptionRecommendation.HIGH)) OptionRecommendation.HIGH))
log.info("using existing cover")
else:
log.info("no existing cover, generating new cover")
generate_new_cover = True
else:
log.info("no existing cover, generating new cover")
generate_new_cover = True
except: except:
pass pass
if generate_new_cover:
new_cover_path = PersistentTemporaryFile(suffix='.jpg')
new_cover = calibre_cover(opts.catalog_title.replace('"', '\\"'), 'calibre')
new_cover_path.write(new_cover)
new_cover_path.close()
recommendations.append(('cover', new_cover_path.name, OptionRecommendation.HIGH))
if opts.verbose:
log.info("Invoking Plumber with recommendations:\n %s" % recommendations)
# Run ebook-convert # Run ebook-convert
from calibre.ebooks.conversion.plumber import Plumber from calibre.ebooks.conversion.plumber import Plumber
plumber = Plumber(os.path.join(catalog.catalogPath, plumber = Plumber(os.path.join(catalog.catalogPath,

View File

@ -1126,7 +1126,7 @@ Author '{0}':
aTag = Tag(soup, "a") aTag = Tag(soup, "a")
current_letter = self.letter_or_symbol(book['author_sort'][0].upper()) current_letter = self.letter_or_symbol(book['author_sort'][0].upper())
if current_letter == self.SYMBOLS: if current_letter == self.SYMBOLS:
aTag['id'] = self.SYMBOLS aTag['id'] = self.SYMBOLS + '_authors'
else: else:
aTag['id'] = "%s_authors" % self.generateUnicodeName(current_letter) aTag['id'] = "%s_authors" % self.generateUnicodeName(current_letter)
pIndexTag.insert(0,aTag) pIndexTag.insert(0,aTag)