def __init__(self, statusbar, prefs): self._statusbar = statusbar self._old_processes = {} self.process_mgr = ProcessManager(self.do_update, prefs.bin_dir, prefs.use_sudo, prefs.use_ssh, prefs.hostname) self.model = gtk.ListStore(gobject.TYPE_INT, # 0 pid gobject.TYPE_STRING) # 1 status gtk.TreeView.__init__(self, self.model) self.connect('button-press-event', self.click) self.connect('popup-menu', self.popupMenu) renderer = gtk.CellRendererText() for index, title in enumerate(["PID", "Status"]): column = gtk.TreeViewColumn(title, renderer, text=index) column.set_reorderable(True) column.set_resizable(True) column.set_sort_column_id(index) self.append_column(column) self.get_column(0).clicked() # sort by pid self.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.set_headers_clickable(True) prefs.subscribe(self.apply_prefs) self.timer = Timer(prefs.process_interval, self.update)
class ProcessWidget(gtk.TreeView): """A widget that displays a list of processes.""" def __init__(self, statusbar, prefs): self._statusbar = statusbar self._old_processes = {} self.process_mgr = ProcessManager(self.do_update, prefs.bin_dir, prefs.use_sudo, prefs.use_ssh, prefs.hostname) self.model = gtk.ListStore(gobject.TYPE_INT, # 0 pid gobject.TYPE_STRING) # 1 status gtk.TreeView.__init__(self, self.model) self.connect('button-press-event', self.click) self.connect('popup-menu', self.popupMenu) renderer = gtk.CellRendererText() for index, title in enumerate(["PID", "Status"]): column = gtk.TreeViewColumn(title, renderer, text=index) column.set_reorderable(True) column.set_resizable(True) column.set_sort_column_id(index) self.append_column(column) self.get_column(0).clicked() # sort by pid self.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.set_headers_clickable(True) prefs.subscribe(self.apply_prefs) self.timer = Timer(prefs.process_interval, self.update) def update(self, new_status="Running exiwhat..."): """Schedule an immediate update of process status.""" self._statusbar.pop(0) self._statusbar.push(0, new_status) self.process_mgr.schedule_update() def do_update(self, processes, info): """Update the process list. Called from a background thread. """ gtk.gdk.threads_enter() try: old_processes = self._old_processes # remove outdated entries iter = self.model.get_iter_first() while iter is not None: next = self.model.iter_next(iter) pid = self.model.get_value(iter, 0) if (pid not in processes or old_processes[pid] != processes[pid]): self.model.remove(iter) iter = next # add new and changed entries to list for pid, status in processes.iteritems(): if pid not in old_processes or old_processes[pid] != status: self.model.append((pid, status)) self._old_processes = processes self._statusbar.pop(0) self._statusbar.push(0, info) finally: gtk.gdk.threads_leave() def click(self, widget, event): """Handle a click in the process widget.""" if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: self.popupMenu(widget, event.button) return True # handled else: return False # not handled def popupMenu(self, widget, button=0): """Pop up the context menu.""" menu = ProcessContextMenu(self.get_selection(), self) menu.show_all() menu.popup(None, None, None, button, gtk.get_current_event_time()) def cleanup(self): """Clean up when the widget is destroyed.""" self.process_mgr.stop() def apply_prefs(self, prefs): self.process_mgr.bin_dir = prefs.bin_dir self.process_mgr.use_sudo = prefs.use_sudo self.process_mgr.use_ssh = prefs.use_ssh self.process_mgr.hostname = prefs.hostname self.timer.set_paused(not prefs.show_process_list) self.timer.update_interval(prefs.process_interval)