#!/usr/bin/env python # Copyright (C) 2006, Eduardo Silva (edsiper@gmail.com). # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys import os import string import wnck import plugin from procmem import proc try: import gtk import gtk.gdk import gobject except: sys.exit(1) class Interface: store_data_types = [] store_data_types_details = [] def __init__(self): # Our GtkTree (Treeview) self.treeview = gtk.TreeView() self.treeview.show() self.button_start = gtk.Button('Start Memphis') self.button_stop = gtk.Button('Stop Memphis') fixed = gtk.Fixed() fixed.add(self.button_start) fixed.add(self.button_stop) vbox = gtk.VBox(False) vbox.set_border_width(5) vbox.pack_start(fixed, True, True, 0) # Our GtkTree (Treeview) self.treeview = gtk.TreeView() t_width = gtk.gdk.screen_width() t_height = gtk.gdk.screen_height() * 83 / 100 self.treeview.set_size_request(t_width, t_height) vbox.pack_start(self.treeview, True, True, 0) vbox.show_all() self.widget = vbox # Loading plugins self.plg = plugin.Plugin() # TOP data types (columns) self.store_data_types = [] for plg in self.plg.list: plg_data = plg.INTERNALS # Give plugin object to plugin plg.INTERNALS['Plg'] = self.plg # Creating a store model and loading process data to Treeview # self.store_data_types, ex [int, str, str, str, int,...] #self.store = gtk.TreeStore(*self.store_data_types) self.data = Data(self, self.treeview, self.plg.list) self.button_stop.hide() self.button_start.connect('clicked', self.data._start_memphis) self.button_stop.connect('clicked', self.data._stop_memphis) class Data: last_col_index = 0 store_data_cols = [] store_data_types = [] store_data_types_details = [] _running_status = False def __init__(self, interface, treeview, plg_list): self.interface = interface # Top data types self.plg_list = plg_list for plg in self.plg_list: if plg.INTERNALS['top_data'] != None: last_dt = len(self.store_data_types) if last_dt > 0: last_dt -= 1 len_dt = len(plg.INTERNALS['top_data']) self.store_data_types_details.append({"plugin": plg, "init": last_dt, "end": last_dt + len_dt}) for dt in plg.INTERNALS['top_data']: self.store_data_types.append(dt) for col in plg.INTERNALS['top_cols']: self.store_data_cols.append(col) # Set global treeview self.treeview = treeview # Basic columns index = 0 for column_name in self.store_data_cols: self.add_column(column_name, index) index += 1 self.store = gtk.TreeStore(*self.store_data_types) treeview.set_model(self.store) def _start_memphis(self, button): # Update information every 1.5 second button.hide() self.interface.button_stop.show() self._running_status = True gobject.timeout_add(1500, self.load_data, self.treeview) def _stop_memphis(self, button): self._running_status = False button.hide() self.interface.button_start.show() # Add a new column to the main treeview def add_column(self, column_name, index): cell = gtk.CellRendererText() col_tv = gtk.TreeViewColumn(column_name, cell, text=index) col_tv.set_resizable(True) col_tv.connect('clicked', self.sort_column_clicked) col_tv.set_property('clickable', True) self.treeview.append_column(col_tv) # Set the last column index added self.last_col_index = index # Sorting def sort_column_clicked(self, TreeViewColumn): cols = self.treeview.get_columns() # Searching column index index = 0 for col in cols: if col == TreeViewColumn: break index += 1 self.store.set_sort_column_id(index, gtk.SORT_DESCENDING) def load_data(self, treeview): self.store.clear() # Getting procfs data self.procdata = proc.ProcInfo() self.process_list = [] pids = [] screen = wnck.screen_get_default() windows = screen.get_windows() current_pid = os.getpid() for win in windows: pid = int(win.get_pid()) if current_pid != pid: pids.append(pid) self.process_list = set(pids) # Sort rows using pid #self.process_list.sort(key=operator.itemgetter('pid')) self.process_iter = [] for pid in self.process_list: pi = self.build_row(self.store, None, self.procdata, pid) self.process_iter.append(pi) treeview.set_rules_hint(True) treeview.expand_all() return self._running_status def build_row(self, store, parent_iter, proc_data, pid): data = [] pinfo = proc_data.MemoryInfo(pid) # Look for plugins that need to update the top data treeview for plg in self.plg_list: plg_data = [] if plg.INTERNALS['top_data'] != None: # data = [xxx, yyy,zzz,...] plg_data = plg.info.plg_on_top_data_refresh(plg, pinfo) for field in plg_data: data.append(field) pi = self.insert_row(store, parent_iter, data) return pi # Insert a Row in our TreeView def insert_row(self, store, parent, row_data): iter = store.insert_after(parent, None) index = 0 for data in row_data: store.set_value(iter, index , data) index += 1 return iter