tools: in performance-log-viewer.py, allow inverting selection

In the perofmance-log viewer, add header-bar buttons to clear and
invert the selection, and allow inverting the selection by ctrl-
right-clicking on the sample-selection area.

Update the docs.

(cherry picked from commit b74c33db5c)
This commit is contained in:
Ell
2019-01-16 03:55:18 -05:00
parent 46c5e8f33f
commit 940cf5f196
2 changed files with 57 additions and 8 deletions

View File

@ -28,7 +28,8 @@ report performance-related issues.
- [4.2.4.1.2. Call-Graph Direction](#42412-call-graph-direction) - [4.2.4.1.2. Call-Graph Direction](#42412-call-graph-direction)
- [4.2.4.2. Function Columns](#4242-function-columns) - [4.2.4.2. Function Columns](#4242-function-columns)
- [4.2.4.3. Source Columns](#4243-source-columns) - [4.2.4.3. Source Columns](#4243-source-columns)
- [4.3. Searching Samples](#43-searching-samples) - [4.3. Selection Modifiers](#43-selection-modifiers)
- [4.3.1. Searching Samples](#431-searching-samples)
- [4.4. History Navigation](#44-history-navigation) - [4.4. History Navigation](#44-history-navigation)
- [4.5. Environment Variables](#45-environment-variables) - [4.5. Environment Variables](#45-environment-variables)
- [5. Performance-Log Parameters](#5-performance-log-parameters) - [5. Performance-Log Parameters](#5-performance-log-parameters)
@ -212,11 +213,13 @@ add-to, subtract-from, and intersect-with the current selection, respectively.
Samples can also be selected using the keyboard, with the arrow, *Home*/*End*, Samples can also be selected using the keyboard, with the arrow, *Home*/*End*,
and *Shift* keys, while any of the graphs has focus. and *Shift* keys, while any of the graphs has focus.
Right clicking on any of the graphs, or pressing *Escape* while they have Right-clicking on any of the graphs, or pressing *Escape* while they have
focus, clears the selection. focus, clears the selection.
The behavior when the selection is empty is equivalent to selecting all The behavior when the selection is empty is equivalent to selecting all
samples. samples.
*Ctrl*-right-clicking on any of the graphs inverts the selection.
### 4.2. Information Area ### 4.2. Information Area
The lower part of the viewer window is the *information area*. The lower part of the viewer window is the *information area*.
@ -497,10 +500,18 @@ the selected line, if possible (see
[section *4.5*](#45-environment-variables)). [section *4.5*](#45-environment-variables)).
The button's tooltip shows the full path to the file. The button's tooltip shows the full path to the file.
### 4.3. Searching Samples ### 4.3. Selection Modifiers
The *Find Samples* button on the right side of the window's titlebar allows The buttons on the right side of the window's titlebar allow modifying the
searching for samples matching a user-defined condition. selection in various ways:
The *Clear Selection* and *Invert Selection* buttons clear and invert the
selection, respectively.
The *Find Samples* button allows searching for samples, as explained below.
#### 4.3.1. Searching Samples
The *Find Samples* button opens a popover allowing searching for all samples
matching a user-defined condition.
The condition should be a Python expression, evaluating to a boolean value. The condition should be a Python expression, evaluating to a boolean value.
The selected samples are those for which the expression evaluates to `True`. The selected samples are those for which the expression evaluates to `True`.

View File

@ -605,6 +605,12 @@ class Selection (GObject.GObject):
else: else:
self.select (set (), op) self.select (set (), op)
def clear (self):
self.select (set ())
def invert (self):
self.select_range (0, len (samples), SelectionOp.XOR)
def change_complete (self): def change_complete (self):
if self.pending_change_completion: if self.pending_change_completion:
self.pending_change_completion = False self.pending_change_completion = False
@ -972,6 +978,8 @@ class SampleGraph (Gtk.DrawingArea):
selection.cursor_dir = i1 - i0 selection.cursor_dir = i1 - i0
def do_button_press_event (self, event): def do_button_press_event (self, event):
state = event.state & Gdk.ModifierType.MODIFIER_MASK
self.grab_focus () self.grab_focus ()
if event.button == 1: if event.button == 1:
@ -986,8 +994,6 @@ class SampleGraph (Gtk.DrawingArea):
self.selection_op = SelectionOp.REPLACE self.selection_op = SelectionOp.REPLACE
self.selection_range = event.type != Gdk.EventType.BUTTON_PRESS self.selection_range = event.type != Gdk.EventType.BUTTON_PRESS
state = event.state & Gdk.ModifierType.MODIFIER_MASK
if state == Gdk.ModifierType.SHIFT_MASK: if state == Gdk.ModifierType.SHIFT_MASK:
self.selection_op = SelectionOp.ADD self.selection_op = SelectionOp.ADD
elif state == Gdk.ModifierType.CONTROL_MASK: elif state == Gdk.ModifierType.CONTROL_MASK:
@ -1000,7 +1006,10 @@ class SampleGraph (Gtk.DrawingArea):
self.grab_add () self.grab_add ()
elif event.button == 3: elif event.button == 3:
selection.select (set ()) if state == 0:
selection.clear ()
elif state == Gdk.ModifierType.CONTROL_MASK:
selection.invert ()
self.grab_add () self.grab_add ()
@ -3400,6 +3409,34 @@ class LogViewer (Gtk.Window):
self.find_popover = popover self.find_popover = popover
button.set_popover (popover) button.set_popover (popover)
def selection_action (action):
def f (*args):
action (selection)
selection.change_complete ()
return f
button = Gtk.Button.new_from_icon_name (
"object-flip-horizontal-symbolic",
Gtk.IconSize.BUTTON
)
header.pack_end (button)
button.set_tooltip_text ("Invert selection")
button.show ()
button.connect ("clicked", selection_action (Selection.invert))
button = Gtk.Button.new_from_icon_name (
"edit-clear-symbolic",
Gtk.IconSize.BUTTON
)
self.clear_selection_button = button
header.pack_end (button)
button.set_tooltip_text ("Clear selection")
button.show ()
button.connect ("clicked", selection_action (Selection.clear))
paned = Gtk.Paned (orientation = Gtk.Orientation.VERTICAL) paned = Gtk.Paned (orientation = Gtk.Orientation.VERTICAL)
self.paned = paned self.paned = paned
self.add (paned) self.add (paned)
@ -3468,6 +3505,7 @@ class LogViewer (Gtk.Window):
def selection_change_complete (self, selection): def selection_change_complete (self, selection):
self.header.set_subtitle (str (selection)) self.header.set_subtitle (str (selection))
self.clear_selection_button.set_sensitive (selection.selection)
def cflow_notify_available (self, *args): def cflow_notify_available (self, *args):
if self.backtrace_viewer.available: if self.backtrace_viewer.available: