def line_index_from_super (self, super_line_index):
+ if len (self.filters) == 0:
+ # Identity.
+ return super_line_index
+
try:
return self.from_super_index[super_line_index]
except KeyError:
def line_index_to_super (self, line_index):
+ if len (self.filters) == 0:
+ # Identity.
+ return 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:
- return
- filter = self.filters[0] # FIXME
- enum = self.super_model.iter_rows_offset ()
- for row, offset in enum:
- if not offset in self.line_offsets: # FIXME: Slow test.
- if filter.filter_func (row):
- # FIXME: This assumes that offsets are consecutive.
- position = bisect_right (self.line_offsets, offset)
- self.line_offsets.insert (position, offset)
- self.line_levels.insert (position, row[self.COL_LEVEL])
+ last_index = len (self.line_offsets) - 1
+ if end_index < last_index:
+ self.__remove_range (end_index + 1, last_index - 1)
+
+ if start_index > 0:
+ self.__remove_range (0, start_index - 1)
+
+ def __remove_range (self, start, end):
+
+ del self.line_offsets[start:end + 1]
+ 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):
def __len__ (self):
- return self.end - self.start
+ return self.end - self.start + 1
def __iter__ (self):
+ # FIXME: Use itertools, should be faster!
l = self.l
i = self.start
while i <= self.end:
yield l[i]
+ i += 1
class RangeFilteredLogModel (FilteredLogModelBase):
self.line_levels = SubRange (self.super_model.line_levels,
start_index, last_index)
+ def reset (self):
+
+ self.set_range (0, len (self.super_model) - 1,)
+
def line_index_to_super (self, line_index):
start_index = self.line_index_range[0]
def handle_log_view_row_activated (self, view, path, column):
- log_filter = view.props.model
+ log_model = view.props.model
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
if line_model is None:
return
if len (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
position = bisect_right (timestamps, row[line_model.COL_TIME])
else:
self.actions.add_group (self.column_manager.action_group)
self.log_file = None
- self.log_model = LazyLogModel ()
- self.log_filter = FilteredLogModelIdentity (self.log_model)
+ self.setup_model (LazyLogModel ())
glade_filename = os.path.join (Main.Paths.data_dir, "gst-debug-viewer.glade")
self.widget_factory = Common.GUI.WidgetFactory (glade_filename)
self.attach ()
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):
return self.widgets.vbox_main
self.logger.debug ("requesting close from app")
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
previous_model = self.log_view.props.model
if previous_model:
else:
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
if selected_index is None:
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:
filtered_line_index = self.get_active_line_index ()
except ValueError:
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",
filtered_line_index,
last_index,
first_index)
- self.log_filter = RangeFilteredLogModel (self.log_model)
- self.log_filter.set_range (first_index, last_index + 1)
- self.change_model (self.log_filter)
+ self.log_range.set_range (first_index, last_index)
+ if self.log_filter:
+ self.log_filter.super_model_changed_range ()
+ self.update_model ()
self.actions.show_hidden_lines.props.sensitive = True
def handle_hide_before_line_action_activate (self, action):
filtered_line_index = self.get_active_line_index ()
except ValueError:
return
- first_index = self.log_filter.line_index_to_top (filtered_line_index)
- last_index = self.log_filter.line_index_to_top (len (self.log_filter) - 1)
+ model = self.log_view.props.model
+ 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",
filtered_line_index,
first_index,
last_index)
- self.log_filter = RangeFilteredLogModel (self.log_model)
- self.log_filter.set_range (first_index, last_index)
- self.change_model (self.log_filter)
+ self.log_range.set_range (first_index, last_index)
+ if self.log_filter:
+ self.log_filter.super_model_changed_range ()
+ self.update_model ()
self.actions.show_hidden_lines.props.sensitive = True
def handle_show_hidden_lines_action_activate (self, action):
self.logger.info ("restoring model filter to show all lines")
- if hasattr (self, "model_filter"):
- del self.model_filter # FIXME
- self.log_filter = FilteredLogModelIdentity (self.log_model)
- self.change_model (self.log_filter)
+ self.log_range.reset ()
+ self.log_filter = None
+ self.update_model (self.log_range)
self.actions.show_hidden_lines.props.sensitive = False
def handle_edit_copy_line_action_activate (self, action):
dispatcher = Common.Data.GSourceDispatcher ()
self.filter_dispatcher = dispatcher
- if not hasattr (self, "model_filter"): # FIXME
- self.had_model_filter = False
- model = FilteredLogModel (self.log_model)
- model.handle_process_finished = self.handle_model_filter_process_finished
- model.add_filter (filter, dispatcher = dispatcher)
- self.model_filter = model
-
- # FIXME: Unsetting the model to keep e.g. the dispatched timeline
- # 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)
+ # FIXME: Unsetting the model to keep e.g. the dispatched timeline
+ # sentinel from collecting data while we filter idly, which slows
+ # things down for nothing.
+ self.log_view.set_model (None)
+ if self.log_filter is None:
+ self.log_filter = FilteredLogModel (self.log_range)
+ self.log_filter.handle_process_finished = self.handle_log_filter_process_finished
+ self.log_filter.add_filter (filter, dispatcher = dispatcher)
gobject.timeout_add (250, self.update_filter_progress)
if self.progress_dialog is None:
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)
return True
# FIXME: Implement filter cancelling correctly; the stuff below does
# not work.
- self.model_filter.abort_process ()
- self.model_filter.reset ()
+ self.log_filter.abort_process ()
+ self.log_filter.reset ()
# FIXME:
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 = None
- if not self.had_model_filter: # FIXME
- self.change_model (self.model_filter)
- else:
- self.log_view.props.model = self.model_filter
+ self.update_model (self.log_filter)
self.actions.show_hidden_lines.props.sensitive = True
self.logger.debug ("setting log file %r", filename)
try:
- self.log_model = LazyLogModel ()
- self.log_filter = FilteredLogModelIdentity (self.log_model)
+ self.setup_model (LazyLogModel ())
self.dispatcher = Common.Data.GSourceDispatcher ()
self.log_file = Data.LogFile (filename, self.dispatcher)
self.progress_dialog = None
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.groups["RowActions"].props.sensitive = True
self.actions.show_hidden_lines.props.sensitive = False
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)
for feature in self.features:
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.select_path ((0,))
return False