mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
exclusion_rules_table added
This commit is contained in:
parent
3b5fd30b0a
commit
24aab4fb57
@ -38,7 +38,7 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
self._initControlArrays()
|
self._initControlArrays()
|
||||||
|
|
||||||
def _initControlArrays(self):
|
def _initControlArrays(self):
|
||||||
|
# Default values for controls
|
||||||
CheckBoxControls = []
|
CheckBoxControls = []
|
||||||
ComboBoxControls = []
|
ComboBoxControls = []
|
||||||
DoubleSpinBoxControls = []
|
DoubleSpinBoxControls = []
|
||||||
@ -72,13 +72,27 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
|
|
||||||
# LineEditControls
|
# LineEditControls
|
||||||
option_fields += zip(['exclude_genre'],['\[.+\]|\+'],['line_edit'])
|
option_fields += zip(['exclude_genre'],['\[.+\]|\+'],['line_edit'])
|
||||||
option_fields += zip(['exclude_pattern'],[None],['line_edit'])
|
#***option_fields += zip(['exclude_pattern'],[None],['line_edit'])
|
||||||
option_fields += zip(['exclude_tags'],['~,'+_('Catalog')],['line_edit'])
|
#***option_fields += zip(['exclude_tags'],['~,'+_('Catalog')],['line_edit'])
|
||||||
|
|
||||||
# SpinBoxControls
|
# SpinBoxControls
|
||||||
option_fields += zip(['thumb_width'],[1.00],['spin_box'])
|
option_fields += zip(['thumb_width'],[1.00],['spin_box'])
|
||||||
|
|
||||||
# Prefix rules TableWidget
|
# Exclusion rules
|
||||||
|
option_fields += zip(['exclusion_rules_tw','exclusion_rules_tw'],
|
||||||
|
[{'ordinal':0,
|
||||||
|
'enabled':True,
|
||||||
|
'name':'Catalogs',
|
||||||
|
'field':'Tags',
|
||||||
|
'pattern':'Catalog'},
|
||||||
|
{'ordinal':1,
|
||||||
|
'enabled':False,
|
||||||
|
'name':'New rule',
|
||||||
|
'field':'',
|
||||||
|
'pattern':''}],
|
||||||
|
['table_widget','table_widget'])
|
||||||
|
|
||||||
|
# Prefix rules
|
||||||
option_fields += zip(['prefix_rules_tw','prefix_rules_tw','prefix_rules_tw'],
|
option_fields += zip(['prefix_rules_tw','prefix_rules_tw','prefix_rules_tw'],
|
||||||
[{'ordinal':0,
|
[{'ordinal':0,
|
||||||
'enabled':True,
|
'enabled':True,
|
||||||
@ -123,13 +137,13 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
['exclude_source_field','header_note_source_field',
|
['exclude_source_field','header_note_source_field',
|
||||||
'merge_source_field']
|
'merge_source_field']
|
||||||
LineEditControls (c_type: line_edit):
|
LineEditControls (c_type: line_edit):
|
||||||
['exclude_genre','exclude_pattern','exclude_tags']
|
['exclude_genre']
|
||||||
RadioButtonControls (c_type: radio_button):
|
RadioButtonControls (c_type: radio_button):
|
||||||
['merge_before','merge_after']
|
['merge_before','merge_after']
|
||||||
SpinBoxControls (c_type: spin_box):
|
SpinBoxControls (c_type: spin_box):
|
||||||
['thumb_width']
|
['thumb_width']
|
||||||
TableWidgetControls (c_type: table_widget):
|
TableWidgetControls (c_type: table_widget):
|
||||||
['prefix_rules_tw']
|
['exclusion_rules_tw','prefix_rules_tw']
|
||||||
|
|
||||||
'''
|
'''
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -139,6 +153,7 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
|
|
||||||
|
|
||||||
# Update dialog fields from stored options
|
# Update dialog fields from stored options
|
||||||
|
exclusion_rules = []
|
||||||
prefix_rules = []
|
prefix_rules = []
|
||||||
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
|
||||||
@ -159,16 +174,22 @@ 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 opt_value not in exclusion_rules:
|
||||||
|
exclusion_rules.append(opt_value)
|
||||||
elif c_type in ['table_widget'] and c_name == 'prefix_rules_tw':
|
elif c_type in ['table_widget'] and 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)
|
||||||
|
|
||||||
|
'''
|
||||||
|
***
|
||||||
# Init self.exclude_source_field_name
|
# Init self.exclude_source_field_name
|
||||||
self.exclude_source_field_name = ''
|
self.exclude_source_field_name = ''
|
||||||
cs = unicode(self.exclude_source_field.currentText())
|
cs = unicode(self.exclude_source_field.currentText())
|
||||||
if cs > '':
|
if cs > '':
|
||||||
exclude_source_spec = self.exclude_source_fields[cs]
|
exclude_source_spec = self.exclude_source_fields[cs]
|
||||||
self.exclude_source_field_name = exclude_source_spec['field']
|
self.exclude_source_field_name = exclude_source_spec['field']
|
||||||
|
'''
|
||||||
|
|
||||||
# Init self.merge_source_field_name
|
# Init self.merge_source_field_name
|
||||||
self.merge_source_field_name = ''
|
self.merge_source_field_name = ''
|
||||||
@ -190,10 +211,13 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
# Hook changes to Description section
|
# Hook changes to Description section
|
||||||
self.generate_descriptions.stateChanged.connect(self.generate_descriptions_changed)
|
self.generate_descriptions.stateChanged.connect(self.generate_descriptions_changed)
|
||||||
|
|
||||||
|
# Initialize exclusion rules
|
||||||
|
self.exclusion_rules_table = ExclusionRules(self.exclusion_rules_gb_hl,
|
||||||
|
"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, "prefix_rules_tw",
|
self.prefix_rules_table = PrefixRules(self.prefix_rules_gb_hl,
|
||||||
prefix_rules, self.eligible_custom_fields,
|
"prefix_rules_tw",prefix_rules, self.eligible_custom_fields,self.db)
|
||||||
self.db)
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
# Save/return the current options
|
# Save/return the current options
|
||||||
@ -204,6 +228,8 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
opts_dict = {}
|
opts_dict = {}
|
||||||
# Save values to gprefs
|
# Save values to gprefs
|
||||||
prefix_rules_processed = False
|
prefix_rules_processed = False
|
||||||
|
exclusion_rules_processed = False
|
||||||
|
|
||||||
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_type in ['check_box', 'radio_button']:
|
if c_type in ['check_box', 'radio_button']:
|
||||||
@ -215,7 +241,10 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
elif c_type in ['spin_box']:
|
elif c_type in ['spin_box']:
|
||||||
opt_value = unicode(getattr(self, c_name).value())
|
opt_value = unicode(getattr(self, c_name).value())
|
||||||
elif c_type in ['table_widget']:
|
elif c_type in ['table_widget']:
|
||||||
opt_value = self.prefix_rules_table.get_data()
|
if c_name == 'prefix_rules_tw':
|
||||||
|
opt_value = self.prefix_rules_table.get_data()
|
||||||
|
if c_name == 'exclusion_rules_tw':
|
||||||
|
opt_value = self.exclusion_rules_table.get_data()
|
||||||
|
|
||||||
gprefs.set(self.name + '_' + c_name, opt_value)
|
gprefs.set(self.name + '_' + c_name, opt_value)
|
||||||
|
|
||||||
@ -246,19 +275,49 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
|
|
||||||
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
|
prefix_rules_processed = True
|
||||||
|
|
||||||
|
elif c_name == 'exclusion_rules_tw':
|
||||||
|
if exclusion_rules_processed:
|
||||||
|
continue
|
||||||
|
rule_set = []
|
||||||
|
for rule in opt_value:
|
||||||
|
# Test for empty name/field/pattern/prefix, continue
|
||||||
|
# If pattern = any or unspecified, convert to regex
|
||||||
|
if not rule['enabled']:
|
||||||
|
continue
|
||||||
|
elif not rule['field'] or not rule['pattern']:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if rule['field'] != 'Tags':
|
||||||
|
# Look up custom column name
|
||||||
|
#print(self.eligible_custom_fields[rule['field']]['field'])
|
||||||
|
rule['field'] = self.eligible_custom_fields[rule['field']]['field']
|
||||||
|
if rule['pattern'].startswith('any'):
|
||||||
|
rule['pattern'] = '.*'
|
||||||
|
elif rule['pattern'] == 'unspecified':
|
||||||
|
rule['pattern'] = 'None'
|
||||||
|
|
||||||
|
pr = (rule['name'],rule['field'],rule['pattern'])
|
||||||
|
rule_set.append(pr)
|
||||||
|
|
||||||
|
opt_value = tuple(rule_set)
|
||||||
|
opts_dict['exclusion_rules'] = opt_value
|
||||||
|
exclusion_rules_processed = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
opts_dict[c_name] = opt_value
|
opts_dict[c_name] = opt_value
|
||||||
|
|
||||||
|
'''
|
||||||
|
***
|
||||||
# Generate markers for hybrids
|
# Generate markers for hybrids
|
||||||
#opts_dict['read_book_marker'] = "%s:%s" % (self.read_source_field_name,
|
#opts_dict['read_book_marker'] = "%s:%s" % (self.read_source_field_name,
|
||||||
# self.read_pattern.text())
|
# self.read_pattern.text())
|
||||||
opts_dict['exclude_book_marker'] = "%s:%s" % (self.exclude_source_field_name,
|
opts_dict['exclude_book_marker'] = "%s:%s" % (self.exclude_source_field_name,
|
||||||
self.exclude_pattern.text())
|
self.exclude_pattern.text())
|
||||||
|
'''
|
||||||
|
|
||||||
# Generate specs for merge_comments, header_note_source_field
|
# Generate specs for merge_comments, header_note_source_field
|
||||||
checked = ''
|
checked = ''
|
||||||
@ -306,6 +365,8 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
if field_md['datatype'] in ['bool','composite','datetime','enumeration','text']:
|
if field_md['datatype'] in ['bool','composite','datetime','enumeration','text']:
|
||||||
custom_fields[field_md['name']] = {'field':custom_field,
|
custom_fields[field_md['name']] = {'field':custom_field,
|
||||||
'datatype':field_md['datatype']}
|
'datatype':field_md['datatype']}
|
||||||
|
'''
|
||||||
|
***
|
||||||
# Blank field first
|
# Blank field first
|
||||||
self.exclude_source_field.addItem('')
|
self.exclude_source_field.addItem('')
|
||||||
# Add the sorted eligible fields to the combo box
|
# Add the sorted eligible fields to the combo box
|
||||||
@ -313,7 +374,7 @@ class PluginWidget(QWidget,Ui_Form):
|
|||||||
self.exclude_source_field.addItem(cf)
|
self.exclude_source_field.addItem(cf)
|
||||||
self.exclude_source_fields = custom_fields
|
self.exclude_source_fields = custom_fields
|
||||||
self.exclude_source_field.currentIndexChanged.connect(self.exclude_source_field_changed)
|
self.exclude_source_field.currentIndexChanged.connect(self.exclude_source_field_changed)
|
||||||
|
'''
|
||||||
|
|
||||||
# Populate the 'Header note' combo box
|
# Populate the 'Header note' combo box
|
||||||
custom_fields = {}
|
custom_fields = {}
|
||||||
@ -488,7 +549,7 @@ class NoWheelComboBox(QComboBox):
|
|||||||
# Disable the mouse wheel on top of the combo box changing selection as plays havoc in a grid
|
# Disable the mouse wheel on top of the combo box changing selection as plays havoc in a grid
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
class PrefixRulesComboBox(NoWheelComboBox):
|
class ComboBox(NoWheelComboBox):
|
||||||
# Caller is responsible for providing the list in the preferred order
|
# Caller is responsible for providing the list in the preferred order
|
||||||
def __init__(self, parent, items, selected_text,insert_blank=True):
|
def __init__(self, parent, items, selected_text,insert_blank=True):
|
||||||
NoWheelComboBox.__init__(self, parent)
|
NoWheelComboBox.__init__(self, parent)
|
||||||
@ -511,8 +572,8 @@ 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, prefix_rules, eligible_custom_fields, db):
|
def __init__(self, parent_gb_hl, object_name, rules, eligible_custom_fields, db):
|
||||||
self.prefix_rules = prefix_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)
|
||||||
@ -525,12 +586,11 @@ class GenericRulesTable(QTableWidget):
|
|||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
|
||||||
self.setSizePolicy(sizePolicy)
|
self.setSizePolicy(sizePolicy)
|
||||||
self.setMaximumSize(QSize(16777215, 118))
|
self.setMaximumSize(QSize(16777215, 114))
|
||||||
self.setColumnCount(0)
|
self.setColumnCount(0)
|
||||||
self.setRowCount(0)
|
self.setRowCount(0)
|
||||||
self.layout.addWidget(self)
|
self.layout.addWidget(self)
|
||||||
|
|
||||||
|
|
||||||
self._init_table_widget()
|
self._init_table_widget()
|
||||||
self._init_controls()
|
self._init_controls()
|
||||||
self._initialize()
|
self._initialize()
|
||||||
@ -686,10 +746,138 @@ class GenericRulesTable(QTableWidget):
|
|||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def resize_name(self, scale):
|
||||||
|
current_width = self.columnWidth(1)
|
||||||
|
self.setColumnWidth(1, min(225,int(current_width * scale)))
|
||||||
|
|
||||||
|
def rule_name_edited(self):
|
||||||
|
current_row = self.currentRow()
|
||||||
|
self.cellWidget(current_row,1).home(False)
|
||||||
|
self.setFocus()
|
||||||
|
self.select_and_scroll_to_row(current_row)
|
||||||
|
|
||||||
|
def select_and_scroll_to_row(self, row):
|
||||||
|
self.selectRow(row)
|
||||||
|
self.scrollToItem(self.currentItem())
|
||||||
|
|
||||||
|
class ExclusionRules(GenericRulesTable):
|
||||||
|
|
||||||
|
def _init_table_widget(self):
|
||||||
|
header_labels = ['','Name','Field','Value']
|
||||||
|
self.setColumnCount(len(header_labels))
|
||||||
|
self.setHorizontalHeaderLabels(header_labels)
|
||||||
|
self.setSortingEnabled(False)
|
||||||
|
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
|
||||||
|
def _initialize(self):
|
||||||
|
# Override max size (118) set in GenericRulesTable
|
||||||
|
self.setMaximumSize(QSize(16777215, 83))
|
||||||
|
|
||||||
|
self.populate()
|
||||||
|
self.resizeColumnsToContents()
|
||||||
|
self.resize_name(1.5)
|
||||||
|
self.horizontalHeader().setStretchLastSection(True)
|
||||||
|
|
||||||
|
def convert_row_to_data(self, row):
|
||||||
|
data = self.create_blank_row_data()
|
||||||
|
data['ordinal'] = row
|
||||||
|
data['enabled'] = self.item(row,0).checkState() == Qt.Checked
|
||||||
|
data['name'] = unicode(self.cellWidget(row,1).text()).strip()
|
||||||
|
data['field'] = unicode(self.cellWidget(row,2).currentText()).strip()
|
||||||
|
data['pattern'] = unicode(self.cellWidget(row,3).currentText()).strip()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def create_blank_row_data(self):
|
||||||
|
data = {}
|
||||||
|
data['ordinal'] = -1
|
||||||
|
data['enabled'] = False
|
||||||
|
data['name'] = 'New rule'
|
||||||
|
data['field'] = ''
|
||||||
|
data['pattern'] = ''
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
data_items = []
|
||||||
|
for row in range(self.rowCount()):
|
||||||
|
data = self.convert_row_to_data(row)
|
||||||
|
data_items.append(
|
||||||
|
{'ordinal':data['ordinal'],
|
||||||
|
'enabled':data['enabled'],
|
||||||
|
'name':data['name'],
|
||||||
|
'field':data['field'],
|
||||||
|
'pattern':data['pattern']})
|
||||||
|
return data_items
|
||||||
|
|
||||||
|
def populate(self):
|
||||||
|
# Format of rules list is different if default values vs retrieved JSON
|
||||||
|
# Hack to normalize list style
|
||||||
|
rules = self.rules
|
||||||
|
if rules and type(rules[0]) is list:
|
||||||
|
rules = rules[0]
|
||||||
|
self.setFocus()
|
||||||
|
rules = sorted(rules, key=lambda k: k['ordinal'])
|
||||||
|
for row, rule in enumerate(rules):
|
||||||
|
self.insertRow(row)
|
||||||
|
self.select_and_scroll_to_row(row)
|
||||||
|
self.populate_table_row(row, rule)
|
||||||
|
self.selectRow(0)
|
||||||
|
|
||||||
|
def populate_table_row(self, row, data):
|
||||||
|
|
||||||
|
def set_rule_name_in_row(row, col, name=''):
|
||||||
|
rule_name = QLineEdit(name)
|
||||||
|
rule_name.home(False)
|
||||||
|
rule_name.editingFinished.connect(self.rule_name_edited)
|
||||||
|
self.setCellWidget(row, col, rule_name)
|
||||||
|
|
||||||
|
def set_source_field_in_row(row, col, field=''):
|
||||||
|
source_combo = ComboBox(self, sorted(self.eligible_custom_fields.keys(), key=sort_key), field)
|
||||||
|
source_combo.currentIndexChanged.connect(partial(self.source_index_changed, source_combo, row))
|
||||||
|
self.setCellWidget(row, col, source_combo)
|
||||||
|
return source_combo
|
||||||
|
|
||||||
|
# Entry point
|
||||||
|
self.blockSignals(True)
|
||||||
|
|
||||||
|
# Column 0: Enabled
|
||||||
|
self.setItem(row, 0, CheckableTableWidgetItem(data['enabled']))
|
||||||
|
|
||||||
|
# Column 1: Rule name
|
||||||
|
set_rule_name_in_row(row, 1, name=data['name'])
|
||||||
|
|
||||||
|
# Column 2: Source field
|
||||||
|
source_combo = set_source_field_in_row(row, 2, field=data['field'])
|
||||||
|
|
||||||
|
# Column 3: Pattern
|
||||||
|
# The contents of the Pattern field is driven by the Source field
|
||||||
|
self.source_index_changed(source_combo, row, 3, pattern=data['pattern'])
|
||||||
|
|
||||||
|
self.blockSignals(False)
|
||||||
|
|
||||||
|
def source_index_changed(self, combo, row, col, pattern=''):
|
||||||
|
# Populate the Pattern field based upon the Source field
|
||||||
|
source_field = str(combo.currentText())
|
||||||
|
if source_field == '':
|
||||||
|
values = []
|
||||||
|
elif source_field == 'Tags':
|
||||||
|
values = sorted(self.db.all_tags(), key=sort_key)
|
||||||
|
else:
|
||||||
|
if self.eligible_custom_fields[source_field]['datatype'] in ['enumeration', 'text']:
|
||||||
|
values = self.db.all_custom(self.db.field_metadata.key_to_label(
|
||||||
|
self.eligible_custom_fields[source_field]['field']))
|
||||||
|
values = sorted(values, key=sort_key)
|
||||||
|
elif self.eligible_custom_fields[source_field]['datatype'] in ['bool']:
|
||||||
|
values = ['True','False','unspecified']
|
||||||
|
elif self.eligible_custom_fields[source_field]['datatype'] in ['composite']:
|
||||||
|
values = ['any value','unspecified']
|
||||||
|
|
||||||
|
values_combo = ComboBox(self, values, pattern)
|
||||||
|
self.setCellWidget(row, 3, values_combo)
|
||||||
|
|
||||||
class PrefixRules(GenericRulesTable):
|
class PrefixRules(GenericRulesTable):
|
||||||
|
|
||||||
def _init_table_widget(self):
|
def _init_table_widget(self):
|
||||||
header_labels = ['','Name','Prefix','Source','Pattern']
|
header_labels = ['','Name','Prefix','Field','Value']
|
||||||
self.setColumnCount(len(header_labels))
|
self.setColumnCount(len(header_labels))
|
||||||
self.setHorizontalHeaderLabels(header_labels)
|
self.setHorizontalHeaderLabels(header_labels)
|
||||||
self.setSortingEnabled(False)
|
self.setSortingEnabled(False)
|
||||||
@ -873,8 +1061,8 @@ class PrefixRules(GenericRulesTable):
|
|||||||
def populate(self):
|
def populate(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.prefix_rules
|
rules = self.rules
|
||||||
if type(rules[0]) is list:
|
if rules and type(rules[0]) is list:
|
||||||
rules = rules[0]
|
rules = rules[0]
|
||||||
self.setFocus()
|
self.setFocus()
|
||||||
rules = sorted(rules, key=lambda k: k['ordinal'])
|
rules = sorted(rules, key=lambda k: k['ordinal'])
|
||||||
@ -887,7 +1075,7 @@ class PrefixRules(GenericRulesTable):
|
|||||||
def populate_table_row(self, row, data):
|
def populate_table_row(self, row, data):
|
||||||
|
|
||||||
def set_prefix_field_in_row(row, col, field=''):
|
def set_prefix_field_in_row(row, col, field=''):
|
||||||
prefix_combo = PrefixRulesComboBox(self, self.prefix_list, field)
|
prefix_combo = ComboBox(self, self.prefix_list, field)
|
||||||
self.setCellWidget(row, col, prefix_combo)
|
self.setCellWidget(row, col, prefix_combo)
|
||||||
|
|
||||||
def set_rule_name_in_row(row, col, name=''):
|
def set_rule_name_in_row(row, col, name=''):
|
||||||
@ -897,7 +1085,7 @@ class PrefixRules(GenericRulesTable):
|
|||||||
self.setCellWidget(row, col, rule_name)
|
self.setCellWidget(row, col, rule_name)
|
||||||
|
|
||||||
def set_source_field_in_row(row, col, field=''):
|
def set_source_field_in_row(row, col, field=''):
|
||||||
source_combo = PrefixRulesComboBox(self, sorted(self.eligible_custom_fields.keys(), key=sort_key), field)
|
source_combo = ComboBox(self, sorted(self.eligible_custom_fields.keys(), key=sort_key), field)
|
||||||
source_combo.currentIndexChanged.connect(partial(self.source_index_changed, source_combo, row))
|
source_combo.currentIndexChanged.connect(partial(self.source_index_changed, source_combo, row))
|
||||||
self.setCellWidget(row, col, source_combo)
|
self.setCellWidget(row, col, source_combo)
|
||||||
return source_combo
|
return source_combo
|
||||||
@ -926,22 +1114,9 @@ class PrefixRules(GenericRulesTable):
|
|||||||
|
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
def resize_name(self, scale):
|
|
||||||
current_width = self.columnWidth(1)
|
|
||||||
self.setColumnWidth(1, min(225,int(current_width * scale)))
|
|
||||||
|
|
||||||
def rule_name_edited(self):
|
|
||||||
current_row = self.currentRow()
|
|
||||||
self.cellWidget(current_row,1).home(False)
|
|
||||||
self.setFocus()
|
|
||||||
self.select_and_scroll_to_row(current_row)
|
|
||||||
|
|
||||||
def select_and_scroll_to_row(self, row):
|
|
||||||
self.selectRow(row)
|
|
||||||
self.scrollToItem(self.currentItem())
|
|
||||||
|
|
||||||
def source_index_changed(self, combo, row, col, pattern=''):
|
def source_index_changed(self, combo, row, col, pattern=''):
|
||||||
# Populate the Pattern field based upon the Source field
|
# Populate the Pattern field based upon the Source field
|
||||||
|
# row, col are the control that changed
|
||||||
|
|
||||||
source_field = str(combo.currentText())
|
source_field = str(combo.currentText())
|
||||||
if source_field == '':
|
if source_field == '':
|
||||||
@ -960,6 +1135,6 @@ class PrefixRules(GenericRulesTable):
|
|||||||
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']
|
||||||
|
|
||||||
values_combo = PrefixRulesComboBox(self, values, pattern)
|
values_combo = ComboBox(self, values, pattern)
|
||||||
self.setCellWidget(row, 4, values_combo)
|
self.setCellWidget(row, 4, values_combo)
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="excludedBooks">
|
<widget class="QGroupBox" name="exclusion_rules_gb">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -198,130 +198,14 @@ p, li { white-space: pre-wrap; }
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Books matching either pattern will not be included in generated catalog. </string>
|
<string>Matching books will not be included in generated catalog. </string>
|
||||||
</property>
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Excluded books</string>
|
<string>Excluded books</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<property name="fieldGrowthPolicy">
|
<item>
|
||||||
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
<layout class="QHBoxLayout" name="exclusion_rules_gb_hl"/>
|
||||||
</property>
|
|
||||||
<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>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>exclude_tags</cstring>
|
|
||||||
</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><p>Comma-separated list of tags to exclude.
|
|
||||||
Default: ~,Catalog</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>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>exclude_source_field</cstring>
|
|
||||||
</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 additional 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>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@ -335,7 +219,7 @@ Default: ~,Catalog</string>
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>The first matching rule will be used to add a prefix to book listings in the generated catalog.</string>
|
<string>The earliest 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>
|
||||||
@ -369,9 +253,9 @@ Default: ~,Catalog</string>
|
|||||||
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_10">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>175</width>
|
<width>175</width>
|
||||||
@ -385,16 +269,13 @@ Default: ~,Catalog</string>
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Thumbnail width</string>
|
<string>&Thumb width</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>thumb_width</cstring>
|
<cstring>merge_source_field</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -406,6 +287,12 @@ Default: ~,Catalog</string>
|
|||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>137</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Size hint for Description cover thumbnails</string>
|
<string>Size hint for Description cover thumbnails</string>
|
||||||
</property>
|
</property>
|
||||||
@ -426,38 +313,17 @@ Default: ~,Catalog</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" colspan="2">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="Line" name="line_3">
|
||||||
<property name="sizePolicy">
|
<property name="orientation">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<enum>Qt::Vertical</enum>
|
||||||
<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="toolTip">
|
|
||||||
<string/>
|
|
||||||
</property>
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Description note</string>
|
<string>&Extra note</string>
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>header_note_source_field</cstring>
|
<cstring>header_note_source_field</cstring>
|
||||||
@ -478,6 +344,12 @@ Default: ~,Catalog</string>
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</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 note to include in Description header area</string>
|
||||||
</property>
|
</property>
|
||||||
@ -485,7 +357,7 @@ Default: ~,Catalog</string>
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="2">
|
<item row="1" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="label_9">
|
||||||
|
@ -48,29 +48,13 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
Option('--exclude-genre',
|
Option('--exclude-genre',
|
||||||
default='\[.+\]',
|
default='\[.+\]|\+',
|
||||||
dest='exclude_genre',
|
dest='exclude_genre',
|
||||||
action = None,
|
action = None,
|
||||||
help=_("Regex describing tags to exclude as genres.\n" "Default: '%default' excludes bracketed tags, e.g. '[<tag>]'\n"
|
help=_("Regex describing tags to exclude as genres.\n"
|
||||||
|
"Default: '%default' excludes bracketed tags, e.g. '[Project Gutenberg]', and '+', the default tag for read books.\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
|
|
||||||
# Option('--exclude-book-marker',
|
|
||||||
# default=':',
|
|
||||||
# dest='exclude_book_marker',
|
|
||||||
# action = None,
|
|
||||||
# help=_("#<custom field>:pattern specifying custom field/contents indicating book should be excluded.\n"
|
|
||||||
# "For example: '#status:Archived' will exclude a book with a value of 'Archived' in the custom column 'status'.\n"
|
|
||||||
# "Default: '%default'\n"
|
|
||||||
# "Applies to ePub, MOBI output formats")),
|
|
||||||
# Option('--exclude-tags',
|
|
||||||
# default=('~,Catalog'),
|
|
||||||
# dest='exclude_tags',
|
|
||||||
# action = None,
|
|
||||||
# help=_("Comma-separated list of tag words indicating book should be excluded from output. "
|
|
||||||
# "For example: 'skip' will match 'skip this book' and 'Skip will like this'. "
|
|
||||||
# "Default:'%default'\n"
|
|
||||||
# "Applies to: ePub, MOBI output formats")),
|
|
||||||
|
|
||||||
Option('--exclusion-rules',
|
Option('--exclusion-rules',
|
||||||
default="(('Excluded tags','Tags','~,Catalog'),)",
|
default="(('Excluded tags','Tags','~,Catalog'),)",
|
||||||
dest='exclusion_rules',
|
dest='exclusion_rules',
|
||||||
|
@ -657,14 +657,36 @@ Author '{0}':
|
|||||||
|
|
||||||
# Merge opts.exclude_tags with opts.search_text
|
# Merge opts.exclude_tags with opts.search_text
|
||||||
# Updated to use exact match syntax
|
# Updated to use exact match syntax
|
||||||
empty_exclude_tags = False if len(self.opts.exclude_tags) else True
|
|
||||||
|
exclude_tags = []
|
||||||
|
for rule in self.opts.exclusion_rules:
|
||||||
|
if rule[1].lower() == 'tags':
|
||||||
|
exclude_tags.extend(rule[2].split(','))
|
||||||
|
|
||||||
|
# Remove dups
|
||||||
|
self.exclude_tags = exclude_tags = list(set(exclude_tags))
|
||||||
|
|
||||||
|
if self.opts.verbose and self.exclude_tags:
|
||||||
|
#self.opts.log.info(" excluding tag list %s" % exclude_tags)
|
||||||
|
search_terms = []
|
||||||
|
for tag in exclude_tags:
|
||||||
|
search_terms.append("tag:=%s" % tag)
|
||||||
|
search_phrase = "%s" % " or ".join(search_terms)
|
||||||
|
self.opts.search_text = search_phrase
|
||||||
|
data = self.plugin.search_sort_db(self.db, self.opts)
|
||||||
|
for record in data:
|
||||||
|
self.opts.log.info("\t- %s (Exclusion rule %s)" % (record['title'], exclude_tags))
|
||||||
|
# Reset the database
|
||||||
|
self.opts.search_text = ''
|
||||||
|
data = self.plugin.search_sort_db(self.db, self.opts)
|
||||||
|
|
||||||
search_phrase = ''
|
search_phrase = ''
|
||||||
if not empty_exclude_tags:
|
if exclude_tags:
|
||||||
exclude_tags = self.opts.exclude_tags.split(',')
|
|
||||||
search_terms = []
|
search_terms = []
|
||||||
for tag in exclude_tags:
|
for tag in exclude_tags:
|
||||||
search_terms.append("tag:=%s" % tag)
|
search_terms.append("tag:=%s" % tag)
|
||||||
search_phrase = "not (%s)" % " or ".join(search_terms)
|
search_phrase = "not (%s)" % " or ".join(search_terms)
|
||||||
|
|
||||||
# If a list of ids are provided, don't use search_text
|
# If a list of ids are provided, don't use search_text
|
||||||
if self.opts.ids:
|
if self.opts.ids:
|
||||||
self.opts.search_text = search_phrase
|
self.opts.search_text = search_phrase
|
||||||
@ -1672,14 +1694,13 @@ Author '{0}':
|
|||||||
|
|
||||||
self.opts.sort_by = 'series'
|
self.opts.sort_by = 'series'
|
||||||
|
|
||||||
# Merge opts.exclude_tags with opts.search_text
|
# Merge self.exclude_tags with opts.search_text
|
||||||
# Updated to use exact match syntax
|
# Updated to use exact match syntax
|
||||||
empty_exclude_tags = False if len(self.opts.exclude_tags) else True
|
|
||||||
search_phrase = 'series:true '
|
search_phrase = 'series:true '
|
||||||
if not empty_exclude_tags:
|
if self.exclude_tags:
|
||||||
exclude_tags = self.opts.exclude_tags.split(',')
|
|
||||||
search_terms = []
|
search_terms = []
|
||||||
for tag in exclude_tags:
|
for tag in self.exclude_tags:
|
||||||
search_terms.append("tag:=%s" % tag)
|
search_terms.append("tag:=%s" % tag)
|
||||||
search_phrase += "not (%s)" % " or ".join(search_terms)
|
search_phrase += "not (%s)" % " or ".join(search_terms)
|
||||||
|
|
||||||
@ -3120,7 +3141,7 @@ Author '{0}':
|
|||||||
Evaluate conditions for including prefixes in various listings
|
Evaluate conditions for including prefixes in various listings
|
||||||
'''
|
'''
|
||||||
def log_prefix_rule_match_info(rule, record):
|
def log_prefix_rule_match_info(rule, record):
|
||||||
self.opts.log.info(" %s %s by %s (Prefix rule '%s': %s:%s)" %
|
self.opts.log.info("\t%s %s by %s (Prefix rule '%s': %s:%s)" %
|
||||||
(rule['prefix'],record['title'],
|
(rule['prefix'],record['title'],
|
||||||
record['authors'][0], rule['name'],
|
record['authors'][0], rule['name'],
|
||||||
rule['field'],rule['pattern']))
|
rule['field'],rule['pattern']))
|
||||||
@ -3816,9 +3837,14 @@ Author '{0}':
|
|||||||
return friendly_tag
|
return friendly_tag
|
||||||
|
|
||||||
def getMarkerTags(self):
|
def getMarkerTags(self):
|
||||||
''' 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
|
||||||
|
exclusion_rules = ('name','Tags|#column','[]|pattern')
|
||||||
|
'''
|
||||||
markerTags = []
|
markerTags = []
|
||||||
markerTags.extend(self.opts.exclude_tags.split(','))
|
for rule in self.opts.exclusion_rules:
|
||||||
|
if rule[1].lower() == 'tags':
|
||||||
|
markerTags.extend(rule[2].split(','))
|
||||||
return markerTags
|
return markerTags
|
||||||
|
|
||||||
def letter_or_symbol(self,char):
|
def letter_or_symbol(self,char):
|
||||||
@ -3996,21 +4022,40 @@ Author '{0}':
|
|||||||
'''
|
'''
|
||||||
Remove excluded entries
|
Remove excluded entries
|
||||||
'''
|
'''
|
||||||
field, pat = self.opts.exclude_book_marker.split(':')
|
|
||||||
if pat == '':
|
|
||||||
return data_set
|
|
||||||
filtered_data_set = []
|
filtered_data_set = []
|
||||||
for record in data_set:
|
exclusion_pairs = []
|
||||||
field_contents = self.__db.get_field(record['id'],
|
exclusion_set = []
|
||||||
field,
|
for rule in self.opts.exclusion_rules:
|
||||||
index_is_id=True)
|
if rule[1].startswith('#') and rule[2] != '':
|
||||||
if field_contents:
|
field = rule[1]
|
||||||
if re.search(pat, unicode(field_contents),
|
pat = rule[2]
|
||||||
re.IGNORECASE) is not None:
|
exclusion_pairs.append((field,pat))
|
||||||
continue
|
else:
|
||||||
filtered_data_set.append(record)
|
continue
|
||||||
|
|
||||||
return filtered_data_set
|
if exclusion_pairs:
|
||||||
|
for record in data_set:
|
||||||
|
for exclusion_pair in exclusion_pairs:
|
||||||
|
field,pat = exclusion_pair
|
||||||
|
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:
|
||||||
|
if self.opts.verbose:
|
||||||
|
self.opts.log.info(" excluding '%s' (%s:%s)" % (record['title'], field, pat))
|
||||||
|
exclusion_set.append(record)
|
||||||
|
if record in filtered_data_set:
|
||||||
|
filtered_data_set.remove(record)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if (record not in filtered_data_set and
|
||||||
|
record not in exclusion_set):
|
||||||
|
filtered_data_set.append(record)
|
||||||
|
return filtered_data_set
|
||||||
|
else:
|
||||||
|
return data_set
|
||||||
|
|
||||||
def processSpecialTags(self, tags, this_title, opts):
|
def processSpecialTags(self, tags, this_title, opts):
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user