mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Catalogs: Generate cover for mobi/azw3 catalogs
This commit is contained in:
commit
015845c7d3
@ -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()
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user