Fix #1044619 (When connected to itunes and set to device won't sort by author) and add a link ot the catalog help in the catalog dialog

This commit is contained in:
Kovid Goyal 2012-09-06 16:23:33 +05:30
commit 36939fbfe0
9 changed files with 3811 additions and 2865 deletions

View File

@ -13,7 +13,8 @@ from calibre.constants import isosx, iswindows
from calibre.devices.errors import OpenFeedback, UserFeedback from calibre.devices.errors import OpenFeedback, UserFeedback
from calibre.devices.usbms.deviceconfig import DeviceConfig from calibre.devices.usbms.deviceconfig import DeviceConfig
from calibre.devices.interface import DevicePlugin from calibre.devices.interface import DevicePlugin
from calibre.ebooks.metadata import authors_to_string, MetaInformation, title_sort from calibre.ebooks.metadata import (author_to_author_sort, authors_to_string,
MetaInformation, title_sort)
from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.book.base import Metadata
from calibre.utils.config import config_dir, dynamic, prefs from calibre.utils.config import config_dir, dynamic, prefs
from calibre.utils.date import now, parse_date from calibre.utils.date import now, parse_date
@ -3478,6 +3479,7 @@ class Book(Metadata):
''' '''
def __init__(self,title,author): def __init__(self,title,author):
Metadata.__init__(self, title, authors=author.split(' & ')) Metadata.__init__(self, title, authors=author.split(' & '))
self.author_sort = author_to_author_sort(author)
@property @property
def title_sorter(self): def title_sorter(self):

View File

@ -67,7 +67,7 @@ class GenerateCatalogAction(InterfaceAction):
# jobs.results is a list - the first entry is the intended title for the dialog # jobs.results is a list - the first entry is the intended title for the dialog
# Subsequent strings are error messages # Subsequent strings are error messages
dialog_title = job.result.pop(0) dialog_title = job.result.pop(0)
if re.match('warning:', job.result[0].lower()): if re.search('warning', job.result[0].lower()):
msg = _("Catalog generation complete, with warnings.") msg = _("Catalog generation complete, with warnings.")
warning_dialog(self.gui, dialog_title, msg, det_msg='\n'.join(job.result), show=True) warning_dialog(self.gui, dialog_title, msg, det_msg='\n'.join(job.result), show=True)
else: else:

View File

