Improved focus handling for tables. Removed obsolete characters in profiles.py. Revised tool tips.

This commit is contained in:
GRiker 2012-08-06 17:34:47 -06:00
parent e40bd0164d
commit 1f2e84181f
4 changed files with 84 additions and 172 deletions

View File

@ -251,10 +251,8 @@ class OutputProfile(Plugin):
periodical_date_in_title = True periodical_date_in_title = True
#: Characters used in jackets and catalogs #: Characters used in jackets and catalogs
missing_char = u'x'
ratings_char = u'*' ratings_char = u'*'
empty_ratings_char = u' ' empty_ratings_char = u' '
read_char = u'+'
#: Unsupported unicode characters to be replaced during preprocessing #: Unsupported unicode characters to be replaced during preprocessing
unsupported_unicode_chars = [] unsupported_unicode_chars = []
@ -292,10 +290,8 @@ class iPadOutput(OutputProfile):
} }
] ]
missing_char = u'\u2715\u200a' # stylized 'x' plus hair space
ratings_char = u'\u2605' # filled star ratings_char = u'\u2605' # filled star
empty_ratings_char = u'\u2606' # hollow star empty_ratings_char = u'\u2606' # hollow star
read_char = u'\u2713' # check mark
touchscreen = True touchscreen = True
# touchscreen_news_css {{{ # touchscreen_news_css {{{
@ -626,10 +622,8 @@ class KindleOutput(OutputProfile):
supports_mobi_indexing = True supports_mobi_indexing = True
periodical_date_in_title = False periodical_date_in_title = False
missing_char = u'x\u2009'
empty_ratings_char = u'\u2606' empty_ratings_char = u'\u2606'
ratings_char = u'\u2605' ratings_char = u'\u2605'
read_char = u'\u2713'
mobi_ems_per_blockquote = 2.0 mobi_ems_per_blockquote = 2.0
@ -651,10 +645,8 @@ class KindleDXOutput(OutputProfile):
#comic_screen_size = (741, 1022) #comic_screen_size = (741, 1022)
supports_mobi_indexing = True supports_mobi_indexing = True
periodical_date_in_title = False periodical_date_in_title = False
missing_char = u'x\u2009'
empty_ratings_char = u'\u2606' empty_ratings_char = u'\u2606'
ratings_char = u'\u2605' ratings_char = u'\u2605'
read_char = u'\u2713'
mobi_ems_per_blockquote = 2.0 mobi_ems_per_blockquote = 2.0
@classmethod @classmethod

View File

