Permit use of arbitrary category fields and grouped search terms in "similar searches". Permit changing the match kind.

This commit is contained in:
Charles Haley 2012-06-10 11:44:14 +02:00
parent 0ec404bce2
commit 3bbc1f1342
4 changed files with 74 additions and 30 deletions

View File

@ -26,40 +26,56 @@ class SimilarBooksAction(InterfaceAction):
(_('Books in this series'), 'books_in_series.png', 'series', (_('Books in this series'), 'books_in_series.png', 'series',
_('Alt+Shift+S')), _('Alt+Shift+S')),
(_('Books by this publisher'), 'publisher.png', 'publisher', _('Alt+P')), (_('Books by this publisher'), 'publisher.png', 'publisher', _('Alt+P')),
(_('Books with the same tags'), 'tags.png', 'tag', _('Alt+T')),]: (_('Books with the same tags'), 'tags.png', 'tags', _('Alt+T')),]:
ac = self.create_action(spec=(text, icon, None, shortcut), ac = self.create_action(spec=(text, icon, None, shortcut),
attr=target) attr=target)
m.addAction(ac) m.addAction(ac)
ac.triggered.connect(partial(self.show_similar_books, target)) ac.triggered.connect(partial(self.show_similar_books, target))
self.qaction.setMenu(m) self.qaction.setMenu(m)
def show_similar_books(self, type, *args): def show_similar_books(self, typ, *args):
search, join = [], ' '
idx = self.gui.library_view.currentIndex() idx = self.gui.library_view.currentIndex()
db = self.gui.library_view.model().db
if not idx.isValid(): if not idx.isValid():
return return
db = idx.model().db
row = idx.row() row = idx.row()
if type == 'series':
series = idx.model().db.series(row) # Get the parameters for this search
if series: col = db.prefs['similar_' + typ + '_search_key']
search = [db.prefs['similar_series_search_key'] + ':"'+series+'"'] match = db.prefs['similar_' + typ + '_match_kind']
elif type == 'publisher': if match == _('Match all'):
publisher = idx.model().db.publisher(row) join = ' and '
if publisher: else:
search = [db.prefs['similar_publisher_search_key'] + ':"'+publisher+'"'] join = ' or '
elif type == 'tag':
tags = idx.model().db.tags(row) # Get all the data for the current record
if tags: mi = db.get_metadata(row)
search = [db.prefs['similar_tags_search_key'] + ':"='+t+'"'
for t in tags.split(',')] # Get the definitive field name to use for this search. If the field
elif type in ('author', 'authors'): # is a grouped search term, the function returns the list of fields that
authors = idx.model().db.authors(row) # are to be searched, otherwise it returns the field name.
if authors: loc = db.field_metadata.search_term_to_field_key(icu_lower(col))
search = [db.prefs['similar_authors_search_key'] + if isinstance(loc, list):
':"='+a.strip().replace('|', ',')+'"' \ # Grouped search terms are a list of fields. Get all the values,
for a in authors.split(',')] # pruning duplicates
join = ' or ' val = set()
for f in loc:
v = mi.get(f, None)
if not v:
continue
if isinstance(v, list):
val.update(v)
else:
val.add(v)
else:
# Get the value of the requested field. Can be a list or a simple val
val = mi.get(col, None)
if not val:
return
if not isinstance(val, (list, set)):
val = [val]
search = [col + ':"='+t+'"' for t in val]
if search: if search:
self.gui.search.set_search_string(join.join(search), self.gui.search.set_search_string(join.join(search),
store_in_history=True) store_in_history=True)

View File

