Commit 940cf5f1 authored by Ell's avatar Ell

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 b74c33db)
parent 46c5e8f3
...@@ -28,7 +28,8 @@ report performance-related issues. ...@@ -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. ...@@ -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 ...@@ -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 buttons on the right side of the window's titlebar allow modifying the
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 on the right side of the window's titlebar allows The *Find Samples* button opens a popover allowing searching for all samples
searching for samples matching a user-defined condition. 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`.
......
...@@ -605,6 +605,12 @@ class Selection (GObject.GObject): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment