mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Tag browser: Clicking on a nested category now searches for the category alone. Clicking twice searches fo rthe category and all its descendants and so on. Fixes #9166 (hierarchy indicator for no children). Also fix 9169
This commit is contained in:
commit
bc27bf06ce
BIN
resources/images/minusminus.png
Normal file
BIN
resources/images/minusminus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
resources/images/plusplus.png
Normal file
BIN
resources/images/plusplus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
@ -178,8 +178,10 @@ class TagCategories(QDialog, Ui_TagCategories):
|
|||||||
'multiple periods in a row or spaces before '
|
'multiple periods in a row or spaces before '
|
||||||
'or after periods.')).exec_()
|
'or after periods.')).exec_()
|
||||||
return False
|
return False
|
||||||
for c in self.categories:
|
for c in sorted(self.categories.keys(), key=sort_key):
|
||||||
if strcmp(c, cat_name) == 0:
|
if strcmp(c, cat_name) == 0 or \
|
||||||
|
(icu_lower(cat_name).startswith(icu_lower(c) + '.') and\
|
||||||
|
not cat_name.startswith(c + '.')):
|
||||||
error_dialog(self, _('Name already used'),
|
error_dialog(self, _('Name already used'),
|
||||||
_('That name is already used, perhaps with different case.')).exec_()
|
_('That name is already used, perhaps with different case.')).exec_()
|
||||||
return False
|
return False
|
||||||
|
@ -217,11 +217,15 @@ class SearchBox2(QComboBox): # {{{
|
|||||||
self.clear()
|
self.clear()
|
||||||
else:
|
else:
|
||||||
self.normalize_state()
|
self.normalize_state()
|
||||||
|
self.lineEdit().setCompleter(None)
|
||||||
self.setEditText(txt)
|
self.setEditText(txt)
|
||||||
self.line_edit.end(False)
|
self.line_edit.end(False)
|
||||||
if emit_changed:
|
if emit_changed:
|
||||||
self.changed.emit()
|
self.changed.emit()
|
||||||
self._do_search(store_in_history=store_in_history)
|
self._do_search(store_in_history=store_in_history)
|
||||||
|
c = QCompleter()
|
||||||
|
self.lineEdit().setCompleter(c)
|
||||||
|
c.setCompletionMode(c.PopupCompletion)
|
||||||
self.focus_to_library.emit()
|
self.focus_to_library.emit()
|
||||||
finally:
|
finally:
|
||||||
if not store_in_history:
|
if not store_in_history:
|
||||||
|
@ -21,6 +21,7 @@ from PyQt4.Qt import Qt, QTreeView, QApplication, pyqtSignal, QFont, QSize, \
|
|||||||
from calibre.ebooks.metadata import title_sort
|
from calibre.ebooks.metadata import title_sort
|
||||||
from calibre.gui2 import config, NONE, gprefs
|
from calibre.gui2 import config, NONE, gprefs
|
||||||
from calibre.library.field_metadata import TagsIcons, category_icon_map
|
from calibre.library.field_metadata import TagsIcons, category_icon_map
|
||||||
|
from calibre.library.database2 import Tag
|
||||||
from calibre.utils.config import tweaks
|
from calibre.utils.config import tweaks
|
||||||
from calibre.utils.icu import sort_key, lower, strcmp
|
from calibre.utils.icu import sort_key, lower, strcmp
|
||||||
from calibre.utils.search_query_parser import saved_searches
|
from calibre.utils.search_query_parser import saved_searches
|
||||||
@ -69,7 +70,8 @@ class TagDelegate(QItemDelegate): # {{{
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
TAG_SEARCH_STATES = {'clear': 0, 'mark_plus': 1, 'mark_minus': 2}
|
TAG_SEARCH_STATES = {'clear': 0, 'mark_plus': 1, 'mark_plusplus': 2,
|
||||||
|
'mark_minus': 3, 'mark_minusminus': 4}
|
||||||
|
|
||||||
class TagsView(QTreeView): # {{{
|
class TagsView(QTreeView): # {{{
|
||||||
|
|
||||||
@ -127,12 +129,16 @@ class TagsView(QTreeView): # {{{
|
|||||||
self.set_new_model(self._model.get_filter_categories_by())
|
self.set_new_model(self._model.get_filter_categories_by())
|
||||||
|
|
||||||
def set_database(self, db, tag_match, sort_by):
|
def set_database(self, db, tag_match, sort_by):
|
||||||
self.hidden_categories = db.prefs.get('tag_browser_hidden_categories', None)
|
hidden_cats = db.prefs.get('tag_browser_hidden_categories', None)
|
||||||
|
self.hidden_categories = []
|
||||||
# migrate from config to db prefs
|
# migrate from config to db prefs
|
||||||
if self.hidden_categories is None:
|
if hidden_cats is None:
|
||||||
self.hidden_categories = config['tag_browser_hidden_categories']
|
hidden_cats = config['tag_browser_hidden_categories']
|
||||||
|
# strip out any non-existence field keys
|
||||||
|
for cat in hidden_cats:
|
||||||
|
if cat in db.field_metadata:
|
||||||
|
self.hidden_categories.append(cat)
|
||||||
db.prefs.set('tag_browser_hidden_categories', list(self.hidden_categories))
|
db.prefs.set('tag_browser_hidden_categories', list(self.hidden_categories))
|
||||||
else:
|
|
||||||
self.hidden_categories = set(self.hidden_categories)
|
self.hidden_categories = set(self.hidden_categories)
|
||||||
|
|
||||||
old = getattr(self, '_model', None)
|
old = getattr(self, '_model', None)
|
||||||
@ -370,14 +376,15 @@ class TagsView(QTreeView): # {{{
|
|||||||
action='delete_user_category', key=key))
|
action='delete_user_category', key=key))
|
||||||
self.context_menu.addSeparator()
|
self.context_menu.addSeparator()
|
||||||
# Hide/Show/Restore categories
|
# Hide/Show/Restore categories
|
||||||
if not key.startswith('@') or key.find('.') < 0:
|
#if not key.startswith('@') or key.find('.') < 0:
|
||||||
self.context_menu.addAction(_('Hide category %s') % category,
|
self.context_menu.addAction(_('Hide category %s') % category,
|
||||||
partial(self.context_menu_handler, action='hide',
|
partial(self.context_menu_handler, action='hide',
|
||||||
category=category))
|
category=key))
|
||||||
if self.hidden_categories:
|
if self.hidden_categories:
|
||||||
m = self.context_menu.addMenu(_('Show category'))
|
m = self.context_menu.addMenu(_('Show category'))
|
||||||
for col in sorted(self.hidden_categories, key=sort_key):
|
for col in sorted(self.hidden_categories,
|
||||||
m.addAction(col,
|
key=lambda x: sort_key(self.db.field_metadata[x]['name'])):
|
||||||
|
m.addAction(self.db.field_metadata[col]['name'],
|
||||||
partial(self.context_menu_handler, action='show', category=col))
|
partial(self.context_menu_handler, action='show', category=col))
|
||||||
|
|
||||||
# search by category
|
# search by category
|
||||||
@ -540,6 +547,7 @@ class TagTreeItem(object): # {{{
|
|||||||
self.id_set = set()
|
self.id_set = set()
|
||||||
self.is_gst = False
|
self.is_gst = False
|
||||||
self.boxed = False
|
self.boxed = False
|
||||||
|
self.icon_state_map = list(map(QVariant, icon_map))
|
||||||
if self.parent is not None:
|
if self.parent is not None:
|
||||||
self.parent.append(self)
|
self.parent.append(self)
|
||||||
if data is None:
|
if data is None:
|
||||||
@ -554,9 +562,11 @@ class TagTreeItem(object): # {{{
|
|||||||
self.bold_font = QVariant(self.bold_font)
|
self.bold_font = QVariant(self.bold_font)
|
||||||
self.category_key = category_key
|
self.category_key = category_key
|
||||||
self.temporary = temporary
|
self.temporary = temporary
|
||||||
|
self.tag = Tag(data)
|
||||||
|
self.tag.is_hierarchical = category_key.startswith('@')
|
||||||
elif self.type == self.TAG:
|
elif self.type == self.TAG:
|
||||||
icon_map[0] = data.icon
|
icon_map[0] = data.icon
|
||||||
self.tag, self.icon_state_map = data, list(map(QVariant, icon_map))
|
self.tag = data
|
||||||
if tooltip:
|
if tooltip:
|
||||||
self.tooltip = tooltip + ' '
|
self.tooltip = tooltip + ' '
|
||||||
else:
|
else:
|
||||||
@ -593,6 +603,8 @@ class TagTreeItem(object): # {{{
|
|||||||
if role == Qt.EditRole:
|
if role == Qt.EditRole:
|
||||||
return QVariant(self.py_name)
|
return QVariant(self.py_name)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
|
if self.tag.state:
|
||||||
|
return self.icon_state_map[self.tag.state]
|
||||||
return self.icon
|
return self.icon
|
||||||
if role == Qt.FontRole:
|
if role == Qt.FontRole:
|
||||||
return self.bold_font
|
return self.bold_font
|
||||||
@ -642,9 +654,19 @@ class TagTreeItem(object): # {{{
|
|||||||
'''
|
'''
|
||||||
set_to: None => advance the state, otherwise a value from TAG_SEARCH_STATES
|
set_to: None => advance the state, otherwise a value from TAG_SEARCH_STATES
|
||||||
'''
|
'''
|
||||||
if self.type == self.TAG:
|
|
||||||
if set_to is None:
|
if set_to is None:
|
||||||
self.tag.state = (self.tag.state + 1)%3
|
while True:
|
||||||
|
self.tag.state = (self.tag.state + 1)%5
|
||||||
|
if self.tag.state == TAG_SEARCH_STATES['mark_plus'] or \
|
||||||
|
self.tag.state == TAG_SEARCH_STATES['mark_minus']:
|
||||||
|
if self.tag.is_editable:
|
||||||
|
break
|
||||||
|
elif self.tag.state == TAG_SEARCH_STATES['mark_plusplus'] or\
|
||||||
|
self.tag.state == TAG_SEARCH_STATES['mark_minusminus']:
|
||||||
|
if self.tag.is_hierarchical and len(self.children):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
self.tag.state = set_to
|
self.tag.state = set_to
|
||||||
|
|
||||||
@ -677,7 +699,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
self.categories_with_ratings = ['authors', 'series', 'publisher', 'tags']
|
self.categories_with_ratings = ['authors', 'series', 'publisher', 'tags']
|
||||||
self.drag_drop_finished = drag_drop_finished
|
self.drag_drop_finished = drag_drop_finished
|
||||||
|
|
||||||
self.icon_state_map = [None, QIcon(I('plus.png')), QIcon(I('minus.png'))]
|
self.icon_state_map = [None, QIcon(I('plus.png')), QIcon(I('plusplus.png')),
|
||||||
|
QIcon(I('minus.png')), QIcon(I('minusminus.png'))]
|
||||||
self.db = db
|
self.db = db
|
||||||
self.tags_view = parent
|
self.tags_view = parent
|
||||||
self.hidden_categories = hidden_categories
|
self.hidden_categories = hidden_categories
|
||||||
@ -691,26 +714,33 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
|
|
||||||
data = self.get_node_tree(config['sort_tags_by'])
|
data = self.get_node_tree(config['sort_tags_by'])
|
||||||
gst = db.prefs.get('grouped_search_terms', {})
|
gst = db.prefs.get('grouped_search_terms', {})
|
||||||
self.root_item = TagTreeItem()
|
self.root_item = TagTreeItem(icon_map=self.icon_state_map)
|
||||||
self.category_nodes = []
|
self.category_nodes = []
|
||||||
|
|
||||||
last_category_node = None
|
last_category_node = None
|
||||||
category_node_map = {}
|
category_node_map = {}
|
||||||
self.category_node_tree = {}
|
self.category_node_tree = {}
|
||||||
for i, r in enumerate(self.row_map):
|
for i, key in enumerate(self.row_map):
|
||||||
if self.hidden_categories and self.categories[i] in self.hidden_categories:
|
if self.hidden_categories:
|
||||||
|
if key in self.hidden_categories:
|
||||||
|
continue
|
||||||
|
found = False
|
||||||
|
for cat in self.hidden_categories:
|
||||||
|
if cat.startswith('@') and key.startswith(cat + '.'):
|
||||||
|
found = True
|
||||||
|
if found:
|
||||||
continue
|
continue
|
||||||
is_gst = False
|
is_gst = False
|
||||||
if r.startswith('@') and r[1:] in gst:
|
if key.startswith('@') and key[1:] in gst:
|
||||||
tt = _(u'The grouped search term name is "{0}"').format(r[1:])
|
tt = _(u'The grouped search term name is "{0}"').format(key[1:])
|
||||||
is_gst = True
|
is_gst = True
|
||||||
elif r == 'news':
|
elif key == 'news':
|
||||||
tt = ''
|
tt = ''
|
||||||
else:
|
else:
|
||||||
tt = _(u'The lookup/search name is "{0}"').format(r)
|
tt = _(u'The lookup/search name is "{0}"').format(key)
|
||||||
|
|
||||||
if r.startswith('@'):
|
if key.startswith('@'):
|
||||||
path_parts = [p for p in r.split('.')]
|
path_parts = [p for p in key.split('.')]
|
||||||
path = ''
|
path = ''
|
||||||
last_category_node = self.root_item
|
last_category_node = self.root_item
|
||||||
tree_root = self.category_node_tree
|
tree_root = self.category_node_tree
|
||||||
@ -719,9 +749,10 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
if path not in category_node_map:
|
if path not in category_node_map:
|
||||||
node = TagTreeItem(parent=last_category_node,
|
node = TagTreeItem(parent=last_category_node,
|
||||||
data=p[1:] if i == 0 else p,
|
data=p[1:] if i == 0 else p,
|
||||||
category_icon=self.category_icon_map[r],
|
category_icon=self.category_icon_map[key],
|
||||||
tooltip=tt if path == r else path,
|
tooltip=tt if path == key else path,
|
||||||
category_key=path)
|
category_key=path,
|
||||||
|
icon_map=self.icon_state_map)
|
||||||
last_category_node = node
|
last_category_node = node
|
||||||
category_node_map[path] = node
|
category_node_map[path] = node
|
||||||
self.category_nodes.append(node)
|
self.category_nodes.append(node)
|
||||||
@ -736,11 +767,12 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
path += '.'
|
path += '.'
|
||||||
else:
|
else:
|
||||||
node = TagTreeItem(parent=self.root_item,
|
node = TagTreeItem(parent=self.root_item,
|
||||||
data=self.categories[i],
|
data=self.categories[key],
|
||||||
category_icon=self.category_icon_map[r],
|
category_icon=self.category_icon_map[key],
|
||||||
tooltip=tt, category_key=r)
|
tooltip=tt, category_key=key,
|
||||||
|
icon_map=self.icon_state_map)
|
||||||
node.is_gst = False
|
node.is_gst = False
|
||||||
category_node_map[r] = node
|
category_node_map[key] = node
|
||||||
last_category_node = node
|
last_category_node = node
|
||||||
self.category_nodes.append(node)
|
self.category_nodes.append(node)
|
||||||
self.refresh(data=data)
|
self.refresh(data=data)
|
||||||
@ -1015,7 +1047,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
def get_node_tree(self, sort):
|
def get_node_tree(self, sort):
|
||||||
old_row_map = self.row_map[:]
|
old_row_map = self.row_map[:]
|
||||||
self.row_map = []
|
self.row_map = []
|
||||||
self.categories = []
|
self.categories = {}
|
||||||
|
|
||||||
# Get the categories
|
# Get the categories
|
||||||
if self.search_restriction:
|
if self.search_restriction:
|
||||||
@ -1062,7 +1094,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
for category in tb_categories:
|
for category in tb_categories:
|
||||||
if category in data: # The search category can come and go
|
if category in data: # The search category can come and go
|
||||||
self.row_map.append(category)
|
self.row_map.append(category)
|
||||||
self.categories.append(tb_categories[category]['name'])
|
self.categories[category] = tb_categories[category]['name']
|
||||||
|
|
||||||
if len(old_row_map) != 0 and len(old_row_map) != len(self.row_map):
|
if len(old_row_map) != 0 and len(old_row_map) != len(self.row_map):
|
||||||
# A category has been added or removed. We must force a rebuild of
|
# A category has been added or removed. We must force a rebuild of
|
||||||
@ -1163,7 +1195,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
sub_cat = TagTreeItem(parent=category, data = name,
|
sub_cat = TagTreeItem(parent=category, data = name,
|
||||||
tooltip = None, temporary=True,
|
tooltip = None, temporary=True,
|
||||||
category_icon = category_node.icon,
|
category_icon = category_node.icon,
|
||||||
category_key=category_node.category_key)
|
category_key=category_node.category_key,
|
||||||
|
icon_map=self.icon_state_map)
|
||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
else: # by 'first letter'
|
else: # by 'first letter'
|
||||||
cl = cl_list[idx]
|
cl = cl_list[idx]
|
||||||
@ -1173,7 +1206,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
data = collapse_letter,
|
data = collapse_letter,
|
||||||
category_icon = category_node.icon,
|
category_icon = category_node.icon,
|
||||||
tooltip = None, temporary=True,
|
tooltip = None, temporary=True,
|
||||||
category_key=category_node.category_key)
|
category_key=category_node.category_key,
|
||||||
|
icon_map=self.icon_state_map)
|
||||||
node_parent = sub_cat
|
node_parent = sub_cat
|
||||||
else:
|
else:
|
||||||
node_parent = category
|
node_parent = category
|
||||||
@ -1284,16 +1318,19 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
user_cats = self.db.prefs.get('user_categories', {})
|
user_cats = self.db.prefs.get('user_categories', {})
|
||||||
|
user_cat_keys_lower = [icu_lower(k) for k in user_cats]
|
||||||
ckey = item.category_key[1:]
|
ckey = item.category_key[1:]
|
||||||
|
ckey_lower = icu_lower(ckey)
|
||||||
dotpos = ckey.rfind('.')
|
dotpos = ckey.rfind('.')
|
||||||
if dotpos < 0:
|
if dotpos < 0:
|
||||||
nkey = val
|
nkey = val
|
||||||
else:
|
else:
|
||||||
nkey = ckey[:dotpos+1] + val
|
nkey = ckey[:dotpos+1] + val
|
||||||
for c in user_cats:
|
nkey_lower = icu_lower(nkey)
|
||||||
if c.startswith(ckey):
|
for c in sorted(user_cats.keys(), key=sort_key):
|
||||||
|
if icu_lower(c).startswith(ckey_lower):
|
||||||
if len(c) == len(ckey):
|
if len(c) == len(ckey):
|
||||||
if nkey in user_cats:
|
if nkey_lower in user_cat_keys_lower:
|
||||||
error_dialog(self.tags_view, _('Rename user category'),
|
error_dialog(self.tags_view, _('Rename user category'),
|
||||||
_('The name %s is already used')%nkey, show=True)
|
_('The name %s is already used')%nkey, show=True)
|
||||||
return False
|
return False
|
||||||
@ -1301,7 +1338,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
del user_cats[ckey]
|
del user_cats[ckey]
|
||||||
elif c[len(ckey)] == '.':
|
elif c[len(ckey)] == '.':
|
||||||
rest = c[len(ckey):]
|
rest = c[len(ckey):]
|
||||||
if (nkey + rest) in user_cats:
|
if icu_lower(nkey + rest) in user_cat_keys_lower:
|
||||||
error_dialog(self.tags_view, _('Rename user category'),
|
error_dialog(self.tags_view, _('Rename user category'),
|
||||||
_('The name %s is already used')%(nkey+rest), show=True)
|
_('The name %s is already used')%(nkey+rest), show=True)
|
||||||
return False
|
return False
|
||||||
@ -1477,7 +1514,6 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
def reset_all_states(self, except_=None):
|
def reset_all_states(self, except_=None):
|
||||||
update_list = []
|
update_list = []
|
||||||
def process_tag(tag_item):
|
def process_tag(tag_item):
|
||||||
if tag_item.type != TagTreeItem.CATEGORY:
|
|
||||||
tag = tag_item.tag
|
tag = tag_item.tag
|
||||||
if tag is except_:
|
if tag is except_:
|
||||||
tag_index = self.createIndex(tag_item.row(), 0, tag_item)
|
tag_index = self.createIndex(tag_item.row(), 0, tag_item)
|
||||||
@ -1503,13 +1539,11 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
'''
|
'''
|
||||||
if not index.isValid(): return False
|
if not index.isValid(): return False
|
||||||
item = index.internalPointer()
|
item = index.internalPointer()
|
||||||
if item.type == TagTreeItem.TAG:
|
|
||||||
item.toggle(set_to=set_to)
|
item.toggle(set_to=set_to)
|
||||||
if exclusive:
|
if exclusive:
|
||||||
self.reset_all_states(except_=item.tag)
|
self.reset_all_states(except_=item.tag)
|
||||||
self.dataChanged.emit(index, index)
|
self.dataChanged.emit(index, index)
|
||||||
return True
|
return True
|
||||||
return False
|
|
||||||
|
|
||||||
def tokens(self):
|
def tokens(self):
|
||||||
ans = []
|
ans = []
|
||||||
@ -1523,19 +1557,31 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
# into the search string only once. The nodes_seen set helps us do that
|
# into the search string only once. The nodes_seen set helps us do that
|
||||||
nodes_seen = set()
|
nodes_seen = set()
|
||||||
|
|
||||||
|
node_searches = {TAG_SEARCH_STATES['mark_plus'] : 'true',
|
||||||
|
TAG_SEARCH_STATES['mark_plusplus'] : '.true',
|
||||||
|
TAG_SEARCH_STATES['mark_minus'] : 'false',
|
||||||
|
TAG_SEARCH_STATES['mark_minusminus'] : '.false'}
|
||||||
|
|
||||||
for node in self.category_nodes:
|
for node in self.category_nodes:
|
||||||
|
if node.tag.state:
|
||||||
|
ans.append('%s:%s'%(node.category_key, node_searches[node.tag.state]))
|
||||||
|
|
||||||
key = node.category_key
|
key = node.category_key
|
||||||
for tag_item in node.child_tags():
|
for tag_item in node.child_tags():
|
||||||
tag = tag_item.tag
|
tag = tag_item.tag
|
||||||
if tag.state != TAG_SEARCH_STATES['clear']:
|
if tag.state != TAG_SEARCH_STATES['clear']:
|
||||||
prefix = ' not ' if tag.state == TAG_SEARCH_STATES['mark_minus'] \
|
if tag.state == TAG_SEARCH_STATES['mark_minus'] or \
|
||||||
else ''
|
tag.state == TAG_SEARCH_STATES['mark_minusminus']:
|
||||||
|
prefix = ' not '
|
||||||
|
else:
|
||||||
|
prefix = ''
|
||||||
category = tag.category if key != 'news' else 'tag'
|
category = tag.category if key != 'news' else 'tag'
|
||||||
if tag.name and tag.name[0] == u'\u2605': # char is a star. Assume rating
|
if tag.name and tag.name[0] == u'\u2605': # char is a star. Assume rating
|
||||||
ans.append('%s%s:%s'%(prefix, category, len(tag.name)))
|
ans.append('%s%s:%s'%(prefix, category, len(tag.name)))
|
||||||
else:
|
else:
|
||||||
name = original_name(tag)
|
name = original_name(tag)
|
||||||
use_prefix = tag.is_hierarchical
|
use_prefix = tag.state in [TAG_SEARCH_STATES['mark_plusplus'],
|
||||||
|
TAG_SEARCH_STATES['mark_minusminus']]
|
||||||
if category == 'tags':
|
if category == 'tags':
|
||||||
if name in tags_seen:
|
if name in tags_seen:
|
||||||
continue
|
continue
|
||||||
|
@ -419,28 +419,23 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
|
|
||||||
def get_user_category_matches(self, location, query, candidates):
|
def get_user_category_matches(self, location, query, candidates):
|
||||||
res = set([])
|
res = set([])
|
||||||
if self.db_prefs is None:
|
if self.db_prefs is None or len(query) < 2:
|
||||||
return res
|
return res
|
||||||
user_cats = self.db_prefs.get('user_categories', [])
|
user_cats = self.db_prefs.get('user_categories', [])
|
||||||
c = set(candidates)
|
c = set(candidates)
|
||||||
l = location.rfind('.')
|
|
||||||
if l > 0:
|
if query.startswith('.'):
|
||||||
alt_loc = location[0:l]
|
check_subcats = True
|
||||||
alt_item = location[l+1:]
|
query = query[1:]
|
||||||
else:
|
else:
|
||||||
alt_loc = None
|
check_subcats = False
|
||||||
|
|
||||||
for key in user_cats:
|
for key in user_cats:
|
||||||
if key == location or key.startswith(location + '.'):
|
if key == location or (check_subcats and key.startswith(location + '.')):
|
||||||
for (item, category, ign) in user_cats[key]:
|
for (item, category, ign) in user_cats[key]:
|
||||||
s = self.get_matches(category, '=' + item, candidates=c)
|
s = self.get_matches(category, '=' + item, candidates=c)
|
||||||
c -= s
|
c -= s
|
||||||
res |= s
|
res |= s
|
||||||
elif key == alt_loc:
|
|
||||||
for (item, category, ign) in user_cats[key]:
|
|
||||||
if item == alt_item:
|
|
||||||
s = self.get_matches(category, '=' + item, candidates=c)
|
|
||||||
c -= s
|
|
||||||
res |= s
|
|
||||||
if query == 'false':
|
if query == 'false':
|
||||||
return candidates - res
|
return candidates - res
|
||||||
return res
|
return res
|
||||||
|
Loading…
x
Reference in New Issue
Block a user