mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Improved focus handling for tables. Removed obsolete characters in profiles.py. Revised tool tips.
This commit is contained in:
parent
e40bd0164d
commit
1f2e84181f
@ -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
|
||||||
|
@ -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,12 +161,13 @@ 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 opt_value not in exclusion_rules:
|
if c_name == 'exclusion_rules_tw':
|
||||||
exclusion_rules.append(opt_value)
|
if opt_value not in exclusion_rules:
|
||||||
elif c_type in ['table_widget'] and c_name == 'prefix_rules_tw':
|
exclusion_rules.append(opt_value)
|
||||||
if opt_value not in prefix_rules:
|
if c_name == 'prefix_rules_tw':
|
||||||
prefix_rules.append(opt_value)
|
if opt_value not in prefix_rules:
|
||||||
|
prefix_rules.append(opt_value)
|
||||||
|
|
||||||
# Add icon to the reset button
|
# Add icon to the reset button
|
||||||
self.reset_exclude_genres_tb.setIcon(QIcon(I('trash.png')))
|
self.reset_exclude_genres_tb.setIcon(QIcon(I('trash.png')))
|
||||||
@ -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']:
|
||||||
@ -250,24 +248,22 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
# Look up custom column name
|
# Look up custom column name
|
||||||
#print(self.eligible_custom_fields[rule['field']]['field'])
|
#print(self.eligible_custom_fields[rule['field']]['field'])
|
||||||
rule['field'] = self.eligible_custom_fields[rule['field']]['field']
|
rule['field'] = self.eligible_custom_fields[rule['field']]['field']
|
||||||
if rule['pattern'].startswith('any'):
|
if rule['pattern'].startswith('any'):
|
||||||
rule['pattern'] = '.*'
|
rule['pattern'] = '.*'
|
||||||
elif rule['pattern'] == 'unspecified':
|
elif rule['pattern'] == 'unspecified':
|
||||||
rule['pattern'] = 'None'
|
rule['pattern'] = 'None'
|
||||||
|
|
||||||
pr = (rule['name'],rule['field'],rule['pattern'],rule['prefix'])
|
pr = (rule['name'],rule['field'],rule['pattern'],rule['prefix'])
|
||||||
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']:
|
||||||
@ -277,17 +273,15 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
# Look up custom column name
|
# Look up custom column name
|
||||||
#print(self.eligible_custom_fields[rule['field']]['field'])
|
#print(self.eligible_custom_fields[rule['field']]['field'])
|
||||||
rule['field'] = self.eligible_custom_fields[rule['field']]['field']
|
rule['field'] = self.eligible_custom_fields[rule['field']]['field']
|
||||||
if rule['pattern'].startswith('any'):
|
if rule['pattern'].startswith('any'):
|
||||||
rule['pattern'] = '.*'
|
rule['pattern'] = '.*'
|
||||||
elif rule['pattern'] == 'unspecified':
|
elif rule['pattern'] == 'unspecified':
|
||||||
rule['pattern'] = 'None'
|
rule['pattern'] = 'None'
|
||||||
|
|
||||||
pr = (rule['name'],rule['field'],rule['pattern'])
|
|
||||||
rule_set.append(pr)
|
|
||||||
|
|
||||||
|
pr = (rule['name'],rule['field'],rule['pattern'])
|
||||||
|
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)
|
||||||
|
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
<string>A regular expression describing genres to be excluded from the generated catalog. Genres are derived from the tags applied to your books.
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
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; }
|
|
||||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A regular expression describing genres to be excluded from the generated catalog. Genres are derived from the tags applied to your books.</p>
|
|
||||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Project Gutenberg], and '+', the default tag for a read book.</p></body></html></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>&Before</string>
|
<string>&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>&After</string>
|
<string>&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>&Separator</string>
|
<string>&Separator</string>
|
||||||
|
@ -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 "▪" if self.generateForKindle else '+'
|
return "▪" 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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user