mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 17:20:36 +00:00
Preserve clamped timestamp range when filtering and vice versa
This commit is contained in:
parent
98444f652f
commit
d87731efcc
1 changed files with 97 additions and 63 deletions
160
debug-viewer/GstDebugViewer/GUI.py
Executable file → Normal file
160
debug-viewer/GstDebugViewer/GUI.py
Executable file → Normal file
|
@ -518,6 +518,10 @@ class FilteredLogModel (FilteredLogModelBase):
|
||||||
|
|
||||||
def line_index_from_super (self, super_line_index):
|
def line_index_from_super (self, super_line_index):
|
||||||
|
|
||||||
|
if len (self.filters) == 0:
|
||||||
|
# Identity.
|
||||||
|
return super_line_index
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self.from_super_index[super_line_index]
|
return self.from_super_index[super_line_index]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -525,25 +529,37 @@ class FilteredLogModel (FilteredLogModelBase):
|
||||||
|
|
||||||
def line_index_to_super (self, line_index):
|
def line_index_to_super (self, line_index):
|
||||||
|
|
||||||
|
if len (self.filters) == 0:
|
||||||
|
# Identity.
|
||||||
|
return line_index
|
||||||
|
|
||||||
return self.super_index[line_index]
|
return self.super_index[line_index]
|
||||||
|
|
||||||
def super_model_changed (self):
|
def super_model_changed_range (self):
|
||||||
|
|
||||||
from bisect import bisect_right
|
range_model = self.super_model
|
||||||
|
super_start, super_end = range_model.line_index_range
|
||||||
|
|
||||||
self.reset () # FIXME: Only remove obsolete lines.
|
start_index = self.line_index_from_super (super_start)
|
||||||
|
end_index = self.line_index_from_super (super_end)
|
||||||
|
|
||||||
if not self.filters:
|
last_index = len (self.line_offsets) - 1
|
||||||
return
|
if end_index < last_index:
|
||||||
filter = self.filters[0] # FIXME
|
self.__remove_range (end_index + 1, last_index - 1)
|
||||||
enum = self.super_model.iter_rows_offset ()
|
|
||||||
for row, offset in enum:
|
if start_index > 0:
|
||||||
if not offset in self.line_offsets: # FIXME: Slow test.
|
self.__remove_range (0, start_index - 1)
|
||||||
if filter.filter_func (row):
|
|
||||||
# FIXME: This assumes that offsets are consecutive.
|
def __remove_range (self, start, end):
|
||||||
position = bisect_right (self.line_offsets, offset)
|
|
||||||
self.line_offsets.insert (position, offset)
|
del self.line_offsets[start:end + 1]
|
||||||
self.line_levels.insert (position, row[self.COL_LEVEL])
|
del self.line_levels[start:end + 1]
|
||||||
|
for super_index in self.super_index[start:end + 1]:
|
||||||
|
del self.from_super_index[super_index]
|
||||||
|
del self.super_index[start:end + 1]
|
||||||
|
if start > 0:
|
||||||
|
for super_index in self.super_index:
|
||||||
|
self.from_super_index[super_index] -= start
|
||||||
|
|
||||||
class Filter (object):
|
class Filter (object):
|
||||||
|
|
||||||
|
@ -584,14 +600,16 @@ class SubRange (object):
|
||||||
|
|
||||||
def __len__ (self):
|
def __len__ (self):
|
||||||
|
|
||||||
return self.end - self.start
|
return self.end - self.start + 1
|
||||||
|
|
||||||
def __iter__ (self):
|
def __iter__ (self):
|
||||||
|
|
||||||
|
# FIXME: Use itertools, should be faster!
|
||||||
l = self.l
|
l = self.l
|
||||||
i = self.start
|
i = self.start
|
||||||
while i <= self.end:
|
while i <= self.end:
|
||||||
yield l[i]
|
yield l[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
class RangeFilteredLogModel (FilteredLogModelBase):
|
class RangeFilteredLogModel (FilteredLogModelBase):
|
||||||
|
|
||||||
|
@ -609,6 +627,10 @@ class RangeFilteredLogModel (FilteredLogModelBase):
|
||||||
self.line_levels = SubRange (self.super_model.line_levels,
|
self.line_levels = SubRange (self.super_model.line_levels,
|
||||||
start_index, last_index)
|
start_index, last_index)
|
||||||
|
|
||||||
|
def reset (self):
|
||||||
|
|
||||||
|
self.set_range (0, len (self.super_model) - 1,)
|
||||||
|
|
||||||
def line_index_to_super (self, line_index):
|
def line_index_to_super (self, line_index):
|
||||||
|
|
||||||
start_index = self.line_index_range[0]
|
start_index = self.line_index_range[0]
|
||||||
|
@ -1343,17 +1365,17 @@ class LineView (object):
|
||||||
|
|
||||||
def handle_log_view_row_activated (self, view, path, column):
|
def handle_log_view_row_activated (self, view, path, column):
|
||||||
|
|
||||||
log_filter = view.props.model
|
log_model = view.props.model
|
||||||
line_index = path[0]
|
line_index = path[0]
|
||||||
|
|
||||||
super_line_index = log_filter.line_index_to_super (line_index)
|
super_line_index = log_model.line_index_to_super (line_index)
|
||||||
line_model = self.line_view.props.model
|
line_model = self.line_view.props.model
|
||||||
if line_model is None:
|
if line_model is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if len (line_model):
|
if len (line_model):
|
||||||
timestamps = [row[line_model.COL_TIME] for row in line_model]
|
timestamps = [row[line_model.COL_TIME] for row in line_model]
|
||||||
row = log_filter[(line_index,)]
|
row = log_model[(line_index,)]
|
||||||
from bisect import bisect_right
|
from bisect import bisect_right
|
||||||
position = bisect_right (timestamps, row[line_model.COL_TIME])
|
position = bisect_right (timestamps, row[line_model.COL_TIME])
|
||||||
else:
|
else:
|
||||||
|
@ -1481,8 +1503,7 @@ class Window (object):
|
||||||
self.actions.add_group (self.column_manager.action_group)
|
self.actions.add_group (self.column_manager.action_group)
|
||||||
|
|
||||||
self.log_file = None
|
self.log_file = None
|
||||||
self.log_model = LazyLogModel ()
|
self.setup_model (LazyLogModel ())
|
||||||
self.log_filter = FilteredLogModelIdentity (self.log_model)
|
|
||||||
|
|
||||||
glade_filename = os.path.join (Main.Paths.data_dir, "gst-debug-viewer.glade")
|
glade_filename = os.path.join (Main.Paths.data_dir, "gst-debug-viewer.glade")
|
||||||
self.widget_factory = Common.GUI.WidgetFactory (glade_filename)
|
self.widget_factory = Common.GUI.WidgetFactory (glade_filename)
|
||||||
|
@ -1510,6 +1531,16 @@ class Window (object):
|
||||||
self.attach ()
|
self.attach ()
|
||||||
self.column_manager.attach (self.log_view)
|
self.column_manager.attach (self.log_view)
|
||||||
|
|
||||||
|
def setup_model (self, model, filter = False):
|
||||||
|
|
||||||
|
self.log_model = model
|
||||||
|
self.log_range = RangeFilteredLogModel (self.log_model)
|
||||||
|
if filter:
|
||||||
|
self.log_filter = FilteredLogModel (self.log_range)
|
||||||
|
self.log_filter.handle_process_finished = self.handle_log_filter_process_finished
|
||||||
|
else:
|
||||||
|
self.log_filter = None
|
||||||
|
|
||||||
def get_top_attach_point (self):
|
def get_top_attach_point (self):
|
||||||
|
|
||||||
return self.widgets.vbox_main
|
return self.widgets.vbox_main
|
||||||
|
@ -1592,8 +1623,10 @@ class Window (object):
|
||||||
self.logger.debug ("requesting close from app")
|
self.logger.debug ("requesting close from app")
|
||||||
self.app.close_window (self)
|
self.app.close_window (self)
|
||||||
|
|
||||||
def change_model (self, model):
|
def update_model (self, model = None):
|
||||||
|
|
||||||
|
if model is None:
|
||||||
|
model = self.log_view.props.model
|
||||||
selected_index = None
|
selected_index = None
|
||||||
previous_model = self.log_view.props.model
|
previous_model = self.log_view.props.model
|
||||||
if previous_model:
|
if previous_model:
|
||||||
|
@ -1604,6 +1637,9 @@ class Window (object):
|
||||||
else:
|
else:
|
||||||
selected_index = previous_model.line_index_to_super (line_index)
|
selected_index = previous_model.line_index_to_super (line_index)
|
||||||
|
|
||||||
|
if previous_model == model:
|
||||||
|
# Force update.
|
||||||
|
self.log_view.set_model (None)
|
||||||
self.log_view.props.model = model
|
self.log_view.props.model = model
|
||||||
|
|
||||||
if selected_index is None:
|
if selected_index is None:
|
||||||
|
@ -1682,21 +1718,23 @@ class Window (object):
|
||||||
|
|
||||||
def handle_hide_after_line_action_activate (self, action):
|
def handle_hide_after_line_action_activate (self, action):
|
||||||
|
|
||||||
first_index = self.log_filter.line_index_to_top (0)
|
model = self.log_view.props.model
|
||||||
|
first_index = model.line_index_to_top (0)
|
||||||
try:
|
try:
|
||||||
filtered_line_index = self.get_active_line_index ()
|
filtered_line_index = self.get_active_line_index ()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return
|
return
|
||||||
last_index = self.log_filter.line_index_to_top (filtered_line_index)
|
last_index = model.line_index_to_top (filtered_line_index)
|
||||||
|
|
||||||
self.logger.info ("hiding lines after %i (abs %i), first line is abs %i",
|
self.logger.info ("hiding lines after %i (abs %i), first line is abs %i",
|
||||||
filtered_line_index,
|
filtered_line_index,
|
||||||
last_index,
|
last_index,
|
||||||
first_index)
|
first_index)
|
||||||
|
|
||||||
self.log_filter = RangeFilteredLogModel (self.log_model)
|
self.log_range.set_range (first_index, last_index)
|
||||||
self.log_filter.set_range (first_index, last_index + 1)
|
if self.log_filter:
|
||||||
self.change_model (self.log_filter)
|
self.log_filter.super_model_changed_range ()
|
||||||
|
self.update_model ()
|
||||||
self.actions.show_hidden_lines.props.sensitive = True
|
self.actions.show_hidden_lines.props.sensitive = True
|
||||||
|
|
||||||
def handle_hide_before_line_action_activate (self, action):
|
def handle_hide_before_line_action_activate (self, action):
|
||||||
|
@ -1705,26 +1743,27 @@ class Window (object):
|
||||||
filtered_line_index = self.get_active_line_index ()
|
filtered_line_index = self.get_active_line_index ()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return
|
return
|
||||||
first_index = self.log_filter.line_index_to_top (filtered_line_index)
|
model = self.log_view.props.model
|
||||||
last_index = self.log_filter.line_index_to_top (len (self.log_filter) - 1)
|
first_index = model.line_index_to_top (filtered_line_index)
|
||||||
|
last_index = model.line_index_to_top (len (model) - 1)
|
||||||
|
|
||||||
self.logger.info ("hiding lines before %i (abs %i), last line is abs %i",
|
self.logger.info ("hiding lines before %i (abs %i), last line is abs %i",
|
||||||
filtered_line_index,
|
filtered_line_index,
|
||||||
first_index,
|
first_index,
|
||||||
last_index)
|
last_index)
|
||||||
|
|
||||||
self.log_filter = RangeFilteredLogModel (self.log_model)
|
self.log_range.set_range (first_index, last_index)
|
||||||
self.log_filter.set_range (first_index, last_index)
|
if self.log_filter:
|
||||||
self.change_model (self.log_filter)
|
self.log_filter.super_model_changed_range ()
|
||||||
|
self.update_model ()
|
||||||
self.actions.show_hidden_lines.props.sensitive = True
|
self.actions.show_hidden_lines.props.sensitive = True
|
||||||
|
|
||||||
def handle_show_hidden_lines_action_activate (self, action):
|
def handle_show_hidden_lines_action_activate (self, action):
|
||||||
|
|
||||||
self.logger.info ("restoring model filter to show all lines")
|
self.logger.info ("restoring model filter to show all lines")
|
||||||
if hasattr (self, "model_filter"):
|
self.log_range.reset ()
|
||||||
del self.model_filter # FIXME
|
self.log_filter = None
|
||||||
self.log_filter = FilteredLogModelIdentity (self.log_model)
|
self.update_model (self.log_range)
|
||||||
self.change_model (self.log_filter)
|
|
||||||
self.actions.show_hidden_lines.props.sensitive = False
|
self.actions.show_hidden_lines.props.sensitive = False
|
||||||
|
|
||||||
def handle_edit_copy_line_action_activate (self, action):
|
def handle_edit_copy_line_action_activate (self, action):
|
||||||
|
@ -1750,21 +1789,14 @@ class Window (object):
|
||||||
dispatcher = Common.Data.GSourceDispatcher ()
|
dispatcher = Common.Data.GSourceDispatcher ()
|
||||||
self.filter_dispatcher = dispatcher
|
self.filter_dispatcher = dispatcher
|
||||||
|
|
||||||
if not hasattr (self, "model_filter"): # FIXME
|
# FIXME: Unsetting the model to keep e.g. the dispatched timeline
|
||||||
self.had_model_filter = False
|
# sentinel from collecting data while we filter idly, which slows
|
||||||
model = FilteredLogModel (self.log_model)
|
# things down for nothing.
|
||||||
model.handle_process_finished = self.handle_model_filter_process_finished
|
self.log_view.set_model (None)
|
||||||
model.add_filter (filter, dispatcher = dispatcher)
|
if self.log_filter is None:
|
||||||
self.model_filter = model
|
self.log_filter = FilteredLogModel (self.log_range)
|
||||||
|
self.log_filter.handle_process_finished = self.handle_log_filter_process_finished
|
||||||
# FIXME: Unsetting the model to keep e.g. the dispatched timeline
|
self.log_filter.add_filter (filter, dispatcher = dispatcher)
|
||||||
# sentinel from collecting data while we filter idly, which slows
|
|
||||||
# things down for nothing.
|
|
||||||
self.log_view.set_model (None)
|
|
||||||
else:
|
|
||||||
self.had_model_filter = True
|
|
||||||
self.log_view.set_model (None)
|
|
||||||
self.model_filter.add_filter (filter, dispatcher = dispatcher)
|
|
||||||
|
|
||||||
gobject.timeout_add (250, self.update_filter_progress)
|
gobject.timeout_add (250, self.update_filter_progress)
|
||||||
|
|
||||||
|
@ -1773,7 +1805,12 @@ class Window (object):
|
||||||
if self.progress_dialog is None:
|
if self.progress_dialog is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
progress = self.model_filter.get_filter_progress ()
|
try:
|
||||||
|
progress = self.log_filter.get_filter_progress ()
|
||||||
|
except ValueError:
|
||||||
|
self.logger.warning ("no filter process running")
|
||||||
|
return False
|
||||||
|
|
||||||
self.progress_dialog.update (progress)
|
self.progress_dialog.update (progress)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -1788,20 +1825,17 @@ class Window (object):
|
||||||
# FIXME: Implement filter cancelling correctly; the stuff below does
|
# FIXME: Implement filter cancelling correctly; the stuff below does
|
||||||
# not work.
|
# not work.
|
||||||
|
|
||||||
self.model_filter.abort_process ()
|
self.log_filter.abort_process ()
|
||||||
self.model_filter.reset ()
|
self.log_filter.reset ()
|
||||||
# FIXME:
|
# FIXME:
|
||||||
self.actions.show_hidden_lines.activate ()
|
self.actions.show_hidden_lines.activate ()
|
||||||
|
|
||||||
def handle_model_filter_process_finished (self):
|
def handle_log_filter_process_finished (self):
|
||||||
|
|
||||||
self.progress_dialog.destroy ()
|
self.progress_dialog.destroy ()
|
||||||
self.progress_dialog = None
|
self.progress_dialog = None
|
||||||
|
|
||||||
if not self.had_model_filter: # FIXME
|
self.update_model (self.log_filter)
|
||||||
self.change_model (self.model_filter)
|
|
||||||
else:
|
|
||||||
self.log_view.props.model = self.model_filter
|
|
||||||
|
|
||||||
self.actions.show_hidden_lines.props.sensitive = True
|
self.actions.show_hidden_lines.props.sensitive = True
|
||||||
|
|
||||||
|
@ -1858,8 +1892,7 @@ class Window (object):
|
||||||
self.logger.debug ("setting log file %r", filename)
|
self.logger.debug ("setting log file %r", filename)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.log_model = LazyLogModel ()
|
self.setup_model (LazyLogModel ())
|
||||||
self.log_filter = FilteredLogModelIdentity (self.log_model)
|
|
||||||
|
|
||||||
self.dispatcher = Common.Data.GSourceDispatcher ()
|
self.dispatcher = Common.Data.GSourceDispatcher ()
|
||||||
self.log_file = Data.LogFile (filename, self.dispatcher)
|
self.log_file = Data.LogFile (filename, self.dispatcher)
|
||||||
|
@ -1931,18 +1964,19 @@ class Window (object):
|
||||||
self.progress_dialog = None
|
self.progress_dialog = None
|
||||||
|
|
||||||
self.log_model.set_log (self.log_file)
|
self.log_model.set_log (self.log_file)
|
||||||
self.log_filter = FilteredLogModelIdentity (self.log_model)
|
self.log_range.reset ()
|
||||||
|
self.log_filter = None
|
||||||
|
|
||||||
self.actions.reload_file.props.sensitive = True
|
self.actions.reload_file.props.sensitive = True
|
||||||
self.actions.groups["RowActions"].props.sensitive = True
|
self.actions.groups["RowActions"].props.sensitive = True
|
||||||
self.actions.show_hidden_lines.props.sensitive = False
|
self.actions.show_hidden_lines.props.sensitive = False
|
||||||
|
|
||||||
def idle_set ():
|
def idle_set ():
|
||||||
self.log_view.props.model = self.log_filter
|
self.log_view.props.model = self.log_range
|
||||||
self.line_view.handle_attach_log_file (self)
|
self.line_view.handle_attach_log_file (self)
|
||||||
for feature in self.features:
|
for feature in self.features:
|
||||||
feature.handle_attach_log_file (self, self.log_file)
|
feature.handle_attach_log_file (self, self.log_file)
|
||||||
if len (self.log_filter):
|
if len (self.log_range):
|
||||||
sel = self.log_view.get_selection ()
|
sel = self.log_view.get_selection ()
|
||||||
sel.select_path ((0,))
|
sel.select_path ((0,))
|
||||||
return False
|
return False
|
||||||
|
|
Loading…
Reference in a new issue