Make change list searchable
Change-Id: I5edc1a9082dc81dfd06dc00f42abf05f0b03dc26
This commit is contained in:
parent
7a149db6cf
commit
1f25c9b450
@ -290,6 +290,62 @@ class SearchableText(urwid.Text):
|
||||
self._invalidate()
|
||||
return found
|
||||
|
||||
class Searchable(object):
|
||||
def searchInit(self):
|
||||
self.search = None
|
||||
self.results = []
|
||||
self.current_result = 0
|
||||
|
||||
def searchValidChar(self, ch):
|
||||
return urwid.util.is_wide_char(ch, 0) or (len(ch) == 1 and ord(ch) >= 32)
|
||||
|
||||
def searchKeypress(self, size, key):
|
||||
if self.search is not None:
|
||||
if self.searchValidChar(key) or key == 'backspace':
|
||||
if key == 'backspace':
|
||||
self.search = self.search[:-1]
|
||||
else:
|
||||
self.search += key
|
||||
self.interactiveSearch(self.search)
|
||||
return True
|
||||
else:
|
||||
commands = self.app.config.keymap.getCommands([key])
|
||||
if keymap.INTERACTIVE_SEARCH in commands:
|
||||
self.nextSearchResult()
|
||||
return True
|
||||
else:
|
||||
self.app.status.update(title=self.title)
|
||||
if not self.search:
|
||||
self.interactiveSearch(None)
|
||||
self.search = None
|
||||
if key in ['enter', 'esc']:
|
||||
return True
|
||||
return False
|
||||
|
||||
def searchStart(self):
|
||||
self.search = ''
|
||||
self.app.status.update(title=("Search: "))
|
||||
|
||||
def interactiveSearch(self, search):
|
||||
if search is not None:
|
||||
self.app.status.update(title=("Search: " + search))
|
||||
self.results = []
|
||||
self.current_result = 0
|
||||
for i, line in enumerate(self.listbox.body):
|
||||
if hasattr(line, 'search'):
|
||||
if line.search(search, 'search-result'):
|
||||
self.results.append(i)
|
||||
|
||||
def nextSearchResult(self):
|
||||
if not self.results:
|
||||
return
|
||||
dest = self.results[self.current_result]
|
||||
self.listbox.set_focus(dest)
|
||||
self.listbox._invalidate()
|
||||
self.current_result += 1
|
||||
if self.current_result >= len(self.results):
|
||||
self.current_result = 0
|
||||
|
||||
class HyperText(urwid.Text):
|
||||
_selectable = True
|
||||
|
||||
|
@ -111,13 +111,13 @@ class ChangeRow(urwid.Button, ChangeListColumns):
|
||||
self.change_key = change.key
|
||||
self.prefix = prefix
|
||||
self.enabled_columns = enabled_columns
|
||||
self.subject = urwid.Text(u'', wrap='clip')
|
||||
self.number = urwid.Text(u'')
|
||||
self.updated = urwid.Text(u'')
|
||||
self.project = urwid.Text(u'', wrap='clip')
|
||||
self.owner = urwid.Text(u'', wrap='clip')
|
||||
self.branch = urwid.Text(u'', wrap='clip')
|
||||
self.topic = urwid.Text(u'', wrap='clip')
|
||||
self.subject = mywid.SearchableText(u'', wrap='clip')
|
||||
self.number = mywid.SearchableText(u'')
|
||||
self.updated = mywid.SearchableText(u'')
|
||||
self.project = mywid.SearchableText(u'', wrap='clip')
|
||||
self.owner = mywid.SearchableText(u'', wrap='clip')
|
||||
self.branch = mywid.SearchableText(u'', wrap='clip')
|
||||
self.topic = mywid.SearchableText(u'', wrap='clip')
|
||||
self.mark = False
|
||||
self.columns = urwid.Columns([], dividechars=1)
|
||||
self.row_style = urwid.AttrMap(self.columns, '')
|
||||
@ -125,6 +125,23 @@ class ChangeRow(urwid.Button, ChangeListColumns):
|
||||
self.category_columns = []
|
||||
self.update(change, categories)
|
||||
|
||||
def search(self, search, attribute):
|
||||
if self.subject.search(search, attribute):
|
||||
return True
|
||||
if self.number.search(search, attribute):
|
||||
return True
|
||||
if self.project.search(search, attribute):
|
||||
return True
|
||||
if self.branch.search(search, attribute):
|
||||
return True
|
||||
if self.owner.search(search, attribute):
|
||||
return True
|
||||
if self.topic.search(search, attribute):
|
||||
return True
|
||||
if self.updated.search(search, attribute):
|
||||
return True
|
||||
return False
|
||||
|
||||
def update(self, change, categories):
|
||||
if change.reviewed or change.hidden:
|
||||
style = 'reviewed-change'
|
||||
@ -181,7 +198,6 @@ class ChangeRow(urwid.Button, ChangeListColumns):
|
||||
self.columns.options('given', 2)))
|
||||
self.updateColumns()
|
||||
|
||||
|
||||
class ChangeListHeader(urwid.WidgetWrap, ChangeListColumns):
|
||||
def __init__(self, enabled_columns):
|
||||
self.enabled_columns = enabled_columns
|
||||
@ -205,7 +221,7 @@ class ChangeListHeader(urwid.WidgetWrap, ChangeListColumns):
|
||||
|
||||
|
||||
@mouse_scroll_decorator.ScrollByWheel
|
||||
class ChangeListView(urwid.WidgetWrap):
|
||||
class ChangeListView(urwid.WidgetWrap, mywid.Searchable):
|
||||
required_columns = set(['Number', 'Subject', 'Updated'])
|
||||
optional_columns = set(['Topic', 'Branch'])
|
||||
|
||||
@ -249,6 +265,8 @@ class ChangeListView(urwid.WidgetWrap):
|
||||
"Reverse the sort"),
|
||||
(keymap.LOCAL_CHERRY_PICK,
|
||||
"Cherry-pick the most recent revision of the selected change onto the local repo"),
|
||||
(keymap.INTERACTIVE_SEARCH,
|
||||
"Interactive search"),
|
||||
]
|
||||
|
||||
def help(self):
|
||||
@ -260,6 +278,7 @@ class ChangeListView(urwid.WidgetWrap):
|
||||
unreviewed=False, sort_by=None, reverse=None):
|
||||
super(ChangeListView, self).__init__(urwid.Pile([]))
|
||||
self.log = logging.getLogger('gertty.view.change_list')
|
||||
self.searchInit()
|
||||
self.app = app
|
||||
self.query = query
|
||||
self.query_desc = query_desc or query
|
||||
@ -521,6 +540,9 @@ class ChangeListView(urwid.WidgetWrap):
|
||||
self.listbox.focus_position = pos
|
||||
|
||||
def keypress(self, size, key):
|
||||
if self.searchKeypress(size, key):
|
||||
return None
|
||||
|
||||
if not self.app.input_buffer:
|
||||
key = super(ChangeListView, self).keypress(size, key)
|
||||
keys = self.app.input_buffer + [key]
|
||||
@ -681,6 +703,9 @@ class ChangeListView(urwid.WidgetWrap):
|
||||
if keymap.RESTORE_CHANGE in commands:
|
||||
self.restoreChange()
|
||||
return True
|
||||
if keymap.INTERACTIVE_SEARCH in commands:
|
||||
self.searchStart()
|
||||
return True
|
||||
return False
|
||||
|
||||
def onSelect(self, button, change_key):
|
||||
|
@ -156,7 +156,7 @@ class DiffContextButton(urwid.WidgetWrap):
|
||||
self.view.expandChunk(self.diff, self.chunk, from_end=-10)
|
||||
|
||||
@mouse_scroll_decorator.ScrollByWheel
|
||||
class BaseDiffView(urwid.WidgetWrap):
|
||||
class BaseDiffView(urwid.WidgetWrap, mywid.Searchable):
|
||||
def getCommands(self):
|
||||
return [
|
||||
(keymap.ACTIVATE,
|
||||
@ -182,9 +182,7 @@ class BaseDiffView(urwid.WidgetWrap):
|
||||
|
||||
def _init(self):
|
||||
del self._w.contents[:]
|
||||
self.search = None
|
||||
self.results = []
|
||||
self.current_result = None
|
||||
self.searchInit()
|
||||
with self.app.db.getSession() as session:
|
||||
new_revision = session.getRevision(self.new_revision_key)
|
||||
old_comments = []
|
||||
@ -443,30 +441,9 @@ class BaseDiffView(urwid.WidgetWrap):
|
||||
context = item.context
|
||||
return context
|
||||
|
||||
def search_valid_char(self, ch):
|
||||
return urwid.util.is_wide_char(ch, 0) or (len(ch) == 1 and ord(ch) >= 32)
|
||||
|
||||
def keypress(self, size, key):
|
||||
if self.search is not None:
|
||||
if self.search_valid_char(key) or key == 'backspace':
|
||||
if key == 'backspace':
|
||||
self.search = self.search[:-1]
|
||||
else:
|
||||
self.search += key
|
||||
self.interactiveSearch(self.search)
|
||||
return None
|
||||
else:
|
||||
commands = self.app.config.keymap.getCommands([key])
|
||||
if keymap.INTERACTIVE_SEARCH in commands:
|
||||
self.nextSearchResult()
|
||||
return None
|
||||
else:
|
||||
self.app.status.update(title=self.title)
|
||||
if not self.search:
|
||||
self.interactiveSearch(None)
|
||||
self.search = None
|
||||
if key in ['enter', 'esc']:
|
||||
return None
|
||||
if self.searchKeypress(size, key):
|
||||
return None
|
||||
|
||||
old_focus = self.listbox.focus
|
||||
if not self.app.input_buffer:
|
||||
@ -489,8 +466,7 @@ class BaseDiffView(urwid.WidgetWrap):
|
||||
self.openPatchsetDialog()
|
||||
return None
|
||||
if keymap.INTERACTIVE_SEARCH in commands:
|
||||
self.search = ''
|
||||
self.app.status.update(title=("Search: "))
|
||||
self.searchStart()
|
||||
return None
|
||||
return key
|
||||
|
||||
@ -561,23 +537,3 @@ class BaseDiffView(urwid.WidgetWrap):
|
||||
self.app.backScreen()
|
||||
self.old_revision_key, self.new_revision_key = dialog.getSelected()
|
||||
self._init()
|
||||
|
||||
def interactiveSearch(self, search):
|
||||
if search is not None:
|
||||
self.app.status.update(title=("Search: " + search))
|
||||
self.results = []
|
||||
self.current_result = 0
|
||||
for i, line in enumerate(self.listbox.body):
|
||||
if hasattr(line, 'search'):
|
||||
if line.search(search, 'search-result'):
|
||||
self.results.append(i)
|
||||
|
||||
def nextSearchResult(self):
|
||||
if not self.results:
|
||||
return
|
||||
dest = self.results[self.current_result]
|
||||
self.listbox.set_focus(dest)
|
||||
self.listbox._invalidate()
|
||||
self.current_result += 1
|
||||
if self.current_result >= len(self.results):
|
||||
self.current_result = 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user