Improvements on tags search. Add '*x' which restricts the tags browser to those matching x. Clean up some signal handling.

This commit is contained in:
Charles Haley 2010-12-30 17:19:37 +00:00
parent 138c323f2d
commit 0e44baa997

View File

@ -336,12 +336,13 @@ class TagsView(QTreeView): # {{{
# If the number of user categories changed, if custom columns have come or # If the number of user categories changed, if custom columns have come or
# gone, or if columns have been hidden or restored, we must rebuild the # gone, or if columns have been hidden or restored, we must rebuild the
# model. Reason: it is much easier than reconstructing the browser tree. # model. Reason: it is much easier than reconstructing the browser tree.
def set_new_model(self): def set_new_model(self, filter_categories_by = None):
try: try:
self._model = TagsModel(self.db, parent=self, self._model = TagsModel(self.db, parent=self,
hidden_categories=self.hidden_categories, hidden_categories=self.hidden_categories,
search_restriction=self.search_restriction, search_restriction=self.search_restriction,
drag_drop_finished=self.drag_drop_finished) drag_drop_finished=self.drag_drop_finished,
filter_categories_by=filter_categories_by)
self.setModel(self._model) self.setModel(self._model)
except: except:
# The DB must be gone. Set the model to None and hope that someone # The DB must be gone. Set the model to None and hope that someone
@ -461,7 +462,8 @@ class TagTreeItem(object): # {{{
class TagsModel(QAbstractItemModel): # {{{ class TagsModel(QAbstractItemModel): # {{{
def __init__(self, db, parent, hidden_categories=None, def __init__(self, db, parent, hidden_categories=None,
search_restriction=None, drag_drop_finished=None): search_restriction=None, drag_drop_finished=None,
filter_categories_by=None):
QAbstractItemModel.__init__(self, parent) QAbstractItemModel.__init__(self, parent)
# must do this here because 'QPixmap: Must construct a QApplication # must do this here because 'QPixmap: Must construct a QApplication
@ -481,6 +483,7 @@ class TagsModel(QAbstractItemModel): # {{{
self.hidden_categories = hidden_categories self.hidden_categories = hidden_categories
self.search_restriction = search_restriction self.search_restriction = search_restriction
self.row_map = [] self.row_map = []
self.filter_categories_by = filter_categories_by
# get_node_tree cannot return None here, because row_map is empty # get_node_tree cannot return None here, because row_map is empty
data = self.get_node_tree(config['sort_tags_by']) data = self.get_node_tree(config['sort_tags_by'])
@ -648,6 +651,11 @@ class TagsModel(QAbstractItemModel): # {{{
else: else:
data = self.db.get_categories(sort=sort, icon_map=self.category_icon_map) data = self.db.get_categories(sort=sort, icon_map=self.category_icon_map)
if self.filter_categories_by:
for category in data.keys():
data[category] = [t for t in data[category]
if lower(t.name).find(self.filter_categories_by) >= 0]
tb_categories = self.db.field_metadata tb_categories = self.db.field_metadata
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
@ -948,7 +956,7 @@ class TagsModel(QAbstractItemModel): # {{{
if not txt: if not txt:
return None return None
txt = lower(txt) txt = lower(txt)
if start_index is None: if start_index is None or not start_index.isValid():
start_index = QModelIndex() start_index = QModelIndex()
self.node_found = None self.node_found = None
@ -1017,7 +1025,8 @@ class TagsModel(QAbstractItemModel): # {{{
for i in xrange(self.rowCount(QModelIndex())): for i in xrange(self.rowCount(QModelIndex())):
process_level(self.index(i, 0, QModelIndex())) process_level(self.index(i, 0, QModelIndex()))
def get_filter_categories_by(self):
return self.filter_categories_by
# }}} # }}}
@ -1151,7 +1160,9 @@ class TagBrowserWidget(QWidget): # {{{
'Search for items. This is a "contains" search; items containing the\n' 'Search for items. This is a "contains" search; items containing the\n'
'text anywhere in the name will be found. You can limit the search\n' 'text anywhere in the name will be found. You can limit the search\n'
'to particular categories using syntax similar to search. For example,\n' 'to particular categories using syntax similar to search. For example,\n'
'tags:foo will find foo in any tag, but not in authors etc.')) 'tags:foo will find foo in any tag, but not in authors etc. Entering\n'
'*foo will filter all categories at once, showing only those items\n'
'containing the text "foo"'))
search_layout.addWidget(self.item_search) search_layout.addWidget(self.item_search)
self.search_button = QPushButton() self.search_button = QPushButton()
self.search_button.setText(_('Find!')) self.search_button.setText(_('Find!'))
@ -1161,8 +1172,9 @@ class TagBrowserWidget(QWidget): # {{{
self.current_position = None self.current_position = None
self.search_button.clicked.connect(self.find) self.search_button.clicked.connect(self.find)
self.item_search.initialize('tag_browser_search') self.item_search.initialize('tag_browser_search')
self.item_search.lineEdit().returnPressed.connect(self.find_text_changed) self.item_search.lineEdit().returnPressed.connect(self.do_find)
self.item_search.activated[QString].connect(self.find_text_changed) self.item_search.lineEdit().textEdited.connect(self.find_text_changed)
self.item_search.activated[QString].connect(self.do_find)
self.item_search.completer().setCaseSensitivity(Qt.CaseSensitive) self.item_search.completer().setCaseSensitivity(Qt.CaseSensitive)
parent.tags_view = TagsView(parent) parent.tags_view = TagsView(parent)
@ -1199,18 +1211,34 @@ class TagBrowserWidget(QWidget): # {{{
def set_pane_is_visible(self, to_what): def set_pane_is_visible(self, to_what):
self.tags_view.set_pane_is_visible(to_what) self.tags_view.set_pane_is_visible(to_what)
def find_text_changed(self, str=None): def find_text_changed(self, str):
self.current_position = None
def do_find(self, str=None):
self.current_position = None self.current_position = None
self.find() self.find()
def find(self): def find(self):
self.search_button.setFocus(True)
model = self.tags_view.model() model = self.tags_view.model()
model.clear_boxed() model.clear_boxed()
txt = unicode(self.item_search.currentText()) txt = unicode(self.item_search.currentText()).strip()
if txt.startswith('*'):
self.tags_view.set_new_model(filter_categories_by=txt[1:])
self.current_position = None
return
if model.get_filter_categories_by():
self.tags_view.set_new_model(filter_categories_by=None)
self.current_position = None
model = self.tags_view.model()
if not txt:
return
idx = self.item_search.findText(txt, Qt.MatchFixedString)
self.item_search.blockSignals(True) self.item_search.blockSignals(True)
self.item_search.lineEdit().blockSignals(True)
self.search_button.setFocus(True)
idx = self.item_search.findText(txt, Qt.MatchFixedString)
if idx < 0: if idx < 0:
self.item_search.insertItem(0, txt) self.item_search.insertItem(0, txt)
else: else:
@ -1219,6 +1247,7 @@ class TagBrowserWidget(QWidget): # {{{
self.item_search.insertItem(0, t) self.item_search.insertItem(0, t)
self.item_search.setCurrentIndex(0) self.item_search.setCurrentIndex(0)
self.item_search.blockSignals(False) self.item_search.blockSignals(False)
self.item_search.lineEdit().blockSignals(False)
colon = txt.find(':') colon = txt.find(':')
key = None key = None
@ -1226,6 +1255,7 @@ class TagBrowserWidget(QWidget): # {{{
key = self.parent.library_view.model().db.\ key = self.parent.library_view.model().db.\
field_metadata.search_term_to_field_key(txt[:colon]) field_metadata.search_term_to_field_key(txt[:colon])
txt = txt[colon+1:] txt = txt[colon+1:]
self.current_position = model.find_node(key, txt, self.current_position) self.current_position = model.find_node(key, txt, self.current_position)
if self.current_position: if self.current_position:
model.show_item_at_index(self.current_position, box=True) model.show_item_at_index(self.current_position, box=True)