Update the spacing and style.

Signed-off-by: John Kacur <jka...@redhat.com>
---
 tuna/gui/procview.py | 1333 +++++++++++++++++++++---------------------
 1 file changed, 661 insertions(+), 672 deletions(-)

diff --git a/tuna/gui/procview.py b/tuna/gui/procview.py
index 62ba9cf27949..fa70ab400a43 100755
--- a/tuna/gui/procview.py
+++ b/tuna/gui/procview.py
@@ -9,686 +9,675 @@ import re
 import schedutils
 
 try:
-       import perf
+    import perf
 except:
-       pass
+    pass
 
 def N_(s):
-       """gettext_noop"""
-       return s
+    """gettext_noop"""
+    return s
 
 class process_druid:
 
-       ( PROCESS_COL_PID, PROCESS_COL_NAME ) = list(range(2))
-
-       def __init__(self, ps, pid, pid_info, nr_cpus, gladefile):
-               self.ps = ps
-               self.pid = pid
-               self.pid_info = pid_info
-               self.nr_cpus = nr_cpus
-               self.window = Gtk.glade.XML(gladefile, 
"set_process_attributes", "tuna")
-               self.dialog = self.window.get_widget("set_process_attributes")
-               pixbuf = self.dialog.render_icon(Gtk.STOCK_PREFERENCES,
-                                                Gtk.IconSize.SMALL_TOOLBAR)
-               self.dialog.set_icon(pixbuf)
-               event_handlers = { "on_cmdline_regex_changed" : 
self.on_cmdline_regex_changed,
-                                  "on_affinity_text_changed" : 
self.on_affinity_text_changed,
-                                  "on_sched_policy_combo_changed" : 
self.on_sched_policy_combo_changed,
-                                  "on_command_regex_clicked" : 
self.on_command_regex_clicked,
-                                  "on_all_these_threads_clicked" : 
self.on_all_these_threads_clicked,
-                                  "on_just_this_thread_clicked" : 
self.on_just_this_thread_clicked }
-               self.window.signal_autoconnect(event_handlers)
-
-               self.sched_pri = self.window.get_widget("sched_pri_spin")
-               self.sched_policy = self.window.get_widget("sched_policy_combo")
-               self.regex_edit = self.window.get_widget("cmdline_regex")
-               self.affinity = self.window.get_widget("affinity_text")
-               self.just_this_thread = 
self.window.get_widget("just_this_thread")
-               self.all_these_threads = 
self.window.get_widget("all_these_threads")
-               processes = self.window.get_widget("matching_process_list")
-
-               self.sched_pri.set_value(int(pid_info["stat"]["rt_priority"]))
-               cmdline_regex = procfs.process_cmdline(pid_info)
-               self.affinity_text = 
tuna.list_to_cpustring(schedutils.get_affinity(pid))
-               self.affinity.set_text(self.affinity_text)
-               self.create_matching_process_model(processes)
-               self.create_policy_model(self.sched_policy)
-               self.sched_policy.set_active(schedutils.get_scheduler(pid))
-               self.regex_edit.set_text(cmdline_regex)
-               self.just_this_thread.set_active(True)
-               self.regex_edit.set_sensitive(False)
-               if pid not in ps or "threads" not in ps[pid]:
-                       self.all_these_threads.hide()
-               self.on_just_this_thread_clicked(None)
-
-       def refresh_match_pids(self, cmdline_regex):
-               self.process_list_store.clear()
-               for match_pid in self.ps.find_by_cmdline_regex(cmdline_regex):
-                       info = self.process_list_store.append()
-                       pid_info = self.ps[match_pid]
-                       cmdline = procfs.process_cmdline(pid_info)
-                       self.process_list_store.set(info, self.PROCESS_COL_PID, 
match_pid,
-                                                   self.PROCESS_COL_NAME,
-                                                   cmdline)
-
-       def create_matching_process_model(self, processes):
-               labels = [ "PID", "Name" ]
-
-               self.process_list_store = Gtk.ListStore(GObject.TYPE_UINT,
-                                                       GObject.TYPE_STRING)
-               renderer = Gtk.CellRendererText()
-
-               for col in range(len(labels)):
-                       column = Gtk.TreeViewColumn(labels[col], renderer, text 
= col)
-                       column.set_sort_column_id(col)
-                       processes.append_column(column)
-
-               processes.set_model(self.process_list_store)
-
-       def create_policy_model(self, policy):
-               ( COL_TEXT, COL_SCHED ) = list(range(2))
-               list_store = Gtk.ListStore(GObject.TYPE_STRING,
-                                          GObject.TYPE_UINT)
-               renderer = Gtk.CellRendererText()
-               policy.pack_start(renderer, True)
-               policy.add_attribute(renderer, "text", COL_TEXT)
-               for pol in range(4):
-                       row = list_store.append()
-                       list_store.set(row, COL_TEXT, schedutils.schedstr(pol),
-                                           COL_SCHED, pol)
-               policy.set_model(list_store)
-
-       def on_cmdline_regex_changed(self, entry):
-               process_regex_text = entry.get_text()
-               try:
-                       cmdline_regex = re.compile(process_regex_text)
-               except:
-                       self.process_list_store.clear()
-                       return
-               self.refresh_match_pids(cmdline_regex)
-
-       def on_just_this_thread_clicked(self, button):
-               self.regex_edit.set_sensitive(False)
-               self.process_list_store.clear()
-               info = self.process_list_store.append()
-               cmdline = procfs.process_cmdline(self.pid_info)
-               self.process_list_store.set(info,
-                                           self.PROCESS_COL_PID, self.pid,
-                                           self.PROCESS_COL_NAME, cmdline)
-
-       def on_command_regex_clicked(self, button):
-               self.regex_edit.set_sensitive(True)
-               self.on_cmdline_regex_changed(self.regex_edit)
-
-       def on_all_these_threads_clicked(self, button):
-               self.regex_edit.set_sensitive(False)
-               self.process_list_store.clear()
-               info = self.process_list_store.append()
-               cmdline = procfs.process_cmdline(self.ps[self.pid])
-               self.process_list_store.set(info,
-                                           self.PROCESS_COL_PID, self.pid,
-                                           self.PROCESS_COL_NAME, cmdline)
-               for tid in list(self.ps[self.pid]["threads"].keys()):
-                       child = self.process_list_store.append()
-                       self.process_list_store.set(child,
-                                                   self.PROCESS_COL_PID, tid,
-                                                   self.PROCESS_COL_NAME, 
cmdline)
-
-
-       def on_sched_policy_combo_changed(self, button):
-               new_policy = self.sched_policy.get_active()
-               if new_policy in ( schedutils.SCHED_FIFO, schedutils.SCHED_RR ):
-                       can_change_pri = True
-               else:
-                       can_change_pri = False
-               self.sched_pri.set_sensitive(can_change_pri)
-
-       def on_affinity_text_changed(self, button):
-               gui.on_affinity_text_changed(self)
-
-       def set_attributes_for_regex(self, regex, new_policy, new_prio, 
new_affinity):
-               changed = False
-               cmdline_regex = re.compile(regex)
-               for match_pid in self.ps.find_by_cmdline_regex(cmdline_regex):
-                       if gui.thread_set_attributes(self.ps[match_pid],
-                                                    new_policy, new_prio,
-                                                    new_affinity,
-                                                    self.nr_cpus):
-                               changed = True
-
-               return changed
-
-       def set_attributes_for_threads(self, pid, new_policy, new_prio, 
new_affinity):
-               changed = False
-               threads = self.ps[pid]["threads"]
-               for tid in list(threads.keys()):
-                       if gui.thread_set_attributes(threads[tid], new_policy,
-                                                    new_prio, new_affinity,
-                                                    self.nr_cpus):
-                               changed = True
-
-               return changed
-
-       def run(self):
-               changed = False
-               if self.dialog.run() == Gtk.ResponseType.OK:
-                       new_policy = int(self.sched_policy.get_active())
-                       new_prio = int(self.sched_pri.get_value())
-                       new_affinity = self.affinity.get_text()
-                       if self.just_this_thread.get_active():
-                               changed = 
gui.thread_set_attributes(self.pid_info,
-                                                                   new_policy,
-                                                                   new_prio,
-                                                                   
new_affinity,
-                                                                   
self.nr_cpus)
-                       elif self.all_these_threads.get_active():
-                               if gui.thread_set_attributes(self.pid_info,
-                                                            new_policy, 
new_prio,
-                                                            new_affinity,
-                                                            self.nr_cpus):
-                                       changed = True
-                               if self.set_attributes_for_threads(self.pid,
-                                                                  new_policy,
-                                                                  new_prio,
-                                                                  
new_affinity):
-                                       changed = True
-                       else:
-                               changed = 
self.set_attributes_for_regex(self.regex_edit.get_text(),
-                                                                       
new_policy,
-                                                                       
new_prio,
-                                                                       
new_affinity)
-
-               self.dialog.destroy()
-               return changed
+    (PROCESS_COL_PID, PROCESS_COL_NAME) = list(range(2))
+
+    def __init__(self, ps, pid, pid_info, nr_cpus, gladefile):
+        self.ps = ps
+        self.pid = pid
+        self.pid_info = pid_info
+        self.nr_cpus = nr_cpus
+        self.window = Gtk.glade.XML(gladefile, "set_process_attributes", 
"tuna")
+        self.dialog = self.window.get_widget("set_process_attributes")
+        pixbuf = self.dialog.render_icon(Gtk.STOCK_PREFERENCES,
+                                         Gtk.IconSize.SMALL_TOOLBAR)
+        self.dialog.set_icon(pixbuf)
+        event_handlers = {
+            "on_cmdline_regex_changed" : self.on_cmdline_regex_changed,
+            "on_affinity_text_changed" : self.on_affinity_text_changed,
+            "on_sched_policy_combo_changed" : 
self.on_sched_policy_combo_changed,
+            "on_command_regex_clicked" : self.on_command_regex_clicked,
+            "on_all_these_threads_clicked" : self.on_all_these_threads_clicked,
+            "on_just_this_thread_clicked" : self.on_just_this_thread_clicked}
+        self.window.signal_autoconnect(event_handlers)
+        self.sched_pri = self.window.get_widget("sched_pri_spin")
+        self.sched_policy = self.window.get_widget("sched_policy_combo")
+        self.regex_edit = self.window.get_widget("cmdline_regex")
+        self.affinity = self.window.get_widget("affinity_text")
+        self.just_this_thread = self.window.get_widget("just_this_thread")
+        self.all_these_threads = self.window.get_widget("all_these_threads")
+        processes = self.window.get_widget("matching_process_list")
+
+        self.sched_pri.set_value(int(pid_info["stat"]["rt_priority"]))
+        cmdline_regex = procfs.process_cmdline(pid_info)
+        self.affinity_text = 
tuna.list_to_cpustring(schedutils.get_affinity(pid))
+        self.affinity.set_text(self.affinity_text)
+        self.create_matching_process_model(processes)
+        self.create_policy_model(self.sched_policy)
+        self.sched_policy.set_active(schedutils.get_scheduler(pid))
+        self.regex_edit.set_text(cmdline_regex)
+        self.just_this_thread.set_active(True)
+        self.regex_edit.set_sensitive(False)
+        if pid not in ps or "threads" not in ps[pid]:
+            self.all_these_threads.hide()
+            self.on_just_this_thread_clicked(None)
+
+    def refresh_match_pids(self, cmdline_regex):
+        self.process_list_store.clear()
+        for match_pid in self.ps.find_by_cmdline_regex(cmdline_regex):
+            info = self.process_list_store.append()
+            pid_info = self.ps[match_pid]
+            cmdline = procfs.process_cmdline(pid_info)
+            self.process_list_store.set(info, self.PROCESS_COL_PID, match_pid,
+                                        self.PROCESS_COL_NAME, cmdline)
+
+    def create_matching_process_model(self, processes):
+        labels = ["PID", "Name"]
+
+        self.process_list_store = Gtk.ListStore(GObject.TYPE_UINT,
+                                                GObject.TYPE_STRING)
+        renderer = Gtk.CellRendererText()
+
+        for col in range(len(labels)):
+            column = Gtk.TreeViewColumn(labels[col], renderer, text=col)
+            column.set_sort_column_id(col)
+            processes.append_column(column)
+
+        processes.set_model(self.process_list_store)
+
+    def create_policy_model(self, policy):
+        (COL_TEXT, COL_SCHED) = list(range(2))
+        list_store = Gtk.ListStore(GObject.TYPE_STRING,
+                                   GObject.TYPE_UINT)
+        renderer = Gtk.CellRendererText()
+        policy.pack_start(renderer, True)
+        policy.add_attribute(renderer, "text", COL_TEXT)
+        for pol in range(4):
+            row = list_store.append()
+            list_store.set(row, COL_TEXT, schedutils.schedstr(pol),
+                           COL_SCHED, pol)
+        policy.set_model(list_store)
+
+    def on_cmdline_regex_changed(self, entry):
+        process_regex_text = entry.get_text()
+        try:
+            cmdline_regex = re.compile(process_regex_text)
+        except:
+            self.process_list_store.clear()
+            return
+        self.refresh_match_pids(cmdline_regex)
+
+    def on_just_this_thread_clicked(self, button):
+        self.regex_edit.set_sensitive(False)
+        self.process_list_store.clear()
+        info = self.process_list_store.append()
+        cmdline = procfs.process_cmdline(self.pid_info)
+        self.process_list_store.set(info,
+                                    self.PROCESS_COL_PID, self.pid,
+                                    self.PROCESS_COL_NAME, cmdline)
+
+    def on_command_regex_clicked(self, button):
+        self.regex_edit.set_sensitive(True)
+        self.on_cmdline_regex_changed(self.regex_edit)
+
+    def on_all_these_threads_clicked(self, button):
+        self.regex_edit.set_sensitive(False)
+        self.process_list_store.clear()
+        info = self.process_list_store.append()
+        cmdline = procfs.process_cmdline(self.ps[self.pid])
+        self.process_list_store.set(info,
+                                    self.PROCESS_COL_PID, self.pid,
+                                    self.PROCESS_COL_NAME, cmdline)
+        for tid in list(self.ps[self.pid]["threads"].keys()):
+            child = self.process_list_store.append()
+            self.process_list_store.set(child,
+                                        self.PROCESS_COL_PID, tid,
+                                        self.PROCESS_COL_NAME, cmdline)
+
+
+    def on_sched_policy_combo_changed(self, button):
+        new_policy = self.sched_policy.get_active()
+        if new_policy in (schedutils.SCHED_FIFO, schedutils.SCHED_RR):
+            can_change_pri = True
+        else:
+            can_change_pri = False
+        self.sched_pri.set_sensitive(can_change_pri)
+
+    def on_affinity_text_changed(self, button):
+        gui.on_affinity_text_changed(self)
+
+    def set_attributes_for_regex(self, regex, new_policy, new_prio, 
new_affinity):
+        changed = False
+        cmdline_regex = re.compile(regex)
+        for match_pid in self.ps.find_by_cmdline_regex(cmdline_regex):
+            if gui.thread_set_attributes(self.ps[match_pid],
+                                         new_policy, new_prio,
+                                         new_affinity, self.nr_cpus):
+                changed = True
+
+        return changed
+
+    def set_attributes_for_threads(self, pid, new_policy, new_prio, 
new_affinity):
+        changed = False
+        threads = self.ps[pid]["threads"]
+        for tid in list(threads.keys()):
+            if gui.thread_set_attributes(threads[tid], new_policy,
+                                         new_prio, new_affinity, self.nr_cpus):
+                changed = True
+
+        return changed
+
+    def run(self):
+        changed = False
+        if self.dialog.run() == Gtk.ResponseType.OK:
+            new_policy = int(self.sched_policy.get_active())
+            new_prio = int(self.sched_pri.get_value())
+            new_affinity = self.affinity.get_text()
+            if self.just_this_thread.get_active():
+                changed = gui.thread_set_attributes(self.pid_info, new_policy,
+                                                    new_prio, new_affinity,
+                                                    self.nr_cpus)
+            elif self.all_these_threads.get_active():
+                if gui.thread_set_attributes(self.pid_info, new_policy,
+                                             new_prio, new_affinity,
+                                             self.nr_cpus):
+                    changed = True
+                if self.set_attributes_for_threads(self.pid, new_policy,
+                                                   new_prio, new_affinity):
+                    changed = True
+                else:
+                    changed = 
self.set_attributes_for_regex(self.regex_edit.get_text(),
+                                                            new_policy,
+                                                            new_prio,
+                                                            new_affinity)
+
+        self.dialog.destroy()
+        return changed
 
 class procview:
 