@ -6,6 +6,7 @@ __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
from functools import partial from functools import partial
from calibre.ebooks.conversion.config import load_defaults from calibre.ebooks.conversion.config import load_defaults
@ -138,7 +139,6 @@ class PluginWidget(QWidget,Ui_Form):
self.fetchEligibleCustomFields() self.fetchEligibleCustomFields()
self.populate_combo_boxes() self.populate_combo_boxes()
# Update dialog fields from stored options # Update dialog fields from stored options
exclusion_rules = [] exclusion_rules = []
prefix_rules = [] prefix_rules = []
@ -161,10 +161,11 @@ class PluginWidget(QWidget,Ui_Form):
getattr(self, c_name).setChecked(opt_value) getattr(self, c_name).setChecked(opt_value)
elif c_type in ['spin_box']: elif c_type in ['spin_box']:
getattr(self, c_name).setValue(float(opt_value)) getattr(self, c_name).setValue(float(opt_value))
elif c_type in ['table_widget'] and c_name == 'exclusion_rules_tw': if c_type == 'table_widget':
if c_name == 'exclusion_rules_tw':
if opt_value not in exclusion_rules: if opt_value not in exclusion_rules:
exclusion_rules.append(opt_value) exclusion_rules.append(opt_value)
elif c_type in ['table_widget'] and c_name == 'prefix_rules_tw': if c_name == 'prefix_rules_tw':
if opt_value not in prefix_rules: if opt_value not in prefix_rules:
prefix_rules.append(opt_value) prefix_rules.append(opt_value)
@ -187,20 +188,13 @@ class PluginWidget(QWidget,Ui_Form):
self.header_note_source_field_name = header_note_source_spec['field'] self.header_note_source_field_name = header_note_source_spec['field']
# Initialize exclusion rules # Initialize exclusion rules
self.exclusion_rules_table = ExclusionRules(self.exclusion_rules_gb_hl, self.exclusion_rules_table = ExclusionRules(self.exclusion_rules_gb,
"exclusion_rules_tw",exclusion_rules, self.eligible_custom_fields,self.db) "exclusion_rules_tw",exclusion_rules, self.eligible_custom_fields,self.db)
# Initialize prefix rules # Initialize prefix rules
self.prefix_rules_table = PrefixRules(self.prefix_rules_gb_hl, 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)
# Hook changes to thumb_width
self.thumb_width.valueChanged.connect(self.thumb_width_changed)
# Hook changes to Description section
self.generate_descriptions.stateChanged.connect(self.generate_descriptions_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
@ -214,6 +208,11 @@ class PluginWidget(QWidget,Ui_Form):
for opt in self.OPTION_FIELDS: for opt in self.OPTION_FIELDS:
c_name, c_def, c_type = opt c_name, c_def, c_type = opt
if c_name == 'exclusion_rules_tw' and exclusion_rules_processed:
continue
if c_name == 'prefix_rules_tw' and prefix_rules_processed:
continue
if c_type in ['check_box', 'radio_button']: if c_type in ['check_box', 'radio_button']:
opt_value = getattr(self, c_name).isChecked() opt_value = getattr(self, c_name).isChecked()
elif c_type in ['combo_box']: elif c_type in ['combo_box']:
@ -225,22 +224,21 @@ class PluginWidget(QWidget,Ui_Form):
elif c_type in ['table_widget']: elif c_type in ['table_widget']:
if c_name == 'prefix_rules_tw': if c_name == 'prefix_rules_tw':
opt_value = self.prefix_rules_table.get_data() opt_value = self.prefix_rules_table.get_data()
prefix_rules_processed = True
if c_name == 'exclusion_rules_tw': if c_name == 'exclusion_rules_tw':
opt_value = self.exclusion_rules_table.get_data() opt_value = self.exclusion_rules_table.get_data()
exclusion_rules_processed = True
# Store UI values to gui.json in config dir
gprefs.set(self.name + '_' + c_name, opt_value) gprefs.set(self.name + '_' + c_name, opt_value)
# Construct opts object for catalog builder # Construct opts object for catalog builder
if c_name == 'exclude_tags': if c_name == 'prefix_rules_tw':
# store as list
opts_dict[c_name] = opt_value.split(',')
elif c_name == 'prefix_rules_tw':
if prefix_rules_processed:
continue
rule_set = [] rule_set = []
for rule in opt_value: for stored_rule in opt_value:
# Test for empty name/field/pattern/prefix, continue # Test for empty name/field/pattern/prefix, continue
# If pattern = any or unspecified, convert to regex # If pattern = any or unspecified, convert to regex
rule = copy(stored_rule)
if not rule['enabled']: if not rule['enabled']:
continue continue
elif not rule['field'] or not rule['pattern'] or not rule['prefix']: elif not rule['field'] or not rule['pattern'] or not rule['prefix']:
@ -259,15 +257,13 @@ class PluginWidget(QWidget,Ui_Form):
rule_set.append(pr) rule_set.append(pr)
opt_value = tuple(rule_set) opt_value = tuple(rule_set)
opts_dict['prefix_rules'] = opt_value opts_dict['prefix_rules'] = opt_value
prefix_rules_processed = True
elif c_name == 'exclusion_rules_tw': elif c_name == 'exclusion_rules_tw':
if exclusion_rules_processed:
continue
rule_set = [] rule_set = []
for rule in opt_value: for stored_rule in opt_value:
# Test for empty name/field/pattern/prefix, continue # Test for empty name/field/pattern/prefix, continue
# If pattern = any or unspecified, convert to regex # If pattern = any or unspecified, convert to regex
rule = copy(stored_rule)
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']:
@ -284,10 +280,8 @@ class PluginWidget(QWidget,Ui_Form):
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)
opts_dict['exclusion_rules'] = opt_value opts_dict['exclusion_rules'] = opt_value
exclusion_rules_processed = True
else: else:
opts_dict[c_name] = opt_value opts_dict[c_name] = opt_value
@ -372,74 +366,6 @@ 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 read_source_field_changed(self,new_index):
'''
Process changes in the read_source_field combo box
Currently using QLineEdit for all field types
Possible to modify to switch QWidget type
'''
new_source = unicode(self.read_source_field.currentText())
read_source_spec = self.read_source_fields[new_source]
self.read_source_field_name = read_source_spec['field']
# Change pattern input widget to match the source field datatype
if read_source_spec['datatype'] in ['bool','composite','datetime','text']:
if not isinstance(self.read_pattern, QLineEdit):
self.read_spec_hl.removeWidget(self.read_pattern)
dw = QLineEdit(self)
dw.setObjectName('read_pattern')
dw.setToolTip('Pattern for read book')
self.read_pattern = 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[unicode(new_source)]
self.exclude_source_field_name = exclude_source_spec['field']
self.exclude_pattern.setEnabled(True)
# 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.setEnabled(False)
def generate_descriptions_changed(self,new_state):
'''
Process changes to Descriptions section
0: unchecked
2: checked
'''
return
'''
if new_state == 0:
# unchecked
self.merge_source_field.setEnabled(False)
self.merge_before.setEnabled(False)
self.merge_after.setEnabled(False)
self.include_hr.setEnabled(False)
elif new_state == 2:
# checked
self.merge_source_field.setEnabled(True)
self.merge_before.setEnabled(True)
self.merge_after.setEnabled(True)
self.include_hr.setEnabled(True)
'''
def header_note_source_field_changed(self,new_index): def header_note_source_field_changed(self,new_index):
''' '''
Process changes in the header_note_source_field combo box Process changes in the header_note_source_field combo box
@ -476,12 +402,6 @@ class PluginWidget(QWidget,Ui_Form):
self.exclude_genre.setText(default[1]) self.exclude_genre.setText(default[1])
break break
def thumb_width_changed(self,new_value):
'''
Process changes in the thumb_width spin box
'''
pass
class CheckableTableWidgetItem(QTableWidgetItem): class CheckableTableWidgetItem(QTableWidgetItem):
''' '''
@ -540,13 +460,14 @@ class GenericRulesTable(QTableWidget):
placeholders for basic methods to be overriden placeholders for basic methods to be overriden
''' '''
def __init__(self, parent_gb_hl, object_name, rules, eligible_custom_fields, db): def __init__(self, parent_gb, object_name, rules, eligible_custom_fields, db):
self.rules = rules self.rules = rules
self.eligible_custom_fields = eligible_custom_fields self.eligible_custom_fields = eligible_custom_fields
self.db = db self.db = db
QTableWidget.__init__(self) QTableWidget.__init__(self)
self.setObjectName(object_name) self.setObjectName(object_name)
self.layout = parent_gb_hl self.layout = QHBoxLayout()
parent_gb.setLayout(self.layout)
# Add ourselves to the layout # Add ourselves to the layout
#print("verticalHeader: %s" % dir(self.verticalHeader())) #print("verticalHeader: %s" % dir(self.verticalHeader()))
@ -559,9 +480,11 @@ class GenericRulesTable(QTableWidget):
self.setColumnCount(0) self.setColumnCount(0)
self.setRowCount(0) self.setRowCount(0)
self.layout.addWidget(self) self.layout.addWidget(self)
self.last_row_selected = self.currentRow()
self.last_rows_selected = self.selectionModel().selectedRows()
self._init_controls() self._init_controls()
def _init_controls(self): def _init_controls(self):
@ -599,12 +522,12 @@ class GenericRulesTable(QTableWidget):
def add_row(self): def add_row(self):
self.setFocus() self.setFocus()
row = self.currentRow() + 1 row = self.last_row_selected + 1
self.insertRow(row) self.insertRow(row)
self.populate_table_row(row, self.create_blank_row_data()) self.populate_table_row(row, self.create_blank_row_data())
self.select_and_scroll_to_row(row) self.select_and_scroll_to_row(row)
self.resizeColumnsToContents() self.resizeColumnsToContents()
# Just in case table was empty # In case table was empty
self.horizontalHeader().setStretchLastSection(True) self.horizontalHeader().setStretchLastSection(True)
def convert_row_to_data(self): def convert_row_to_data(self):
@ -621,12 +544,16 @@ class GenericRulesTable(QTableWidget):
def delete_row(self): def delete_row(self):
self.setFocus() self.setFocus()
rows = self.selectionModel().selectedRows() rows = self.last_rows_selected
if len(rows) == 0: if len(rows) == 0:
return return
message = '<p>Are you sure you want to delete this rule?'
first = rows[0].row() + 1
last = rows[-1].row() + 1
message = '<p>Are you sure you want to delete rule %d?' % first
if len(rows) > 1: if len(rows) > 1:
message = '<p>Are you sure you want to delete the %d selected rules?'%len(rows) message = '<p>Are you sure you want to delete rules %d-%d?' % (first, last)
if not question_dialog(self, _('Are you sure?'), message, show_copy_button=False): if not question_dialog(self, _('Are you sure?'), message, show_copy_button=False):
return return
first_sel_row = self.currentRow() first_sel_row = self.currentRow()
@ -637,16 +564,18 @@ class GenericRulesTable(QTableWidget):
elif self.rowCount() > 0: elif self.rowCount() > 0:
self.select_and_scroll_to_row(first_sel_row - 1) self.select_and_scroll_to_row(first_sel_row - 1)
def focusOutEvent(self,e):
# Override of QTableWidget method - clear selection when table loses focus
self.last_row_selected = self.currentRow()
self.last_rows_selected = self.selectionModel().selectedRows()
self.clearSelection()
def get_data(self): def get_data(self):
pass pass
def focusOutEvent(self,e):
# Override of QTableWidget method
self.clearSelection()
def move_row_down(self): def move_row_down(self):
self.setFocus() self.setFocus()
rows = self.selectionModel().selectedRows() rows = self.last_rows_selected
if len(rows) == 0: if len(rows) == 0:
return return
last_sel_row = rows[-1].row() last_sel_row = rows[-1].row()
@ -673,11 +602,11 @@ class GenericRulesTable(QTableWidget):
scroll_to_row = last_sel_row + 1 scroll_to_row = last_sel_row + 1
if scroll_to_row < self.rowCount() - 1: if scroll_to_row < self.rowCount() - 1:
scroll_to_row = scroll_to_row + 1 scroll_to_row = scroll_to_row + 1
self.scrollToItem(self.item(scroll_to_row, 0)) self.select_and_scroll_to_row(scroll_to_row)
def move_row_up(self): def move_row_up(self):
self.setFocus() self.setFocus()
rows = self.selectionModel().selectedRows() rows = self.last_rows_selected
if len(rows) == 0: if len(rows) == 0:
return return
first_sel_row = rows[0].row() first_sel_row = rows[0].row()
@ -699,7 +628,7 @@ class GenericRulesTable(QTableWidget):
scroll_to_row = first_sel_row - 1 scroll_to_row = first_sel_row - 1
if scroll_to_row > 0: if scroll_to_row > 0:
scroll_to_row = scroll_to_row - 1 scroll_to_row = scroll_to_row - 1
self.scrollToItem(self.item(scroll_to_row, 0)) self.select_and_scroll_to_row(scroll_to_row)
def populate_table_row(self): def populate_table_row(self):
''' '''
@ -744,7 +673,7 @@ class ExclusionRules(GenericRulesTable):
self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setSelectionBehavior(QAbstractItemView.SelectRows)
def _initialize(self): def _initialize(self):
self.populate() self.populate_table()
self.resizeColumnsToContents() self.resizeColumnsToContents()
self.resize_name(1.5) self.resize_name(1.5)
self.horizontalHeader().setStretchLastSection(True) self.horizontalHeader().setStretchLastSection(True)
@ -780,7 +709,7 @@ class ExclusionRules(GenericRulesTable):
'pattern':data['pattern']}) 'pattern':data['pattern']})
return data_items return data_items
def populate(self): def populate_table(self):
# Format of rules list is different if default values vs retrieved JSON # Format of rules list is different if default values vs retrieved JSON
# Hack to normalize list style # Hack to normalize list style
rules = self.rules rules = self.rules
@ -842,6 +771,8 @@ class ExclusionRules(GenericRulesTable):
values = ['True','False','unspecified'] values = ['True','False','unspecified']
elif self.eligible_custom_fields[source_field]['datatype'] in ['composite']: elif self.eligible_custom_fields[source_field]['datatype'] in ['composite']:
values = ['any value','unspecified'] values = ['any value','unspecified']
elif self.eligible_custom_fields[source_field]['datatype'] in ['datetime']:
values = ['any date','unspecified']
values_combo = ComboBox(self, values, pattern) values_combo = ComboBox(self, values, pattern)
self.setCellWidget(row, 3, values_combo) self.setCellWidget(row, 3, values_combo)
@ -862,7 +793,7 @@ class PrefixRules(GenericRulesTable):
def _initialize(self): def _initialize(self):
self.generate_prefix_list() self.generate_prefix_list()
self.populate() self.populate_table()
self.resizeColumnsToContents() self.resizeColumnsToContents()
self.resize_name(1.5) self.resize_name(1.5)
self.horizontalHeader().setStretchLastSection(True) self.horizontalHeader().setStretchLastSection(True)
@ -1036,7 +967,7 @@ class PrefixRules(GenericRulesTable):
'prefix':data['prefix']}) 'prefix':data['prefix']})
return data_items return data_items
def populate(self): def populate_table(self):
# Format of rules list is different if default values vs retrieved JSON # Format of rules list is different if default values vs retrieved JSON
# Hack to normalize list style # Hack to normalize list style
rules = self.rules rules = self.rules
@ -1108,10 +1039,10 @@ class PrefixRules(GenericRulesTable):
values = sorted(values, key=sort_key) values = sorted(values, key=sort_key)
elif self.eligible_custom_fields[source_field]['datatype'] in ['bool']: elif self.eligible_custom_fields[source_field]['datatype'] in ['bool']:
values = ['True','False','unspecified'] values = ['True','False','unspecified']
elif self.eligible_custom_fields[source_field]['datatype'] in ['datetime']:
values = ['any date','unspecified']
elif self.eligible_custom_fields[source_field]['datatype'] in ['composite']: elif self.eligible_custom_fields[source_field]['datatype'] in ['composite']:
values = ['any value','unspecified'] values = ['any value','unspecified']
elif self.eligible_custom_fields[source_field]['datatype'] in ['datetime']:
values = ['any date','unspecified']
values_combo = ComboBox(self, values, pattern) values_combo = ComboBox(self, values, pattern)
self.setCellWidget(row, 4, values_combo) self.setCellWidget(row, 4, values_combo)

