mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Tag browser 'Find' improvements:
- Add exact match searching by using '=' as prefix, as in "=Science Fiction" - Add option to show only categories containing items, as if a '*' prefix had been used - Override the collapse option using a prefix of ':', as in :foo - Make Quickview use exact match searching when items are double-clicked
This commit is contained in:
parent
966d4303b1
commit
2ff634034e
@ -150,6 +150,7 @@ def create_defs():
|
|||||||
defs['ui_style'] = 'calibre' if iswindows or isosx else 'system'
|
defs['ui_style'] = 'calibre' if iswindows or isosx else 'system'
|
||||||
defs['tag_browser_old_look'] = False
|
defs['tag_browser_old_look'] = False
|
||||||
defs['tag_browser_hide_empty_categories'] = False
|
defs['tag_browser_hide_empty_categories'] = False
|
||||||
|
defs['tag_browser_always_autocollapse'] = False
|
||||||
defs['book_list_tooltips'] = True
|
defs['book_list_tooltips'] = True
|
||||||
defs['show_layout_buttons'] = False
|
defs['show_layout_buttons'] = False
|
||||||
defs['bd_show_cover'] = True
|
defs['bd_show_cover'] = True
|
||||||
|
@ -281,7 +281,7 @@ class Quickview(QDialog, Ui_Quickview):
|
|||||||
def item_doubleclicked(self, item):
|
def item_doubleclicked(self, item):
|
||||||
tb = self.gui.stack.tb_widget
|
tb = self.gui.stack.tb_widget
|
||||||
tb.set_focus_to_find_box()
|
tb.set_focus_to_find_box()
|
||||||
tb.item_search.lineEdit().setText(self.current_key + ':' + item.text())
|
tb.item_search.lineEdit().setText(self.current_key + ':=' + item.text())
|
||||||
tb.do_find()
|
tb.do_find()
|
||||||
|
|
||||||
def show_context_menu(self, point):
|
def show_context_menu(self, point):
|
||||||
|
@ -412,6 +412,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('row_numbers_in_book_list', gprefs)
|
r('row_numbers_in_book_list', gprefs)
|
||||||
r('tag_browser_old_look', gprefs)
|
r('tag_browser_old_look', gprefs)
|
||||||
r('tag_browser_hide_empty_categories', gprefs)
|
r('tag_browser_hide_empty_categories', gprefs)
|
||||||
|
r('tag_browser_always_autocollapse', gprefs)
|
||||||
r('tag_browser_show_tooltips', gprefs)
|
r('tag_browser_show_tooltips', gprefs)
|
||||||
r('bd_show_cover', gprefs)
|
r('bd_show_cover', gprefs)
|
||||||
r('bd_overlay_cover_size', gprefs)
|
r('bd_overlay_cover_size', gprefs)
|
||||||
|
@ -995,6 +995,18 @@ then the tags will be displayed each on their own line.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="13" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_tag_browser_always_autocollapse">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>When checked, Find in the Tag browser will show all items
|
||||||
|
that match the search instead of the first one. If Hide empty categories is
|
||||||
|
also checked then only categories containing a matched item will be shown.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Find &shows all items that match in the Tag browser</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="opt_tags_browser_partition_method">
|
<widget class="QComboBox" name="opt_tags_browser_partition_method">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
|
@ -994,9 +994,19 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
self.restriction_error.emit()
|
self.restriction_error.emit()
|
||||||
|
|
||||||
if self.filter_categories_by:
|
if self.filter_categories_by:
|
||||||
|
if self.filter_categories_by.startswith('='):
|
||||||
|
use_exact_match = True
|
||||||
|
filter_by = self.filter_categories_by[1:]
|
||||||
|
else:
|
||||||
|
use_exact_match = False
|
||||||
|
filter_by = self.filter_categories_by
|
||||||
for category in data.keys():
|
for category in data.keys():
|
||||||
data[category] = [t for t in data[category]
|
if use_exact_match:
|
||||||
if lower(t.name).find(self.filter_categories_by) >= 0]
|
data[category] = [t for t in data[category]
|
||||||
|
if lower(t.name) == filter_by]
|
||||||
|
else:
|
||||||
|
data[category] = [t for t in data[category]
|
||||||
|
if lower(t.name).find(filter_by) >= 0]
|
||||||
|
|
||||||
# Build a dict of the keys that have data
|
# Build a dict of the keys that have data
|
||||||
tb_categories = self.db.field_metadata
|
tb_categories = self.db.field_metadata
|
||||||
|
@ -429,13 +429,16 @@ class TagBrowserBar(QWidget): # {{{
|
|||||||
self.item_search.setSizeAdjustPolicy(self.item_search.AdjustToMinimumContentsLengthWithIcon)
|
self.item_search.setSizeAdjustPolicy(self.item_search.AdjustToMinimumContentsLengthWithIcon)
|
||||||
self.item_search.initialize('tag_browser_search')
|
self.item_search.initialize('tag_browser_search')
|
||||||
self.item_search.completer().setCaseSensitivity(Qt.CaseSensitive)
|
self.item_search.completer().setCaseSensitivity(Qt.CaseSensitive)
|
||||||
self.item_search.setToolTip(_(
|
self.item_search.setToolTip(
|
||||||
'Search for items. This is a "contains" search; items containing the\n'
|
'<p>' +_(
|
||||||
'text anywhere in the name will be found. You can limit the search\n'
|
'Search for items. If the text begins with equals (=) the search is '
|
||||||
'to particular categories using syntax similar to search. For example,\n'
|
'exact match, otherwise it is "contains" finding items containing '
|
||||||
'tags:foo will find foo in any tag, but not in authors etc. Entering\n'
|
'the text anywhere in the item name. Both exact and contains '
|
||||||
'*foo will filter all categories at once, showing only those items\n'
|
'searches ignore case. You can limit the search to particular '
|
||||||
'containing the text "foo"'))
|
'categories using syntax similar to search. For example, '
|
||||||
|
'tags:foo will find foo in any tag, but not in authors etc. Entering '
|
||||||
|
'*foo will collapse all categories then showing only those categories '
|
||||||
|
'with items containing the text "foo"') + '</p')
|
||||||
ac = QAction(parent)
|
ac = QAction(parent)
|
||||||
parent.addAction(ac)
|
parent.addAction(ac)
|
||||||
parent.keyboard.register_shortcut('tag browser find box',
|
parent.keyboard.register_shortcut('tag browser find box',
|
||||||
@ -639,8 +642,32 @@ class TagBrowserWidget(QFrame): # {{{
|
|||||||
def find(self):
|
def find(self):
|
||||||
model = self.tags_view.model()
|
model = self.tags_view.model()
|
||||||
model.clear_boxed()
|
model.clear_boxed()
|
||||||
txt = self.find_text
|
|
||||||
|
|
||||||
|
# When a key is specified don't use the auto-collapsing search.
|
||||||
|
# A colon separates the lookup key from the search string.
|
||||||
|
# A leading colon says not to use autocollapsing search but search all keys
|
||||||
|
txt = self.find_text
|
||||||
|
colon = txt.find(':')
|
||||||
|
if colon >= 0:
|
||||||
|
key = self._parent.library_view.model().db.\
|
||||||
|
field_metadata.search_term_to_field_key(txt[:colon])
|
||||||
|
if key in self._parent.library_view.model().db.field_metadata:
|
||||||
|
txt = txt[colon+1:]
|
||||||
|
else:
|
||||||
|
key = ''
|
||||||
|
txt = txt[1:] if colon == 0 else txt
|
||||||
|
else:
|
||||||
|
key = None
|
||||||
|
|
||||||
|
# key is None indicates that no colon was found.
|
||||||
|
# key == '' means either a leading : was found or the key is invalid
|
||||||
|
|
||||||
|
# At this point the txt might have a leading =, in which case do an
|
||||||
|
# exact match search
|
||||||
|
|
||||||
|
if (gprefs.get('tag_browser_always_autocollapse', False) and
|
||||||
|
key is None and not txt.startswith('*')):
|
||||||
|
txt = '*' + txt
|
||||||
if txt.startswith('*'):
|
if txt.startswith('*'):
|
||||||
self.tags_view.collapseAll()
|
self.tags_view.collapseAll()
|
||||||
model.set_categories_filter(txt[1:])
|
model.set_categories_filter(txt[1:])
|
||||||
@ -659,18 +686,14 @@ class TagBrowserWidget(QFrame): # {{{
|
|||||||
self.search_button.setFocus(True)
|
self.search_button.setFocus(True)
|
||||||
self.item_search.lineEdit().blockSignals(False)
|
self.item_search.lineEdit().blockSignals(False)
|
||||||
|
|
||||||
key = None
|
if txt.startswith('='):
|
||||||
colon = txt.find(':') if len(txt) > 2 else 0
|
equals_match = True
|
||||||
if colon > 0:
|
txt = txt[1:]
|
||||||
key = self._parent.library_view.model().db.\
|
else:
|
||||||
field_metadata.search_term_to_field_key(txt[:colon])
|
equals_match = False
|
||||||
if key in self._parent.library_view.model().db.field_metadata:
|
|
||||||
txt = txt[colon+1:]
|
|
||||||
else:
|
|
||||||
key = None
|
|
||||||
|
|
||||||
self.current_find_position = \
|
self.current_find_position = \
|
||||||
model.find_item_node(key, txt, self.current_find_position)
|
model.find_item_node(key, txt, self.current_find_position,
|
||||||
|
equals_match=equals_match)
|
||||||
|
|
||||||
if self.current_find_position:
|
if self.current_find_position:
|
||||||
self.tags_view.show_item_at_path(self.current_find_position, box=True)
|
self.tags_view.show_item_at_path(self.current_find_position, box=True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user