mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Permit use of arbitrary category fields and grouped search terms in "similar searches". Permit changing the match kind.
This commit is contained in:
parent
0ec404bce2
commit
3bbc1f1342
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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><p>When you search for similar books by right clicking the book and selecting "Similar books...",
|
<string><p>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.</p></string>
|
search multiple columns at once.</p></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>
|
||||||
|
@ -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'] = \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user