View File

@ -35,7 +35,7 @@
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Sections to include in catalog.</string> <string>Enabled sections will be included in the generated catalog.</string>
</property> </property>
<property name="title"> <property name="title">
<string>Included sections</string> <string>Included sections</string>
@ -107,12 +107,8 @@
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>A regular expression describing genres to be excluded from the generated catalog. Genres are derived from the tags applied to your books.
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book], and '+', the default tag for a read book.</string>
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A regular expression describing genres to be excluded from the generated catalog. Genres are derived from the tags applied to your books.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Project Gutenberg], and '+', the default tag for a read book.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="title"> <property name="title">
<string>Excluded genres</string> <string>Excluded genres</string>
@ -209,16 +205,11 @@ p, li { white-space: pre-wrap; }
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Matching books will not be included in generated catalog. </string> <string>Books matching any of the exclusion rules will be excluded from the generated catalog. </string>
</property> </property>
<property name="title"> <property name="title">
<string>Excluded books</string> <string>Excluded books</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QHBoxLayout" name="exclusion_rules_gb_hl"/>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
@ -230,16 +221,11 @@ p, li { white-space: pre-wrap; }
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>The earliest enabled matching rule will be used to add a prefix to book listings in the generated catalog.</string> <string>The first enabled matching rule will be used to add a prefix to book listings in the generated catalog.</string>
</property> </property>
<property name="title"> <property name="title">
<string>Prefix rules</string> <string>Prefix rules</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<layout class="QHBoxLayout" name="prefix_rules_gb_hl"/>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
@ -305,7 +291,7 @@ p, li { white-space: pre-wrap; }
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Size hint for Description cover thumbnails</string> <string>Size hint for cover thumbnails included in Descriptions section.</string>
</property> </property>
<property name="suffix"> <property name="suffix">
<string> inch</string> <string> inch</string>
@ -362,7 +348,7 @@ p, li { white-space: pre-wrap; }
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Custom column source for note to include in Description header area</string> <string>Custom column source for text to include in Description section.</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -404,7 +390,7 @@ p, li { white-space: pre-wrap; }
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Additional content merged with Comments during catalog generation</string> <string>Custom column containing additional content to be merged with Comments metadata.</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -418,7 +404,7 @@ p, li { white-space: pre-wrap; }
<item> <item>
<widget class="QRadioButton" name="merge_before"> <widget class="QRadioButton" name="merge_before">
<property name="toolTip"> <property name="toolTip">
<string>Merge additional content before Comments</string> <string>Merge additional content before Comments metadata.</string>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Before</string> <string>&amp;Before</string>
@ -428,7 +414,7 @@ p, li { white-space: pre-wrap; }
<item> <item>
<widget class="QRadioButton" name="merge_after"> <widget class="QRadioButton" name="merge_after">
<property name="toolTip"> <property name="toolTip">
<string>Merge additional content after Comments</string> <string>Merge additional content after Comments metadata.</string>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;After</string> <string>&amp;After</string>
@ -445,7 +431,7 @@ p, li { white-space: pre-wrap; }
<item> <item>
<widget class="QCheckBox" name="include_hr"> <widget class="QCheckBox" name="include_hr">
<property name="toolTip"> <property name="toolTip">
<string>Separate Comments and additional content with 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>&amp;Separator</string>