@ -6,17 +6,19 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from copy import copy import re, sys
from functools import partial from functools import partial
from calibre.ebooks.conversion.config import load_defaults from calibre.ebooks.conversion.config import load_defaults
from calibre.gui2 import gprefs, question_dialog from calibre.gui2 import gprefs, open_url, question_dialog
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
from catalog_epub_mobi_ui import Ui_Form from catalog_epub_mobi_ui import Ui_Form
from PyQt4.Qt import (Qt, QAbstractItemView, QCheckBox, QComboBox, from PyQt4.Qt import (Qt, QAbstractItemView, QCheckBox, QComboBox,
QDoubleSpinBox, QIcon, QLineEdit, QObject, QRadioButton, QSize, QSizePolicy, QDoubleSpinBox, QIcon, QLineEdit, QObject, QRadioButton, QSize, QSizePolicy,
QTableWidget, QTableWidgetItem, QToolButton, QVBoxLayout, QWidget, QTableWidget, QTableWidgetItem, QTextEdit, QToolButton, QUrl,
QVBoxLayout, QWidget,
SIGNAL) SIGNAL)
class PluginWidget(QWidget,Ui_Form): class PluginWidget(QWidget,Ui_Form):
@ -44,6 +46,7 @@ class PluginWidget(QWidget,Ui_Form):
LineEditControls = [] LineEditControls = []
RadioButtonControls = [] RadioButtonControls = []
TableWidgetControls = [] TableWidgetControls = []
TextEditControls = []
for item in self.__dict__: for item in self.__dict__:
if type(self.__dict__[item]) is QCheckBox: if type(self.__dict__[item]) is QCheckBox:
@ -58,6 +61,8 @@ class PluginWidget(QWidget,Ui_Form):
RadioButtonControls.append(str(self.__dict__[item].objectName())) RadioButtonControls.append(str(self.__dict__[item].objectName()))
elif type(self.__dict__[item]) is QTableWidget: elif type(self.__dict__[item]) is QTableWidget:
TableWidgetControls.append(str(self.__dict__[item].objectName())) TableWidgetControls.append(str(self.__dict__[item].objectName()))
elif type(self.__dict__[item]) is QTextEdit:
TextEditControls.append(str(self.__dict__[item].objectName()))
option_fields = zip(CheckBoxControls, option_fields = zip(CheckBoxControls,
[True for i in CheckBoxControls], [True for i in CheckBoxControls],
@ -72,20 +77,23 @@ class PluginWidget(QWidget,Ui_Form):
# LineEditControls # LineEditControls
option_fields += zip(['exclude_genre'],['\[.+\]|\+'],['line_edit']) option_fields += zip(['exclude_genre'],['\[.+\]|\+'],['line_edit'])
# TextEditControls
#option_fields += zip(['exclude_genre_results'],['excluded genres will appear here'],['text_edit'])
# SpinBoxControls # SpinBoxControls
option_fields += zip(['thumb_width'],[1.00],['spin_box']) option_fields += zip(['thumb_width'],[1.00],['spin_box'])
# Exclusion rules # Exclusion rules
option_fields += zip(['exclusion_rules_tw','exclusion_rules_tw'], option_fields += zip(['exclusion_rules_tw'],
[{'ordinal':0, [{'ordinal':0,
'enabled':True, 'enabled':True,
'name':'Catalogs', 'name':'Catalogs',
'field':'Tags', 'field':'Tags',
'pattern':'Catalog'},], 'pattern':'Catalog'},],
['table_widget','table_widget']) ['table_widget'])
# Prefix rules # Prefix rules
option_fields += zip(['prefix_rules_tw','prefix_rules_tw','prefix_rules_tw'], option_fields += zip(['prefix_rules_tw','prefix_rules_tw'],
[{'ordinal':0, [{'ordinal':0,
'enabled':True, 'enabled':True,
'name':'Read book', 'name':'Read book',
@ -98,7 +106,7 @@ class PluginWidget(QWidget,Ui_Form):
'field':'Tags', 'field':'Tags',
'pattern':'Wishlist', 'pattern':'Wishlist',
'prefix':u'\u00d7'},], 'prefix':u'\u00d7'},],
['table_widget','table_widget','table_widget']) ['table_widget','table_widget'])
self.OPTION_FIELDS = option_fields self.OPTION_FIELDS = option_fields
@ -110,13 +118,13 @@ class PluginWidget(QWidget,Ui_Form):
''' '''
rule_set = [] rule_set = []
for stored_rule in opt_value: for stored_rule in opt_value:
rule = copy(stored_rule) rule = stored_rule.copy()
# Skip disabled and incomplete rules # Skip disabled and incomplete rules
if not rule['enabled']: if not rule['enabled']:
continue continue
elif not rule['field'] or not rule['pattern']: elif not rule['field'] or not rule['pattern']:
continue continue
elif 'prefix' in rule and not rule['prefix']: elif 'prefix' in rule and rule['prefix'] is None:
continue continue
else: else:
if rule['field'] != 'Tags': if rule['field'] != 'Tags':
@ -130,12 +138,58 @@ class PluginWidget(QWidget,Ui_Form):
pr = (rule['name'],rule['field'],rule['pattern'],rule['prefix']) pr = (rule['name'],rule['field'],rule['pattern'],rule['prefix'])
else: else:
pr = (rule['name'],rule['field'],rule['pattern']) pr = (rule['name'],rule['field'],rule['pattern'])
rule_set.append(pr) rule_set.append(pr)
opt_value = tuple(rule_set) opt_value = tuple(rule_set)
# Strip off the trailing '_tw' # Strip off the trailing '_tw'
opts_dict[c_name[:-3]] = opt_value opts_dict[c_name[:-3]] = opt_value
def fetchEligibleCustomFields(self): def exclude_genre_changed(self, regex):
""" Dynamically compute excluded genres.
Run exclude_genre regex against db.all_tags() to show excluded tags.
PROVISIONAL CODE, NEEDS TESTING
Args:
regex (QLineEdit.text()): regex to compile, compute
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(results)
return
try:
pattern = re.compile((str(regex)))
except:
results = _("regex error: %s") % sys.exc_info()[1]
else:
excluded_tags = []
for tag in self.all_tags:
hit = pattern.search(tag)
if hit:
excluded_tags.append(hit.string)
if excluded_tags:
if set(excluded_tags) == set(self.all_tags):
results = _("All genres will be excluded")
else:
results = ', '.join(sorted(excluded_tags))
finally:
if self.DEBUG:
print(results)
self.exclude_genre_results.clear()
self.exclude_genre_results.setText(results)
def exclude_genre_reset(self):
for default in self.OPTION_FIELDS:
if default[0] == 'exclude_genre':
self.exclude_genre.setText(default[1])
break
def fetch_eligible_custom_fields(self):
self.all_custom_fields = self.db.custom_field_keys() self.all_custom_fields = self.db.custom_field_keys()
custom_fields = {} custom_fields = {}
custom_fields['Tags'] = {'field':'tag', 'datatype':u'text'} custom_fields['Tags'] = {'field':'tag', 'datatype':u'text'}
@ -146,28 +200,42 @@ class PluginWidget(QWidget,Ui_Form):
'datatype':field_md['datatype']} 'datatype':field_md['datatype']}
self.eligible_custom_fields = custom_fields 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): def initialize(self, name, db):
''' '''
CheckBoxControls (c_type: check_box): CheckBoxControls (c_type: check_box):
['generate_titles','generate_series','generate_genres', ['generate_titles','generate_series','generate_genres',
'generate_recently_added','generate_descriptions','include_hr'] 'generate_recently_added','generate_descriptions','include_hr']
ComboBoxControls (c_type: combo_box): ComboBoxControls (c_type: combo_box):
['exclude_source_field','header_note_source_field', ['exclude_source_field','header_note_source_field',
'merge_source_field'] 'merge_source_field']
LineEditControls (c_type: line_edit): LineEditControls (c_type: line_edit):
['exclude_genre'] ['exclude_genre']
RadioButtonControls (c_type: radio_button): RadioButtonControls (c_type: radio_button):
['merge_before','merge_after'] ['merge_before','merge_after','generate_new_cover', 'use_existing_cover']
SpinBoxControls (c_type: spin_box): SpinBoxControls (c_type: spin_box):
['thumb_width'] ['thumb_width']
TableWidgetControls (c_type: table_widget): TableWidgetControls (c_type: table_widget):
['exclusion_rules_tw','prefix_rules_tw'] ['exclusion_rules_tw','prefix_rules_tw']
TextEditControls (c_type: text_edit):
['exclude_genre_results']
''' '''
self.name = name self.name = name
self.db = db self.db = db
self.fetchEligibleCustomFields() self.all_tags = db.all_tags()
self.fetch_eligible_custom_fields()
self.populate_combo_boxes() self.populate_combo_boxes()
# Update dialog fields from stored options # Update dialog fields from stored options
@ -200,9 +268,16 @@ class PluginWidget(QWidget,Ui_Form):
if opt_value not in prefix_rules: if opt_value not in prefix_rules:
prefix_rules.append(opt_value) prefix_rules.append(opt_value)
# Add icon to the reset button # Add icon to the reset button, hook textChanged signal
self.reset_exclude_genres_tb.setIcon(QIcon(I('trash.png'))) self.reset_exclude_genres_tb.setIcon(QIcon(I('trash.png')))
self.reset_exclude_genres_tb.clicked.connect(self.reset_exclude_genres) self.reset_exclude_genres_tb.clicked.connect(self.exclude_genre_reset)
# 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 # Init self.merge_source_field_name
self.merge_source_field_name = '' self.merge_source_field_name = ''
@ -226,6 +301,9 @@ class PluginWidget(QWidget,Ui_Form):
self.prefix_rules_table = PrefixRules(self.prefix_rules_gb, self.prefix_rules_table = PrefixRules(self.prefix_rules_gb,
"prefix_rules_tw",prefix_rules, self.eligible_custom_fields,self.db) "prefix_rules_tw",prefix_rules, self.eligible_custom_fields,self.db)
# Initialize excluded genres preview
self.exclude_genre_changed(unicode(getattr(self, 'exclude_genre').text()).strip())
def options(self): def options(self):
# Save/return the current options # Save/return the current options
# exclude_genre stores literally # exclude_genre stores literally
@ -275,16 +353,21 @@ class PluginWidget(QWidget,Ui_Form):
elif self.merge_after.isChecked(): elif self.merge_after.isChecked():
checked = 'after' checked = 'after'
include_hr = self.include_hr.isChecked() include_hr = self.include_hr.isChecked()
opts_dict['merge_comments'] = "%s:%s:%s" % \ opts_dict['merge_comments_rule'] = "%s:%s:%s" % \
(self.merge_source_field_name, checked, include_hr) (self.merge_source_field_name, checked, include_hr)
opts_dict['header_note_source_field'] = self.header_note_source_field_name opts_dict['header_note_source_field'] = self.header_note_source_field_name
# Fix up exclude_genre regex if blank. Assume blank = no exclusions
if opts_dict['exclude_genre'] == '':
opts_dict['exclude_genre'] = 'a^'
# Append the output profile # Append the output profile
try: try:
opts_dict['output_profile'] = [load_defaults('page_setup')['output_profile']] opts_dict['output_profile'] = [load_defaults('page_setup')['output_profile']]
except: except:
opts_dict['output_profile'] = ['default'] opts_dict['output_profile'] = ['default']
if self.DEBUG: if self.DEBUG:
print "opts_dict" print "opts_dict"
for opt in sorted(opts_dict.keys(), key=sort_key): for opt in sorted(opts_dict.keys(), key=sort_key):
@ -377,11 +460,11 @@ class PluginWidget(QWidget,Ui_Form):
self.merge_after.setEnabled(False) self.merge_after.setEnabled(False)
self.include_hr.setEnabled(False) self.include_hr.setEnabled(False)
def reset_exclude_genres(self): def show_help(self):
for default in self.OPTION_FIELDS: '''
if default[0] == 'exclude_genre': Display help file
self.exclude_genre.setText(default[1]) '''
break open_url(QUrl('http://manual.calibre-ebook.com/catalogs.html'))
class CheckableTableWidgetItem(QTableWidgetItem): class CheckableTableWidgetItem(QTableWidgetItem):
''' '''

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>650</width> <width>658</width>
<height>603</height> <height>603</height>
</rect> </rect>
</property> </property>
@ -41,151 +41,74 @@
<string>Included sections</string> <string>Included sections</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QCheckBox" name="generate_genres">
<property name="text">
<string>Books by &amp;Genre</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="generate_recently_added">
<property name="text">
<string>Recently &amp;Added</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="generate_descriptions">
<property name="text">
<string>&amp;Descriptions</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="generate_series">
<property name="text">
<string>Books by &amp;Series</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="generate_titles">
<property name="text">
<string>Books by &amp;Title</string>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="generate_authors"> <widget class="QCheckBox" name="generate_authors">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Books by Author</string> <string>&amp;Authors</string>
</property> </property>
<property name="checked"> <property name="checked">
<bool>false</bool> <bool>false</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2">
<widget class="QCheckBox" name="generate_titles">
<property name="text">
<string>&amp;Titles</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QCheckBox" name="generate_series">
<property name="text">
<string>&amp;Series</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="generate_genres">
<property name="text">
<string>&amp;Genres</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="generate_recently_added">
<property name="text">
<string>&amp;Recently Added</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QCheckBox" name="generate_descriptions">
<property name="text">
<string>&amp;Descriptions</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="excludedGenres"> <widget class="QGroupBox" name="prefix_rules_gb">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>A regular expression describing genres to be excluded from the generated catalog. Genres are derived from the tags applied to your books. <string>The first matching prefix rule applies a prefix to book listings in the generated catalog.</string>
The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book], and '+', the default tag for a read book.</string>
</property> </property>
<property name="title"> <property name="title">
<string>Excluded genres</string> <string>Prefixes</string>
</property> </property>
<layout class="QFormLayout" name="formLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="fieldGrowthPolicy"> <item>
<enum>QFormLayout::FieldsStayAtSizeHint</enum> <layout class="QHBoxLayout" name="horizontalLayout_6"/>
</property>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>-1</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Tags to &amp;exclude</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>exclude_genre</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="exclude_genre">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string extracomment="Default: \[[\w]*\]"/>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="reset_exclude_genres_tb">
<property name="toolTip">
<string>Reset to default</string>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -218,22 +141,148 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="prefix_rules_gb"> <widget class="QGroupBox" name="excludedGenres">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>The first matching prefix rule applies a prefix to book listings in the generated catalog.</string> <string>A regular expression describing genres to be excluded from the generated catalog. Genres are derived from the tags applied to your books.
The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book], and '+', the default tag for a read book.</string>
</property> </property>
<property name="title"> <property name="title">
<string>Prefixes</string> <string>Excluded genres</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_8"> <layout class="QGridLayout" name="gridLayout">
<item> <item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_6"/> <widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Tags to &amp;exclude (regex):</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>exclude_genre</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="exclude_genre">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string extracomment="Default: \[[\w]*\]"/>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="reset_exclude_genres_tb">
<property name="toolTip">
<string>Reset to default</string>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Results of regex:</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>exclude_genre</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="exclude_genre_results">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Tags that will be excluded as genres</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -255,142 +304,9 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
<property name="title"> <property name="title">
<string>Other options</string> <string>Other options</string>
</property> </property>
<layout class="QFormLayout" name="formLayout_4"> <layout class="QGridLayout" name="gridLayout_3">
<property name="fieldGrowthPolicy"> <item row="2" column="1">
<enum>QFormLayout::FieldsStayAtSizeHint</enum> <layout class="QHBoxLayout" name="merge_with_comments_hl">
</property>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_10">
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Thumb width</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>merge_source_field</cstring>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="thumb_width">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>137</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Size hint for cover thumbnails included in Descriptions section.</string>
</property>
<property name="suffix">
<string> inch</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>2.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>&amp;Extra note</string>
</property>
<property name="buddy">
<cstring>header_note_source_field</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="header_note_source_field">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Custom column source for text to include in Description section.</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_9">
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Merge with Comments</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>merge_source_field</cstring>
</property>
</widget>
</item>
<item> <item>
<widget class="QComboBox" name="merge_source_field"> <widget class="QComboBox" name="merge_source_field">
<property name="minimumSize"> <property name="minimumSize">
@ -419,6 +335,9 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
<property name="text"> <property name="text">
<string>&amp;Before</string> <string>&amp;Before</string>
</property> </property>
<attribute name="buttonGroup">
<string>merge_options_bg</string>
</attribute>
</widget> </widget>
</item> </item>
<item> <item>
@ -429,6 +348,9 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
<property name="text"> <property name="text">
<string>&amp;After</string> <string>&amp;After</string>
</property> </property>
<attribute name="buttonGroup">
<string>merge_options_bg</string>
</attribute>
</widget> </widget>
</item> </item>
<item> <item>
@ -444,7 +366,196 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
<string>Separate Comments metadata and additional content with a horizontal rule.</string> <string>Separate Comments metadata and additional content with a horizontal rule.</string>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Separator</string> <string>Include &amp;Separator</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_9">
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Merge with Comments:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>merge_source_field</cstring>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="minimumSize">
<size>
<width>175</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Catalog cover:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="replace_cover_hl">
<item>
<widget class="QRadioButton" name="generate_new_cover">
<property name="text">
<string>Generate new cover</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string>cover_options_bg</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="use_existing_cover">
<property name="text">
<string>Use existing cover</string>
</property>
<attribute name="buttonGroup">
<string>cover_options_bg</string>
</attribute>
</widget>
</item>
<item>
<widget class="QLabel" name="spacer_label">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>E&amp;xtra Description note:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>header_note_source_field</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="header_note_source_field">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Custom column source for text to include in Description section.</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Thumb width:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>merge_source_field</cstring>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="thumb_width">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Size hint for cover thumbnails included in Descriptions section.</string>
</property>
<property name="suffix">
<string> inch</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>2.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
@ -457,4 +568,8 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>
<buttongroups>
<buttongroup name="cover_options_bg"/>
<buttongroup name="merge_options_bg"/>
</buttongroups>
</ui> </ui>

View File

@ -10,7 +10,7 @@ import os, sys, importlib
from calibre.customize.ui import config from calibre.customize.ui import config
from calibre.gui2.dialogs.catalog_ui import Ui_Dialog from calibre.gui2.dialogs.catalog_ui import Ui_Dialog
from calibre.gui2 import dynamic, ResizableDialog from calibre.gui2 import dynamic, ResizableDialog, info_dialog
from calibre.customize.ui import catalog_plugins from calibre.customize.ui import catalog_plugins
class Catalog(ResizableDialog, Ui_Dialog): class Catalog(ResizableDialog, Ui_Dialog):
@ -22,7 +22,6 @@ class Catalog(ResizableDialog, Ui_Dialog):
from PyQt4.uic import compileUi from PyQt4.uic import compileUi
ResizableDialog.__init__(self, parent) ResizableDialog.__init__(self, parent)
self.dbspec, self.ids = dbspec, ids self.dbspec, self.ids = dbspec, ids
# Display the number of books we've been passed # Display the number of books we've been passed
@ -115,6 +114,7 @@ class Catalog(ResizableDialog, Ui_Dialog):
self.format.currentIndexChanged.connect(self.show_plugin_tab) self.format.currentIndexChanged.connect(self.show_plugin_tab)
self.buttonBox.button(self.buttonBox.Apply).clicked.connect(self.apply) self.buttonBox.button(self.buttonBox.Apply).clicked.connect(self.apply)
self.buttonBox.button(self.buttonBox.Help).clicked.connect(self.help)
self.show_plugin_tab(None) self.show_plugin_tab(None)
geom = dynamic.get('catalog_window_geom', None) geom = dynamic.get('catalog_window_geom', None)
@ -129,6 +129,10 @@ class Catalog(ResizableDialog, Ui_Dialog):
if cf in pw.formats: if cf in pw.formats:
self.tabs.addTab(pw, pw.TITLE) self.tabs.addTab(pw, pw.TITLE)
break break
if hasattr(self.tabs.widget(1),'show_help'):
self.buttonBox.button(self.buttonBox.Help).setVisible(True)
else:
self.buttonBox.button(self.buttonBox.Help).setVisible(False)
def format_changed(self, idx): def format_changed(self, idx):
cf = unicode(self.format.currentText()) cf = unicode(self.format.currentText())
@ -165,6 +169,29 @@ class Catalog(ResizableDialog, Ui_Dialog):
self.save_catalog_settings() self.save_catalog_settings()
return ResizableDialog.accept(self) return ResizableDialog.accept(self)
def help(self):
'''
To add help functionality for a specific format:
In gui2.catalog.catalog_<format>.py, add the following:
from calibre.gui2 import open_url
from PyQt4.Qt import QUrl
In the PluginWidget() class, add this method:
def show_help(self):
url = 'file:///' + P('catalog/help_<format>.html')
open_url(QUrl(url))
Create the help file at resources/catalog/help_<format>.html
'''
if self.tabs.count() > 1 and hasattr(self.tabs.widget(1),'show_help'):
try:
self.tabs.widget(1).show_help()
except:
info_dialog(self, _('No help available'),
_('No help available for this output format.'),
show_copy_button=False,
show=True)
def reject(self): def reject(self):
dynamic.set('catalog_window_geom', bytearray(self.saveGeometry())) dynamic.set('catalog_window_geom', bytearray(self.saveGeometry()))
ResizableDialog.reject(self) ResizableDialog.reject(self)

View File

@ -14,7 +14,7 @@
<string>Generate catalog</string> <string>Generate catalog</string>
</property> </property>
<property name="windowIcon"> <property name="windowIcon">
<iconset resource="../../../../resources/images.qrc"> <iconset>
<normaloff>:/images/lt.png</normaloff>:/images/lt.png</iconset> <normaloff>:/images/lt.png</normaloff>:/images/lt.png</iconset>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
@ -37,7 +37,7 @@
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
</item> </item>
@ -54,8 +54,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>666</width> <width>650</width>
<height>599</height> <height>575</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">

View File

@ -17,4 +17,6 @@ FIELDS = ['all', 'title', 'title_sort', 'author_sort', 'authors', 'comments',
TEMPLATE_ALLOWED_FIELDS = [ 'author_sort', 'authors', 'id', 'isbn', 'pubdate', 'title_sort', TEMPLATE_ALLOWED_FIELDS = [ 'author_sort', 'authors', 'id', 'isbn', 'pubdate', 'title_sort',
'publisher', 'series_index', 'series', 'tags', 'timestamp', 'title', 'uuid' ] 'publisher', 'series_index', 'series', 'tags', 'timestamp', 'title', 'uuid' ]
class AuthorSortMismatchException(Exception): pass
class EmptyCatalogException(Exception): pass

View File

@ -7,13 +7,14 @@ __license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os import os, shutil, sys, time
from collections import namedtuple 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.ebooks import calibre_cover
from calibre.library.catalogs import AuthorSortMismatchException, EmptyCatalogException
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
Option = namedtuple('Option', 'option, default, dest, action, help') Option = namedtuple('Option', 'option, default, dest, action, help')
@ -120,9 +121,9 @@ class EPUB_MOBI(CatalogPlugin):
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: AZW3, ePub, MOBI output formats")), "Applies to: AZW3, ePub, MOBI output formats")),
Option('--merge-comments', Option('--merge-comments-rule',
default='::', default='::',
dest='merge_comments', dest='merge_comments_rule',
action = None, action = None,
help=_("#<custom field>:[before|after]:[True|False] specifying:\n" help=_("#<custom field>:[before|after]:[True|False] specifying:\n"
" <custom field> Custom field containing notes to merge with Comments\n" " <custom field> Custom field containing notes to merge with Comments\n"
@ -146,6 +147,13 @@ class EPUB_MOBI(CatalogPlugin):
"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 AZW3, ePub, MOBI output formats")), "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', Option('--thumb-width',
default='1.0', default='1.0',
dest='thumb_width', dest='thumb_width',
@ -182,8 +190,8 @@ class EPUB_MOBI(CatalogPlugin):
else: else:
op = "kindle" op = "kindle"
opts.descriptionClip = 380 if op.endswith('dx') or 'kindle' not in op else 100 opts.description_clip = 380 if op.endswith('dx') or 'kindle' not in op else 100
opts.authorClip = 100 if op.endswith('dx') or 'kindle' not in op else 60 opts.author_clip = 100 if op.endswith('dx') or 'kindle' not in op else 60
opts.output_profile = op opts.output_profile = op
opts.basename = "Catalog" opts.basename = "Catalog"
@ -198,11 +206,12 @@ class EPUB_MOBI(CatalogPlugin):
(self.name,self.fmt,'for %s ' % opts.output_profile if opts.output_profile else '', (self.name,self.fmt,'for %s ' % opts.output_profile if opts.output_profile else '',
'CLI' if opts.cli_environment else 'GUI')) 'CLI' if opts.cli_environment else 'GUI'))
# If exclude_genre is blank, assume user wants all genre tags included # If exclude_genre is blank, assume user wants all tags as genres
if opts.exclude_genre.strip() == '': if opts.exclude_genre.strip() == '':
opts.exclude_genre = '\[^.\]' #opts.exclude_genre = '\[^.\]'
build_log.append(" converting empty exclude_genre to '\[^.\]'") #build_log.append(" converting empty exclude_genre to '\[^.\]'")
opts.exclude_genre = 'a^'
build_log.append(" converting empty exclude_genre to 'a^'")
if opts.connected_device['is_device_connected'] and \ if opts.connected_device['is_device_connected'] and \
opts.connected_device['kind'] == 'device': opts.connected_device['kind'] == 'device':
if opts.connected_device['serial']: if opts.connected_device['serial']:
@ -304,13 +313,13 @@ class EPUB_MOBI(CatalogPlugin):
keys.sort() keys.sort()
build_log.append(" opts:") build_log.append(" opts:")
for key in keys: for key in keys:
if key in ['catalog_title','authorClip','connected_kindle','descriptionClip', if key in ['catalog_title','author_clip','connected_kindle','description_clip',
'exclude_book_marker','exclude_genre','exclude_tags', 'exclude_book_marker','exclude_genre','exclude_tags',
'exclusion_rules', 'exclusion_rules', 'fmt',
'header_note_source_field','merge_comments', 'header_note_source_field','merge_comments_rule',
'output_profile','prefix_rules','read_book_marker', 'output_profile','prefix_rules','read_book_marker',
'search_text','sort_by','sort_descriptions_by_author','sync', '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]))) build_log.append(" %s: %s" % (key, repr(opts_dict[key])))
if opts.verbose: if opts.verbose:
@ -323,26 +332,30 @@ class EPUB_MOBI(CatalogPlugin):
if opts.verbose: if opts.verbose:
log.info(" Begin catalog source generation") log.info(" Begin catalog source generation")
catalog.createDirectoryStructure()
catalog.copyResources()
catalog.calculateThumbnailSize()
catalog_source_built = catalog.buildSources()
if opts.verbose: try:
if catalog_source_built: catalog_source_built = catalog.build_sources()
if opts.verbose:
log.info(" Completed catalog source generation\n") log.info(" Completed catalog source generation\n")
else: except (AuthorSortMismatchException, EmptyCatalogException), e:
log.error(" *** Terminated catalog generation, check log for details ***") log.error(" *** Terminated catalog generation: %s ***" % e)
except:
log.error(" unhandled exception in catalog generator")
raise
if catalog_source_built: else:
recommendations = [] recommendations = []
recommendations.append(('remove_fake_margins', False, recommendations.append(('remove_fake_margins', False,
OptionRecommendation.HIGH)) OptionRecommendation.HIGH))
recommendations.append(('comments', '', OptionRecommendation.HIGH)) recommendations.append(('comments', '', OptionRecommendation.HIGH))
# >>> Use to debug generated catalog code before conversion <<< """
if False: >>> Use to debug generated catalog code before pipeline conversion <<<
setattr(opts,'debug_pipeline',os.path.expanduser("~/Desktop/Catalog debug")) """
GENERATE_DEBUG_EPUB = False
if GENERATE_DEBUG_EPUB:
catalog_debug_path = os.path.join(os.path.expanduser('~'),'Desktop','Catalog debug')
setattr(opts,'debug_pipeline',os.path.expanduser(catalog_debug_path))
dp = getattr(opts, 'debug_pipeline', None) dp = getattr(opts, 'debug_pipeline', None)
if dp is not None: if dp is not None:
@ -357,9 +370,9 @@ class EPUB_MOBI(CatalogPlugin):
recommendations.append(('book_producer',opts.output_profile, recommendations.append(('book_producer',opts.output_profile,
OptionRecommendation.HIGH)) OptionRecommendation.HIGH))
# If cover exists, use it # Use existing cover or generate new cover
cpath = None cpath = None
generate_new_cover = False existing_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')
@ -367,19 +380,18 @@ class EPUB_MOBI(CatalogPlugin):
if matches: if matches:
cpath = db.cover(matches[0], index_is_id=True, as_path=True) cpath = db.cover(matches[0], index_is_id=True, as_path=True)
if cpath and os.path.exists(cpath): if cpath and os.path.exists(cpath):
recommendations.append(('cover', cpath, existing_cover = True
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: if self.opts.use_existing_cover and not existing_cover:
log.warning("no existing catalog cover found")
if self.opts.use_existing_cover and existing_cover:
recommendations.append(('cover', cpath, OptionRecommendation.HIGH))
log.info("using existing catalog cover")
else:
log.info("replacing catalog cover")
new_cover_path = PersistentTemporaryFile(suffix='.jpg') new_cover_path = PersistentTemporaryFile(suffix='.jpg')
new_cover = calibre_cover(opts.catalog_title.replace('"', '\\"'), 'calibre') new_cover = calibre_cover(opts.catalog_title.replace('"', '\\"'), 'calibre')
new_cover_path.write(new_cover) new_cover_path.write(new_cover)
@ -388,7 +400,7 @@ class EPUB_MOBI(CatalogPlugin):
# 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.catalog_path,
opts.basename + '.opf'), path_to_output, log, report_progress=notification, opts.basename + '.opf'), path_to_output, log, report_progress=notification,
abort_after_input_dump=False) abort_after_input_dump=False)
plumber.merge_ui_recommendations(recommendations) plumber.merge_ui_recommendations(recommendations)
@ -399,6 +411,13 @@ class EPUB_MOBI(CatalogPlugin):
except: except:
pass pass
if GENERATE_DEBUG_EPUB:
from calibre.ebooks.tweak import zip_rebuilder
input_path = os.path.join(catalog_debug_path,'input')
shutil.copy(P('catalog/mimetype'),input_path)
shutil.copytree(P('catalog/META-INF'),os.path.join(input_path,'META-INF'))
zip_rebuilder(input_path, os.path.join(catalog_debug_path,'input.epub'))
# returns to gui2.actions.catalog:catalog_generated() # returns to gui2.actions.catalog:catalog_generated()
return catalog.error return catalog.error

File diff suppressed because it is too large Load Diff