-       nr_columns = 8
-       ( COL_PID, COL_POL, COL_PRI, COL_AFF, COL_VOLCTXT, COL_NONVOLCTXT, 
COL_CGROUP, COL_CMDLINE ) = list(range(nr_columns))
-       columns = (gui.list_store_column(_("PID")),
-                  gui.list_store_column(_("Policy"), GObject.TYPE_STRING),
-                  gui.list_store_column(_("Priority")),
-                  gui.list_store_column(_("Affinity"), GObject.TYPE_STRING),
-                  gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
-                  gui.list_store_column(_("NonVolCtxtSwitch"), 
GObject.TYPE_UINT),
-                  gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
-                  gui.list_store_column(_("Command Line"), 
GObject.TYPE_STRING))
-
-       def __init__(self, treeview, ps,
-                    show_kthreads, show_uthreads,
-                    cpus_filtered, gladefile):
-               self.ps = ps
-               self.treeview = treeview
-               self.nr_cpus = procfs.cpuinfo().nr_cpus
-               self.gladefile = gladefile
-       
-               self.evlist = None
-               try:
-                       self.perf_init() 
-               except: # No perf, poll /proc baby, poll
-                       pass
-
-               if "voluntary_ctxt_switches" not in ps[1]["status"]:
-                       self.nr_columns = 5
-               else:
-                       self.nr_columns = 7
-               try:
-                       if ps[1]["cgroups"]:
-                               self.nr_columns = self.nr_columns + 1
-               except:
-                       pass
-
-               self.columns = (gui.list_store_column(_("PID")),
-                                               
gui.list_store_column(_("Policy"), GObject.TYPE_STRING),
-                                               
gui.list_store_column(_("Priority")),
-                                               
gui.list_store_column(_("Affinity"), GObject.TYPE_STRING))
-
-               if self.nr_columns==5:
-                       ( self.COL_PID, self.COL_POL, self.COL_PRI, 
self.COL_AFF, self.COL_CMDLINE ) = list(range(self.nr_columns))
-                       self.columns = self.columns + 
(gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
-               elif self.nr_columns==6:
-                       ( self.COL_PID, self.COL_POL, self.COL_PRI, 
self.COL_AFF, self.COL_CGROUP, self.COL_CMDLINE ) = list(range(self.nr_columns))
-                       self.columns = self.columns + 
(gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
-                                                                               
   gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
-               elif self.nr_columns==7:
-                       ( self.COL_PID, self.COL_POL, self.COL_PRI, 
self.COL_AFF, self.COL_VOLCTXT,
-                               self.NONVOLCTXT, self.COL_CMDLINE ) = 
list(range(self.nr_columns))
-                       self.columns = self.columns + 
(gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
-                                                                               
   gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
-                                                                               
   gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
-               elif self.nr_columns==8:
-                       ( self.COL_PID, self.COL_POL, self.COL_PRI, 
self.COL_AFF, self.COL_VOLCTXT,
-                               self.COL_NONVOLCTXT, self.COL_CGROUP, 
self.COL_CMDLINE ) = list(range(self.nr_columns))
-                       self.columns = self.columns + 
(gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
-                                                                               
   gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
-                                                                               
   gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
-                                                                               
   gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
-               self.tree_store = 
Gtk.TreeStore(*gui.generate_list_store_columns_with_attr(self.columns))
-               self.treeview.set_model(self.tree_store)
-
-               # Allow selecting multiple rows
-               selection = treeview.get_selection()
-               selection.set_mode(Gtk.SelectionMode.MULTIPLE)
-
-               # Allow enable drag and drop of rows
-               
self.treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
-                                                      gui.DND_TARGETS,
-                                                      Gdk.DragAction.DEFAULT | 
Gdk.DragAction.MOVE)
-               self.treeview.connect("drag_data_get", 
self.on_drag_data_get_data)
-               try:
-                       self.treeview.connect("query-tooltip", 
self.on_query_tooltip)
-               except:
-                       # old versions of pygtk2+ doesn't have this signal
-                       pass
-
-               self.renderer = Gtk.CellRendererText()
-               for col in range(self.nr_columns):
-                       column = Gtk.TreeViewColumn(self.columns[col].name,
-                                                   self.renderer, text = col)
-                       column.add_attribute(self.renderer, "weight",
-                                            col + self.nr_columns)
-                       column.set_sort_column_id(col)
-                       if(col == self.COL_CGROUP):
-                               
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
-                               column.set_fixed_width(130)
-                       try:
-                               self.treeview.set_tooltip_column(col)
-                       except:
-                               # old versions of pygtk2+ doesn't have this 
signal
-                               pass
-                       column.set_resizable(True)
-                       self.treeview.append_column(column)
-
-               self.show_kthreads = show_kthreads
-               self.show_uthreads = show_uthreads
-               self.cpus_filtered = cpus_filtered
-               self.refreshing = True
-
-       def perf_process_events(self, source, condition):
-               had_events = True
-               while had_events:
-                       had_events = False
-                       for cpu in self.cpu_map:
-                               event = self.evlist.read_on_cpu(cpu)
-                               if event:
-                                       had_events = True
-                                       if event.type == perf.RECORD_FORK:
-                                               if event.pid == event.tid:
-                                                       try:
-                                                               
self.ps.processes[event.pid] = procfs.process(event.pid)
-                                                       except: # short lived 
thread
-                                                               pass
-                                               else:
-                                                       try:
-                                                               
self.ps.processes[event.pid].threads.processes[event.tid] = 
procfs.process(event.tid)
-                                                       except AttributeError:
-                                                               
self.ps.processes[event.pid].threads = procfs.pidstats("/proc/%d/task/" % 
event.pid)
-                                       elif event.type == perf.RECORD_EXIT:
-                                               del self.ps[int(event.tid)]
-                                       elif event.type == perf.RECORD_SAMPLE:
-                                               tid = event.sample_tid
-                                               if tid in self.perf_counter:
-                                                       self.perf_counter[tid] 
+= event.sample_period
-                                               else:
-                                                       self.perf_counter[tid] 
= event.sample_period
-                       
-               self.show()
-               return True
-
-       def perf_init(self):
-               self.cpu_map = perf.cpu_map()
-               self.thread_map = perf.thread_map()
-               self.evsel_cycles = perf.evsel(task = 1, comm = 1,
-                                              wakeup_events = 1,
-                                              watermark = 1,
-                                              sample_type = perf.SAMPLE_CPU |
-                                                            perf.SAMPLE_TID)
-               self.evsel_cycles.open(cpus = self.cpu_map, threads = 
self.thread_map);
-               self.evlist = perf.evlist(self.cpu_map, self.thread_map)
-               self.evlist.add(self.evsel_cycles)
-               self.evlist.mmap()
-               self.pollfd = self.evlist.get_pollfd()
-               for f in self.pollfd:
-                       GObject.io_add_watch(f, Gdk.INPUT_READ, 
self.perf_process_events)
-               self.perf_counter = {}
-
-       def on_query_tooltip(self, treeview, x, y, keyboard_mode, tooltip):
-               x, y = treeview.convert_widget_to_bin_window_coords(x, y)
-               ret = treeview.get_path_at_pos(x, y)
-               tooltip.set_text(None)
-               if not ret:
-                       return True
-               path, col, xpos, ypos = ret
-               if not path:
-                       return True
-               col_id = col.get_sort_column_id()
-               if col_id != self.COL_CMDLINE:
-                       return True
-               row = self.tree_store.get_iter(path)
-               if not row:
-                       return True
-               pid = int(self.tree_store.get_value(row, self.COL_PID))
-               if not tuna.iskthread(pid):
-                       return True
-               cmdline = self.tree_store.get_value(row, 
self.COL_CMDLINE).split(' ')[0]
-               help = tuna.kthread_help(cmdline)
-               tooltip.set_markup("<b>%s %d(%s)</b>\n%s" % \
+    nr_columns = 8
+    (COL_PID, COL_POL, COL_PRI, COL_AFF, COL_VOLCTXT, COL_NONVOLCTXT,
+     COL_CGROUP, COL_CMDLINE) = list(range(nr_columns))
+    columns = (gui.list_store_column(_("PID")),
+               gui.list_store_column(_("Policy"), GObject.TYPE_STRING),
+               gui.list_store_column(_("Priority")),
+               gui.list_store_column(_("Affinity"), GObject.TYPE_STRING),
+               gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
+               gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
+               gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
+               gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
+
+    def __init__(self, treeview, ps, show_kthreads, show_uthreads,
+                 cpus_filtered, gladefile):
+        self.ps = ps
+        self.treeview = treeview
+        self.nr_cpus = procfs.cpuinfo().nr_cpus
+        self.gladefile = gladefile
+
+        self.evlist = None
+        try:
+            self.perf_init()
+        except: # No perf, poll /proc baby, poll
+            pass
+
+        if "voluntary_ctxt_switches" not in ps[1]["status"]:
+            self.nr_columns = 5
+        else:
+            self.nr_columns = 7
+        try:
+            if ps[1]["cgroups"]:
+                self.nr_columns = self.nr_columns + 1
+        except:
+            pass
+
+        self.columns = (gui.list_store_column(_("PID")),
+                        gui.list_store_column(_("Policy"), 
GObject.TYPE_STRING),
+                        gui.list_store_column(_("Priority")),
+                        gui.list_store_column(_("Affinity"),
+                                              GObject.TYPE_STRING))
+
+        if self.nr_columns == 5:
+            (self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF,
+             self.COL_CMDLINE) = list(range(self.nr_columns))
+            self.columns = self.columns \
+                + (gui.list_store_column(_("Command Line"), 
GObject.TYPE_STRING))
+
+        elif self.nr_columns == 6:
+            (self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF,
+             self.COL_CGROUP, self.COL_CMDLINE) = list(range(self.nr_columns))
+            self.columns = self.columns \
+                + (gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
+                   gui.list_store_column(_("Command Line"), 
GObject.TYPE_STRING))
+        elif self.nr_columns == 7:
+            (self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF, \
+                self.COL_VOLCTXT, self.NONVOLCTXT, self.COL_CMDLINE) \
+                = list(range(self.nr_columns))
+            self.columns = self.columns \
+                + (gui.list_store_column(_("VolCtxtSwitch"), 
GObject.TYPE_UINT),
+                   gui.list_store_column(_("NonVolCtxtSwitch"), 
GObject.TYPE_UINT),
+                   gui.list_store_column(_("Command Line"), 
GObject.TYPE_STRING))
+
+        elif self.nr_columns == 8:
+            (self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF, \
+                self.COL_VOLCTXT, self.COL_NONVOLCTXT, self.COL_CGROUP, \
+                self.COL_CMDLINE) = list(range(self.nr_columns))
+            self.columns = self.columns \
+                + (gui.list_store_column(_("VolCtxtSwitch"), 
GObject.TYPE_UINT),
+                   gui.list_store_column(_("NonVolCtxtSwitch"), 
GObject.TYPE_UINT),
+                   gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
+                   gui.list_store_column(_("Command Line"), 
GObject.TYPE_STRING))
+
+        self.tree_store = 
Gtk.TreeStore(*gui.generate_list_store_columns_with_attr(self.columns))
+        self.treeview.set_model(self.tree_store)
+
+        # Allow selecting multiple rows
+        selection = treeview.get_selection()
+        selection.set_mode(Gtk.SelectionMode.MULTIPLE)
+
+        # Allow enable drag and drop of rows
+        self.treeview.enable_model_drag_source(
+            Gdk.ModifierType.BUTTON1_MASK, gui.DND_TARGETS,
+            Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
+        self.treeview.connect("drag_data_get", self.on_drag_data_get_data)
+        try:
+            self.treeview.connect("query-tooltip", self.on_query_tooltip)
+        except:
+            # old versions of pygtk2+ doesn't have this signal
+            pass
+
+        self.renderer = Gtk.CellRendererText()
+        for col in range(self.nr_columns):
+            column = Gtk.TreeViewColumn(self.columns[col].name,
+                                        self.renderer, text=col)
+            column.add_attribute(self.renderer, "weight",
+                                 col + self.nr_columns)
+            column.set_sort_column_id(col)
+            if col == self.COL_CGROUP:
+                column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
+                column.set_fixed_width(130)
+            try:
+                self.treeview.set_tooltip_column(col)
+            except:
+                # old versions of pygtk2+ doesn't have this signal
+                pass
+            column.set_resizable(True)
+            self.treeview.append_column(column)
+
+        self.show_kthreads = show_kthreads
+        self.show_uthreads = show_uthreads
+        self.cpus_filtered = cpus_filtered
+        self.refreshing = True
+
+    def perf_process_events(self, source, condition):
+        had_events = True
+        while had_events:
+            had_events = False
+            for cpu in self.cpu_map:
+                event = self.evlist.read_on_cpu(cpu)
+                if event:
+                    had_events = True
+                    if event.type == perf.RECORD_FORK:
+                        if event.pid == event.tid:
+                            try:
+                                self.ps.processes[event.pid] = 
procfs.process(event.pid)
+                            except: # short lived thread
+                                pass
+                        else:
+                            try:
+                                
self.ps.processes[event.pid].threads.processes[event.tid] = 
procfs.process(event.tid)
+                            except AttributeError:
+                                self.ps.processes[event.pid].threads = 
procfs.pidstats("/proc/%d/task/" % event.pid)
+                    elif event.type == perf.RECORD_EXIT:
+                        del self.ps[int(event.tid)]
+                    elif event.type == perf.RECORD_SAMPLE:
+                        tid = event.sample_tid
+                        if tid in self.perf_counter:
+                            self.perf_counter[tid] += event.sample_period
+                        else:
+                            self.perf_counter[tid] = event.sample_period
+
+        self.show()
+        return True
+
+    def perf_init(self):
+        self.cpu_map = perf.cpu_map()
+        self.thread_map = perf.thread_map()
+        self.evsel_cycles = perf.evsel(task=1, comm=1, wakeup_events=1, \
+            watermark=1, sample_type=perf.SAMPLE_CPU | perf.SAMPLE_TID)
+        self.evsel_cycles.open(cpus=self.cpu_map, threads=self.thread_map)
+        self.evlist = perf.evlist(self.cpu_map, self.thread_map)
+        self.evlist.add(self.evsel_cycles)
+        self.evlist.mmap()
+        self.pollfd = self.evlist.get_pollfd()
+        for f in self.pollfd:
+            GObject.io_add_watch(f, Gdk.INPUT_READ, self.perf_process_events)
+        self.perf_counter = {}
+
+    def on_query_tooltip(self, treeview, x, y, keyboard_mode, tooltip):
+        x, y = treeview.convert_widget_to_bin_window_coords(x, y)
+        ret = treeview.get_path_at_pos(x, y)
+        tooltip.set_text(None)
+        if not ret:
+            return True
+        path, col, xpos, ypos = ret
+        if not path:
+            return True
+        col_id = col.get_sort_column_id()
+        if col_id != self.COL_CMDLINE:
+            return True
+        row = self.tree_store.get_iter(path)
+        if not row:
+            return True
+        pid = int(self.tree_store.get_value(row, self.COL_PID))
+        if not tuna.iskthread(pid):
+            return True
+        cmdline = self.tree_store.get_value(row, self.COL_CMDLINE).split(' 
')[0]
+        help = tuna.kthread_help(cmdline)
+        tooltip.set_markup("<b>%s %d(%s)</b>\n%s" % \
                        (_("Kernel Thread"), pid, cmdline, _(help)))
-               return True
-
-       def foreach_selected_cb(self, model, path, iter, pid_list):
-               pid = model.get_value(iter, self.COL_PID)
-               pid_list.append(str(pid))
-
-       def on_drag_data_get_data(self, treeview, context,
-                                 selection, target_id, etime):
-               treeselection = treeview.get_selection()
-               pid_list = []
-               treeselection.selected_foreach(self.foreach_selected_cb, 
pid_list)
-               selection.set(selection.target, 8, "pid:" + ",".join(pid_list))
-
-       def set_thread_columns(self, iter, tid, thread_info):
-               new_value = [ None ] * self.nr_columns
-
-               new_value[self.COL_PRI] = 
int(thread_info["stat"]["rt_priority"])
-               new_value[self.COL_POL] = 
schedutils.schedstr(schedutils.get_scheduler(tid))[6:]
-               thread_affinity_list = schedutils.get_affinity(tid)
-
-               new_value[self.COL_PID] = tid
-               new_value[self.COL_AFF] = 
tuna.list_to_cpustring(thread_affinity_list)
-               try:
-                       new_value[self.COL_VOLCTXT] = 
int(thread_info["status"]["voluntary_ctxt_switches"])
-                       new_value[self.COL_NONVOLCTXT] = 
int(thread_info["status"]["nonvoluntary_ctxt_switches"])
-                       new_value[self.COL_CGROUP] = thread_info["cgroups"]
-               except:
-                       pass
-
-               new_value[self.COL_CMDLINE] = 
procfs.process_cmdline(thread_info)
-
-               gui.set_store_columns(self.tree_store, iter, new_value)
-
-       def show(self, force_refresh = False):
-               # Start with the first row, if there is one, on the
-               # process list. If the first time update_rows will just
-               # have everything in new_tids and append_new_tids will
-               # create the rows.
-               if not self.refreshing and not force_refresh:
-                       return
-               row = self.tree_store.get_iter_first()
-               self.update_rows(self.ps, row, None)
-               self.treeview.show_all()
-
-       def update_rows(self, threads, row, parent_row):
-               new_tids = list(threads.keys())
-               previous_row = None
-               while row:
-                       tid = self.tree_store.get_value(row, self.COL_PID)
-                       if previous_row:
-                               previous_tid = 
self.tree_store.get_value(previous_row, self.COL_PID)
-                               if previous_tid == tid:
-                                       # print "WARNING: tree_store dup %d, 
fixing..." % tid
-                                       self.tree_store.remove(previous_row)
-                       if tid not in threads:
-                               if self.tree_store.remove(row):
-                                       # removed and now row is the next one
-                                       continue
-                               # removed and its the last one
-                               break
-                       else:
-                               try:
-                                       new_tids.remove(tid)
-                               except:
-                                       # FIXME: understand in what situation 
this
-                                       # can happen, seems harmless from visual
-                                       # inspection.
-                                       pass
-                               if tuna.thread_filtered(tid, self.cpus_filtered,
-                                                       self.show_kthreads,
-                                                       self.show_uthreads):
-                                       if self.tree_store.remove(row):
-                                               # removed and now row is the 
next one
-                                               continue
-                                       # removed and its the last one
-                                       break
-                               else:
-                                       try:
-                                               self.set_thread_columns(row, 
tid, threads[tid])
-
-                                               if "threads" in threads[tid]:
-                                                       children = 
threads[tid]["threads"]
-                                               else:
-                                                       children = {}
-
-                                               child_row = 
self.tree_store.iter_children(row)
-                                               self.update_rows(children, 
child_row, row)
-                                       except: # thread doesn't exists anymore
-                                               if self.tree_store.remove(row):
-                                                       # removed and now row 
is the next one
-                                                       continue
-                                               # removed and its the last one
-                                               break
-
-                       previous_row = row
-                       row = self.tree_store.iter_next(row)
-
-               new_tids.sort()
-               self.append_new_tids(parent_row, threads, new_tids)
-
-       def append_new_tids(self, parent_row, threads, tid_list):
-               for tid in tid_list:
-                       if tuna.thread_filtered(tid, self.cpus_filtered,
-                                               self.show_kthreads,
-                                               self.show_uthreads):
-                               continue
-
-                       row = self.tree_store.append(parent_row)
-
-                       try:
-                               self.set_thread_columns(row, tid, threads[tid])
-                       except: # Thread doesn't exists anymore
-                               self.tree_store.remove(row)
-                               continue
-
-                       if "threads" in threads[tid]:
-                               children = threads[tid]["threads"]
-                               children_list = list(children.keys())
-                               children_list.sort()
-                               for child in children_list:
-                                       child_row = self.tree_store.append(row)
-                                       try:
-                                               
self.set_thread_columns(child_row,
-                                                                       child,
-                                                                       
children[child])
-                                       except: # Thread doesn't exists anymore
-                                               
self.tree_store.remove(child_row)
-
-       def refresh(self):
-               self.ps.reload()
-               self.ps.reload_threads()
-
-               self.show(True)
-
-       def edit_attributes(self, a):
-               ret = self.treeview.get_path_at_pos(self.last_x, self.last_y)
-               if not ret:
-                       return
-               path, col, xpos, ypos = ret
-               if not path:
-                       return
-               row = self.tree_store.get_iter(path)
-               pid = self.tree_store.get_value(row, self.COL_PID)
-               if pid in self.ps:
-                       pid_info = self.ps[pid]
-               else:
-                       parent = self.tree_store.iter_parent(row)
-                       ppid = self.tree_store.get_value(parent, self.COL_PID)
-                       pid_info = self.ps[ppid].threads[pid]
-
-               dialog = process_druid(self.ps, pid, pid_info, self.nr_cpus,
-                                      self.gladefile)
-               if dialog.run():
-                       self.refresh()
-
-       def kthreads_view_toggled(self, a):
-               self.show_kthreads = not self.show_kthreads
-               self.show(True)
-
-       def uthreads_view_toggled(self, a):
-               self.show_uthreads = not self.show_uthreads
-               self.show(True)
-
-       def help_dialog(self, a):
-               ret = self.treeview.get_path_at_pos(self.last_x, self.last_y)
-               if not ret:
-                       return
-               path, col, xpos, ypos = ret
-               if not path:
-                       return
-               row = self.tree_store.get_iter(path)
-               pid = self.tree_store.get_value(row, self.COL_PID)
-               if pid not in self.ps:
-                       return
-
-               cmdline = self.tree_store.get_value(row, self.COL_CMDLINE)
-               help, title = tuna.kthread_help_plain_text(pid, cmdline)
-
-               dialog = Gtk.MessageDialog(None,
-                                          Gtk.DialogFlags.MODAL | 
Gtk.DialogFlags.DESTROY_WITH_PARENT,
-                                          Gtk.MessageType.INFO,
-                                          Gtk.ButtonsType.OK, _(help))
-               dialog.set_title(title)
-               ret = dialog.run()
-               dialog.destroy()
-
-       def refresh_toggle(self, a):
-               self.refreshing = not self.refreshing
-
-       def save_kthreads_tunings(self, a):
-               dialog = Gtk.FileChooserDialog(_("Save As"),
-                                              None,
-                                              Gtk.FileChooserAction.SAVE,
-                                              (Gtk.STOCK_CANCEL, 
Gtk.ResponseType.CANCEL,
-                                               Gtk.STOCK_OK, 
Gtk.ResponseType.OK))
-               dialog.set_default_response(Gtk.ResponseType.OK)
-
-               try:
-                       dialog.set_do_overwrite_confirmation(True)
-               except:
-                       pass
-
-               filter = Gtk.FileFilter()
-               filter.set_name("rtctl config files")
-               filter.add_pattern("*.rtctl")
-               filter.add_pattern("*.tuna")
-               filter.add_pattern("*rtgroup*")
-               dialog.add_filter(filter)
-
-               filter = Gtk.FileFilter()
-               filter.set_name("All files")
-               filter.add_pattern("*")
-               dialog.add_filter(filter)
-
-               response = dialog.run()
-
-               filename = dialog.get_filename()
-               dialog.destroy()
-
-               if response != Gtk.ResponseType.OK:
-                       return
-
-               self.refresh()
-               kthreads = tuna.get_kthread_sched_tunings(self.ps)
-               tuna.generate_rtgroups(filename, kthreads, self.nr_cpus)
-
-               if filename != "/etc/rtgroups":
-                       dialog = Gtk.MessageDialog(None,
-                                                  Gtk.DialogFlags.MODAL | 
Gtk.DialogFlags.DESTROY_WITH_PARENT,
-                                                  Gtk.MessageType.INFO,
-                                                  Gtk.ButtonsType.YES_NO,
-                                                  "Kernel thread tunings 
saved!\n\n"
-                                                  "Now you can use it with 
rtctl:\n\n"
-                                                  "rtctl --file %s reset\n\n"
-                                                  "If you want the changes to 
be in "
-                                                  "effect every time you boot 
the system "
-                                                  "please move %s to 
/etc/rtgroups\n\n"
-                                                  "Do you want to do that 
now?" % (filename, filename))
-                       response = dialog.run()
-                       dialog.destroy()
-                       if response == Gtk.ResponseType.YES:
-                               filename = "/etc/rtgroups"
-                               tuna.generate_rtgroups(filename, kthreads, 
self.nr_cpus)
-
-               dialog = Gtk.MessageDialog(None,
-                                          Gtk.DialogFlags.MODAL | 
Gtk.DialogFlags.DESTROY_WITH_PARENT,
-                                          Gtk.MessageType.INFO,
-                                          Gtk.ButtonsType.OK,
-                                          _("Kernel thread tunings saved to 
%s!") % filename)
-               dialog.run()
-               dialog.destroy()
-
-       def on_processlist_button_press_event(self, treeview, event):
-               if event.type != Gdk.EventType.BUTTON_PRESS or event.button != 
3:
-                       return
-
-               self.last_x = int(event.x)
-               self.last_y = int(event.y)
-
-               menu = Gtk.Menu()
-
-               setattr = Gtk.MenuItem(_("_Set process attributes"))
-               if self.refreshing:
-                       refresh = Gtk.MenuItem(_("Sto_p refreshing the process 
list"))
-               else:
-                       refresh = Gtk.MenuItem(_("_Refresh the process list"))
-
-               if self.show_kthreads:
-                       kthreads = Gtk.MenuItem(_("_Hide kernel threads"))
-               else:
-                       kthreads = Gtk.MenuItem(_("_Show kernel threads"))
-
-               if self.show_uthreads:
-                       uthreads = Gtk.MenuItem(_("_Hide user threads"))
-               else:
-                       uthreads = Gtk.MenuItem(_("_Show user threads"))
-
-               help = Gtk.MenuItem(_("_What is this?"))
-
-               save_kthreads_tunings = Gtk.MenuItem(_("_Save kthreads 
tunings"))
-
-               menu.add(save_kthreads_tunings)
-               menu.add(setattr)
-               menu.add(refresh)
-               menu.add(kthreads)
-               menu.add(uthreads)
-               menu.add(help)
-
-               save_kthreads_tunings.connect_object('activate',
+        return True
+
+    def foreach_selected_cb(self, model, path, iter, pid_list):
+        pid = model.get_value(iter, self.COL_PID)
+        pid_list.append(str(pid))
+
+    def on_drag_data_get_data(self, treeview, context, selection,
+                              target_id, etime):
+        treeselection = treeview.get_selection()
+        pid_list = []
+        treeselection.selected_foreach(self.foreach_selected_cb, pid_list)
+        selection.set(selection.target, 8, "pid:" + ",".join(pid_list))
+
+    def set_thread_columns(self, iter, tid, thread_info):
+        new_value = [None] * self.nr_columns
+
+        new_value[self.COL_PRI] = int(thread_info["stat"]["rt_priority"])
+        new_value[self.COL_POL] = 
schedutils.schedstr(schedutils.get_scheduler(tid))[6:]
+        thread_affinity_list = schedutils.get_affinity(tid)
+
+        new_value[self.COL_PID] = tid
+        new_value[self.COL_AFF] = tuna.list_to_cpustring(thread_affinity_list)
+        try:
+            new_value[self.COL_VOLCTXT] = 
int(thread_info["status"]["voluntary_ctxt_switches"])
+            new_value[self.COL_NONVOLCTXT] \
+                = int(thread_info["status"]["nonvoluntary_ctxt_switches"])
+            new_value[self.COL_CGROUP] = thread_info["cgroups"]
+        except:
+            pass
+
+        new_value[self.COL_CMDLINE] = procfs.process_cmdline(thread_info)
+
+        gui.set_store_columns(self.tree_store, iter, new_value)
+
+    def show(self, force_refresh=False):
+        # Start with the first row, if there is one, on the
+        # process list. If the first time update_rows will just
+        # have everything in new_tids and append_new_tids will
+        # create the rows.
+        if not self.refreshing and not force_refresh:
+            return
+        row = self.tree_store.get_iter_first()
+        self.update_rows(self.ps, row, None)
+        self.treeview.show_all()
+
+    def update_rows(self, threads, row, parent_row):
+        new_tids = list(threads.keys())
+        previous_row = None
+        while row:
+            tid = self.tree_store.get_value(row, self.COL_PID)
+            if previous_row:
+                previous_tid = self.tree_store.get_value(previous_row, 
self.COL_PID)
+                if previous_tid == tid:
+                    # print "WARNING: tree_store dup %d, fixing..." % tid
+                    self.tree_store.remove(previous_row)
+            if tid not in threads:
+                if self.tree_store.remove(row):
+                    # removed and now row is the next one
+                    continue
+                # removed and its the last one
+                break
+            else:
+                try:
+                    new_tids.remove(tid)
+                except:
+                    # FIXME: understand in what situation this
+                    # can happen, seems harmless from visual
+                    # inspection.
+                    pass
+                if tuna.thread_filtered(tid, self.cpus_filtered,
+                                        self.show_kthreads, 
self.show_uthreads):
+                    if self.tree_store.remove(row):
+                        # removed and now row is the next one
+                        continue
+                    # removed and its the last one
+                    break
+                else:
+                    try:
+                        self.set_thread_columns(row, tid, threads[tid])
+                        if "threads" in threads[tid]:
+                            children = threads[tid]["threads"]
+                        else:
+                            children = {}
+                        child_row = self.tree_store.iter_children(row)
+                        self.update_rows(children, child_row, row)
+                    except: # thread doesn't exists anymore
+                        if self.tree_store.remove(row):
+                            # removed and now row is the next one
+                            continue
+                        # removed and its the last one
+                        break
+
+            previous_row = row
+            row = self.tree_store.iter_next(row)
+
+        new_tids.sort()
+        self.append_new_tids(parent_row, threads, new_tids)
+
+    def append_new_tids(self, parent_row, threads, tid_list):
+        for tid in tid_list:
+            if tuna.thread_filtered(tid, self.cpus_filtered, 
self.show_kthreads,
+                                    self.show_uthreads):
+                continue
+
+            row = self.tree_store.append(parent_row)
+
+            try:
+                self.set_thread_columns(row, tid, threads[tid])
+            except: # Thread doesn't exists anymore
+                self.tree_store.remove(row)
+                continue
+
+            if "threads" in threads[tid]:
+                children = threads[tid]["threads"]
+                children_list = list(children.keys())
+                children_list.sort()
+                for child in children_list:
+                    child_row = self.tree_store.append(row)
+                    try:
+                        self.set_thread_columns(child_row, child,
+                                                children[child])
+                    except: # Thread doesn't exists anymore
+                        self.tree_store.remove(child_row)
+
+    def refresh(self):
+        self.ps.reload()
+        self.ps.reload_threads()
+
+        self.show(True)
+
+    def edit_attributes(self, a):
+        ret = self.treeview.get_path_at_pos(self.last_x, self.last_y)
+        if not ret:
+            return
+        path, col, xpos, ypos = ret
+        if not path:
+            return
+        row = self.tree_store.get_iter(path)
+        pid = self.tree_store.get_value(row, self.COL_PID)
+        if pid in self.ps:
+            pid_info = self.ps[pid]
+        else:
+            parent = self.tree_store.iter_parent(row)
+            ppid = self.tree_store.get_value(parent, self.COL_PID)
+            pid_info = self.ps[ppid].threads[pid]
+
+            dialog = process_druid(self.ps, pid, pid_info, self.nr_cpus,
+                                   self.gladefile)
+            if dialog.run():
+                self.refresh()
+
+    def kthreads_view_toggled(self, a):
+        self.show_kthreads = not self.show_kthreads
+        self.show(True)
+
+    def uthreads_view_toggled(self, a):
+        self.show_uthreads = not self.show_uthreads
+        self.show(True)
+
+    def help_dialog(self, a):
+        ret = self.treeview.get_path_at_pos(self.last_x, self.last_y)
+        if not ret:
+            return
+        path, col, xpos, ypos = ret
+        if not path:
+            return
+        row = self.tree_store.get_iter(path)
+        pid = self.tree_store.get_value(row, self.COL_PID)
+        if pid not in self.ps:
+            return
+
+        cmdline = self.tree_store.get_value(row, self.COL_CMDLINE)
+        help, title = tuna.kthread_help_plain_text(pid, cmdline)
+
+        dialog = Gtk.MessageDialog(None, \
+            Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, \
+            Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _(help))
+        dialog.set_title(title)
+        ret = dialog.run()
+        dialog.destroy()
+
+    def refresh_toggle(self, a):
+        self.refreshing = not self.refreshing
+
+    def save_kthreads_tunings(self, a):
+        dialog = Gtk.FileChooserDialog(_("Save As"), None, \
+            Gtk.FileChooserAction.SAVE, \
+            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, \
+            Gtk.STOCK_OK, Gtk.ResponseType.OK))
+        dialog.set_default_response(Gtk.ResponseType.OK)
+
+        try:
+            dialog.set_do_overwrite_confirmation(True)
+        except:
+            pass
+
+        filter = Gtk.FileFilter()
+        filter.set_name("rtctl config files")
+        filter.add_pattern("*.rtctl")
+        filter.add_pattern("*.tuna")
+        filter.add_pattern("*rtgroup*")
+        dialog.add_filter(filter)
+
+        filter = Gtk.FileFilter()
+        filter.set_name("All files")
+        filter.add_pattern("*")
+        dialog.add_filter(filter)
+
+        response = dialog.run()
+
+        filename = dialog.get_filename()
+        dialog.destroy()
+
+        if response != Gtk.ResponseType.OK:
+            return
+
+        self.refresh()
+        kthreads = tuna.get_kthread_sched_tunings(self.ps)
+        tuna.generate_rtgroups(filename, kthreads, self.nr_cpus)
+
+        if filename != "/etc/rtgroups":
+            dialog = Gtk.MessageDialog(None, \
+                Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, \
+                Gtk.MessageType.INFO, Gtk.ButtonsType.YES_NO, \
+                "Kernel thread tunings saved!\n\n" \
+                "Now you can use it with rtctl:\n\n" \
+                "rtctl --file %s reset\n\n" \
+                "If you want the changes to be in " \
+                "effect every time you boot the system " \
+                "please move %s to /etc/rtgroups\n\n" \
+                "Do you want to do that now?" % (filename, filename))
+            response = dialog.run()
+            dialog.destroy()
+            if response == Gtk.ResponseType.YES:
+                filename = "/etc/rtgroups"
+                tuna.generate_rtgroups(filename, kthreads, self.nr_cpus)
+
+        dialog = Gtk.MessageDialog(None, \
+            Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, \
+            Gtk.MessageType.INFO, Gtk.ButtonsType.OK, \
+            _("Kernel thread tunings saved to %s!") % filename)
+        dialog.run()
+        dialog.destroy()
+
+    def on_processlist_button_press_event(self, treeview, event):
+        if event.type != Gdk.EventType.BUTTON_PRESS or event.button != 3:
+            return
+
+        self.last_x = int(event.x)
+        self.last_y = int(event.y)
+
+        menu = Gtk.Menu()
+
+        setattr = Gtk.MenuItem(_("_Set process attributes"))
+        if self.refreshing:
+            refresh = Gtk.MenuItem(_("Sto_p refreshing the process list"))
+        else:
+            refresh = Gtk.MenuItem(_("_Refresh the process list"))
+
+        if self.show_kthreads:
+            kthreads = Gtk.MenuItem(_("_Hide kernel threads"))
+        else:
+            kthreads = Gtk.MenuItem(_("_Show kernel threads"))
+
+        if self.show_uthreads:
+            uthreads = Gtk.MenuItem(_("_Hide user threads"))
+        else:
+            uthreads = Gtk.MenuItem(_("_Show user threads"))
+
+        help = Gtk.MenuItem(_("_What is this?"))
+
+        save_kthreads_tunings = Gtk.MenuItem(_("_Save kthreads tunings"))
+
+        menu.add(save_kthreads_tunings)
+        menu.add(setattr)
+        menu.add(refresh)
+        menu.add(kthreads)
+        menu.add(uthreads)
+        menu.add(help)
+
+        save_kthreads_tunings.connect_object('activate',
                                                     
self.save_kthreads_tunings, event)
-               setattr.connect_object('activate', self.edit_attributes, event)
-               refresh.connect_object('activate', self.refresh_toggle, event)
-               kthreads.connect_object('activate', self.kthreads_view_toggled, 
event)
-               uthreads.connect_object('activate', self.uthreads_view_toggled, 
event)
-               help.connect_object('activate', self.help_dialog, event)
-
-               save_kthreads_tunings.show()
-               setattr.show()
-               refresh.show()
-               kthreads.show()
-               uthreads.show()
-               help.show()
-
-               menu.popup(None, None, None, event.button, event.time)
-
-       def toggle_mask_cpu(self, cpu, enabled):
-               if not enabled:
-                       if cpu not in self.cpus_filtered:
-                               self.cpus_filtered.append(cpu)
-                               self.show(True)
-               else:
-                       if cpu in self.cpus_filtered:
-                               self.cpus_filtered.remove(cpu)
-                               self.show(True)
+        setattr.connect_object('activate', self.edit_attributes, event)
+        refresh.connect_object('activate', self.refresh_toggle, event)
+        kthreads.connect_object('activate', self.kthreads_view_toggled, event)
+        uthreads.connect_object('activate', self.uthreads_view_toggled, event)
+        help.connect_object('activate', self.help_dialog, event)
+
+        save_kthreads_tunings.show()
+        setattr.show()
+        refresh.show()
+        kthreads.show()
+        uthreads.show()
+        help.show()
+
+        menu.popup(None, None, None, event.button, event.time)
+
+    def toggle_mask_cpu(self, cpu, enabled):
+        if not enabled:
+            if cpu not in self.cpus_filtered:
+                self.cpus_filtered.append(cpu)
+                self.show(True)
+        else:
+            if cpu in self.cpus_filtered:
+                self.cpus_filtered.remove(cpu)
+                self.show(True)
-- 
2.26.2
_______________________________________________
tuna-devel mailing list -- tuna-devel@lists.fedorahosted.org
To unsubscribe send an email to tuna-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/tuna-devel@lists.fedorahosted.org

Reply via email to