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



commit b74c33db5ce5d3706353f65741a3f96e40e375e7
Author: Ell <ell_se yahoo com>
Date:   Wed Jan 16 03:55:18 2019 -0500

    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.

 devel-docs/performance-logs/performance-logs.md | 21 +++++++++---
 tools/performance-log-viewer.py                 | 44 +++++++++++++++++++++++--
 2 files changed, 57 insertions(+), 8 deletions(-)
---
diff --git a/devel-docs/performance-logs/performance-logs.md b/devel-docs/performance-logs/performance-logs.md
index c764c34944..a131049c7c 100644
--- a/devel-docs/performance-logs/performance-logs.md
+++ b/devel-docs/performance-logs/performance-logs.md
@@ -28,7 +28,8 @@ report performance-related issues.
           - [4.2.4.1.2. Call-Graph Direction](#42412-call-graph-direction)
         - [4.2.4.2. Function Columns](#4242-function-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.5. Environment Variables](#45-environment-variables)
   - [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*,
 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.
 The behavior when the selection is empty is equivalent to selecting all
 samples.
 
+*Ctrl*-right-clicking on any of the graphs inverts the selection.
+
 ### 4.2. 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)).
 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
-searching for samples matching a user-defined condition.
+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 selected samples are those for which the expression evaluates to `True`.
 
diff --git a/tools/performance-log-viewer.py b/tools/performance-log-viewer.py
index 4c90c682c4..aa58625bed 100755
--- a/tools/performance-log-viewer.py
+++ b/tools/performance-log-viewer.py
@@ -605,6 +605,12 @@ class Selection (GObject.GObject):
         else:
             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):
         if self.pending_change_completion:
             self.pending_change_completion = False
@@ -972,6 +978,8 @@ class SampleGraph (Gtk.DrawingArea):
         selection.cursor_dir = i1 - i0
 
     def do_button_press_event (self, event):
+        state = event.state & Gdk.ModifierType.MODIFIER_MASK
+
         self.grab_focus ()
 
         if event.button == 1:
@@ -986,8 +994,6 @@ class SampleGraph (Gtk.DrawingArea):
             self.selection_op    = SelectionOp.REPLACE
             self.selection_range = event.type != Gdk.EventType.BUTTON_PRESS
 
-            state = event.state & Gdk.ModifierType.MODIFIER_MASK
-
             if state == Gdk.ModifierType.SHIFT_MASK:
                 self.selection_op = SelectionOp.ADD
             elif state == Gdk.ModifierType.CONTROL_MASK:
@@ -1000,7 +1006,10 @@ class SampleGraph (Gtk.DrawingArea):
 
             self.grab_add ()
         elif event.button == 3:
-            selection.select (set ())
+            if state == 0:
+                selection.clear ()
+            elif state == Gdk.ModifierType.CONTROL_MASK:
+                selection.invert ()
 
             self.grab_add ()
 
@@ -3400,6 +3409,34 @@ class LogViewer (Gtk.Window):
         self.find_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)
         self.paned = paned
         self.add (paned)
@@ -3468,6 +3505,7 @@ class LogViewer (Gtk.Window):
 
     def selection_change_complete (self, selection):
         self.header.set_subtitle (str (selection))
+        self.clear_selection_button.set_sensitive (selection.selection)
 
     def cflow_notify_available (self, *args):
         if self.backtrace_viewer.available:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]