refactoring of catalog building code wip

This commit is contained in:
GRiker 2012-08-31 03:31:24 -06:00
parent 47119d6f42
commit d4027a8230
3 changed files with 3380 additions and 2639 deletions

View File

@ -6,7 +6,8 @@ __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 import re, sys
from functools import partial from functools import partial
from calibre.ebooks.conversion.config import load_defaults from calibre.ebooks.conversion.config import load_defaults
@ -16,7 +17,7 @@ from calibre.utils.icu import sort_key
from catalog_epub_mobi_ui import Ui_Form from catalog_epub_mobi_ui import Ui_Form
from PyQt4.Qt import (Qt, QAbstractItemView, QCheckBox, QComboBox, from PyQt4.Qt import (Qt, QAbstractItemView, QCheckBox, QComboBox,
QDoubleSpinBox, QIcon, QLineEdit, QObject, QRadioButton, QSize, QSizePolicy, QDoubleSpinBox, QIcon, QLineEdit, QObject, QRadioButton, QSize, QSizePolicy,
QTableWidget, QTableWidgetItem, QToolButton, QVBoxLayout, QWidget, QTableWidget, QTableWidgetItem, QTextEdit, QToolButton, QVBoxLayout, QWidget,
SIGNAL) SIGNAL)
class PluginWidget(QWidget,Ui_Form): class PluginWidget(QWidget,Ui_Form):
@ -44,6 +45,7 @@ class PluginWidget(QWidget,Ui_Form):
LineEditControls = [] LineEditControls = []
RadioButtonControls = [] RadioButtonControls = []
TableWidgetControls = [] TableWidgetControls = []
TextEditControls = []
for item in self.__dict__: for item in self.__dict__:
if type(self.__dict__[item]) is QCheckBox: if type(self.__dict__[item]) is QCheckBox:
@ -58,6 +60,8 @@ class PluginWidget(QWidget,Ui_Form):
RadioButtonControls.append(str(self.__dict__[item].objectName())) RadioButtonControls.append(str(self.__dict__[item].objectName()))
elif type(self.__dict__[item]) is QTableWidget: elif type(self.__dict__[item]) is QTableWidget:
TableWidgetControls.append(str(self.__dict__[item].objectName())) TableWidgetControls.append(str(self.__dict__[item].objectName()))
elif type(self.__dict__[item]) is QTextEdit:
TextEditControls.append(str(self.__dict__[item].objectName()))
option_fields = zip(CheckBoxControls, option_fields = zip(CheckBoxControls,
[True for i in CheckBoxControls], [True for i in CheckBoxControls],
@ -71,21 +75,25 @@ 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_genre_results'],['excluded genres will appear here'],['line_edit'])
# TextEditControls
#option_fields += zip(['exclude_genre_results'],['excluded genres will appear here'],['text_edit'])
# SpinBoxControls # SpinBoxControls
option_fields += zip(['thumb_width'],[1.00],['spin_box']) option_fields += zip(['thumb_width'],[1.00],['spin_box'])
# Exclusion rules # Exclusion rules
option_fields += zip(['exclusion_rules_tw','exclusion_rules_tw'], option_fields += zip(['exclusion_rules_tw'],
[{'ordinal':0, [{'ordinal':0,
'enabled':True, 'enabled':True,
'name':'Catalogs', 'name':'Catalogs',
'field':'Tags', 'field':'Tags',
'pattern':'Catalog'},], 'pattern':'Catalog'},],
['table_widget','table_widget']) ['table_widget'])
# Prefix rules # Prefix rules
option_fields += zip(['prefix_rules_tw','prefix_rules_tw','prefix_rules_tw'], option_fields += zip(['prefix_rules_tw','prefix_rules_tw'],
[{'ordinal':0, [{'ordinal':0,
'enabled':True, 'enabled':True,
'name':'Read book', 'name':'Read book',
@ -98,7 +106,7 @@ class PluginWidget(QWidget,Ui_Form):
'field':'Tags', 'field':'Tags',
'pattern':'Wishlist', 'pattern':'Wishlist',
'prefix':u'\u00d7'},], 'prefix':u'\u00d7'},],
['table_widget','table_widget','table_widget']) ['table_widget','table_widget'])
self.OPTION_FIELDS = option_fields self.OPTION_FIELDS = option_fields
@ -110,20 +118,20 @@ class PluginWidget(QWidget,Ui_Form):
''' '''
rule_set = [] rule_set = []
for stored_rule in opt_value: for stored_rule in opt_value:
rule = copy(stored_rule) rule = stored_rule.copy()
# Skip disabled and incomplete rules # Skip disabled and incomplete rules
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']:
continue continue
elif 'prefix' in rule and not rule['prefix']: elif 'prefix' in rule and rule['prefix'] is None:
continue continue
else: else:
if rule['field'] != 'Tags': if rule['field'] != 'Tags':
# Look up custom column friendly name # Look up custom column friendly name
rule['field'] = self.eligible_custom_fields[rule['field']]['field'] rule['field'] = self.eligible_custom_fields[rule['field']]['field']
if rule['pattern'] in [_('any value'),_('any date')]: if rule['pattern'] in [_('any value'),_('any date')]:
rule['pattern'] = '.*' rule_pattern = '.*'
elif rule['pattern'] == _('unspecified'): elif rule['pattern'] == _('unspecified'):
rule['pattern'] = 'None' rule['pattern'] = 'None'
if 'prefix' in rule: if 'prefix' in rule:
@ -135,6 +143,48 @@ class PluginWidget(QWidget,Ui_Form):
# Strip off the trailing '_tw' # Strip off the trailing '_tw'
opts_dict[c_name[:-3]] = opt_value opts_dict[c_name[:-3]] = opt_value
def exclude_genre_changed(self, regex):
""" Dynamically compute excluded genres.
Run exclude_genre regex against db.all_tags() to show excluded tags.
PROVISIONAL CODE, NEEDS TESTING
Args:
regex (QLineEdit.text()): regex to compile, compute
Output:
self.exclude_genre_results (QLabel): updated to show tags to be excluded as genres
"""
if not regex:
self.exclude_genre_results.clear()
self.exclude_genre_results.setText(_('No genres will be excluded'))
return
results = _('Regex does not match any tags in database')
try:
pattern = re.compile((str(regex)))
except:
results = _("regex error: %s") % sys.exc_info()[1]
else:
excluded_tags = []
for tag in self.all_tags:
hit = pattern.search(tag)
if hit:
excluded_tags.append(hit.string)
if excluded_tags:
results = ', '.join(excluded_tags)
finally:
if self.DEBUG:
print(results)
self.exclude_genre_results.clear()
self.exclude_genre_results.setText(results)
def exclude_genre_reset(self):
for default in self.OPTION_FIELDS:
if default[0] == 'exclude_genre':
self.exclude_genre.setText(default[1])
break
def fetchEligibleCustomFields(self): def fetchEligibleCustomFields(self):
self.all_custom_fields = self.db.custom_field_keys() self.all_custom_fields = self.db.custom_field_keys()
custom_fields = {} custom_fields = {}
@ -163,10 +213,13 @@ class PluginWidget(QWidget,Ui_Form):
['thumb_width'] ['thumb_width']
TableWidgetControls (c_type: table_widget): TableWidgetControls (c_type: table_widget):
['exclusion_rules_tw','prefix_rules_tw'] ['exclusion_rules_tw','prefix_rules_tw']
TextEditControls (c_type: text_edit):
['exclude_genre_results']
''' '''
self.name = name self.name = name
self.db = db self.db = db
self.all_tags = db.all_tags()
self.fetchEligibleCustomFields() self.fetchEligibleCustomFields()
self.populate_combo_boxes() self.populate_combo_boxes()
@ -200,9 +253,12 @@ class PluginWidget(QWidget,Ui_Form):
if opt_value not in prefix_rules: if opt_value not in prefix_rules:
prefix_rules.append(opt_value) prefix_rules.append(opt_value)
# Add icon to the reset button # Add icon to the reset button, hook textChanged signal
self.reset_exclude_genres_tb.setIcon(QIcon(I('trash.png'))) self.reset_exclude_genres_tb.setIcon(QIcon(I('trash.png')))
self.reset_exclude_genres_tb.clicked.connect(self.reset_exclude_genres) self.reset_exclude_genres_tb.clicked.connect(self.exclude_genre_reset)
# Hook textChanged event for exclude_genre QLineEdit
self.exclude_genre.textChanged.connect(self.exclude_genre_changed)
# Init self.merge_source_field_name # Init self.merge_source_field_name
self.merge_source_field_name = '' self.merge_source_field_name = ''
@ -226,6 +282,9 @@ class PluginWidget(QWidget,Ui_Form):
self.prefix_rules_table = PrefixRules(self.prefix_rules_gb, 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)
# Initialize excluded genres preview
self.exclude_genre_changed(unicode(getattr(self, 'exclude_genre').text()).strip())
def options(self): def options(self):
# Save/return the current options # Save/return the current options
# exclude_genre stores literally # exclude_genre stores literally
@ -377,12 +436,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 reset_exclude_genres(self):
for default in self.OPTION_FIELDS:
if default[0] == 'exclude_genre':
self.exclude_genre.setText(default[1])
break
class CheckableTableWidgetItem(QTableWidgetItem): class CheckableTableWidgetItem(QTableWidgetItem):
''' '''
Borrowed from kiwidude Borrowed from kiwidude

View File

@ -41,151 +41,74 @@
<string>Included sections</string> <string>Included sections</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QCheckBox" name="generate_genres">
<property name="text">
<string>Books by &amp;Genre</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="generate_recently_added">
<property name="text">
<string>Recently &amp;Added</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="generate_descriptions">
<property name="text">
<string>&amp;Descriptions</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="generate_series">
<property name="text">
<string>Books by &amp;Series</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="generate_titles">
<property name="text">
<string>Books by &amp;Title</string>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="generate_authors"> <widget class="QCheckBox" name="generate_authors">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Books by Author</string> <string>&amp;Authors</string>
</property> </property>
<property name="checked"> <property name="checked">
<bool>false</bool> <bool>false</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2">
<widget class="QCheckBox" name="generate_titles">
<property name="text">
<string>&amp;Titles</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QCheckBox" name="generate_series">
<property name="text">
<string>&amp;Series</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="generate_genres">
<property name="text">
<string>&amp;Genres</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="generate_recently_added">
<property name="text">
<string>&amp;Recently Added</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QCheckBox" name="generate_descriptions">
<property name="text">
<string>&amp;Descriptions</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="excludedGenres"> <widget class="QGroupBox" name="prefix_rules_gb">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>A regular expression describing genres to be excluded from the generated catalog. Genres are derived from the tags applied to your books. <string>The first matching prefix rule applies a prefix to book listings in the generated catalog.</string>
The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book], and '+', the default tag for a read book.</string>
</property> </property>
<property name="title"> <property name="title">
<string>Excluded genres</string> <string>Prefixes</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
</property>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>-1</number>
</property>
<property name="leftMargin">
<number>0</number>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item> <item>
<widget class="QLabel" name="label"> <layout class="QHBoxLayout" name="horizontalLayout_6"/>
<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 &amp;exclude</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>exclude_genre</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="exclude_genre">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string extracomment="Default: \[[\w]*\]"/>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="reset_exclude_genres_tb">
<property name="toolTip">
<string>Reset to default</string>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -218,22 +141,148 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="prefix_rules_gb"> <widget class="QGroupBox" name="excludedGenres">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>The first matching prefix rule applies a prefix to book listings in the generated catalog.</string> <string>A regular expression describing genres to be excluded from the generated catalog. Genres are derived from the tags applied to your books.
The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book], and '+', the default tag for a read book.</string>
</property> </property>
<property name="title"> <property name="title">
<string>Prefixes</string> <string>Excluded genres</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_8"> <layout class="QGridLayout" name="gridLayout">
<item> <item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_6"/> <widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Tags to &amp;exclude (regex)</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>exclude_genre</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="exclude_genre">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string extracomment="Default: \[[\w]*\]"/>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="reset_exclude_genres_tb">
<property name="toolTip">
<string>Reset to default</string>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<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>Results of regex</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>exclude_genre</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="exclude_genre_results">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>List of tags that will be excluded as genres</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

File diff suppressed because it is too large Load Diff