View File

@ -470,6 +470,7 @@ class CatalogBuilder(object):
return self.__output_profile.empty_ratings_char return self.__output_profile.empty_ratings_char
return property(fget=fget) return property(fget=fget)
@dynamic_property @dynamic_property
def READ_PROGRESS_SYMBOL(self): def READ_PROGRESS_SYMBOL(self):
def fget(self): def fget(self):
return "&#9642;" if self.generateForKindle else '+' return "&#9642;" if self.generateForKindle else '+'
@ -672,7 +673,7 @@ Author '{0}':
for record in data: for record in data:
matched = list(set(record['tags']) & set(exclude_tags)) matched = list(set(record['tags']) & set(exclude_tags))
if matched : if matched :
self.opts.log.info(" - %s (Exclusion rule %s)" % (record['title'], matched)) self.opts.log.info(" - %s (Exclusion rule Tags: '%s')" % (record['title'], str(matched[0])))
search_phrase = '' search_phrase = ''
if exclude_tags: if exclude_tags:
@ -4038,7 +4039,9 @@ Author '{0}':
if re.search(pat, unicode(field_contents), if re.search(pat, unicode(field_contents),
re.IGNORECASE) is not None: re.IGNORECASE) is not None:
if self.opts.verbose: if self.opts.verbose:
self.opts.log.info(" excluding '%s' (%s:%s)" % (record['title'], field, pat)) field_md = self.db.metadata_for_field(field)
self.opts.log.info(" - %s (Exclusion rule '%s': %s:%s)" %
(record['title'], field_md['name'], field,pat))
exclusion_set.append(record) exclusion_set.append(record)
if record in filtered_data_set: if record in filtered_data_set:
filtered_data_set.remove(record) filtered_data_set.remove(record)