mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
GwR catalog UI revisions
This commit is contained in:
parent
3c254aca3f
commit
230d92dcb5
@ -108,6 +108,13 @@ p.date_read {
|
|||||||
text-indent:-6em;
|
text-indent:-6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr.annotations_divider {
|
||||||
|
width:50%;
|
||||||
|
margin-left:1em;
|
||||||
|
margin-top:0em;
|
||||||
|
margin-bottom:0em;
|
||||||
|
}
|
||||||
|
|
||||||
hr.description_divider {
|
hr.description_divider {
|
||||||
width:90%;
|
width:90%;
|
||||||
margin-left:5%;
|
margin-left:5%;
|
||||||
@ -117,18 +124,20 @@ hr.description_divider {
|
|||||||
border-left: solid white 0px;
|
border-left: solid white 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr.annotations_divider {
|
hr.merged_comments_divider {
|
||||||
width:50%;
|
width:80%;
|
||||||
margin-left:1em;
|
margin-left:10%;
|
||||||
margin-top:0em;
|
border-top: solid white 0px;
|
||||||
margin-bottom:0em;
|
border-right: solid white 0px;
|
||||||
|
border-bottom: dotted grey 2px;
|
||||||
|
border-left: solid white 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.publisher, td.date {
|
td.publisher, td.date {
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
}
|
}
|
||||||
td.rating {
|
td.rating, td.notes {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
td.thumbnail img {
|
td.thumbnail img {
|
||||||
|
@ -57,7 +57,7 @@ class GenerateCatalogAction(InterfaceAction):
|
|||||||
if job.result:
|
if job.result:
|
||||||
# Search terms nulled catalog results
|
# Search terms nulled catalog results
|
||||||
return error_dialog(self.gui, _('No books found'),
|
return error_dialog(self.gui, _('No books found'),
|
||||||
_("No books to catalog\nCheck exclude tags"),
|
_("No books to catalog\nCheck exclusion criteria"),
|
||||||
show=True)
|
show=True)
|
||||||
if job.failed:
|
if job.failed:
|
||||||
return self.gui.job_exception(job)
|
return self.gui.job_exception(job)
|
||||||
|
@ -17,18 +17,55 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
|
|
||||||
TITLE = _('E-book options')
|
TITLE = _('E-book options')
|
||||||
HELP = _('Options specific to')+' EPUB/MOBI '+_('output')
|
HELP = _('Options specific to')+' EPUB/MOBI '+_('output')
|
||||||
OPTION_FIELDS = [('exclude_genre','\[.+\]'),
|
|
||||||
('exclude_tags','~,'+_('Catalog')),
|
|
||||||
('generate_titles', True),
|
|
||||||
('generate_series', True),
|
|
||||||
('generate_recently_added', True),
|
|
||||||
('note_tag','*'),
|
|
||||||
('numbers_as_text', False),
|
|
||||||
('read_pattern','+'),
|
|
||||||
('read_source_field_cb','Tag'),
|
|
||||||
('wishlist_tag','Wishlist'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
CheckBoxControls = [
|
||||||
|
'generate_titles',
|
||||||
|
'generate_series',
|
||||||
|
'generate_genres',
|
||||||
|
'generate_recently_added',
|
||||||
|
'generate_descriptions',
|
||||||
|
'include_hr'
|
||||||
|
]
|
||||||
|
ComboBoxControls = [
|
||||||
|
'read_source_field',
|
||||||
|
'exclude_source_field',
|
||||||
|
'header_note_source_field',
|
||||||
|
'merge_source_field'
|
||||||
|
]
|
||||||
|
LineEditControls = [
|
||||||
|
'exclude_genre',
|
||||||
|
'exclude_pattern',
|
||||||
|
'exclude_tags',
|
||||||
|
'read_pattern',
|
||||||
|
'wishlist_tag'
|
||||||
|
]
|
||||||
|
RadioButtonControls = [
|
||||||
|
'merge_before',
|
||||||
|
'merge_after'
|
||||||
|
]
|
||||||
|
SpinBoxControls = [
|
||||||
|
'thumb_width'
|
||||||
|
]
|
||||||
|
|
||||||
|
OPTION_FIELDS = zip(CheckBoxControls,
|
||||||
|
[True for i in CheckBoxControls],
|
||||||
|
['check_box' for i in CheckBoxControls])
|
||||||
|
OPTION_FIELDS += zip(ComboBoxControls,
|
||||||
|
[None for i in ComboBoxControls],
|
||||||
|
['combo_box' for i in ComboBoxControls])
|
||||||
|
OPTION_FIELDS += zip(RadioButtonControls,
|
||||||
|
[None for i in RadioButtonControls],
|
||||||
|
['radio_button' for i in RadioButtonControls])
|
||||||
|
|
||||||
|
# LineEditControls
|
||||||
|
OPTION_FIELDS += zip(['exclude_genre'],['\[.+\]'],['line_edit'])
|
||||||
|
OPTION_FIELDS += zip(['exclude_pattern'],[None],['line_edit'])
|
||||||
|
OPTION_FIELDS += zip(['exclude_tags'],['~,'+_('Catalog')],['line_edit'])
|
||||||
|
OPTION_FIELDS += zip(['read_pattern'],['+'],['line_edit'])
|
||||||
|
OPTION_FIELDS += zip(['wishlist_tag'],['Wishlist'],['line_edit'])
|
||||||
|
|
||||||
|
# SpinBoxControls
|
||||||
|
OPTION_FIELDS += zip(['thumb_width'],[1.00],['spin_box'])
|
||||||
|
|
||||||
# Output synced to the connected device?
|
# Output synced to the connected device?
|
||||||
sync_enabled = True
|
sync_enabled = True
|
||||||
@ -42,105 +79,203 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
|
|
||||||
def initialize(self, name, db):
|
def initialize(self, name, db):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.db = db
|
||||||
# Populate the 'Read book' source fields
|
self.populateComboBoxes()
|
||||||
all_custom_fields = db.custom_field_keys()
|
|
||||||
custom_fields = {}
|
|
||||||
custom_fields['Tag'] = {'field':'tag', 'datatype':u'text'}
|
|
||||||
for custom_field in all_custom_fields:
|
|
||||||
field_md = db.metadata_for_field(custom_field)
|
|
||||||
if field_md['datatype'] in ['bool','composite','datetime','text']:
|
|
||||||
custom_fields[field_md['name']] = {'field':custom_field,
|
|
||||||
'datatype':field_md['datatype']}
|
|
||||||
|
|
||||||
# Add the sorted eligible fields to the combo box
|
|
||||||
for cf in sorted(custom_fields):
|
|
||||||
self.read_source_field_cb.addItem(cf)
|
|
||||||
|
|
||||||
self.read_source_fields = custom_fields
|
|
||||||
self.read_source_field_cb.currentIndexChanged.connect(self.read_source_field_changed)
|
|
||||||
|
|
||||||
# Update dialog fields from stored options
|
# Update dialog fields from stored options
|
||||||
for opt in self.OPTION_FIELDS:
|
for opt in self.OPTION_FIELDS:
|
||||||
opt_value = gprefs.get(self.name + '_' + opt[0], opt[1])
|
c_name, c_def, c_type = opt
|
||||||
if opt[0] in [
|
opt_value = gprefs.get(self.name + '_' + c_name, c_def)
|
||||||
'generate_recently_added',
|
if c_type in ['check_box']:
|
||||||
'generate_series',
|
getattr(self, c_name).setChecked(eval(str(opt_value)))
|
||||||
'generate_titles',
|
elif c_type in ['combo_box'] and opt_value is not None:
|
||||||
'numbers_as_text',
|
# *** Test this code with combo boxes ***
|
||||||
]:
|
#index = self.read_source_field.findText(opt_value)
|
||||||
getattr(self, opt[0]).setChecked(opt_value)
|
index = getattr(self,c_name).findText(opt_value)
|
||||||
|
if index == -1 and c_name == 'read_source_field':
|
||||||
|
index = self.read_source_field.findText('Tag')
|
||||||
|
#self.read_source_field.setCurrentIndex(index)
|
||||||
|
getattr(self,c_name).setCurrentIndex(index)
|
||||||
|
elif c_type in ['line_edit']:
|
||||||
|
getattr(self, c_name).setText(opt_value)
|
||||||
|
elif c_type in ['radio_button'] and opt_value is not None:
|
||||||
|
getattr(self, c_name).setChecked(opt_value)
|
||||||
|
elif c_type in ['spin_box']:
|
||||||
|
getattr(self, c_name).setValue(float(opt_value))
|
||||||
|
|
||||||
# Combo box
|
# Init self.read_source_field_name
|
||||||
elif opt[0] in ['read_source_field_cb']:
|
cs = unicode(self.read_source_field.currentText())
|
||||||
# Look for last-stored combo box value
|
|
||||||
index = self.read_source_field_cb.findText(opt_value)
|
|
||||||
if index == -1:
|
|
||||||
index = self.read_source_field_cb.findText('Tag')
|
|
||||||
self.read_source_field_cb.setCurrentIndex(index)
|
|
||||||
|
|
||||||
# Text fields
|
|
||||||
else:
|
|
||||||
getattr(self, opt[0]).setText(opt_value)
|
|
||||||
|
|
||||||
# Init self.read_source_field
|
|
||||||
cs = unicode(self.read_source_field_cb.currentText())
|
|
||||||
read_source_spec = self.read_source_fields[cs]
|
read_source_spec = self.read_source_fields[cs]
|
||||||
self.read_source_field = read_source_spec['field']
|
self.read_source_field_name = read_source_spec['field']
|
||||||
|
|
||||||
|
# Init self.exclude_source_field_name
|
||||||
|
self.exclude_source_field_name = ''
|
||||||
|
cs = unicode(self.exclude_source_field.currentText())
|
||||||
|
if cs > '':
|
||||||
|
exclude_source_spec = self.exclude_source_fields[cs]
|
||||||
|
self.exclude_source_field_name = exclude_source_spec['field']
|
||||||
|
|
||||||
|
# Init self.merge_source_field_name
|
||||||
|
self.merge_source_field_name = ''
|
||||||
|
cs = unicode(self.merge_source_field.currentText())
|
||||||
|
if cs > '':
|
||||||
|
merge_source_spec = self.merge_source_fields[cs]
|
||||||
|
self.merge_source_field_name = merge_source_spec['field']
|
||||||
|
|
||||||
|
# Init self.header_note_source_field_name
|
||||||
|
self.header_note_source_field_name = ''
|
||||||
|
cs = unicode(self.header_note_source_field.currentText())
|
||||||
|
if cs > '':
|
||||||
|
header_note_source_spec = self.header_note_source_fields[cs]
|
||||||
|
self.header_note_source_field_name = header_note_source_spec['field']
|
||||||
|
|
||||||
|
# Hook changes to thumb_width
|
||||||
|
self.thumb_width.valueChanged.connect(self.thumb_width_changed)
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
# Save/return the current options
|
# Save/return the current options
|
||||||
# exclude_genre stores literally
|
# exclude_genre stores literally
|
||||||
# generate_titles, generate_recently_added, numbers_as_text stores as True/False
|
# generate_titles, generate_recently_added, numbers_as_text stores as True/False
|
||||||
# others store as lists
|
# others store as lists
|
||||||
|
|
||||||
opts_dict = {}
|
opts_dict = {}
|
||||||
|
# Save values to gprefs
|
||||||
for opt in self.OPTION_FIELDS:
|
for opt in self.OPTION_FIELDS:
|
||||||
# Save values to gprefs
|
c_name, c_def, c_type = opt
|
||||||
if opt[0] in [
|
if c_type in ['check_box', 'radio_button']:
|
||||||
'generate_recently_added',
|
opt_value = getattr(self, c_name).isChecked()
|
||||||
'generate_series',
|
elif c_type in ['combo_box']:
|
||||||
'generate_titles',
|
opt_value = unicode(getattr(self,c_name).currentText())
|
||||||
'numbers_as_text',
|
elif c_type in ['line_edit']:
|
||||||
]:
|
opt_value = unicode(getattr(self, c_name).text())
|
||||||
opt_value = getattr(self,opt[0]).isChecked()
|
elif c_type in ['spin_box']:
|
||||||
|
opt_value = unicode(getattr(self, c_name).cleanText())
|
||||||
|
gprefs.set(self.name + '_' + c_name, opt_value)
|
||||||
|
|
||||||
# Combo box uses .currentText()
|
# Construct opts object
|
||||||
elif opt[0] in ['read_source_field_cb']:
|
if c_name == 'exclude_tags':
|
||||||
opt_value = unicode(getattr(self, opt[0]).currentText())
|
# store as list
|
||||||
|
opts_dict[c_name] = opt_value.split(',')
|
||||||
# text fields use .text()
|
|
||||||
else:
|
else:
|
||||||
opt_value = unicode(getattr(self, opt[0]).text())
|
opts_dict[c_name] = opt_value
|
||||||
gprefs.set(self.name + '_' + opt[0], opt_value)
|
|
||||||
|
|
||||||
# Construct opts
|
# Generate markers for hybrids
|
||||||
if opt[0] in [
|
opts_dict['read_book_marker'] = "%s:%s" % (self.read_source_field_name,
|
||||||
'exclude_genre',
|
self.read_pattern.text())
|
||||||
'generate_recently_added',
|
opts_dict['exclude_book_marker'] = "%s:%s" % (self.exclude_source_field_name,
|
||||||
'generate_series',
|
self.exclude_pattern.text())
|
||||||
'generate_titles',
|
|
||||||
'numbers_as_text',
|
|
||||||
]:
|
|
||||||
opts_dict[opt[0]] = opt_value
|
|
||||||
else:
|
|
||||||
opts_dict[opt[0]] = opt_value.split(',')
|
|
||||||
|
|
||||||
# Generate read_book_marker
|
# Generate specs for merge_comments, header_note_source_field
|
||||||
opts_dict['read_book_marker'] = "%s:%s" % (self.read_source_field, self.read_pattern.text())
|
checked = ''
|
||||||
|
if self.merge_before.isChecked():
|
||||||
|
checked = 'before'
|
||||||
|
elif self.merge_after.isChecked():
|
||||||
|
checked = 'after'
|
||||||
|
include_hr = self.include_hr.isChecked()
|
||||||
|
opts_dict['merge_comments'] = "%s:%s:%s" % \
|
||||||
|
(self.merge_source_field_name, checked, include_hr)
|
||||||
|
|
||||||
|
opts_dict['header_note_source_field'] = self.header_note_source_field_name
|
||||||
|
|
||||||
# Append the output profile
|
# Append the output profile
|
||||||
opts_dict['output_profile'] = [load_defaults('page_setup')['output_profile']]
|
opts_dict['output_profile'] = [load_defaults('page_setup')['output_profile']]
|
||||||
|
if False:
|
||||||
|
print "opts_dict"
|
||||||
|
for opt in sorted(opts_dict.keys()):
|
||||||
|
print " %s: %s" % (opt, repr(opts_dict[opt]))
|
||||||
return opts_dict
|
return opts_dict
|
||||||
|
|
||||||
|
def populateComboBoxes(self):
|
||||||
|
# Custom column types declared in
|
||||||
|
# gui2.preferences.create_custom_column:CreateCustomColumn()
|
||||||
|
# As of 0.7.34:
|
||||||
|
# bool Yes/No
|
||||||
|
# comments Long text, like comments, not shown in tag browser
|
||||||
|
# composite Column built from other columns
|
||||||
|
# datetime Date
|
||||||
|
# enumeration Text, but with a fixed set of permitted values
|
||||||
|
# float Floating point numbers
|
||||||
|
# int Integers
|
||||||
|
# rating Ratings, shown with stars
|
||||||
|
# series Text column for keeping series-like information
|
||||||
|
# text Column shown in the tag browser
|
||||||
|
# *text Comma-separated text, like tags, shown in tag browser
|
||||||
|
|
||||||
|
all_custom_fields = self.db.custom_field_keys()
|
||||||
|
# Populate the 'Read book' hybrid
|
||||||
|
custom_fields = {}
|
||||||
|
custom_fields['Tag'] = {'field':'tag', 'datatype':u'text'}
|
||||||
|
for custom_field in all_custom_fields:
|
||||||
|
field_md = self.db.metadata_for_field(custom_field)
|
||||||
|
if field_md['datatype'] in ['bool','composite','datetime','enumeration','text']:
|
||||||
|
custom_fields[field_md['name']] = {'field':custom_field,
|
||||||
|
'datatype':field_md['datatype']}
|
||||||
|
# Add the sorted eligible fields to the combo box
|
||||||
|
for cf in sorted(custom_fields):
|
||||||
|
self.read_source_field.addItem(cf)
|
||||||
|
self.read_source_fields = custom_fields
|
||||||
|
self.read_source_field.currentIndexChanged.connect(self.read_source_field_changed)
|
||||||
|
|
||||||
|
|
||||||
|
# Populate the 'Excluded books' hybrid
|
||||||
|
custom_fields = {}
|
||||||
|
for custom_field in all_custom_fields:
|
||||||
|
field_md = self.db.metadata_for_field(custom_field)
|
||||||
|
if field_md['datatype'] in ['bool','composite','datetime','enumeration','text']:
|
||||||
|
custom_fields[field_md['name']] = {'field':custom_field,
|
||||||
|
'datatype':field_md['datatype']}
|
||||||
|
# Blank field first
|
||||||
|
self.exclude_source_field.addItem('')
|
||||||
|
# Add the sorted eligible fields to the combo box
|
||||||
|
for cf in sorted(custom_fields):
|
||||||
|
self.exclude_source_field.addItem(cf)
|
||||||
|
self.exclude_source_fields = custom_fields
|
||||||
|
self.exclude_source_field.currentIndexChanged.connect(self.exclude_source_field_changed)
|
||||||
|
|
||||||
|
|
||||||
|
# Populate the 'Header note' combo box
|
||||||
|
custom_fields = {}
|
||||||
|
for custom_field in all_custom_fields:
|
||||||
|
field_md = self.db.metadata_for_field(custom_field)
|
||||||
|
if field_md['datatype'] in ['composite','datetime','enumeration','text']:
|
||||||
|
custom_fields[field_md['name']] = {'field':custom_field,
|
||||||
|
'datatype':field_md['datatype']}
|
||||||
|
# Blank field first
|
||||||
|
self.header_note_source_field.addItem('')
|
||||||
|
# Add the sorted eligible fields to the combo box
|
||||||
|
for cf in sorted(custom_fields):
|
||||||
|
self.header_note_source_field.addItem(cf)
|
||||||
|
self.header_note_source_fields = custom_fields
|
||||||
|
self.header_note_source_field.currentIndexChanged.connect(self.header_note_source_field_changed)
|
||||||
|
|
||||||
|
|
||||||
|
# Populate the 'Merge with Comments' combo box
|
||||||
|
custom_fields = {}
|
||||||
|
for custom_field in all_custom_fields:
|
||||||
|
field_md = self.db.metadata_for_field(custom_field)
|
||||||
|
if field_md['datatype'] in ['text','comments']:
|
||||||
|
custom_fields[field_md['name']] = {'field':custom_field,
|
||||||
|
'datatype':field_md['datatype']}
|
||||||
|
# Blank field first
|
||||||
|
self.merge_source_field.addItem('')
|
||||||
|
# Add the sorted eligible fields to the combo box
|
||||||
|
for cf in sorted(custom_fields):
|
||||||
|
self.merge_source_field.addItem(cf)
|
||||||
|
self.merge_source_fields = custom_fields
|
||||||
|
self.merge_source_field.currentIndexChanged.connect(self.merge_source_field_changed)
|
||||||
|
self.merge_before.setEnabled(False)
|
||||||
|
self.merge_after.setEnabled(False)
|
||||||
|
self.include_hr.setEnabled(False)
|
||||||
|
|
||||||
def read_source_field_changed(self,new_index):
|
def read_source_field_changed(self,new_index):
|
||||||
'''
|
'''
|
||||||
Process changes in the read_source_field combo box
|
Process changes in the read_source_field combo box
|
||||||
Currently using QLineEdit for all field types
|
Currently using QLineEdit for all field types
|
||||||
Possible to modify to switch QWidget type
|
Possible to modify to switch QWidget type
|
||||||
'''
|
'''
|
||||||
new_source = str(self.read_source_field_cb.currentText())
|
new_source = str(self.read_source_field.currentText())
|
||||||
read_source_spec = self.read_source_fields[str(new_source)]
|
read_source_spec = self.read_source_fields[str(new_source)]
|
||||||
self.read_source_field = read_source_spec['field']
|
self.read_source_field_name = read_source_spec['field']
|
||||||
|
|
||||||
# Change pattern input widget to match the source field datatype
|
# Change pattern input widget to match the source field datatype
|
||||||
if read_source_spec['datatype'] in ['bool','composite','datetime','text']:
|
if read_source_spec['datatype'] in ['bool','composite','datetime','text']:
|
||||||
@ -152,3 +287,62 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
self.read_pattern = dw
|
self.read_pattern = dw
|
||||||
self.read_spec_hl.addWidget(dw)
|
self.read_spec_hl.addWidget(dw)
|
||||||
|
|
||||||
|
def exclude_source_field_changed(self,new_index):
|
||||||
|
'''
|
||||||
|
Process changes in the exclude_source_field combo box
|
||||||
|
Currently using QLineEdit for all field types
|
||||||
|
Possible to modify to switch QWidget type
|
||||||
|
'''
|
||||||
|
new_source = str(self.exclude_source_field.currentText())
|
||||||
|
self.exclude_source_field_name = new_source
|
||||||
|
if new_source > '':
|
||||||
|
exclude_source_spec = self.exclude_source_fields[str(new_source)]
|
||||||
|
self.exclude_source_field_name = exclude_source_spec['field']
|
||||||
|
|
||||||
|
# Change pattern input widget to match the source field datatype
|
||||||
|
if exclude_source_spec['datatype'] in ['bool','composite','datetime','text']:
|
||||||
|
if not isinstance(self.exclude_pattern, QLineEdit):
|
||||||
|
self.exclude_spec_hl.removeWidget(self.exclude_pattern)
|
||||||
|
dw = QLineEdit(self)
|
||||||
|
dw.setObjectName('exclude_pattern')
|
||||||
|
dw.setToolTip('Exclusion pattern')
|
||||||
|
self.exclude_pattern = dw
|
||||||
|
self.exclude_spec_hl.addWidget(dw)
|
||||||
|
else:
|
||||||
|
self.exclude_pattern.setText('')
|
||||||
|
|
||||||
|
def header_note_source_field_changed(self,new_index):
|
||||||
|
'''
|
||||||
|
Process changes in the header_note_source_field combo box
|
||||||
|
'''
|
||||||
|
new_source = str(self.header_note_source_field.currentText())
|
||||||
|
self.header_note_source_field_name = new_source
|
||||||
|
if new_source > '':
|
||||||
|
header_note_source_spec = self.header_note_source_fields[str(new_source)]
|
||||||
|
self.header_note_source_field_name = header_note_source_spec['field']
|
||||||
|
|
||||||
|
def merge_source_field_changed(self,new_index):
|
||||||
|
'''
|
||||||
|
Process changes in the header_note_source_field combo box
|
||||||
|
'''
|
||||||
|
new_source = str(self.merge_source_field.currentText())
|
||||||
|
self.merge_source_field_name = new_source
|
||||||
|
if new_source > '':
|
||||||
|
merge_source_spec = self.merge_source_fields[str(new_source)]
|
||||||
|
self.merge_source_field_name = merge_source_spec['field']
|
||||||
|
if not self.merge_before.isChecked() and not self.merge_after.isChecked():
|
||||||
|
self.merge_after.setChecked(True)
|
||||||
|
self.merge_before.setEnabled(True)
|
||||||
|
self.merge_after.setEnabled(True)
|
||||||
|
self.include_hr.setEnabled(True)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.merge_before.setEnabled(False)
|
||||||
|
self.merge_after.setEnabled(False)
|
||||||
|
self.include_hr.setEnabled(False)
|
||||||
|
|
||||||
|
def thumb_width_changed(self,new_value):
|
||||||
|
'''
|
||||||
|
Process changes in the thumb_width spin box
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
@ -6,163 +6,653 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>627</width>
|
<width>650</width>
|
||||||
<height>549</height>
|
<height>582</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item row="0" column="0">
|
<item>
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QGroupBox" name="includedSections">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>'Don't include this book' tag:</string>
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="minimumSize">
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="exclude_tags">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string extracomment="Default: ~,Catalog"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Additional note tag prefix:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLineEdit" name="note_tag">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string extracomment="Default: *"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QLineEdit" name="exclude_genre">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string extracomment="Default: \[[\w]*\]"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Regex pattern describing tags to exclude as genres:</string>
|
|
||||||
</property>
|
|
||||||
<property name="textFormat">
|
|
||||||
<enum>Qt::LogText</enum>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Regex tips:
|
|
||||||
- The default regex - \[.+\] - excludes genre tags of the form [tag], e.g., [Amazon Freebie]
|
|
||||||
- A regex pattern of a single dot excludes all genre tags, generating no Genre Section</string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>0</width>
|
||||||
<height>40</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
<property name="toolTip">
|
||||||
</item>
|
<string>Sections to include in generated catalog. A minimal catalog includes 'Books by Author'.</string>
|
||||||
<item row="10" column="0">
|
|
||||||
<widget class="QCheckBox" name="generate_titles">
|
|
||||||
<property name="text">
|
|
||||||
<string>Include 'Titles' Section</string>
|
|
||||||
</property>
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Included sections (Books by Author included by default)</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="generate_titles">
|
||||||
|
<property name="text">
|
||||||
|
<string>Books by Title</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="generate_series">
|
||||||
|
<property name="text">
|
||||||
|
<string>Books by Series</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QCheckBox" name="generate_recently_added">
|
||||||
|
<property name="text">
|
||||||
|
<string>Recently Added</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QCheckBox" name="generate_genres">
|
||||||
|
<property name="text">
|
||||||
|
<string>Books by Genre</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="2">
|
||||||
|
<widget class="QCheckBox" name="generate_descriptions">
|
||||||
|
<property name="text">
|
||||||
|
<string>Descriptions</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="12" column="0">
|
<item>
|
||||||
<widget class="QCheckBox" name="generate_recently_added">
|
<widget class="QGroupBox" name="excludedGenres">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>Include 'Recently Added' Section</string>
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Default pattern </p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier';">\[.+\]</span></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">excludes tags of the form [<span style=" font-style:italic;">tag</span>]</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Excluded genres</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
||||||
|
</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 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>
|
||||||
|
</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>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" column="0">
|
<item>
|
||||||
<widget class="QCheckBox" name="numbers_as_text">
|
<widget class="QGroupBox" name="excludedBooks">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>Sort numbers as text</string>
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Exclude matching books from generated catalog</string>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Excluded books</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<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 exclude</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="exclude_tags">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Comma-separated list of tags to exclude.</span></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Default:</span><span style=" font-family:'Courier New,courier'; font-size:12pt;"> ~,Catalog</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="exclude_spec_hl">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<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>Column/value</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="exclude_source_field">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Column containing exclusion criteria</string>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
|
||||||
|
</property>
|
||||||
|
<property name="minimumContentsLength">
|
||||||
|
<number>18</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="exclude_pattern">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Exclusion pattern</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="0">
|
<item>
|
||||||
<widget class="QCheckBox" name="generate_series">
|
<widget class="QGroupBox" name="readBooks">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>Include 'Series' Section</string>
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Matching books will be displayed with ✓</string>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Read books</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="read_spec_hl">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<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>Column/value</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="read_source_field">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Column containing 'read' status</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
|
||||||
|
</property>
|
||||||
|
<property name="minimumContentsLength">
|
||||||
|
<number>18</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="read_pattern">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>'read book' pattern</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item>
|
||||||
<widget class="QLineEdit" name="wishlist_tag"/>
|
<widget class="QGroupBox" name="otherOptions">
|
||||||
</item>
|
<property name="sizePolicy">
|
||||||
<item row="3" column="0">
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
<widget class="QLabel" name="label_5">
|
<horstretch>0</horstretch>
|
||||||
<property name="text">
|
<verstretch>0</verstretch>
|
||||||
<string>Wishlist tag:</string>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="minimumSize">
|
||||||
</item>
|
<size>
|
||||||
<item row="2" column="1">
|
<width>0</width>
|
||||||
<layout class="QHBoxLayout" name="read_spec_hl">
|
<height>0</height>
|
||||||
<property name="sizeConstraint">
|
</size>
|
||||||
<enum>QLayout::SetMinimumSize</enum>
|
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<property name="title">
|
||||||
<widget class="QComboBox" name="read_source_field_cb">
|
<string>Other options</string>
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Source column for read book</string>
|
|
||||||
</property>
|
|
||||||
<property name="statusTip">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="read_pattern">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Pattern for read book</string>
|
|
||||||
</property>
|
|
||||||
<property name="statusTip">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Books marked as read:</string>
|
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_4">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<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="toolTip">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Wishlist tag</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="wishlist_tag">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Wishlist items will be displayed with ✕</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<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>Thumbnail width</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</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="toolTip">
|
||||||
|
<string>Size hint for cover thumbnails included in Descriptions</string>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string>"</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>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<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>Header note</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</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="toolTip">
|
||||||
|
<string>Column containing header note</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="4" 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>Merge with Comments</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="merge_source_field">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Column containing additional content to merge</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="merge_before">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Merge before Comments</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Before</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="merge_after">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Merge after Comments</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>After</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="include_hr">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Separate with horizontal rule</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string><hr /></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>579</width>
|
<width>650</width>
|
||||||
<height>411</height>
|
<height>575</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>611</width>
|
<width>674</width>
|
||||||
<height>514</height>
|
<height>660</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -33,6 +33,18 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
<item row="1" column="0" colspan="2">
|
||||||
<widget class="QTabWidget" name="tabs">
|
<widget class="QTabWidget" name="tabs">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>650</width>
|
||||||
|
<height>575</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -550,6 +550,13 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
"of the conversion process a bug is occurring.\n"
|
"of the conversion process a bug is occurring.\n"
|
||||||
"Default: '%default'None\n"
|
"Default: '%default'None\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
|
Option('--exclude-book-marker',
|
||||||
|
default=':',
|
||||||
|
dest='exclude_book_marker',
|
||||||
|
action = None,
|
||||||
|
help=_("field:pattern specifying custom field/contents indicating book should be excluded.\n"
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to ePub, MOBI output formats")),
|
||||||
Option('--exclude-genre',
|
Option('--exclude-genre',
|
||||||
default='\[.+\]',
|
default='\[.+\]',
|
||||||
dest='exclude_genre',
|
dest='exclude_genre',
|
||||||
@ -585,6 +592,23 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
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: ePub, MOBI output formats")),
|
||||||
|
Option('--header-note-source-field',
|
||||||
|
default='',
|
||||||
|
dest='header_note_source_field',
|
||||||
|
action = None,
|
||||||
|
help=_("Custom field containing note text to insert in Description header.\n"
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to: ePub, MOBI output formats")),
|
||||||
|
Option('--merge-comments',
|
||||||
|
default='::',
|
||||||
|
dest='merge_comments',
|
||||||
|
action = None,
|
||||||
|
help=_("<custom field>:[before|after]:[True|False] specifying:\n"
|
||||||
|
" <custom field> Custom field containing notes to merge with Comments\n"
|
||||||
|
" [before|after] Placement of notes with respect to Comments\n"
|
||||||
|
" [True|False] - A horizontal rule is inserted between notes and Comments\n"
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to ePub, MOBI output formats")),
|
||||||
Option('--note-tag',
|
Option('--note-tag',
|
||||||
default='*',
|
default='*',
|
||||||
dest='note_tag',
|
dest='note_tag',
|
||||||
@ -845,6 +869,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
catalog.copyResources()
|
catalog.copyResources()
|
||||||
catalog.buildSources()
|
catalog.buildSources()
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# A single number creates 'Last x days' only.
|
# A single number creates 'Last x days' only.
|
||||||
# Multiple numbers create 'Last x days', 'x to y days ago' ...
|
# Multiple numbers create 'Last x days', 'x to y days ago' ...
|
||||||
# e.g, [7,15,30,60], [30]
|
# e.g, [7,15,30,60], [30]
|
||||||
@ -889,6 +914,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
and self.generateForKindle \
|
and self.generateForKindle \
|
||||||
else False
|
else False
|
||||||
self.__genres = None
|
self.__genres = None
|
||||||
|
self.genres = []
|
||||||
self.__genre_tags_dict = None
|
self.__genre_tags_dict = None
|
||||||
self.__htmlFileList = []
|
self.__htmlFileList = []
|
||||||
self.__markerTags = self.getMarkerTags()
|
self.__markerTags = self.getMarkerTags()
|
||||||
@ -900,13 +926,15 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.__progressString = ''
|
self.__progressString = ''
|
||||||
f, _, p = opts.read_book_marker.partition(':')
|
f, _, p = opts.read_book_marker.partition(':')
|
||||||
self.__read_book_marker = {'field':f, 'pattern':p}
|
self.__read_book_marker = {'field':f, 'pattern':p}
|
||||||
|
f, p, hr = self.opts.merge_comments.split(':')
|
||||||
|
self.__merge_comments = {'field':f, 'position':p, 'hr':hr}
|
||||||
self.__reporter = report_progress
|
self.__reporter = report_progress
|
||||||
self.__stylesheet = stylesheet
|
self.__stylesheet = stylesheet
|
||||||
self.__thumbs = None
|
self.__thumbs = None
|
||||||
self.__thumbWidth = 0
|
self.__thumbWidth = 0
|
||||||
self.__thumbHeight = 0
|
self.__thumbHeight = 0
|
||||||
self.__title = opts.catalog_title
|
self.__title = opts.catalog_title
|
||||||
self.__totalSteps = 11.0
|
self.__totalSteps = 8.0
|
||||||
self.__useSeriesPrefixInTitlesSection = False
|
self.__useSeriesPrefixInTitlesSection = False
|
||||||
self.__verbose = opts.verbose
|
self.__verbose = opts.verbose
|
||||||
|
|
||||||
@ -916,17 +944,36 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.__output_profile = profile
|
self.__output_profile = profile
|
||||||
break
|
break
|
||||||
|
|
||||||
# Confirm/create thumbs archive
|
# Confirm/create thumbs archive.
|
||||||
if not os.path.exists(self.__cache_dir):
|
if not os.path.exists(self.__cache_dir):
|
||||||
self.opts.log.info(" creating new thumb cache '%s'" % self.__cache_dir)
|
self.opts.log.info(" creating new thumb cache '%s'" % self.__cache_dir)
|
||||||
os.makedirs(self.__cache_dir)
|
os.makedirs(self.__cache_dir)
|
||||||
if not os.path.exists(self.__archive_path):
|
if not os.path.exists(self.__archive_path):
|
||||||
self.opts.log.info(" creating thumbnail archive")
|
self.opts.log.info(' creating thumbnail archive, thumb_width: %1.2f"' %
|
||||||
|
float(self.opts.thumb_width))
|
||||||
zfw = ZipFile(self.__archive_path, mode='w')
|
zfw = ZipFile(self.__archive_path, mode='w')
|
||||||
zfw.writestr("Catalog Thumbs Archive",'')
|
zfw.writestr("Catalog Thumbs Archive",'')
|
||||||
|
zfw.comment = "thumb_width: %1.2f" % float(self.opts.thumb_width)
|
||||||
zfw.close()
|
zfw.close()
|
||||||
else:
|
else:
|
||||||
self.opts.log.info(" existing thumb cache at '%s'" % self.__archive_path)
|
with closing(ZipFile(self.__archive_path, mode='r')) as zfr:
|
||||||
|
try:
|
||||||
|
cached_thumb_width = float(zfr.comment[len('thumb_width: '):])
|
||||||
|
except:
|
||||||
|
cached_thumb_width = "0.0"
|
||||||
|
|
||||||
|
if float(cached_thumb_width) != float(self.opts.thumb_width):
|
||||||
|
self.opts.log.info(" invalidating cache at '%s'" % self.__archive_path)
|
||||||
|
self.opts.log.info(' thumb_width: %1.2f" => %1.2f"' %
|
||||||
|
(float(cached_thumb_width),float(self.opts.thumb_width)))
|
||||||
|
os.remove(self.__archive_path)
|
||||||
|
zfw = ZipFile(self.__archive_path, mode='w')
|
||||||
|
zfw.writestr("Catalog Thumbs Archive",'')
|
||||||
|
zfw.comment = "thumb_width: %1.2f" % float(self.opts.thumb_width)
|
||||||
|
zfw.close()
|
||||||
|
else:
|
||||||
|
self.opts.log.info(' existing thumb cache at %s, cached_thumb_width: %1.2f"' %
|
||||||
|
(self.__archive_path, float(cached_thumb_width)))
|
||||||
|
|
||||||
# Tweak build steps based on optional sections: 1 call for HTML, 1 for NCX
|
# Tweak build steps based on optional sections: 1 call for HTML, 1 for NCX
|
||||||
if self.opts.generate_titles:
|
if self.opts.generate_titles:
|
||||||
@ -937,6 +984,9 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.__totalSteps += 2
|
self.__totalSteps += 2
|
||||||
if self.opts.generate_series:
|
if self.opts.generate_series:
|
||||||
self.__totalSteps += 2
|
self.__totalSteps += 2
|
||||||
|
if self.opts.generate_descriptions:
|
||||||
|
# +1 thumbs
|
||||||
|
self.__totalSteps += 3
|
||||||
|
|
||||||
# Accessors
|
# Accessors
|
||||||
if True:
|
if True:
|
||||||
@ -1246,7 +1296,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
return False
|
return False
|
||||||
self.fetchBooksByAuthor()
|
self.fetchBooksByAuthor()
|
||||||
self.fetchBookmarks()
|
self.fetchBookmarks()
|
||||||
self.generateHTMLDescriptions()
|
if self.opts.generate_descriptions:
|
||||||
|
self.generateHTMLDescriptions()
|
||||||
self.generateHTMLByAuthor()
|
self.generateHTMLByAuthor()
|
||||||
if self.opts.generate_titles:
|
if self.opts.generate_titles:
|
||||||
self.generateHTMLByTitle()
|
self.generateHTMLByTitle()
|
||||||
@ -1256,10 +1307,10 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.generateHTMLByDateAdded()
|
self.generateHTMLByDateAdded()
|
||||||
if self.generateRecentlyRead:
|
if self.generateRecentlyRead:
|
||||||
self.generateHTMLByDateRead()
|
self.generateHTMLByDateRead()
|
||||||
self.generateHTMLByTags()
|
if self.opts.generate_genres:
|
||||||
|
self.generateHTMLByTags()
|
||||||
self.generateThumbnails()
|
if self.opts.generate_descriptions:
|
||||||
|
self.generateThumbnails()
|
||||||
self.generateOPF()
|
self.generateOPF()
|
||||||
self.generateNCXHeader()
|
self.generateNCXHeader()
|
||||||
self.generateNCXByAuthor("Authors")
|
self.generateNCXByAuthor("Authors")
|
||||||
@ -1271,8 +1322,11 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.generateNCXByDateAdded("Recently Added")
|
self.generateNCXByDateAdded("Recently Added")
|
||||||
if self.generateRecentlyRead:
|
if self.generateRecentlyRead:
|
||||||
self.generateNCXByDateRead("Recently Read")
|
self.generateNCXByDateRead("Recently Read")
|
||||||
self.generateNCXByGenre("Genres")
|
if self.opts.generate_genres:
|
||||||
self.generateNCXDescriptions("Descriptions")
|
self.generateNCXByGenre("Genres")
|
||||||
|
if self.opts.generate_descriptions:
|
||||||
|
self.generateNCXDescriptions("Descriptions")
|
||||||
|
|
||||||
self.writeNCX()
|
self.writeNCX()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -1340,6 +1394,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
#print "fetchBooksByTitle(): opts.search_text: %s" % self.opts.search_text
|
#print "fetchBooksByTitle(): opts.search_text: %s" % self.opts.search_text
|
||||||
# Fetch the database as a dictionary
|
# Fetch the database as a dictionary
|
||||||
data = self.plugin.search_sort_db(self.db, self.opts)
|
data = self.plugin.search_sort_db(self.db, self.opts)
|
||||||
|
data = self.processExclusions(data)
|
||||||
|
|
||||||
# Populate this_title{} from data[{},{}]
|
# Populate this_title{} from data[{},{}]
|
||||||
titles = []
|
titles = []
|
||||||
@ -1388,6 +1443,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
record['comments'] = record['comments'][:ad_offset]
|
record['comments'] = record['comments'][:ad_offset]
|
||||||
|
|
||||||
this_title['description'] = self.markdownComments(record['comments'])
|
this_title['description'] = self.markdownComments(record['comments'])
|
||||||
|
|
||||||
|
# Create short description
|
||||||
paras = BeautifulSoup(this_title['description']).findAll('p')
|
paras = BeautifulSoup(this_title['description']).findAll('p')
|
||||||
tokens = []
|
tokens = []
|
||||||
for p in paras:
|
for p in paras:
|
||||||
@ -1399,6 +1456,10 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
this_title['description'] = None
|
this_title['description'] = None
|
||||||
this_title['short_description'] = None
|
this_title['short_description'] = None
|
||||||
|
|
||||||
|
# Merge with custom field/value
|
||||||
|
if self.__merge_comments['field']:
|
||||||
|
this_title['description'] = self.mergeComments(this_title)
|
||||||
|
|
||||||
if record['cover']:
|
if record['cover']:
|
||||||
this_title['cover'] = re.sub('&', '&', record['cover'])
|
this_title['cover'] = re.sub('&', '&', record['cover'])
|
||||||
|
|
||||||
@ -1413,6 +1474,14 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
formats.append(self.convertHTMLEntities(format))
|
formats.append(self.convertHTMLEntities(format))
|
||||||
this_title['formats'] = formats
|
this_title['formats'] = formats
|
||||||
|
|
||||||
|
# Add user notes to be displayed in header
|
||||||
|
if self.opts.header_note_source_field:
|
||||||
|
notes = self.__db.get_field(record['id'],
|
||||||
|
self.opts.header_note_source_field,
|
||||||
|
index_is_id=True)
|
||||||
|
if notes:
|
||||||
|
this_title['notes'] = notes
|
||||||
|
|
||||||
titles.append(this_title)
|
titles.append(this_title)
|
||||||
|
|
||||||
# Re-sort based on title_sort
|
# Re-sort based on title_sort
|
||||||
@ -1712,7 +1781,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
for tag in title.get('tags', []):
|
for tag in title.get('tags', []):
|
||||||
aTag = Tag(soup,'a')
|
aTag = Tag(soup,'a')
|
||||||
#print "aTag: %s" % "Genre_%s.html" % re.sub("\W","",tag.lower())
|
#print "aTag: %s" % "Genre_%s.html" % re.sub("\W","",tag.lower())
|
||||||
aTag['href'] = "Genre_%s.html" % re.sub("\W","",tag.lower())
|
if self.opts.generate_genres:
|
||||||
|
aTag['href'] = "Genre_%s.html" % re.sub("\W","",tag.lower())
|
||||||
aTag.insert(0,escape(NavigableString(tag)))
|
aTag.insert(0,escape(NavigableString(tag)))
|
||||||
emTag = Tag(soup, "em")
|
emTag = Tag(soup, "em")
|
||||||
emTag.insert(0, aTag)
|
emTag.insert(0, aTag)
|
||||||
@ -1771,7 +1841,6 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
#ratingLabel = body.find('td',text="Rating").replaceWith("Unrated")
|
#ratingLabel = body.find('td',text="Rating").replaceWith("Unrated")
|
||||||
ratingTag.insert(0,NavigableString('<br/>'))
|
ratingTag.insert(0,NavigableString('<br/>'))
|
||||||
|
|
||||||
|
|
||||||
# Insert user notes or remove Notes label. Notes > 1 line will push formatting down
|
# Insert user notes or remove Notes label. Notes > 1 line will push formatting down
|
||||||
if 'notes' in title:
|
if 'notes' in title:
|
||||||
notesTag = body.find(attrs={'class':'notes'})
|
notesTag = body.find(attrs={'class':'notes'})
|
||||||
@ -1894,7 +1963,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
# Link to book
|
# Link to book
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
if self.opts.generate_descriptions:
|
||||||
|
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
||||||
aTag.insert(0,escape(book['title']))
|
aTag.insert(0,escape(book['title']))
|
||||||
pBookTag.insert(ptc, aTag)
|
pBookTag.insert(ptc, aTag)
|
||||||
ptc += 1
|
ptc += 1
|
||||||
@ -2067,8 +2137,9 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
ptc += 1
|
ptc += 1
|
||||||
|
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
if self.opts.generate_descriptions:
|
||||||
# Use series, series index if avail else just title, + year of publication
|
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
||||||
|
# Use series, series index if avail else title, + year of publication
|
||||||
if current_series:
|
if current_series:
|
||||||
aTag.insert(0,'%s (%s)' % (escape(book['title'][len(book['series'])+1:]),
|
aTag.insert(0,'%s (%s)' % (escape(book['title'][len(book['series'])+1:]),
|
||||||
book['date'].split()[1]))
|
book['date'].split()[1]))
|
||||||
@ -2079,7 +2150,6 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
pBookTag.insert(ptc, aTag)
|
pBookTag.insert(ptc, aTag)
|
||||||
ptc += 1
|
ptc += 1
|
||||||
|
|
||||||
|
|
||||||
divTag.insert(dtc, pBookTag)
|
divTag.insert(dtc, pBookTag)
|
||||||
dtc += 1
|
dtc += 1
|
||||||
|
|
||||||
@ -2200,7 +2270,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
ptc += 1
|
ptc += 1
|
||||||
|
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
if self.opts.generate_descriptions:
|
||||||
|
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
||||||
if current_series:
|
if current_series:
|
||||||
aTag.insert(0,escape(new_entry['title'][len(new_entry['series'])+1:]))
|
aTag.insert(0,escape(new_entry['title'][len(new_entry['series'])+1:]))
|
||||||
else:
|
else:
|
||||||
@ -2251,7 +2322,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
ptc += 1
|
ptc += 1
|
||||||
|
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
if self.opts.generate_descriptions:
|
||||||
|
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
||||||
aTag.insert(0,escape(new_entry['title']))
|
aTag.insert(0,escape(new_entry['title']))
|
||||||
pBookTag.insert(ptc, aTag)
|
pBookTag.insert(ptc, aTag)
|
||||||
ptc += 1
|
ptc += 1
|
||||||
@ -2411,7 +2483,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
ptc += 1
|
ptc += 1
|
||||||
|
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
if self.opts.generate_descriptions:
|
||||||
|
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
||||||
aTag.insert(0,escape(new_entry['title']))
|
aTag.insert(0,escape(new_entry['title']))
|
||||||
pBookTag.insert(ptc, aTag)
|
pBookTag.insert(ptc, aTag)
|
||||||
ptc += 1
|
ptc += 1
|
||||||
@ -2458,7 +2531,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
ptc += 1
|
ptc += 1
|
||||||
|
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
if self.opts.generate_descriptions:
|
||||||
|
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
||||||
aTag.insert(0,escape(new_entry['title']))
|
aTag.insert(0,escape(new_entry['title']))
|
||||||
pBookTag.insert(ptc, aTag)
|
pBookTag.insert(ptc, aTag)
|
||||||
ptc += 1
|
ptc += 1
|
||||||
@ -2699,7 +2773,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
ptc += 1
|
ptc += 1
|
||||||
|
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
if self.opts.generate_descriptions:
|
||||||
|
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
||||||
# Use series, series index if avail else just title
|
# Use series, series index if avail else just title
|
||||||
#aTag.insert(0,'%d. %s · %s' % (book['series_index'],escape(book['title']), ' & '.join(book['authors'])))
|
#aTag.insert(0,'%d. %s · %s' % (book['series_index'],escape(book['title']), ' & '.join(book['authors'])))
|
||||||
|
|
||||||
@ -2983,18 +3058,20 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
manifest.insert(mtc, itemTag)
|
manifest.insert(mtc, itemTag)
|
||||||
mtc += 1
|
mtc += 1
|
||||||
|
|
||||||
# Write the thumbnail images to the manifest
|
# Write the thumbnail images, descriptions to the manifest
|
||||||
for thumb in self.thumbs:
|
sort_descriptions_by = []
|
||||||
itemTag = Tag(soup, "item")
|
if self.opts.generate_descriptions:
|
||||||
itemTag['href'] = "images/%s" % (thumb)
|
for thumb in self.thumbs:
|
||||||
end = thumb.find('.jpg')
|
itemTag = Tag(soup, "item")
|
||||||
itemTag['id'] = "%s-image" % thumb[:end]
|
itemTag['href'] = "images/%s" % (thumb)
|
||||||
itemTag['media-type'] = 'image/jpeg'
|
end = thumb.find('.jpg')
|
||||||
manifest.insert(mtc, itemTag)
|
itemTag['id'] = "%s-image" % thumb[:end]
|
||||||
mtc += 1
|
itemTag['media-type'] = 'image/jpeg'
|
||||||
|
manifest.insert(mtc, itemTag)
|
||||||
|
mtc += 1
|
||||||
|
|
||||||
# HTML files - add books to manifest and spine
|
# HTML files - add descriptions to manifest and spine
|
||||||
sort_descriptions_by = self.booksByAuthor if self.opts.sort_descriptions_by_author \
|
sort_descriptions_by = self.booksByAuthor if self.opts.sort_descriptions_by_author \
|
||||||
else self.booksByTitle
|
else self.booksByTitle
|
||||||
# Add html_files to manifest and spine
|
# Add html_files to manifest and spine
|
||||||
|
|
||||||
@ -3970,15 +4047,15 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
from calibre.customize.ui import output_profiles
|
from calibre.customize.ui import output_profiles
|
||||||
for x in output_profiles():
|
for x in output_profiles():
|
||||||
if x.short_name == self.opts.output_profile:
|
if x.short_name == self.opts.output_profile:
|
||||||
# .9" width aspect ratio: 3:4
|
# aspect ratio: 3:4
|
||||||
self.thumbWidth = int(x.dpi * 1)
|
self.thumbWidth = x.dpi * float(self.opts.thumb_width)
|
||||||
self.thumbHeight = int(self.thumbWidth * 1.33)
|
self.thumbHeight = self.thumbWidth * 1.33
|
||||||
if 'kindle' in x.short_name and self.opts.fmt == 'mobi':
|
if 'kindle' in x.short_name and self.opts.fmt == 'mobi':
|
||||||
# Kindle DPI appears to be off by a factor of 2
|
# Kindle DPI appears to be off by a factor of 2
|
||||||
self.thumbWidth = int(self.thumbWidth/2)
|
self.thumbWidth = self.thumbWidth/2
|
||||||
self.thumbHeight = int(self.thumbHeight/2)
|
self.thumbHeight = self.thumbHeight/2
|
||||||
break
|
break
|
||||||
if False and self.verbose:
|
if True and self.verbose:
|
||||||
self.opts.log(" DPI = %d; thumbnail dimensions: %d x %d" % \
|
self.opts.log(" DPI = %d; thumbnail dimensions: %d x %d" % \
|
||||||
(x.dpi, self.thumbWidth, self.thumbHeight))
|
(x.dpi, self.thumbWidth, self.thumbHeight))
|
||||||
|
|
||||||
@ -4238,7 +4315,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
# Add the book title
|
# Add the book title
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
if self.opts.generate_descriptions:
|
||||||
|
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
||||||
# Use series, series index if avail else just title
|
# Use series, series index if avail else just title
|
||||||
if current_series:
|
if current_series:
|
||||||
aTag.insert(0,escape(book['title'][len(book['series'])+1:]))
|
aTag.insert(0,escape(book['title'][len(book['series'])+1:]))
|
||||||
@ -4460,7 +4538,9 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
# Leading numbers optionally translated to text equivalent
|
# Leading numbers optionally translated to text equivalent
|
||||||
# Capitalize leading sort word
|
# Capitalize leading sort word
|
||||||
if i==0:
|
if i==0:
|
||||||
if self.opts.numbers_as_text and re.match('[0-9]+',word[0]):
|
# *** Keep this code in case we need to restore numbers_as_text ***
|
||||||
|
if False:
|
||||||
|
#if self.opts.numbers_as_text and re.match('[0-9]+',word[0]):
|
||||||
translated.append(EPUB_MOBI.NumberToText(word).text.capitalize())
|
translated.append(EPUB_MOBI.NumberToText(word).text.capitalize())
|
||||||
else:
|
else:
|
||||||
if re.match('[0-9]+',word[0]):
|
if re.match('[0-9]+',word[0]):
|
||||||
@ -4540,7 +4620,6 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
''' Return a list of special marker tags to be excluded from genre list '''
|
''' Return a list of special marker tags to be excluded from genre list '''
|
||||||
markerTags = []
|
markerTags = []
|
||||||
markerTags.extend(self.opts.exclude_tags.split(','))
|
markerTags.extend(self.opts.exclude_tags.split(','))
|
||||||
markerTags.extend(self.opts.note_tag.split(','))
|
|
||||||
return markerTags
|
return markerTags
|
||||||
|
|
||||||
def letter_or_symbol(self,char):
|
def letter_or_symbol(self,char):
|
||||||
@ -4663,13 +4742,63 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
return result.renderContents(encoding=None)
|
return result.renderContents(encoding=None)
|
||||||
|
|
||||||
|
def mergeComments(self, record):
|
||||||
|
'''
|
||||||
|
merge ['description'] with custom field contents to be displayed in Descriptions
|
||||||
|
'''
|
||||||
|
merged = ''
|
||||||
|
if record['description']:
|
||||||
|
addendum = self.__db.get_field(record['id'],
|
||||||
|
self.__merge_comments['field'],
|
||||||
|
index_is_id=True)
|
||||||
|
include_hr = eval(self.__merge_comments['hr'])
|
||||||
|
if self.__merge_comments['position'] == 'before':
|
||||||
|
merged = addendum
|
||||||
|
if include_hr:
|
||||||
|
merged += '<hr class="merged_comments_divider"/>'
|
||||||
|
else:
|
||||||
|
merged += '\n'
|
||||||
|
merged += record['description']
|
||||||
|
else:
|
||||||
|
merged = record['description']
|
||||||
|
if include_hr:
|
||||||
|
merged += '<hr class="merged_comments_divider"/>'
|
||||||
|
else:
|
||||||
|
merged += '\n'
|
||||||
|
merged += addendum
|
||||||
|
else:
|
||||||
|
# Return the custom field contents
|
||||||
|
merged = self.__db.get_field(record['id'],
|
||||||
|
self.__merge_comments['field'],
|
||||||
|
index_is_id=True)
|
||||||
|
|
||||||
|
return merged
|
||||||
|
|
||||||
|
def processExclusions(self, data_set):
|
||||||
|
'''
|
||||||
|
Remove excluded entries
|
||||||
|
'''
|
||||||
|
field, pat = self.opts.exclude_book_marker.split(':')
|
||||||
|
if pat == '':
|
||||||
|
return data_set
|
||||||
|
filtered_data_set = []
|
||||||
|
for record in data_set:
|
||||||
|
field_contents = self.__db.get_field(record['id'],
|
||||||
|
field,
|
||||||
|
index_is_id=True)
|
||||||
|
if field_contents:
|
||||||
|
if re.search(pat, unicode(field_contents),
|
||||||
|
re.IGNORECASE) is not None:
|
||||||
|
continue
|
||||||
|
filtered_data_set.append(record)
|
||||||
|
|
||||||
|
return filtered_data_set
|
||||||
|
|
||||||
def processSpecialTags(self, tags, this_title, opts):
|
def processSpecialTags(self, tags, this_title, opts):
|
||||||
tag_list = []
|
tag_list = []
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
tag = self.convertHTMLEntities(tag)
|
tag = self.convertHTMLEntities(tag)
|
||||||
if tag.startswith(opts.note_tag):
|
if re.search(opts.exclude_genre, tag):
|
||||||
this_title['notes'] = tag[len(self.opts.note_tag):]
|
|
||||||
elif re.search(opts.exclude_genre, tag):
|
|
||||||
continue
|
continue
|
||||||
elif self.__read_book_marker['field'] == 'tag' and \
|
elif self.__read_book_marker['field'] == 'tag' and \
|
||||||
tag == self.__read_book_marker['pattern']:
|
tag == self.__read_book_marker['pattern']:
|
||||||
@ -4767,13 +4896,16 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
if opts_dict['ids']:
|
if opts_dict['ids']:
|
||||||
build_log.append(" book count: %d" % len(opts_dict['ids']))
|
build_log.append(" book count: %d" % len(opts_dict['ids']))
|
||||||
|
|
||||||
sections_list = ['Descriptions','Authors']
|
sections_list = ['Authors']
|
||||||
if opts.generate_titles:
|
if opts.generate_titles:
|
||||||
sections_list.append('Titles')
|
sections_list.append('Titles')
|
||||||
if opts.generate_recently_added:
|
if opts.generate_recently_added:
|
||||||
sections_list.append('Recently Added')
|
sections_list.append('Recently Added')
|
||||||
if not opts.exclude_genre.strip() == '.':
|
if opts.generate_genres:
|
||||||
sections_list.append('Genres')
|
sections_list.append('Genres')
|
||||||
|
if opts.generate_descriptions:
|
||||||
|
sections_list.append('Descriptions')
|
||||||
|
|
||||||
build_log.append(u" Sections: %s" % ', '.join(sections_list))
|
build_log.append(u" Sections: %s" % ', '.join(sections_list))
|
||||||
|
|
||||||
# Display opts
|
# Display opts
|
||||||
@ -4782,11 +4914,12 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
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','authorClip','connected_kindle','descriptionClip',
|
||||||
'exclude_genre','exclude_tags','note_tag','numbers_as_text',
|
'exclude_book_marker','exclude_genre','exclude_tags',
|
||||||
|
'header_note_source_field','merge_comments',
|
||||||
'output_profile','read_book_marker',
|
'output_profile','read_book_marker',
|
||||||
'search_text','sort_by','sort_descriptions_by_author','sync',
|
'search_text','sort_by','sort_descriptions_by_author','sync',
|
||||||
'wishlist_tag']:
|
'thumb_width','wishlist_tag']:
|
||||||
build_log.append(" %s: %s" % (key, opts_dict[key]))
|
build_log.append(" %s: %s" % (key, repr(opts_dict[key])))
|
||||||
|
|
||||||
if opts.verbose:
|
if opts.verbose:
|
||||||
log('\n'.join(line for line in build_log))
|
log('\n'.join(line for line in build_log))
|
||||||
@ -4801,6 +4934,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
catalog.copyResources()
|
catalog.copyResources()
|
||||||
catalog.calculateThumbnailSize()
|
catalog.calculateThumbnailSize()
|
||||||
catalog_source_built = catalog.buildSources()
|
catalog_source_built = catalog.buildSources()
|
||||||
|
|
||||||
if opts.verbose:
|
if opts.verbose:
|
||||||
if catalog_source_built:
|
if catalog_source_built:
|
||||||
log.info(" Completed catalog source generation\n")
|
log.info(" Completed catalog source generation\n")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user