diff options
author | René Stadler <mail@renestadler.de> | 2012-08-24 01:50:44 +0200 |
---|---|---|
committer | René Stadler <mail@renestadler.de> | 2012-08-24 01:58:34 +0200 |
commit | eeba6d7b20435e647676d7f68b7ac70c9ecc48db (patch) | |
tree | fd1660606d2937735460403a092484a8e672a553 /GstDebugViewer | |
parent | 91cc5b693f075e290bdc3f6637ca9d25b141c2d3 (diff) |
Simplify and optimize filtered model implementation
RangeFilteredLogModel is gone. The functionality is trivially implemented in
FilteredLogModel now. Changing the range is now O(log n) at worst (was O(n) at
best, for rewriting the arrays). Stacking filtered models is not supported
anymore, which simplifies the code.
Diffstat (limited to 'GstDebugViewer')
-rw-r--r-- | GstDebugViewer/GUI/models.py | 240 | ||||
-rw-r--r-- | GstDebugViewer/GUI/window.py | 33 |
2 files changed, 53 insertions, 220 deletions
diff --git a/GstDebugViewer/GUI/models.py b/GstDebugViewer/GUI/models.py index 9d57b05..e760b2b 100644 --- a/GstDebugViewer/GUI/models.py +++ b/GstDebugViewer/GUI/models.py @@ -233,41 +233,6 @@ class FilteredLogModelBase (LogModelBase): raise NotImplementedError ("index conversion not supported") - def line_index_to_top (self, line_index): - - _log_indices = [line_index] - - super_index = line_index - for model in self._iter_hierarchy (): - super_index = model.line_index_to_super (super_index) - _log_indices.append (super_index) - - _log_trans = " -> ".join ([str (x) for x in _log_indices]) - self.logger.debug ("translated index to top: %s", _log_trans) - - return super_index - - def line_index_from_top (self, super_index): - - _log_indices = [super_index] - - line_index = super_index - for model in reversed (list (self._iter_hierarchy ())): - line_index = model.line_index_from_super (line_index) - _log_indices.append (line_index) - - _log_trans = " -> ".join ([str (x) for x in _log_indices]) - self.logger.debug ("translated index from top: %s", _log_trans) - - return line_index - - def _iter_hierarchy (self): - - model = self - while hasattr (model, "super_model") and model.super_model: - yield model - model = model.super_model - class FilteredLogModel (FilteredLogModelBase): def __init__ (self, super_model): @@ -276,29 +241,16 @@ class FilteredLogModel (FilteredLogModelBase): self.logger = logging.getLogger ("filtered-log-model") - self.range_model = RangeFilteredLogModel (super_model) - self.filters = [] - self.super_index = [] - self.from_super_index = {} self.reset () self.__active_process = None self.__filter_progress = 0. - def _iter_hierarchy (self): - - yield self - yield self.range_model - def reset (self): - range_model = self.range_model - range_model.reset () - self.line_offsets = range_model.line_offsets - self.line_levels = range_model.line_levels - - del self.super_index[:] - self.from_super_index.clear () + self.line_offsets = self.super_model.line_offsets + self.line_levels = self.super_model.line_levels + self.super_index = xrange (len (self.line_offsets)) del self.filters[:] @@ -312,23 +264,14 @@ class FilteredLogModel (FilteredLogModelBase): new_line_offsets = [] new_line_levels = [] new_super_index = [] - new_from_super_index = {} level_id = self.COL_LEVEL func = filter.filter_func - if len (self.filters) == 1: - # This is the first filter that gets applied. - def enum (): - i = 0 - for row, offset in self.iter_rows_offset (): - yield (i, row, offset,) - i += 1 - else: - def enum (): - i = 0 - for row, offset in self.iter_rows_offset (): - line_index = self.super_index[i] - yield (line_index, row, offset,) - i += 1 + def enum (): + i = 0 + for row, offset in self.iter_rows_offset (): + line_index = self.super_index[i] + yield (line_index, row, offset,) + i += 1 self.logger.debug ("running filter") progress = 0. progress_full = float (len (self)) @@ -338,7 +281,6 @@ class FilteredLogModel (FilteredLogModelBase): new_line_offsets.append (offset) new_line_levels.append (row[level_id]) new_super_index.append (i) - new_from_super_index[i] = len (new_super_index) - 1 y -= 1 if y == 0: progress += float (YIELD_LIMIT) @@ -348,7 +290,6 @@ class FilteredLogModel (FilteredLogModelBase): self.line_offsets = new_line_offsets self.line_levels = new_line_levels self.super_index = new_super_index - self.from_super_index = new_from_super_index self.logger.debug ("filtering finished") self.__filter_progress = 1. @@ -395,112 +336,45 @@ class FilteredLogModel (FilteredLogModelBase): 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: - raise IndexError ("super index %i not handled" % (super_line_index,)) + return bisect_left (self.super_index, super_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] - def __filtered_indices_in_range (self, start, stop): - - if start < 0: - raise ValueError ("start cannot be negative (got %r)" % (start,)) - - super_start = bisect_left (self.super_index, start) - super_stop = bisect_left (self.super_index, stop) + def set_range (self, super_start, super_stop): - return super_stop - super_start + old_super_start = self.line_index_to_super (0) + old_super_stop = self.line_index_to_super (len (self.super_index) - 1) + 1 - def set_range (self, start_index, stop_index): + self.logger.debug ("set range (%i, %i), current (%i, %i)", + super_start, super_stop, old_super_start, old_super_stop) - range_model = self.range_model - old_start, old_stop = range_model.line_index_range - range_model.set_range (start_index, stop_index) - - if isinstance (self.line_offsets, SubRange): - # FIXME: Can only take this shortcut when shrinking the range. - self.line_offsets = range_model.line_offsets - self.line_levels = range_model.line_levels + if len (self.filters) == 0: + # Identity. + self.super_index = xrange (super_start, super_stop) + self.line_offsets = SubRange (self.super_model.line_offsets, + super_start, super_stop) + self.line_levels = SubRange (self.super_model.line_levels, + super_start, super_stop) return - super_start, super_stop = range_model.line_index_range - - super_start_offset = super_start - old_start - if super_start_offset < 0: + if super_start < old_super_start: # TODO: raise NotImplementedError ("Only handling further restriction of the range" - " (start offset = %i)" % (super_start_offset,)) + " (start offset = %i)" % (start_offset,)) - super_end_offset = super_stop - old_stop - if super_end_offset > 0: + if super_stop > old_super_stop: # TODO: raise NotImplementedError ("Only handling further restriction of the range" - " (end offset = %i)" % (super_end_offset,)) - - if super_end_offset < 0: - if not self.super_index: - # Identity; there are no filters. - end_offset = len (self.line_offsets) + super_end_offset - else: - n_filtered = self.__filtered_indices_in_range (super_stop - super_start, - old_stop - super_start) - end_offset = len (self.line_offsets) - n_filtered - stop = len (self.line_offsets) # FIXME? - assert end_offset < stop - - self.__remove_range (end_offset, stop) - - if super_start_offset > 0: - if not self.super_index: - # Identity; there are no filters. - n_filtered = super_start_offset - start_offset = n_filtered - else: - n_filtered = self.__filtered_indices_in_range (0, super_start_offset) - start_offset = n_filtered - - if n_filtered > 0: - self.__remove_range (0, start_offset) - - from_super = self.from_super_index - for i in self.super_index: - old_index = from_super[i] - del from_super[i] - from_super[i - super_start_offset] = old_index - start_offset - - for i in range (len (self.super_index)): - self.super_index[i] -= super_start_offset - - def __remove_range (self, start, stop): - - if start < 0: - raise ValueError ("start cannot be negative (got %r)" % (start,)) - if start == stop: - return - if stop > len (self.line_offsets): - raise ValueError ("stop value out of range (got %r)" % (stop,)) - if start > stop: - raise ValueError ("start cannot be greater than stop (got %r, %r)" % (start, stop,)) + " (end offset = %i)" % (stop_offset,)) - self.logger.debug ("removing line range (%i, %i)", - start, stop) + start = self.line_index_from_super (super_start) + stop = self.line_index_from_super (super_stop) - del self.line_offsets[start:stop] - del self.line_levels[start:stop] - for super_index in self.super_index[start:stop]: - del self.from_super_index[super_index] - del self.super_index[start:stop] + self.super_index = SubRange (self.super_index, start, stop) + self.line_offsets = SubRange (self.line_offsets, start, stop) + self.line_levels = SubRange (self.line_levels, start, stop) class SubRange (object): @@ -511,6 +385,12 @@ class SubRange (object): if start > stop: raise ValueError ("need start <= stop (got %r, %r)" % (start, stop,)) + if type (l) == type (self): + # Another SubRange, don't stack: + start += l.start + stop += l.start + l = l.l + self.l = l self.start = start self.stop = stop @@ -529,51 +409,6 @@ class SubRange (object): for i in xrange (self.start, self.stop): yield l[i] -class RangeFilteredLogModel (FilteredLogModelBase): - - def __init__ (self, super_model): - - FilteredLogModelBase.__init__ (self, super_model) - - self.logger = logging.getLogger ("range-filtered-model") - - self.line_index_range = None - - def set_range (self, start_index, stop_index): - - self.logger.debug ("setting range to start = %i, stop = %i", - start_index, stop_index) - - self.line_index_range = (start_index, stop_index,) - self.line_offsets = SubRange (self.super_model.line_offsets, - start_index, stop_index) - self.line_levels = SubRange (self.super_model.line_levels, - start_index, stop_index) - - def reset (self): - - self.logger.debug ("reset") - - start_index = 0 - stop_index = len (self.super_model) - - self.set_range (start_index, stop_index,) - - def line_index_to_super (self, line_index): - - start_index = self.line_index_range[0] - - return line_index + start_index - - def line_index_from_super (self, li): - - start, stop = self.line_index_range - - if li < start or li >= stop: - raise IndexError ("not in range") - - return li - start - class LineViewLogModel (FilteredLogModelBase): def __init__ (self, super_model): @@ -627,4 +462,3 @@ class LineViewLogModel (FilteredLogModelBase): path = (line_index,) self.row_deleted (path) - diff --git a/GstDebugViewer/GUI/window.py b/GstDebugViewer/GUI/window.py index 75d79a1..4c7e201 100644 --- a/GstDebugViewer/GUI/window.py +++ b/GstDebugViewer/GUI/window.py @@ -41,8 +41,7 @@ from GstDebugViewer.GUI.filters import (CategoryFilter, from GstDebugViewer.GUI.models import (FilteredLogModel, LazyLogModel, LineViewLogModel, - LogModelBase, - RangeFilteredLogModel) + LogModelBase) def action (func): @@ -119,8 +118,8 @@ class LineView (object): line_index = path[0] line_model = view.get_model () log_model = self.log_view.get_model () - top_index = line_model.line_index_to_top (line_index) - log_index = log_model.line_index_from_top (top_index) + super_index = line_model.line_index_to_super (line_index) + log_index = log_model.line_index_from_super (super_index) path = (log_index,) self.log_view.scroll_to_cell (path, use_align = True, row_align = .5) sel = self.log_view.get_selection () @@ -131,7 +130,7 @@ class LineView (object): log_model = view.get_model () line_index = path[0] - top_line_index = log_model.line_index_to_top (line_index) + super_index = log_model.line_index_to_super (line_index) line_model = self.line_view.get_model () if line_model is None: return @@ -143,14 +142,14 @@ class LineView (object): else: position = 0 if len (line_model) > 1: - other_index = line_model.line_index_to_top (position - 1) + other_index = line_model.line_index_to_super (position - 1) else: other_index = -1 - if other_index == top_line_index and position != 1: + if other_index == super_index and position != 1: # Already have the line. pass else: - line_model.insert_line (position, top_line_index) + line_model.insert_line (position, super_index) self.clear_action.props.sensitive = True def handle_log_view_selection_changed (self, selection): @@ -165,7 +164,7 @@ class LineView (object): return path = model.get_path (tree_iter) - line_index = model.line_index_to_top (path[0]) + line_index = model.line_index_to_super (path[0]) if len (line_model) == 0: line_model.insert_line (0, line_index) @@ -409,7 +408,7 @@ class Window (object): super_index = None self.logger.debug ("no line selected") else: - super_index = model.line_index_to_top (line_index) + super_index = model.line_index_to_super (line_index) self.logger.debug ("pushing selected line %i (abs %i)", line_index, super_index) @@ -419,7 +418,7 @@ class Window (object): if vis_range is not None: start_path, end_path = vis_range start_index = start_path[0] - self.default_start_index = model.line_index_to_top (start_index) + self.default_start_index = model.line_index_to_super (start_index) def update_model (self, model = None): @@ -445,7 +444,7 @@ class Window (object): if selected_index is not None: try: - select_index = model.line_index_from_top (selected_index) + select_index = model.line_index_from_super (selected_index) except IndexError as exc: self.logger.debug ("abs line index %i filtered out, not reselecting", selected_index) @@ -467,7 +466,7 @@ class Window (object): yield i for current_index in traverse (): try: - target_index = model.line_index_from_top (current_index) + target_index = model.line_index_from_super (current_index) except IndexError: continue else: @@ -574,16 +573,16 @@ class Window (object): return if after: - first_index = model.line_index_to_top (0) - last_index = model.line_index_to_top (filtered_line_index) + first_index = model.line_index_to_super (0) + last_index = model.line_index_to_super (filtered_line_index) self.logger.info ("hiding lines after %i (abs %i), first line is abs %i", filtered_line_index, last_index, first_index) else: - first_index = model.line_index_to_top (filtered_line_index) - last_index = model.line_index_to_top (len (model) - 1) + first_index = model.line_index_to_super (filtered_line_index) + last_index = model.line_index_to_super (len (model) - 1) self.logger.info ("hiding lines before %i (abs %i), last line is abs %i", filtered_line_index, |