@ -71,6 +71,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.gst_value.update_items_cache(fl) self.gst_value.update_items_cache(fl)
self.fill_gst_box(select=None) self.fill_gst_box(select=None)
self.category_fields = fl
ml = [_('Match any'), _('Match all')]
r('similar_authors_match_kind', db.prefs, choices=ml)
r('similar_tags_match_kind', db.prefs, choices=ml)
r('similar_series_match_kind', db.prefs, choices=ml)
r('similar_publisher_match_kind', db.prefs, choices=ml)
self.set_similar_fields(initial=True) self.set_similar_fields(initial=True)
self.similar_authors_search_key.currentIndexChanged[int].connect(self.something_changed) self.similar_authors_search_key.currentIndexChanged[int].connect(self.something_changed)
self.similar_tags_search_key.currentIndexChanged[int].connect(self.something_changed) self.similar_tags_search_key.currentIndexChanged[int].connect(self.something_changed)
@ -107,7 +113,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
val = self.db.prefs[name] val = self.db.prefs[name]
field.blockSignals(True) field.blockSignals(True)
field.clear() field.clear()
choices = [first_item] choices = []
choices.extend(self.category_fields)
choices.extend(sorted(self.gst.keys(), key=sort_key)) choices.extend(sorted(self.gst.keys(), key=sort_key))
field.addItems(choices) field.addItems(choices)
dex = field.findText(val) dex = field.findText(val)

View File

@ -207,13 +207,14 @@ to be shown as user categories</string>
<string>What to search when searching similar books</string> <string>What to search when searching similar books</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_22"> <layout class="QGridLayout" name="gridLayout_22">
<item row="0" column="0" colspan="4"> <item row="0" column="0" colspan="6">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>&lt;p&gt;When you search for similar books by right clicking the book and selecting "Similar books...", <string>&lt;p&gt;When you search for similar books by right clicking the
book and selecting "Similar books...",
calibre constructs a search using the column lookup names defined below. calibre constructs a search using the column lookup names defined below.
By changing the lookup name to a grouped search term you can By changing the lookup name to a grouped search term you can
search multiple columns.&lt;/p&gt;</string> search multiple columns at once.&lt;/p&gt;</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -238,13 +239,17 @@ to be shown as user categories</string>
</widget> </widget>
</item> </item>
<item row="1" column="2"> <item row="1" column="2">
<widget class="QComboBox" name="opt_similar_authors_match_kind">
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_222"> <widget class="QLabel" name="label_222">
<property name="text"> <property name="text">
<string>Similar series: </string> <string>Similar series: </string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="3"> <item row="1" column="4">
<widget class="QComboBox" name="similar_series_search_key"> <widget class="QComboBox" name="similar_series_search_key">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -254,6 +259,10 @@ to be shown as user categories</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="5">
<widget class="QComboBox" name="opt_similar_series_match_kind">
</widget>
</item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_223"> <widget class="QLabel" name="label_223">
<property name="text"> <property name="text">
@ -266,16 +275,24 @@ to be shown as user categories</string>
</widget> </widget>
</item> </item>
<item row="2" column="2"> <item row="2" column="2">
<widget class="QComboBox" name="opt_similar_tags_match_kind">
</widget>
</item>
<item row="2" column="3">
<widget class="QLabel" name="label_224"> <widget class="QLabel" name="label_224">
<property name="text"> <property name="text">
<string>Similar publishers: </string> <string>Similar publishers: </string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="3"> <item row="2" column="4">
<widget class="QComboBox" name="similar_publisher_search_key"> <widget class="QComboBox" name="similar_publisher_search_key">
</widget> </widget>
</item> </item>
<item row="2" column="5">
<widget class="QComboBox" name="opt_similar_publisher_match_kind">
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -237,9 +237,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
defs['column_color_rules'] = [] defs['column_color_rules'] = []
defs['grouped_search_make_user_categories'] = [] defs['grouped_search_make_user_categories'] = []
defs['similar_authors_search_key'] = 'author' defs['similar_authors_search_key'] = 'author'
defs['similar_authors_match_kind'] = _('Match any')
defs['similar_publisher_search_key'] = 'publisher' defs['similar_publisher_search_key'] = 'publisher'
defs['similar_publisher_match_kind'] = _('Match any')
defs['similar_tags_search_key'] = 'tags' defs['similar_tags_search_key'] = 'tags'
defs['similar_tags_match_kind'] = _('Match all')
defs['similar_series_search_key'] = 'series' defs['similar_series_search_key'] = 'series'
defs['similar_series_match_kind'] = _('Match any')
# Migrate the bool tristate tweak # Migrate the bool tristate tweak
defs['bools_are_tristate'] = \ defs['bools_are_tristate'] = \