diff --git a/src/calibre/gui2/catalog/catalog_epub_mobi.py b/src/calibre/gui2/catalog/catalog_epub_mobi.py
index 8a2035c76f..57a23211e3 100644
--- a/src/calibre/gui2/catalog/catalog_epub_mobi.py
+++ b/src/calibre/gui2/catalog/catalog_epub_mobi.py
@@ -18,7 +18,7 @@ from PyQt4.Qt import (Qt, QAbstractItemView, QCheckBox, QComboBox, QDialog,
QDialogButtonBox, QDoubleSpinBox,
QHBoxLayout, QIcon, QLabel, QLineEdit,
QPlainTextEdit, QRadioButton, QSize, QSizePolicy,
- QTableWidget, QTableWidgetItem,
+ QTableWidget, QTableWidgetItem, QTimer,
QToolButton, QVBoxLayout, QWidget)
class PluginWidget(QWidget,Ui_Form):
@@ -72,8 +72,6 @@ class PluginWidget(QWidget,Ui_Form):
# LineEditControls
option_fields += zip(['exclude_genre'],['\[.+\]|\+'],['line_edit'])
- #***option_fields += zip(['exclude_pattern'],[None],['line_edit'])
- #***option_fields += zip(['exclude_tags'],['~,'+_('Catalog')],['line_edit'])
# SpinBoxControls
option_fields += zip(['thumb_width'],[1.00],['spin_box'])
@@ -84,12 +82,7 @@ class PluginWidget(QWidget,Ui_Form):
'enabled':True,
'name':'Catalogs',
'field':'Tags',
- 'pattern':'Catalog'},
- {'ordinal':1,
- 'enabled':False,
- 'name':'New rule',
- 'field':'',
- 'pattern':''}],
+ 'pattern':'Catalog'},],
['table_widget','table_widget'])
# Prefix rules
@@ -105,13 +98,7 @@ class PluginWidget(QWidget,Ui_Form):
'name':'Wishlist item',
'field':'Tags',
'pattern':'Wishlist',
- 'prefix':u'\u00d7'},
- {'ordinal':2,
- 'enabled':False,
- 'name':'New rule',
- 'field':'',
- 'pattern':'',
- 'prefix':''}],
+ 'prefix':u'\u00d7'},],
['table_widget','table_widget','table_widget'])
self.OPTION_FIELDS = option_fields
@@ -181,15 +168,9 @@ class PluginWidget(QWidget,Ui_Form):
if opt_value not in prefix_rules:
prefix_rules.append(opt_value)
- '''
- ***
- # Init self.exclude_source_field_name
- self.exclude_source_field_name = ''
- cs = unicode(self.exclude_source_field.currentText())
- if cs > '':
- exclude_source_spec = self.exclude_source_fields[cs]
- self.exclude_source_field_name = exclude_source_spec['field']
- '''
+ # Add icon to the reset button
+ self.reset_exclude_genres_tb.setIcon(QIcon(I('trash.png')))
+ self.reset_exclude_genres_tb.clicked.connect(self.reset_exclude_genres)
# Init self.merge_source_field_name
self.merge_source_field_name = ''
@@ -205,12 +186,6 @@ class PluginWidget(QWidget,Ui_Form):
header_note_source_spec = self.header_note_source_fields[cs]
self.header_note_source_field_name = header_note_source_spec['field']
- # Hook changes to thumb_width
- self.thumb_width.valueChanged.connect(self.thumb_width_changed)
-
- # Hook changes to Description section
- 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)
@@ -219,6 +194,13 @@ class PluginWidget(QWidget,Ui_Form):
self.prefix_rules_table = PrefixRules(self.prefix_rules_gb_hl,
"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):
# Save/return the current options
# exclude_genre stores literally
@@ -310,15 +292,6 @@ class PluginWidget(QWidget,Ui_Form):
else:
opts_dict[c_name] = opt_value
- '''
- ***
- # Generate markers for hybrids
- #opts_dict['read_book_marker'] = "%s:%s" % (self.read_source_field_name,
- # self.read_pattern.text())
- opts_dict['exclude_book_marker'] = "%s:%s" % (self.exclude_source_field_name,
- self.exclude_pattern.text())
- '''
-
# Generate specs for merge_comments, header_note_source_field
checked = ''
if self.merge_before.isChecked():
@@ -365,17 +338,6 @@ class PluginWidget(QWidget,Ui_Form):
if field_md['datatype'] in ['bool','composite','datetime','enumeration','text']:
custom_fields[field_md['name']] = {'field':custom_field,
'datatype':field_md['datatype']}
- '''
- ***
- # Blank field first
- self.exclude_source_field.addItem('')
- # Add the sorted eligible fields to the combo box
- for cf in sorted(custom_fields, key=sort_key):
- self.exclude_source_field.addItem(cf)
- self.exclude_source_fields = custom_fields
- self.exclude_source_field.currentIndexChanged.connect(self.exclude_source_field_changed)
- '''
-
# Populate the 'Header note' combo box
custom_fields = {}
for custom_field in self.all_custom_fields:
@@ -508,6 +470,12 @@ class PluginWidget(QWidget,Ui_Form):
self.merge_after.setEnabled(False)
self.include_hr.setEnabled(False)
+ def reset_exclude_genres(self):
+ for default in self.OPTION_FIELDS:
+ if default[0] == 'exclude_genre':
+ self.exclude_genre.setText(default[1])
+ break
+
def thumb_width_changed(self,new_value):
'''
Process changes in the thumb_width spin box
@@ -581,19 +549,20 @@ class GenericRulesTable(QTableWidget):
self.layout = parent_gb_hl
# Add ourselves to the layout
- sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
+ #print("verticalHeader: %s" % dir(self.verticalHeader()))
+ sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
+ #sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
self.setSizePolicy(sizePolicy)
- self.setMaximumSize(QSize(16777215, 114))
+ self.setMaximumSize(QSize(16777215, 113))
+
self.setColumnCount(0)
self.setRowCount(0)
+
self.layout.addWidget(self)
- self._init_table_widget()
self._init_controls()
- self._initialize()
def _init_controls(self):
# Add the control set
@@ -628,18 +597,6 @@ class GenericRulesTable(QTableWidget):
self.layout.addLayout(vbl)
- def _init_table_widget(self):
- '''
- Override this in the specific instance
- '''
- pass
-
- def _initialize(self):
- '''
- Override this in the specific instance
- '''
- pass
-
def add_row(self):
self.setFocus()
row = self.currentRow() + 1
@@ -683,6 +640,10 @@ class GenericRulesTable(QTableWidget):
def get_data(self):
pass
+ def focusOutEvent(self,e):
+ # Override of QTableWidget method
+ self.clearSelection()
+
def move_row_down(self):
self.setFocus()
rows = self.selectionModel().selectedRows()
@@ -760,8 +721,21 @@ class GenericRulesTable(QTableWidget):
self.selectRow(row)
self.scrollToItem(self.currentItem())
+ def tweak_height(self, height=4):
+ for i in range(min(3,self.rowCount())):
+ height += self.rowHeight(i)
+ height += self.verticalHeader().sizeHint().height()
+ print("computed table height for %d rows: %d" % (self.rowCount(),height, ))
+ self.setMinimumSize(QSize(16777215, height))
+ self.setMaximumSize(QSize(16777215, height))
+
class ExclusionRules(GenericRulesTable):
+ def __init__(self, parent_gb_hl, object_name, rules, eligible_custom_fields, db):
+ super(ExclusionRules, self).__init__(parent_gb_hl, object_name, rules, eligible_custom_fields, db)
+ self._init_table_widget()
+ self._initialize()
+
def _init_table_widget(self):
header_labels = ['','Name','Field','Value']
self.setColumnCount(len(header_labels))
@@ -770,13 +744,11 @@ class ExclusionRules(GenericRulesTable):
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)
+ self.clearSelection()
def convert_row_to_data(self, row):
data = self.create_blank_row_data()
@@ -790,7 +762,7 @@ class ExclusionRules(GenericRulesTable):
def create_blank_row_data(self):
data = {}
data['ordinal'] = -1
- data['enabled'] = False
+ data['enabled'] = True
data['name'] = 'New rule'
data['field'] = ''
data['pattern'] = ''
@@ -876,6 +848,11 @@ class ExclusionRules(GenericRulesTable):
class PrefixRules(GenericRulesTable):
+ def __init__(self, parent_gb_hl, object_name, rules, eligible_custom_fields, db):
+ super(PrefixRules, self).__init__(parent_gb_hl, object_name, rules, eligible_custom_fields, db)
+ self._init_table_widget()
+ self._initialize()
+
def _init_table_widget(self):
header_labels = ['','Name','Prefix','Field','Value']
self.setColumnCount(len(header_labels))
@@ -889,6 +866,7 @@ class PrefixRules(GenericRulesTable):
self.resizeColumnsToContents()
self.resize_name(1.5)
self.horizontalHeader().setStretchLastSection(True)
+ self.clearSelection()
def convert_row_to_data(self, row):
data = self.create_blank_row_data()
@@ -903,7 +881,7 @@ class PrefixRules(GenericRulesTable):
def create_blank_row_data(self):
data = {}
data['ordinal'] = -1
- data['enabled'] = False
+ data['enabled'] = True
data['name'] = 'New rule'
data['field'] = ''
data['pattern'] = ''
diff --git a/src/calibre/gui2/catalog/catalog_epub_mobi.ui b/src/calibre/gui2/catalog/catalog_epub_mobi.ui
index 29ca39bf10..784806c15e 100644
--- a/src/calibre/gui2/catalog/catalog_epub_mobi.ui
+++ b/src/calibre/gui2/catalog/catalog_epub_mobi.ui
@@ -111,7 +111,8 @@
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Project Gutenberg], and '+', the default tag for a read book.</p></body></html>
+<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>
Excluded genres
@@ -178,6 +179,16 @@ p, li { white-space: pre-wrap; }
+ -
+
+
+ Reset to default
+
+
+ ...
+
+
+
diff --git a/src/calibre/library/catalogs/epub_mobi_builder.py b/src/calibre/library/catalogs/epub_mobi_builder.py
index 111ceda9fe..63fe02d5f1 100644
--- a/src/calibre/library/catalogs/epub_mobi_builder.py
+++ b/src/calibre/library/catalogs/epub_mobi_builder.py
@@ -666,19 +666,13 @@ Author '{0}':
# Remove dups
self.exclude_tags = exclude_tags = list(set(exclude_tags))
+ # Report tag exclusions
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)
+ data = self.db.get_data_as_dict(ids=self.opts.ids)
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)
+ matched = list(set(record['tags']) & set(exclude_tags))
+ if matched :
+ self.opts.log.info(" - %s (Exclusion rule %s)" % (record['title'], matched))
search_phrase = ''
if exclude_tags:
@@ -3141,7 +3135,7 @@ Author '{0}':
Evaluate conditions for including prefixes in various listings
'''
def log_prefix_rule_match_info(rule, record):
- self.opts.log.info("\t%s %s by %s (Prefix rule '%s': %s:%s)" %
+ self.opts.log.info(" %s %s by %s (Prefix rule '%s': %s:%s)" %
(rule['prefix'],record['title'],
record['authors'][0], rule['name'],
rule['field'],rule['pattern']))