Remove the console. Eduardo is moving the functionalities

out to the log and analyze activities.
master
Marco Pesenti Gritti 17 years ago
parent 2782ce71b0
commit 6768a4216f

@ -66,22 +66,5 @@ shell/view/home/Makefile
shell/model/Makefile
shell/model/devices/Makefile
shell/model/devices/network/Makefile
services/console/lib/Makefile
services/console/lib/graphics/Makefile
services/console/lib/procmem/Makefile
services/console/lib/net/Makefile
services/console/lib/ui/Makefile
services/console/Makefile
services/console/interface/Makefile
services/console/interface/xo/Makefile
services/console/interface/memphis/plugins/clean_size/Makefile
services/console/interface/memphis/plugins/smaps/Makefile
services/console/interface/memphis/plugins/Makefile
services/console/interface/memphis/plugins/memphis_init/Makefile
services/console/interface/memphis/plugins/cpu/Makefile
services/console/interface/memphis/Makefile
services/console/interface/network/Makefile
services/console/interface/logviewer/Makefile
services/console/interface/xserver/Makefile
po/Makefile.in
])

@ -1 +1 @@
SUBDIRS = shell console
SUBDIRS = shell

@ -1,20 +0,0 @@
SUBDIRS = interface lib
servicedir = $(datadir)/dbus-1/services
service_in_files = org.laptop.sugar.Console.service.in
service_DATA = $(service_in_files:.service.in=.service)
$(service_DATA): $(service_in_files) Makefile
@sed -e "s|\@bindir\@|$(bindir)|" $< > $@
sugardir = $(pkgdatadir)/services/console
sugar_PYTHON = \
__init__.py \
console.py \
label.py
bin_SCRIPTS = sugar-console
DISTCLEANFILES = $(service_DATA)
EXTRA_DIST = $(service_in_files) $(bin_SCRIPTS)

@ -1,12 +0,0 @@
Defining new tabs in the developer console
==========================================
The tabs are top-level packages inside 'interface/'.
Each package used as a tab must have a class Interface, instantiatable
with no arguments, with an attribute 'widget' that is a Gtk widget to be
placed in the tab. That's it.
Tabs are automatically run under the GLib main loop, dbus-python is set up
to use it, and the shared dbus-python session-bus connection is expected to
exist.

@ -1,94 +0,0 @@
# 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 dbus
import dbus.glib
import dbus.service
import os
import sys
import gtk
import gobject
sys.path.append(os.path.dirname(__file__))
sys.path.append(os.path.dirname(__file__) + '/lib')
sys.path.append(os.path.dirname(__file__) + '/interface')
CONSOLE_BUS = 'org.laptop.sugar.Console'
CONSOLE_PATH = '/org/laptop/sugar/Console'
CONSOLE_IFACE = 'org.laptop.sugar.Console'
class Console:
def __init__(self):
# Main Window
self.window = gtk.Window()
self.window.set_title('Developer console')
self.window.connect("delete-event", self._delete_event_cb)
self.default_width = gtk.gdk.screen_width() * 95 / 100
self.default_height = gtk.gdk.screen_height() * 95 / 100
self.window.set_default_size(self.default_width, self.default_height)
self.window.realize()
self.window.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
# Notebook
self.notebook = gtk.Notebook()
self._load_interface('xo', 'XO Resources')
self._load_interface('network', 'Network')
self._load_interface('xserver', 'X Server')
self._load_interface('memphis', 'Memphis')
self._load_interface('logviewer', 'Log Viewer')
self._load_interface('ps_watcher', 'Presence')
main_hbox = gtk.HBox()
main_hbox.pack_start(self.notebook, True, True, 0)
main_hbox.show()
self.notebook.show()
self.window.add(main_hbox)
def _load_interface(self, interface, label):
mod = __import__(interface)
widget = mod.Interface().widget
widget.show()
self.notebook.append_page(widget, gtk.Label(label))
def _delete_event_cb(self, window, gdkevent):
gtk.main_quit()
class Service(dbus.service.Object):
def __init__(self, bus, object_path=CONSOLE_PATH):
dbus.service.Object.__init__(self, bus, object_path)
self._console = Console()
@dbus.service.method(CONSOLE_IFACE)
def ToggleVisibility(self):
window = self._console.window
if not window.props.visible:
window.present()
else:
window.hide()
bus = dbus.SessionBus()
name = dbus.service.BusName(CONSOLE_BUS, bus)
obj = Service(name)
gtk.main()

@ -1,6 +0,0 @@
SUBDIRS = memphis network logviewer xo xserver
sugardir = $(pkgdatadir)/services/console/interface
sugar_PYTHON = \
__init__.py \
ps_watcher.py

@ -1,4 +0,0 @@
sugardir = $(pkgdatadir)/services/console/interface/logviewer
sugar_PYTHON = \
__init__.py \
logviewer.py

@ -1 +0,0 @@
from logviewer import Interface

@ -1,228 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# 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
# Rewritten by Eduardo Silva, edsiper@gmail.com
import os
import pygtk
import gtk
import gobject
import pango
import gnomevfs
from sugar import env
class MultiLogView(gtk.VBox):
def __init__(self, path, extra_files):
self._logs_path = path
self._active_log = None
self._extra_files = extra_files
# Creating Main treeview with Actitivities list
self._tv_menu = gtk.TreeView()
self._tv_menu.connect('cursor-changed', self._load_log)
self._tv_menu.set_rules_hint(True)
# Set width
box_width = gtk.gdk.screen_width() * 80 / 100
self._tv_menu.set_size_request(box_width*25/100, 0)
self._store_menu = gtk.TreeStore(str)
self._tv_menu.set_model(self._store_menu)
self._add_column(self._tv_menu, 'Sugar logs', 0)
self._logs = {}
# Activities menu
self.hbox = gtk.HBox(False, 3)
self.hbox.pack_start(self._tv_menu, True, True, 0)
# Activity log, set width
self._view = LogView()
self._view.set_size_request(box_width*75/100, 0)
self.hbox.pack_start(self._view, True, True, 0)
self.hbox.show_all()
self._configure_watcher()
self._create_log_view()
def _configure_watcher(self):
# Setting where gnomeVFS will be watching
gnomevfs.monitor_add('file://' + self._logs_path,
gnomevfs.MONITOR_DIRECTORY,
self._log_file_changed_cb)
for f in self._extra_files:
gnomevfs.monitor_add('file://' + f,
gnomevfs.MONITOR_FILE,
self._log_file_changed_cb)
def _log_file_changed_cb(self, monitor_uri, info_uri, event):
path = info_uri.split('file://')[-1]
filename = self._get_filename_from_path(path)
if event == gnomevfs.MONITOR_EVENT_CHANGED:
self._logs[filename].update()
elif event == gnomevfs.MONITOR_EVENT_DELETED:
self._delete_log_file_view(filename)
elif event == gnomevfs.MONITOR_EVENT_CREATED:
self._add_log_file(path)
# Load the log information in View (textview)
def _load_log(self, treeview):
treeselection = treeview.get_selection()
treestore, iter = treeselection.get_selected()
# Get current selection
act_log = self._store_menu.get_value(iter, 0)
# Set buffer and scroll down
self._view.textview.set_buffer(self._logs[act_log])
self._view.textview.scroll_to_mark(self._logs[act_log].get_insert(), 0)
self._active_log = act_log
def _create_log_view(self):
# Searching log files
for logfile in os.listdir(self._logs_path):
full_log_path = os.path.join(self._logs_path, logfile)
self._add_log_file(full_log_path)
for ext in self._extra_files:
self._add_log_file(ext)
return True
def _delete_log_file_view(self, logkey):
self._store_menu.remove(self._logs[logkey].iter)
del self._logs[logkey]
def _get_filename_from_path(self, path):
return path.split('/')[-1]
def _add_log_file(self, path):
if os.path.isdir(path):
return False
if not os.path.exists(path):
print "ERROR: %s don't exists"
return False
logfile = self._get_filename_from_path(path)
if not self._logs.has_key(logfile):
iter = self._add_log_row(logfile)
model = LogBuffer(path, iter)
self._logs[logfile] = model
self._logs[logfile].update()
written = self._logs[logfile]._written
# Load the first iter
if self._active_log == None:
self._active_log = logfile
iter = self._tv_menu.get_model().get_iter_root()
self._tv_menu.get_selection().select_iter(iter)
self._load_log(self._tv_menu)
if written > 0 and self._active_log == logfile:
self._view.textview.scroll_to_mark(self._logs[logfile].get_insert(), 0)
def _add_log_row(self, name):
return self._insert_row(self._store_menu, None, name)
# Add a new column to the main treeview, (code from Memphis)
def _add_column(self, treeview, column_name, index):
cell = gtk.CellRendererText()
col_tv = gtk.TreeViewColumn(column_name, cell, text=index)
col_tv.set_resizable(True)
col_tv.set_property('clickable', True)
treeview.append_column(col_tv)
# Set the last column index added
self.last_col_index = index
# Insert a Row in our TreeView
def _insert_row(self, store, parent, name):
iter = store.insert_before(parent, None)
index = 0
store.set_value(iter, index , name)
return iter
class LogBuffer(gtk.TextBuffer):
def __init__(self, logfile, iter=None):
gtk.TextBuffer.__init__(self)
self._logfile = logfile
self._pos = 0
self.iter = iter
self.update()
def update(self):
try:
f = open(self._logfile, 'r')
init_pos = self._pos
f.seek(self._pos)
self.insert(self.get_end_iter(), f.read())
self._pos = f.tell()
f.close()
self._written = (self._pos - init_pos)
except:
self.insert(self.get_end_iter(), "Console error: can't open the file\n")
self._written = 0
class LogView(gtk.ScrolledWindow):
def __init__(self):
gtk.ScrolledWindow.__init__(self)
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.textview = gtk.TextView()
self.textview.set_wrap_mode(gtk.WRAP_WORD)
font = pango.FontDescription('Sans 8')
font.set_weight(pango.WEIGHT_LIGHT)
self.textview.modify_font(font)
# Set background color
bgcolor = gtk.gdk.color_parse("#FFFFFF")
self.textview.modify_base(gtk.STATE_NORMAL, bgcolor)
self.textview.set_editable(False)
self.add(self.textview)
self.textview.show()
class Interface:
def __init__(self):
# Main path to watch: ~/.sugar/someuser/logs...
main_path = os.path.join(env.get_profile_path(), 'logs')
# extra files to watch in logviewer
ext_files = []
ext_files.append("/var/log/Xorg.0.log")
ext_files.append("/var/log/syslog")
ext_files.append("/var/log/messages")
viewer = MultiLogView(main_path, ext_files)
self.widget = viewer.hbox

@ -1,8 +0,0 @@
SUBDIRS = plugins
sugardir = $(pkgdatadir)/services/console/interface/memphis
sugar_PYTHON = \
__init__.py \
memphis.py \
plugin.py

@ -1 +0,0 @@
from memphis import Interface

@ -1,235 +0,0 @@
# 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
self._gid = gobject.timeout_add(1500, self.load_data, self.treeview)
def _stop_memphis(self, button):
gobject.source_remove(self._gid)
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

@ -1,48 +0,0 @@
###############################################
# Memphis Plugin Support
###############################################
import sys, os
from procmem import proc, proc_smaps, analysis
class Plugin:
# Plugin list
list = []
proc = proc.ProcInfo()
internal_plugin = "memphis_init"
plg_path = os.path.dirname(os.path.abspath(__file__)) + "/plugins"
# Frequency timer, managed by main program
freq_timer = 0
def __init__(self):
sys.path.insert(0, self.plg_path)
# Including memphis plugin
self.list.append(__import__(self.internal_plugin))
if os.path.isdir(self.plg_path):
# around dir entries
for plg in os.listdir(self.plg_path):
if plg == self.internal_plugin:
continue
if os.path.isdir(self.plg_path + "/" + plg):
p = __import__(plg)
self.list.append(__import__(plg))
# Parse /proc/PID/smaps information
def proc_get_smaps(self, pid):
return proc_smaps.ProcSmaps(pid)
# Parse /proc/PID/maps information
def proc_get_maps(self, pid):
return proc_smaps.ProcMaps(pid)
def proc_analysis(self, pid):
return analysis.Analysis(pid)

@ -1,4 +0,0 @@
SUBDIRS = clean_size cpu smaps memphis_init
sugardir = $(pkgdatadir)/services/console/interface/memphis/plugins
sugar_PYTHON =

@ -1,6 +0,0 @@
sugardir = $(pkgdatadir)/services/console/interface/memphis/plugins/clean_size
sugar_PYTHON = \
README \
__init__.py \
info.py

@ -1,2 +0,0 @@
This plugin give support to get the clean size memory usage
by process using the /proc/PID/maps file.

@ -1,16 +0,0 @@
import info
INTERNALS = {
# Basic information
'PLGNAME': "Clean Size",
'TABNAME': None,
'AUTHOR': "Eduardo Silva",
'DESC': "Print the approx real memory usage",
# Plugin API
'Plg': None, # Plugin object
'top_data': [int], # Top data types needed by memphis core plugin
'top_cols': ["Approx Real Usage (kb)"]
}

@ -1,15 +0,0 @@
###########################################################
# Main function:
# -----------------
# self: self plugin object
# mself: memphis object / principal class
# pinfo: row with information about current tracing process
############################################################
def plg_on_top_data_refresh(self, pinfo):
# Get clean size
maps = self.INTERNALS['Plg'].proc_get_maps(pinfo['pid'])
size = (maps.clean_size/1024)
return [size]

@ -1,6 +0,0 @@
sugardir = $(pkgdatadir)/services/console/interface/memphis/plugins/cpu
sugar_PYTHON = \
README \
__init__.py \
info.py

@ -1,2 +0,0 @@
This plugin give support to draw the Virtual Memory Size
usage by the current tracing process.

@ -1,23 +0,0 @@
import os
import info
INTERNALS = {
'PLGNAME': "cpu",
'TABNAME': None,
'AUTHOR': "Eduardo Silva",
'DESC': "Print CPU usage",
# Plugin API
'Plg': None, # Plugin object
'current_plg': None, # Current plugin object
'current_page': None, # Current page number
# Top process view requirements
'top_data': [int], # Top data types needed by memphis core plugin
'top_cols': ["%CPU "] # Column names
}
# Get CPU frequency
cpu_hz = os.sysconf(2)
pids_ujiffies = {}

@ -1,48 +0,0 @@
###########################################################
# Main function:
# -----------------
# self: self plugin object
# mself: memphis object / principal class
# pinfo: row with information about current tracing process
############################################################
def plg_on_top_data_refresh(self, pinfo):
PI = self.INTERNALS['Plg'].proc
pid = pinfo['pid']
# Get JIFFIES CPU usage
used_jiffies = pinfo['utime'] + pinfo['stime']
last_ujiffies = get_pid_ujiffies(self, pid)
cpu_usage = PI.get_CPU_usage(self.cpu_hz, used_jiffies, pinfo['start_time'])
# Get PERCENT CPU usage
if last_ujiffies == 0.0:
pcpu = 0.0
set_pid_ujiffies(self, pid, cpu_usage['used_jiffies'])
data = [int(pcpu)]
return data
used_jiffies = cpu_usage['used_jiffies'] - last_ujiffies
# Available jiffies are
avail_jiffies = (500/1000.0)*self.cpu_hz # 500 = 0.5 second
pcpu = ((used_jiffies*100)/avail_jiffies)
set_pid_ujiffies(self, pid, cpu_usage['used_jiffies'])
data = [int(pcpu)]
return data
def get_pid_ujiffies(self, pid):
if pid in self.pids_ujiffies:
return self.pids_ujiffies[pid]
else:
set_pid_ujiffies(self, pid, 0)
return self.pids_ujiffies[pid]
def set_pid_ujiffies(self, pid, ujiffies):
self.pids_ujiffies[pid] = ujiffies

@ -1,6 +0,0 @@
sugardir = $(pkgdatadir)/services/console/interface/memphis/plugins/memphis_init
sugar_PYTHON = \
README \
__init__.py \
info.py

@ -1,2 +0,0 @@
This plugin give support to draw the Virtual Memory Size
usage by the current tracing process.

@ -1,15 +0,0 @@
import info
INTERNALS = {
'PLGNAME': "memphis",
'TABNAME': None,
'AUTHOR': "Eduardo Silva",
'DESC': "Print basic process information",
# Plugin API
'Plg': None, # Plugin object
# Top process view requirements
'top_data': [int, str, str], # Top data types needed by memphis core plugin
'top_cols': ["PID", "Process Name", "Status"] # Column names
}

@ -1,14 +0,0 @@
###########################################################
# Main function:
# -----------------
# self: self plugin object
# mself: memphis object / principal class
# pinfo: row with information about current tracing process
############################################################
def plg_on_top_data_refresh(self, ppinfo):
data = [ppinfo['pid'], ppinfo['name'], ppinfo['state_name']]
return data

@ -1,6 +0,0 @@
sugardir = $(pkgdatadir)/services/console/interface/memphis/plugins/dirty_size
sugar_PYTHON = \
README \
__init__.py \
info.py

@ -1,2 +0,0 @@
This plugin give support to get the public and shared dirty memory usage
by process using the /proc/PID/smaps file.

@ -1,17 +0,0 @@
import info
INTERNALS = {
# Basic information
'PLGNAME': "SMaps",
'TABNAME': None, # No tabbed plugin
'AUTHOR': "Eduardo Silva",
'DESC': "Get dirty size and reference memory usage",
# Plugin API
'Plg': None, # Plugin object
'top_data': [int, int], # Top data types needed by memphis core plugin
'top_cols': ["PDRSS (kb)", "Referenced (kb)"]
}

@ -1,19 +0,0 @@
###########################################################
# Main function:
# -----------------
# self: self plugin object
# mself: memphis object / principal class
# pinfo: row with information about current tracing process
############################################################
def plg_on_top_data_refresh(self, ppinfo):
smaps = get_data(self, ppinfo['pid'])
# memphis need an array
return [smaps['private_dirty'], smaps['referenced']]
def get_data(pself, pid):
ProcAnalysis = pself.INTERNALS['Plg'].proc_analysis(pid)
return ProcAnalysis.SMaps()

@ -1,4 +0,0 @@
sugardir = $(pkgdatadir)/services/console/interface/network
sugar_PYTHON = \
__init__.py \
network.py

@ -1 +0,0 @@
from network import Interface

@ -1,103 +0,0 @@
# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import gobject
from net.device import Device
from ui.treeview import TreeView
class NetworkView(TreeView):
def __init__(self):
col_names = []
col_names.append({'index': 0, 'name': 'Interface'})
col_names.append({'index': 1, 'name': 'IP Address'})
col_names.append({'index': 2, 'name': 'NetMask'})
col_names.append({'index': 3, 'name': 'MAC Address'})
col_names.append({'index': 4, 'name': 'Bytes Recv'})
col_names.append({'index': 5, 'name': 'Bytes Sent'})
col_names.append({'index': 6, 'name': 'Packets Recv'})
col_names.append({'index': 7, 'name': 'Packets Sent'})
self._iface_iter = []
cols_type = [str, str, str, str, str, str, str, str]
TreeView.__init__(self, cols_type, col_names)
self._dev = Device()
self.show_all()
gobject.timeout_add(1500, self._update_data)
def _update_data(self):
interfaces = self._dev.get_interfaces()
for iface in interfaces:
info = self._dev.get_iface_info(iface['interface'])
row = []
row.append({'index':0, 'info': iface['interface']})
if info[0]:
row.append({'index':1, 'info': info[0]})
if info[1]:
row.append({'index':2, 'info': info[1]})
if info[2]:
row.append({'index':3, 'info': info[2]})
row.append({'index': 4, 'info': iface['bytes_sent']})
row.append({'index': 5, 'info': iface['packets_sent']})
row.append({'index': 6, 'info': iface['bytes_recv']})
row.append({'index': 7, 'info': iface['packets_recv']})
iter = self._get_iface_iter(iface['interface'])
if not iter:
iter = self.add_row(row)
self._set_iface_iter(iter, iface['interface'])
else:
self.update_row(iter, row)
self._clear_down_interfaces(interfaces)
return True
def _set_iface_iter(self, iter, iface):
self._iface_iter.append([iter, iface])
def _remove_iface_iter(self, search_iter):
i = 0
for [iter, interface] in self._iface_iter:
if iter == search_iter:
del self._iface_iter[i]
return
i+=1
def _get_iface_iter(self, iface):
for [iter, interface] in self._iface_iter:
if iface == interface:
return iter
return None
def _clear_down_interfaces(self, interfaces):
for [iter, iface] in self._iface_iter:
found = False
for dev in interfaces:
if dev['interface']==iface:
found = True
break
if not found:
self.remove_row(iter)
self._remove_iface_iter(iter)
class Interface(object):
def __init__(self):
self.widget = NetworkView()

@ -1,729 +0,0 @@
# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
#
# 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 logging
from hashlib import sha1
import dbus
from gtk import VBox, Label, TreeView, Expander, ListStore, CellRendererText,\
ScrolledWindow, CellRendererToggle, TextView, VPaned
from gobject import timeout_add
logger = logging.getLogger('ps_watcher')
#logging.basicConfig(filename='/tmp/ps_watcher.log')
#logging.getLogger().setLevel(1)
PS_NAME = 'org.laptop.Sugar.Presence'
PS_PATH = '/org/laptop/Sugar/Presence'
PS_IFACE = PS_NAME
ACTIVITY_IFACE = PS_IFACE + '.Activity'
BUDDY_IFACE = PS_IFACE + '.Buddy'
# keep these in sync with the calls to ListStore()
ACT_COL_PATH = 0
ACT_COL_WEIGHT = 1
ACT_COL_STRIKE = 2
ACT_COL_ID = 3
ACT_COL_COLOR = 4
ACT_COL_TYPE = 5
ACT_COL_NAME = 6
ACT_COL_CONN = 7
ACT_COL_CHANNELS = 8
ACT_COL_BUDDIES = 9
BUDDY_COL_PATH = 0
BUDDY_COL_WEIGHT = 1
BUDDY_COL_STRIKE = 2
BUDDY_COL_NICK = 3
BUDDY_COL_OWNER = 4
BUDDY_COL_COLOR = 5
BUDDY_COL_IP4 = 6
BUDDY_COL_CUR_ACT = 7
BUDDY_COL_KEY_ID = 8
BUDDY_COL_ACTIVITIES = 9
BUDDY_COL_HANDLES = 10
class ActivityWatcher(object):
def __init__(self, ps_watcher, object_path):
self.ps_watcher = ps_watcher
self.bus = ps_watcher.bus
self.proxy = self.bus.get_object(self.ps_watcher.unique_name,
object_path)
self.iface = dbus.Interface(self.proxy, ACTIVITY_IFACE)
self.object_path = object_path
self.appearing = True
self.disappearing = False
timeout_add(5000, self._finish_appearing)
self.id = '?'
self.color = '?'
self.type = '?'
self.name = '?'
self.conn = '?'
self.channels = None
self.buddies = None
self.iter = self.ps_watcher.add_activity(self)
self.iface.GetId(reply_handler=self._on_get_id_success,
error_handler=self._on_get_id_failure)
self.iface.GetColor(reply_handler=self._on_get_color_success,
error_handler=self._on_get_color_failure)
self.iface.GetType(reply_handler=self._on_get_type_success,
error_handler=self._on_get_type_failure)
self.iface.GetName(reply_handler=self._on_get_name_success,
error_handler=self._on_get_name_failure)
self.iface.connect_to_signal('NewChannel', self._on_new_channel)
self.iface.GetChannels(reply_handler=self._on_get_channels_success,
error_handler=self._on_get_channels_failure)
self.iface.connect_to_signal('BuddyJoined', self._on_buddy_joined)
self.iface.connect_to_signal('BuddyLeft', self._on_buddy_left)
self.iface.GetJoinedBuddies(reply_handler=self._on_get_buddies_success,
error_handler=self._on_get_buddies_failure)
def _on_buddy_joined(self, buddy):
if self.buddies is None:
return
if buddy.startswith('/org/laptop/Sugar/Presence/Buddies/'):
buddy = '.../' + buddy[35:]
self.ps_watcher.log('INFO: Activity %s emitted BuddyJoined("%s") '
'or mentioned the buddy in GetJoinedBuddies',
self.object_path, buddy)
self.buddies.append(buddy)
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_BUDDIES,
' '.join(self.buddies))
def _on_buddy_left(self, buddy):
if self.buddies is None:
return
if buddy.startswith('/org/laptop/Sugar/Presence/Buddies/'):
buddy = '.../' + buddy[35:]
self.ps_watcher.log('INFO: Activity %s emitted BuddyLeft("%s")',
self.object_path, buddy)
try:
self.buddies.remove(buddy)
except ValueError:
pass
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_BUDDIES,
' '.join(self.buddies))
def _on_get_buddies_success(self, buddies):
self.buddies = []
for buddy in buddies:
self._on_buddy_joined(buddy)
def _on_get_buddies_failure(self, e):
self.log('ERROR: <Activity %s>.GetJoinedBuddies(): %s',
self.object_path, e)
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_BUDDIES,
'!')
def _on_new_channel(self, channel):
if self.channels is None:
return
if channel.startswith(self.full_conn):
channel = '...' + channel[len(self.full_conn):]
self.ps_watcher.log('INFO: Activity %s emitted NewChannel("%s") '
'or mentioned the channel in GetChannels()',
self.object_path, channel)
self.channels.append(channel)
# FIXME: listen for Telepathy Closed signal!
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_CHANNELS,
' '.join(self.channels))
def _on_get_channels_success(self, service, conn, channels):
self.full_conn = conn
if conn.startswith('/org/freedesktop/Telepathy/Connection/'):
self.conn = '.../' + conn[38:]
else:
self.conn = conn
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_CONN,
self.conn)
self.channels = []
for channel in channels:
self._on_new_channel(channel)
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_CHANNELS,
' '.join(self.channels))
def _on_get_channels_failure(self, e):
self.ps_watcher.log('ERROR: <Activity %s>.GetChannels(): %s',
self.object_path, e)
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_CONN,
'!')
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_CHANNELS,
'!')
def _on_get_id_success(self, ident):
self.id = ident
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_ID, ident)
def _on_get_id_failure(self, e):
self.ps_watcher.log('ERROR: <Activity %s>.GetId(): %s',
self.object_path, e)
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_ID,
'!')
def _on_get_color_success(self, color):
self.color = color
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_COLOR,
color)
def _on_get_color_failure(self, e):
self.ps_watcher.log('ERROR: <Activity %s>.GetColor(): %s',
self.object_path, e)
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_COLOR,
'!')
def _on_get_type_success(self, type_):
self.type = type_
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_TYPE,
type_)
def _on_get_type_failure(self, e):
self.ps_watcher.log('ERROR: <Activity %s>.GetType(): %s',
self.object_path, e)
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_TYPE,
'!')
def _on_get_name_success(self, name):
self.name = name
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_NAME,
name)
def _on_get_name_failure(self, e):
self.ps_watcher.log('ERROR: <Activity %s>.GetName(): %s',
self.object_path, e)
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_NAME,
'!')
def _finish_appearing(self):
self.appearing = False
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_WEIGHT,
400)
return False
def disappear(self):
self.disappearing = True
self.ps_watcher.activities_list_store.set(self.iter, ACT_COL_STRIKE,
True)
timeout_add(5000, self._finish_disappearing)
def _finish_disappearing(self):
self.ps_watcher.remove_activity(self)
return False
class BuddyWatcher(object):
def __init__(self, ps_watcher, object_path):
self.ps_watcher = ps_watcher
self.bus = ps_watcher.bus
self.proxy = self.bus.get_object(self.ps_watcher.unique_name,
object_path)
self.iface = dbus.Interface(self.proxy, BUDDY_IFACE)
self.object_path = object_path
self.appearing = True
self.disappearing = False
timeout_add(5000, self._finish_appearing)
self.nick = '?'
self.owner = False
self.color = '?'
self.ipv4 = '?'
self.cur_act = '?'
self.keyid = '?'
self.activities = None
self.handles = None
self.iter = self.ps_watcher.add_buddy(self)
self.iface.connect_to_signal('PropertyChanged', self._on_props_changed,
byte_arrays=True)
self.ps_watcher.log('Calling <Buddy %s>.GetProperties()', object_path)
self.iface.GetProperties(reply_handler=self._on_get_props_success,
error_handler=self._on_get_props_failure,
byte_arrays=True)
self.iface.connect_to_signal('JoinedActivity', self._on_joined)
self.iface.connect_to_signal('LeftActivity', self._on_left)
self.ps_watcher.log('Calling <Buddy %s>.GetJoinedActivities()',
object_path)
self.iface.GetJoinedActivities(reply_handler=self._on_get_acts_success,
error_handler=self._on_get_acts_failure)
self.iface.connect_to_signal('TelepathyHandleAdded',
self._on_handle_added)
self.iface.connect_to_signal('TelepathyHandleRemoved',
self._on_handle_removed)
self.ps_watcher.log('Calling <Buddy %s>.GetTelepathyHandles()',
object_path)
self.iface.GetTelepathyHandles(
reply_handler=self._on_get_handles_success,
error_handler=self._on_get_handles_failure)
def _on_handle_added(self, service, conn, handle):
if self.handles is None:
return
self.ps_watcher.log('INFO: Buddy %s emitted Telepathy HandleAdded('
'"%s", "%s", %u) or mentioned the handle in '
'GetTelepathyHandles()',
self.object_path, service, conn, handle)
if conn.startswith('/org/freedesktop/Telepathy/Connection/'):
conn = '.../' + conn[38:]
self.handles.append('%u@%s' % (handle, conn))
self.ps_watcher.buddies_list_store.set(self.iter,
BUDDY_COL_HANDLES,
' '.join(self.handles))
def _on_handle_removed(self, service, conn, handle):
if self.handles is None:
return
if conn.startswith('/org/freedesktop/Telepathy/Connection/'):
conn = '.../' + conn[38:]
self.ps_watcher.log('INFO: Buddy %s emitted HandleRemoved("%s", '
'"%s", %u)', self.object_path, service, conn,
handle)
try:
self.handles.remove('%u@%s' % (handle, conn))
except ValueError:
pass
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_HANDLES,
' '.join(self.handles))
def _on_get_handles_success(self, handles):
self.handles = []
for service, conn, handle in handles:
self._on_handle_added(service, conn, handle)
def _on_get_handles_failure(self, e):
self.ps_watcher.log('ERROR: <Buddy %s>.GetTelepathyHandles(): %s',
self.object_path, e)
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_HANDLES,
'!')
def _on_joined(self, act):
if self.activities is None:
return
if act.startswith('/org/laptop/Sugar/Presence/Activities/'):
act = '.../' + act[38:]
self.ps_watcher.log('INFO: Buddy %s emitted ActivityJoined("%s") '
'or mentioned it in GetJoinedActivities()',
self.object_path, act)
self.activities.append(act)
self.ps_watcher.buddies_list_store.set(self.iter,
BUDDY_COL_ACTIVITIES,
' '.join(self.activities))
def _on_left(self, act):
if self.activities is None:
return
if act.startswith('/org/laptop/Sugar/Presence/Activities/'):
act = '.../' + act[38:]
self.ps_watcher.log('INFO: Buddy %s emitted ActivityLeft("%s")',
self.object_path, act)
try:
self.activities.remove(act)
except ValueError:
pass
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_ACTIVITIES,
' '.join(self.activities))
def _on_get_acts_success(self, activities):
self.activities = []
for act in activities:
self._on_joined(act)
def _on_get_acts_failure(self, e):
self.ps_watcher.log('ERROR: <Buddy %s>.GetJoinedActivities(): %s',
self.object_path, e)
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_ACTIVITIES,
'!')
def _on_props_changed(self, props):
try:
logger.debug('PropertyChanged(%s, %s)', self, props)
self.ps_watcher.log('INFO: <Buddy %s> emitted PropertyChanged(%r)',
self.object_path, props)
self._props_changed(props)
except Exception, e:
self.ps_watcher.log('INTERNAL ERROR: %s', e)
def _on_get_props_success(self, props):
try:
logger.debug('GetProperties(%s, %s)', self, props)
self.ps_watcher.log('INFO: <Buddy %s>.GetProperties() -> %r',
self.object_path, props)
self._props_changed(props)
except Exception, e:
self.ps_watcher.log('INTERNAL ERROR: %s', e)
def _props_changed(self, props):
logger.debug('Begin _props_changed')
if 'nick' in props:
self.nick = props.get('nick', '?')
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_NICK,
self.nick)
if 'owner' in props:
self.owner = bool(props.get('owner', False))
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_OWNER,
self.owner)
if 'color' in props:
self.color = props.get('color', '?')
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_COLOR,
self.color)
if 'ip4-address' in props:
self.ipv4 = props.get('ip4-address', '?')
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_IP4,
self.ipv4)
if 'current-activity' in props:
self.cur_act = props.get('current-activity', '?')
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_CUR_ACT,
self.cur_act)
if 'key' in props:
key = props.get('key', None)
if key:
self.keyid = '%d bytes, sha1 %s' % (len(key),
sha1(key).hexdigest())
else:
# could be '' (present, empty value) or None (absent). Either way:
self.keyid = '?'
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_KEY_ID,
self.keyid)
logger.debug('End _props_changed')
def _on_get_props_failure(self, e):
self.ps_watcher.log('ERROR: <Buddy %s>.GetProperties(): %s',
self.object_path, e)
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_NICK, '!')
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_OWNER,
False)
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_COLOR, '!')
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_IP4, '!')
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_CUR_ACT,
'!')
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_KEY_ID,
'!')
def _finish_appearing(self):
self.appearing = False
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_WEIGHT,
400)
return False
def disappear(self):
self.disappearing = True
self.ps_watcher.buddies_list_store.set(self.iter, BUDDY_COL_STRIKE,
True)
timeout_add(5000, self._finish_disappearing)
def _finish_disappearing(self):
self.ps_watcher.remove_buddy(self)
return False
class PresenceServiceWatcher(VBox):
def __init__(self, bus, unique_name, log):
VBox.__init__(self)
self.bus = bus
self.unique_name = unique_name
self.proxy = bus.get_object(unique_name, PS_PATH)
self.iface = dbus.Interface(self.proxy, PS_IFACE)
self.log = log
self.activities = None
self.iface.connect_to_signal('ActivityAppeared',
self._on_activity_appeared)
self.iface.connect_to_signal('ActivityDisappeared',
self._on_activity_disappeared)
self.iface.GetActivities(reply_handler=self._on_get_activities_success,
error_handler=self._on_get_activities_failure)
self.buddies = None
self.iface.connect_to_signal('BuddyAppeared',
self._on_buddy_appeared)
self.iface.connect_to_signal('BuddyDisappeared',
self._on_buddy_disappeared)
self.iface.GetBuddies(reply_handler=self._on_get_buddies_success,
error_handler=self._on_get_buddies_failure)
# keep this in sync with the ACT_COL_ constants
self.activities_list_store = ListStore(str, # object path
int, # weight (bold if new)
bool, # strikethrough (dead)
str, # ID
str, # color
str, # type
str, # name
str, # conn
str, # channels
str, # buddies
)
self.pack_start(Label('Activities:'), False, False)
self.activities_list = TreeView(self.activities_list_store)
c = self.activities_list.insert_column_with_attributes(0,
'Object path', CellRendererText(), text=ACT_COL_PATH,
weight=ACT_COL_WEIGHT, strikethrough=ACT_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(ACT_COL_PATH)
c = self.activities_list.insert_column_with_attributes(1, 'ID',
CellRendererText(), text=ACT_COL_ID,
weight=ACT_COL_WEIGHT, strikethrough=ACT_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(ACT_COL_ID)
c = self.activities_list.insert_column_with_attributes(2, 'Color',
CellRendererText(), text=ACT_COL_COLOR,
weight=ACT_COL_WEIGHT, strikethrough=ACT_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(ACT_COL_COLOR)
c = self.activities_list.insert_column_with_attributes(3, 'Type',
CellRendererText(), text=ACT_COL_TYPE, weight=ACT_COL_WEIGHT,
strikethrough=ACT_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(ACT_COL_TYPE)
c = self.activities_list.insert_column_with_attributes(4, 'Name',
CellRendererText(), text=ACT_COL_NAME, weight=ACT_COL_WEIGHT,
strikethrough=ACT_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(ACT_COL_NAME)
c = self.activities_list.insert_column_with_attributes(5, 'Connection',
CellRendererText(), text=ACT_COL_CONN, weight=ACT_COL_WEIGHT,
strikethrough=ACT_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(ACT_COL_CONN)
c = self.activities_list.insert_column_with_attributes(6, 'Channels',
CellRendererText(), text=ACT_COL_CHANNELS, weight=ACT_COL_WEIGHT,
strikethrough=ACT_COL_STRIKE)
c.set_resizable(True)
c = self.activities_list.insert_column_with_attributes(7, 'Buddies',
CellRendererText(), text=ACT_COL_BUDDIES, weight=ACT_COL_WEIGHT,
strikethrough=ACT_COL_STRIKE)
c.set_resizable(True)
scroller = ScrolledWindow()
scroller.add(self.activities_list)
self.pack_start(scroller)
# keep this in sync with the BUDDY_COL_ constants
self.buddies_list_store = ListStore(str, int, bool, str, bool,
str, str, str, str, str, str)
self.pack_start(Label('Buddies:'), False, False)
self.buddies_list = TreeView(self.buddies_list_store)
c = self.buddies_list.insert_column_with_attributes(0, 'Object path',
CellRendererText(), text=BUDDY_COL_PATH,
weight=BUDDY_COL_WEIGHT, strikethrough=BUDDY_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(BUDDY_COL_PATH)
c = self.buddies_list.insert_column_with_attributes(1, 'Pubkey',
CellRendererText(), text=BUDDY_COL_KEY_ID,
weight=BUDDY_COL_WEIGHT, strikethrough=BUDDY_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(BUDDY_COL_KEY_ID)
c = self.buddies_list.insert_column_with_attributes(2, 'Nick',
CellRendererText(), text=BUDDY_COL_NICK,
weight=BUDDY_COL_WEIGHT, strikethrough=BUDDY_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(BUDDY_COL_NICK)
c = self.buddies_list.insert_column_with_attributes(3, 'Owner',
CellRendererToggle(), active=BUDDY_COL_OWNER)
c = self.buddies_list.insert_column_with_attributes(4, 'Color',
CellRendererText(), text=BUDDY_COL_COLOR,
weight=BUDDY_COL_WEIGHT, strikethrough=BUDDY_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(BUDDY_COL_OWNER)
c = self.buddies_list.insert_column_with_attributes(5, 'IPv4',
CellRendererText(), text=BUDDY_COL_IP4,
weight=BUDDY_COL_WEIGHT, strikethrough=BUDDY_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(BUDDY_COL_IP4)
c = self.buddies_list.insert_column_with_attributes(6, 'CurAct',
CellRendererText(), text=BUDDY_COL_CUR_ACT,
weight=BUDDY_COL_WEIGHT, strikethrough=BUDDY_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(BUDDY_COL_CUR_ACT)
c = self.buddies_list.insert_column_with_attributes(7, 'Activities',
CellRendererText(), text=BUDDY_COL_ACTIVITIES,
weight=BUDDY_COL_WEIGHT, strikethrough=BUDDY_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(BUDDY_COL_ACTIVITIES)
c = self.buddies_list.insert_column_with_attributes(8, 'Handles',
CellRendererText(), text=BUDDY_COL_HANDLES,
weight=BUDDY_COL_WEIGHT, strikethrough=BUDDY_COL_STRIKE)
c.set_resizable(True)
c.set_sort_column_id(BUDDY_COL_HANDLES)
scroller = ScrolledWindow()
scroller.add(self.buddies_list)
self.pack_start(scroller)
self.iface.connect_to_signal('ActivityInvitation',
self._on_activity_invitation)
self.iface.connect_to_signal('PrivateInvitation',
self._on_private_invitation)
def _on_get_activities_success(self, paths):
self.log('INFO: PS GetActivities() returned %r', paths)
self.activities = {}
for path in paths:
self.activities[path] = ActivityWatcher(self, path)
def _on_get_activities_failure(self, e):
self.log('ERROR: PS GetActivities() failed with %s', e)
def add_activity(self, act):
path = act.object_path
if path.startswith('/org/laptop/Sugar/Presence/Activities/'):
path = '.../' + path[38:]
return self.activities_list_store.append((path, 700, False,
act.id, act.color, act.type, act.name, act.conn, '?', '?'))
def remove_activity(self, act):
self.activities.pop(act.object_path, None)
self.activities_list_store.remove(act.iter)
def _on_activity_appeared(self, path):
if self.activities is None:
return
self.log('INFO: PS emitted ActivityAppeared("%s")', path)
self.activities[path] = ActivityWatcher(self, path)
def _on_activity_disappeared(self, path):
if self.activities is None:
return
self.log('INFO: PS emitted ActivityDisappeared("%s")', path)
act = self.activities.get(path)
if act is None:
self.log('WARNING: Trying to remove activity "%s" which is '
'already absent', path)
else:
# we don't remove the activity straight away, just cross it out
act.disappear()
def _on_activity_invitation(self, path):
self.log('INFO: PS emitted ActivityInvitation("%s")', path)
def _on_private_invitation(self, bus_name, conn, channel):
self.log('INFO: PS emitted PrivateInvitation("%s", "%s", "%s")',
bus_name, conn, channel)
def _on_get_buddies_success(self, paths):
self.log('INFO: PS GetBuddies() returned %r', paths)
self.buddies = {}
for path in paths:
self.buddies[path] = BuddyWatcher(self, path)
def _on_get_buddies_failure(self, e):
self.log('ERROR: PS GetBuddies() failed with %s', e)
def add_buddy(self, b):
path = b.object_path
if path.startswith('/org/laptop/Sugar/Presence/Buddies/'):
path = '.../' + path[35:]
return self.buddies_list_store.append((path, 700, False,
b.nick, b.owner, b.color, b.ipv4, b.cur_act, b.keyid,
'?', '?'))
def remove_buddy(self, b):
self.buddies.pop(b.object_path, None)
self.buddies_list_store.remove(b.iter)
def _on_buddy_appeared(self, path):
if self.buddies is None:
return
self.log('INFO: PS emitted BuddyAppeared("%s")', path)
self.buddies[path] = BuddyWatcher(self, path)
def _on_buddy_disappeared(self, path):
if self.buddies is None:
return
self.log('INFO: PS emitted BuddyDisappeared("%s")', path)
b = self.buddies.get(path)
if b is None:
self.log('ERROR: Trying to remove buddy "%s" which is already '
'absent', path)
else:
# we don't remove the activity straight away, just cross it out
b.disappear()
class PresenceServiceNameWatcher(VBox):
def __init__(self, bus):
VBox.__init__(self)
self.bus = bus
logger.debug('Running...')
self.label = Label('Looking for Presence Service...')
self.errors = ListStore(str)
errors_tree = TreeView(model=self.errors)
errors_tree.insert_column_with_attributes(0, 'Log', CellRendererText(),
text=0)
scroller = ScrolledWindow()
scroller.add(errors_tree)
self.paned = VPaned()
self.paned.pack1(scroller)
self.pack_start(self.label, False, False)
self.pack_end(self.paned)
bus.watch_name_owner(PS_NAME, self.on_name_owner_change)
self.ps_watcher = Label('-')
self.paned.pack2(self.ps_watcher)
self.show_all()
def log(self, format, *args):
self.errors.append((format % args,))
def on_name_owner_change(self, owner):
try:
if owner:
self.label.set_text('Presence Service running: unique name %s'
% owner)
if self.ps_watcher is not None:
self.paned.remove(self.ps_watcher)
self.ps_watcher = PresenceServiceWatcher(self.bus, owner,
self.log)
self.paned.pack2(self.ps_watcher)
self.show_all()
else:
self.label.set_text('Presence Service not running')
if self.ps_watcher is not None:
self.paned.remove(self.ps_watcher)
self.ps_watcher = Label('-')
self.paned.pack2(self.ps_watcher)
except Exception, e:
self.log('ERROR: %s', e)
class Interface(object):
def __init__(self):
self.widget = PresenceServiceNameWatcher(dbus.SessionBus())

@ -1,7 +0,0 @@
sugardir = $(pkgdatadir)/services/console/interface/xo
sugar_PYTHON = \
__init__.py \
xo.py \
cpu.py \
system.py \
nandflash.py

@ -1,2 +0,0 @@
from xo import Interface

@ -1,111 +0,0 @@
# Copyright (C) 2007, 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 os
import sys
import gtk
import string
import gobject
import cairo
import procmem
from graphics.frequency import HorizontalGraphic
class CPU_Usage:
_CPU_HZ = 0
_last_jiffies = 0
_times = 0
def __init__(self):
self._CPU_HZ = os.sysconf(2)
def _get_CPU_data(self):
# Uptime info
stat_file = "/proc/stat"
try:
infile = file(stat_file, "r")
except:
print "Error trying uptime file"
return -1
stat_line = infile.readline()
cpu_info = string.split(stat_line, ' ')
infile.close()
return cpu_info
def _get_CPU_usage(self):
cpu_info = self._get_CPU_data()
used_jiffies = (int(cpu_info[2]) + int(cpu_info[3]) + int(cpu_info[4]))
if self._times ==0:
self._last_jiffies = used_jiffies
self._times +=1
return 0
new_ujiffies = (used_jiffies - self._last_jiffies)
new_ajiffies = ((self.frequency/1000) * self._CPU_HZ)
if new_ajiffies <= 0:
pcpu = 0.0
else:
pcpu = ((new_ujiffies*100)/new_ajiffies)
if pcpu >100:
pcpu = 100
self._times +=1
self._last_jiffies = used_jiffies
return pcpu
class XO_CPU(gtk.Frame):
_frequency_timer = 1
def __init__(self):
gtk.Frame.__init__(self, 'System CPU Usage')
self.set_border_width(10)
width = (gtk.gdk.screen_width() * 99 / 100) - 50
height = (gtk.gdk.screen_height() * 15 / 100) - 20
# Create graphic
self._graphic = HorizontalGraphic()
self._graphic.set_size_request(width, height)
fixed = gtk.Fixed()
fixed.set_border_width(10)
fixed.add(self._graphic)
self.add(fixed)
self._DRW_CPU = CPU_Usage()
self._DRW_CPU.frequency = 1000 # 1 Second
gobject.timeout_add(self._DRW_CPU.frequency, self._update_cpu_usage)
def _update_cpu_usage(self):
print "update XO CPU"
self._cpu = self._DRW_CPU._get_CPU_usage()
self.set_label('System CPU Usage: ' + str(self._cpu) + '%')
# Draw the value into the graphic
self._graphic.draw_value(self._cpu)
return True

@ -1,119 +0,0 @@
# Copyright (C) 2007, 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 gtk
import gobject
from os import statvfs
from label import Label
from graphics.box import *
class XO_NandFlash(gtk.Fixed):
_MOUNT_POINT = '/'
def __init__(self):
gtk.Fixed.__init__(self)
self._frame_text = 'Nand Flash'
self._frame = gtk.Frame(self._frame_text)
self.set_border_width(10)
self._nandflash_box = BoxGraphic(color_mode=COLOR_MODE_REVERSE)
self._nandflash_box.set_size_request(70, 150)
fixed = gtk.Fixed();
fixed.set_border_width(10)
fixed.add(self._nandflash_box)
hbox = gtk.HBox(False, 0)
hbox.pack_start(fixed, False, False, 4)
# Battery info
table = gtk.Table(2, 3)
table.set_border_width(5)
table.set_col_spacings(7)
table.set_row_spacings(7)
label_total_size = Label('Total: ' , Label.DESCRIPTION)
self._label_total_value = Label('0 KB', Label.DESCRIPTION)
label_used_size = Label('Used: ' , Label.DESCRIPTION)
self._label_used_value = Label('0 KB', Label.DESCRIPTION)
label_free_size = Label('Free: ' , Label.DESCRIPTION)
self._label_free_value = Label('0 KB', Label.DESCRIPTION)
# Total
table.attach(label_total_size, 0, 1, 0, 1)
table.attach(self._label_total_value, 1,2, 0,1)
# Used
table.attach(label_used_size, 0, 2, 1, 2)
table.attach(self._label_used_value, 1,3, 1,2)
# Free
table.attach(label_free_size, 0, 3, 2, 3)
table.attach(self._label_free_value, 1,4, 2,3)
alignment = gtk.Alignment(0,0,0,0)
alignment.add(table)
hbox.pack_start(alignment, False, False, 0)
self._frame.add(hbox)
self.add(self._frame)
self.show()
self.update_status()
def update_status(self):
nand = StorageDevice(self._MOUNT_POINT)
# Byte values
total = (nand.f_bsize*nand.f_blocks)
free = (nand.f_bsize*nand.f_bavail)
used = (total - free)
self._label_total_value.set_label(str(total/1024) + ' KB')
self._label_used_value.set_label(str(used/1024) + ' KB')
self._label_free_value.set_label(str(free/1024) + ' KB')
self._usage_percent = ((used*100)/total)
frame_label = self._frame_text + ': ' + str(self._usage_percent) + '%'
self._frame.set_label(frame_label)
self._nandflash_box.set_capacity(self._usage_percent)
class StorageDevice:
f_bsize = 0
f_frsize = 0
f_blocks = 0
f_bfree = 0
f_bavail = 0
f_files = 0
f_ffree = 0
f_favail = 0
f_flag = 0
f_namemax = 0
def __init__(self, mount_point):
self.f_bsize, self.f_frsize, self.f_blocks, self.f_bfree, \
self.f_bavail, self.f_files, self.f_ffree, \
self.f_favail, self.f_flag, self.f_namemax = statvfs(mount_point)
"""
w = gtk.Window()
a = XO_NandFlash()
w.add(a)
w.show_all()
gtk.main()
"""

@ -1,91 +0,0 @@
# Copyright (C) 2007, 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 os
import gtk
import pango
from label import Label
from label import Style
class XO_System(gtk.Fixed):
def __init__(self):
gtk.Fixed.__init__(self)
self.set_border_width(12)
table = gtk.Table(2, 2)
table.set_border_width(15)
table.set_col_spacings(7)
table.set_row_spacings(7)
# BUILD
build = self._read_file('/boot/olpc_build')
label_build = Label('OLPC Build:', Label.DESCRIPTION)
label_build_value = Label(str(build), Label.DESCRIPTION)
# KERNEL
sysinfo = os.uname()
label_kernel = Label('Kernel Version:', Label.DESCRIPTION)
label_kernel_value = Label(sysinfo[0] + '-' + sysinfo[2],\
Label.DESCRIPTION)
# FIRMWARE
firmware = self._read_file('/ofw/openprom/model')
label_firmware = Label('XO Firmware:', Label.DESCRIPTION)
label_firmware_value = Label(firmware, Label.DESCRIPTION)
# SERIAL NUMBER
serial = self._read_file('/ofw/serial-number')
label_serial = Label('XO Serial Number:', Label.DESCRIPTION)
label_serial_value = Label(serial, Label.DESCRIPTION)
# OLPC Build
table.attach(label_build, 0, 1, 0, 1)
table.attach(label_build_value, 1,2, 0,1)
# Kernel Version
table.attach(label_kernel, 0, 1, 1, 2)
table.attach(label_kernel_value, 1, 2, 1, 2)
# XO Firmware
table.attach(label_firmware, 0, 1, 2, 3)
table.attach(label_firmware_value, 1, 2, 2, 3)
# XO Serial Number
table.attach(label_serial, 0, 1, 3, 4)
table.attach(label_serial_value, 1, 2, 3, 4)
frame = gtk.Frame('System Information')
style = Style()
style.set_title_font(frame);
frame.add(table)
self.add(frame)
self.show_all()
def _read_file(self, path):
try:
f = open(path, 'r')
value = f.read()
f.close()
value = value.split('\n')[0]
if value[len(value) - 1] == '\x00':
value = value[:len(value) - 1]
return value
except:
return "None"

@ -1,57 +0,0 @@
# Copyright (C) 2007, 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 os
import gtk
import gobject
import gtk.gdk
import cairo
import string
from cpu import XO_CPU
from system import XO_System
from nandflash import XO_NandFlash
class Interface:
def __init__(self):
self.widget = self.vbox = gtk.VBox(False, 3)
# System information
xo_system = XO_System()
self.vbox.pack_start(xo_system, False, False, 0)
# CPU usage / Graph
xo_cpu = XO_CPU()
self.vbox.pack_start(xo_cpu, False, False, 0)
# Graphics: Battery Status, NandFlash
self._xo_nandflash = XO_NandFlash()
hbox = gtk.HBox(False, 2)
hbox.pack_start(self._xo_nandflash, False, False, 0)
self.vbox.pack_start(hbox, False, False, 0)
self.vbox.show_all()
# Update every 5 seconds
gobject.timeout_add(5000, self._update_components)
def _update_components(self):
self._xo_nandflash.update_status()
return True

@ -1,4 +0,0 @@
sugardir = $(pkgdatadir)/services/console/interface/xserver
sugar_PYTHON = \
__init__.py \
xserver.py

@ -1 +0,0 @@
from xserver import Interface

@ -1,111 +0,0 @@
# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import gobject
from pyxres import XRes
from ui.treeview import TreeView
class XorgView(TreeView):
def __init__(self):
col_names = []
col_names.append({'index': 0, 'name': 'PID'})
col_names.append({'index': 1, 'name': 'Resource Base'})
col_names.append({'index': 2, 'name': 'Pixmap Bytes'})
col_names.append({'index': 3, 'name': 'Other'})
col_names.append({'index': 4, 'name': 'Total'})
col_names.append({'index': 5, 'name': 'Window Name'})
self._window_iter = []
cols_type = [str, str, str, str, str, str]
TreeView.__init__(self, cols_type, col_names)
self._xres = XRes()
self._display = self._xres.open_display()
self.show_all()
gobject.timeout_add(1500, self._update_data)
def _nice_bytes(self, bytes):
prefix = "B"
value = bytes
if bytes/1024:
prefix = "K"
value = (bytes/1024)
return "%s%s" % (value, prefix)
def _update_data(self):
windows = self._xres.get_windows(self._display)
print windows
for w in windows:
row = []
row.append({'index':0, 'info': w.pid})
bytes = self._nice_bytes(w.pixmap_bytes)
obytes = self._nice_bytes(w.other_bytes)
tbytes = self._nice_bytes(w.pixmap_bytes+w.other_bytes)
row.append({'index':1, 'info': hex(w.resource_base)})
row.append({'index':2, 'info': bytes})
row.append({'index':3, 'info': obytes})
row.append({'index':4, 'info': tbytes})
row.append({'index':5, 'info': w.wm_name})
iter = self._get_window_iter(w.pid)
if not iter:
iter = self.add_row(row)
self._set_window_iter(iter, w.pid)
else:
self.update_row(iter, row)
self._clear_down_windows(windows)
return True
def _set_window_iter(self, iter, pid):
self._window_iter.append([iter, pid])
def _remove_iface_iter(self, search_iter):
i = 0
for [iter, pid] in self._window_iter:
if iter == search_iter:
del self._window_iter[i]
return
i+=1
def _get_window_iter(self, wpid):
for [iter, pid] in self._window_iter:
if wpid == pid:
return iter
return None
def _clear_down_windows(self, windows):
for [iter, pid] in self._window_iter:
found = False
for w in windows:
if w.pid == pid:
found = True
break
if not found:
self.remove_row(iter)
self._remove_window_iter(iter)
class Interface(object):
def __init__(self):
self.widget = XorgView()

@ -1,51 +0,0 @@
# Copyright (C) 2007, 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 gtk
import pango
class Label(gtk.Label):
TITLE = 0
DESCRIPTION = 1
def __init__(self, text, font_type):
gtk.Label.__init__(self)
self.set_text(text)
self.set_alignment(0.0, 0.5)
s = {
self.TITLE: self._set_title_font,
self.DESCRIPTION: self._set_description_font
}[font_type]()
def _set_title_font(self):
font = pango.FontDescription('Sans 12')
font.set_weight(pango.WEIGHT_NORMAL)
self.modify_font(font)
def _set_description_font(self):
font = pango.FontDescription('Sans 8')
font.set_weight(pango.WEIGHT_NORMAL)
self.modify_font(font)
class Style:
def set_title_font(self, object):
font = pango.FontDescription('Sans 20')
font.set_weight(pango.WEIGHT_NORMAL)
object.modify_font(font)

@ -1,6 +0,0 @@
SUBDIRS = procmem graphics net ui
sugardir = $(pkgdatadir)/services/console/lib
sugar_PYTHON = \
pyxres.py

@ -1,7 +0,0 @@
sugardir = $(pkgdatadir)/services/console/lib/graphics
sugar_PYTHON = \
__init__.py \
box.py \
frequency.py

@ -1,101 +0,0 @@
# Copyright (C) 2007, 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 gtk
import gobject
import cairo
COLOR_MODE_NORMAL = 0
COLOR_MODE_REVERSE = 1
class BoxGraphic(gtk.DrawingArea):
__gtype_name__ = 'ConsoleBoxGraphic'
__gproperties__ = {
'color-mode': (gobject.TYPE_INT, None, None, 0, 1, COLOR_MODE_NORMAL,
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY)
}
_color_status_high = [0, 0, 0]
_color_status_medium = [0, 0, 0]
_color_status_low = [0, 0, 0]
_limit_high = 0
_limit_medium = 0
_limit_low = 0
def __init__(self, **kwargs):
gobject.GObject.__init__(self, **kwargs)
gtk.DrawingArea.__init__(self)
self.connect("expose-event", self.do_expose)
self.connect('size-allocate', self._change_size_cb)
def do_expose(self, widget, event):
context = widget.window.cairo_create()
context.rectangle(0, 0, self._width, self._height)
context.set_source_rgb (0,0,0)
context.fill_preserve()
context.stroke()
self._draw_content(context, self._percent)
def do_set_property(self, pspec, value):
if pspec.name == 'color-mode':
self._configure(mode=value)
else:
raise AssertionError
def set_capacity(self, percent):
self._percent = percent
self.queue_draw()
def _configure(self, mode):
# Normal mode configure the box as a battery
# full is good, empty is bad
if mode == COLOR_MODE_NORMAL:
self._color_status_high = [0, 1, 0]
self._color_status_medium = [1,1,0]
self._color_status_low = [1,0,0]
self._limit_high = 60
self._limit_medium = 10
# Reverse mode configure the box as a storage device
# full is bad, empty is good
elif mode == COLOR_MODE_REVERSE:
self._color_status_high = [1,0,0]
self._color_status_medium = [1,1,0]
self._color_status_low = [0, 1, 0]
self._limit_high = 85
self._limit_medium = 40
def _draw_content(self, context, percent):
usage_height = (percent*self._height)/100
context.rectangle(0, self._height - usage_height, self._width, self._height)
if self._percent > self._limit_high:
context.set_source_rgb(*self._color_status_high)
elif self._percent >= self._limit_medium and self._percent <= self._limit_high:
context.set_source_rgb(*self._color_status_medium)
elif self._percent < self._limit_medium:
context.set_source_rgb(*self._color_status_low)
context.fill_preserve()
def _change_size_cb(self, widget, allocation):
self._width = allocation.width
self._height = allocation.height
self.queue_draw()

@ -1,147 +0,0 @@
# Copyright (C) 2007, 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 gtk
class HorizontalGraphic(gtk.DrawingArea):
_MARGIN = 5
_LINE_WIDTH = 2
_GRAPH_OFFSET = 7
_range_x = []
_range_y = []
_frequency_timer = 0
def __init__(self):
gtk.DrawingArea.__init__(self)
self._width = 0
self._height = 0
self._buffer = [0]
self.connect('expose-event', self.do_expose)
self.connect('size-allocate', self._change_size_cb)
def do_expose(self, widget, event):
context = widget.window.cairo_create()
context.rectangle(0, 0, self._width - 1, self._height - 1)
context.set_source_rgb (0,0,0)
context.fill_preserve()
context.set_line_width(self._LINE_WIDTH)
if event.area.x == 0:
draw_all = True
self._draw_border_lines(context)
context.stroke()
else:
draw_all = False
context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
context.clip()
context.set_source_rgb(1, 1, 1)
self._draw_buffer(event, widget, context, draw_all)
context.stroke()
self._updated = False
return False
def draw_value(self, percent):
redraw_all = False
if (len(self._buffer) + 1) *self._GRAPH_OFFSET >= self._width:
redraw_all = True
self._buffer = [self._buffer[-1]]
length = 1
else:
length = len(self._buffer) - 1
self._buffer.append(percent)
self._updated = True
if redraw_all:
area_x = 0
area_y = 0
height = self._height
width = self._width
else:
area_x = self._graph_x + (length*self._GRAPH_OFFSET)
area_y = self._graph_y
width = self._GRAPH_OFFSET*2
height = self._graph_height
self.queue_draw_area(area_x, area_y, width, height)
self._frequency_timer += 1
return True
def _draw_border_lines(self, context):
context.set_source_rgb(1, 1, 1)
self._draw_line(context, self._MARGIN, self._MARGIN, self._MARGIN, self._height - self._MARGIN)
self._draw_line(context, self._MARGIN, self._height - self._MARGIN - 1, self._width - self._MARGIN, self._height - self._MARGIN - 1)
def _draw_line(self, context, from_x, from_y, to_x, to_y):
context.move_to(from_x, from_y)
context.line_to(to_x, to_y)
def _draw_buffer(self, event, drwarea, context, draw_all=True):
buffer_offset = 0
freq = 1 # Frequency timer
length = len(self._buffer)
if length == 0:
return
# Context properties
context.set_line_width(self._LINE_WIDTH)
context.set_source_rgb(0,1,0)
if draw_all == True:
buffer_offset = 0
freq = 0
else:
freq = buffer_offset = (event.area.x/self._GRAPH_OFFSET)
for percent in self._buffer[buffer_offset:length]:
if buffer_offset == 0:
from_y = self._get_y(self._buffer[0])
from_x = self._graph_x
else:
from_y = self._get_y(self._buffer[buffer_offset-1])
from_x = (freq * self._GRAPH_OFFSET)
to_x = (freq+1) * self._GRAPH_OFFSET
to_y = self._get_y(percent)
self._draw_line(context, from_x, from_y, to_x, to_y)
buffer_offset+=1
freq+=1
context.stroke()
def _get_y(self, percent):
if percent==0:
percent = 1
graph_y = ((self._height)/(100 - 1))*(percent - 1)
y = self._LINE_WIDTH + abs(abs(self._height - graph_y) - self._MARGIN*2)
return int(y)
def _change_size_cb(self, widget, allocation):
self._width = allocation.width
self._height = allocation.height
self._graph_x = self._MARGIN + self._LINE_WIDTH
self._graph_y = self._MARGIN
self._graph_width = self._width - (self._MARGIN*2 + self._LINE_WIDTH)
self._graph_height = self._height - ((self._MARGIN*2 + self._LINE_WIDTH))

@ -1,7 +0,0 @@
sugardir = $(pkgdatadir)/services/console/lib/net
sugar_PYTHON = \
__init__.py \
device.py

@ -1,94 +0,0 @@
# Copyright (C) 2007, 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 socket
import fcntl
import struct
import string
class Device:
def __init__(self):
self._dev = self.get_interfaces()
def get_interfaces(self):
netdevfile = "/proc/net/dev"
dev = []
try:
infile = file(netdevfile, "r")
except:
print "Error trying " + netdevfile
skip = 0
for line in infile:
# Skip first two lines
skip += 1
if skip <= 2:
continue
iface = string.split(line, ":",1)
arr = string.split(iface[1])
if len(arr) < 10:
continue
info = {'interface': iface[0].strip(), \
'bytes_recv': arr[0],\
'bytes_sent': arr[8],\
'packets_recv': arr[1],
'packets_sent': arr[9]}
dev.append(info)
return dev
def get_iface_info(self, ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
hwaddr = []
try:
ip = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, \
struct.pack('256s', ifname[:15]))[20:24])
except:
ip = None
try:
netmask = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x891b, \
struct.pack('256s', ifname[:15]))[20:24])
except:
netmask = None
try:
mac = []
info = fcntl.ioctl(s.fileno(), 0x8927, \
struct.pack('256s', ifname[:15]))
for char in info[18:24]:
hdigit = hex(ord(char))[2:]
if len(hdigit):
mac.append(hdigit)
except:
mac = None
mac_string = self.mac_to_string(mac)
return [ip, netmask, mac_string]
def mac_to_string(self, hexa):
string = ''
for value in hexa:
if len(string)==0:
string = value
else:
string += ':'+value
return string

@ -1,8 +0,0 @@
sugardir = $(pkgdatadir)/services/console/lib/procmem
sugar_PYTHON = \
__init__.py \
proc.py \
proc_smaps.py \
analysis.py

@ -1,32 +0,0 @@
import proc, proc_smaps
class Analysis:
pid = 0
def __init__(self, pid):
self.pid = pid
def SMaps(self):
smaps = proc_smaps.ProcSmaps(self.pid)
private_dirty = 0
shared_dirty = 0
referenced = 0
for map in smaps.mappings:
private_dirty += map.private_dirty
shared_dirty += map.shared_dirty
referenced += map.referenced
smaps = {"private_dirty": int(private_dirty), \
"shared_dirty": int(shared_dirty),\
"referenced": int(referenced)}
return smaps
def ApproxRealMemoryUsage(self):
maps = proc_smaps.ProcMaps(self.pid)
size = (maps.clean_size/1024)
return size

@ -1,109 +0,0 @@
import os
import re
import sys
import string
class ProcInfo:
dir_path = "/proc/" # Our cute Proc File System
status_file = "status"
stat_file = "stat"
proc_list = [] # Our PID list :D
proc_info = [] #
def __init__(self):
self.proc_list = self.Get_PID_List()
# Returns Process List
def Get_PID_List(self):
list = []
# Exists our procfs ?
if os.path.isdir(self.dir_path):
# around dir entries
for f in os.listdir(self.dir_path):
if os.path.isdir(self.dir_path+f) & str.isdigit(f):
list.append(int(f))
return list
def MemoryInfo(self, pid):
# Path
pidfile = self.dir_path + str(pid) + "/stat"
try:
infile = open(pidfile, "r")
except:
print "Error trying " + pidfile
return None
# Parsing data , check 'man 5 proc' for details
stat_data = infile.read()
infile.close()
process_name = self._get_process_name(stat_data)
data = self._get_safe_split(stat_data)
state_dic = {
'R': 'Running',
'S': 'Sleeping',
'D': 'Disk sleep',
'Z': 'Zombie',
'T': 'Traced/Stopped',
'W': 'Paging'
}
# user and group owners
pidstat = os.stat(pidfile)
info = {
'pid': int(data[0]), # Process ID
'name': process_name,
'state': data[2], # Process State, ex: R|S|D|Z|T|W
'state_name': state_dic[data[2]], # Process State name, ex: Running, sleeping, Zombie, etc
'ppid': int(data[3]), # Parent process ID
'utime': int(data[13]), # Used jiffies in user mode
'stime': int(data[14]), # Used jiffies in kernel mode
'start_time': int(data[21]), # Process time from system boot (jiffies)
'vsize': int(data[22]), # Virtual memory size used (bytes)
'rss': int(data[23])*4, # Resident Set Size (bytes)
'user_id': pidstat.st_uid, # process owner
'group_id': pidstat.st_gid # owner group
}
return info
# Return the process name
def _get_process_name(self, data):
m = re.search("\(.*\)", data)
return m.string[m.start()+1:m.end()-1]
def _get_safe_split(self, data):
new_data = re.sub("\(.*\)", '()', data)
return new_data.split()
# Returns the CPU usage expressed in Jiffies
def get_CPU_usage(self, cpu_hz, used_jiffies, start_time):
# Uptime info
uptime_file = self.dir_path + "/uptime"
try:
infile = file(uptime_file, "r")
except:
print "Error trying uptime file"
return None
uptime_line = infile.readline()
uptime = string.split(uptime_line, " ",2)
infile.close()
# System uptime, from /proc/uptime
uptime = float(uptime[0])
# Jiffies
avail_jiffies = (uptime * cpu_hz) - start_time
cpu_usage = {'used_jiffies': used_jiffies, 'avail_jiffies': avail_jiffies}
return cpu_usage

@ -1,138 +0,0 @@
####################################################################
# This class open the /proc/PID/maps and /proc/PID/smaps files
# to get useful information about the real memory usage
####################################################################
import os
# Parse the /proc/PID/smaps file
class ProcSmaps:
mappings = [] # Devices information
def __init__(self, pid):
smapfile = "/proc/%s/smaps" % pid
self.mappings = []
# Coded by Federico Mena (script)
try:
infile = open(smapfile, "r")
input = infile.read()
infile.close()
except:
print "Error trying " + smapfile
return
lines = input.splitlines()
num_lines = len (lines)
line_idx = 0
# 08065000-08067000 rw-p 0001c000 03:01 147613 /opt/gnome/bin/evolution-2.6
# Size: 8 kB
# Rss: 8 kB
# Shared_Clean: 0 kB
# Shared_Dirty: 0 kB
# Private_Clean: 8 kB
# Private_Dirty: 0 kB
# Referenced: 4 kb -> Introduced in kernel 2.6.22
while num_lines > 0:
fields = lines[line_idx].split (" ", 5)
if len (fields) == 6:
(offsets, permissions, bin_permissions, device, inode, name) = fields
else:
(offsets, permissions, bin_permissions, device, inode) = fields
name = ""
size = self.parse_smaps_size_line (lines[line_idx + 1])
rss = self.parse_smaps_size_line (lines[line_idx + 2])
shared_clean = self.parse_smaps_size_line (lines[line_idx + 3])
shared_dirty = self.parse_smaps_size_line (lines[line_idx + 4])
private_clean = self.parse_smaps_size_line (lines[line_idx + 5])
private_dirty = self.parse_smaps_size_line (lines[line_idx + 6])
referenced = self.parse_smaps_size_line (lines[line_idx + 7])
name = name.strip ()
mapping = Mapping (size, rss, shared_clean, shared_dirty, \
private_clean, private_dirty, referenced, permissions, name)
self.mappings.append (mapping)
num_lines -= 8
line_idx += 8
self._clear_reference(pid)
def _clear_reference(self, pid):
os.system("echo 1 > /proc/%s/clear_refs" % pid)
# Parses a line of the form "foo: 42 kB" and returns an integer for the "42" field
def parse_smaps_size_line (self, line):
# Rss: 8 kB
fields = line.split ()
return int(fields[1])
class Mapping:
def __init__ (self, size, rss, shared_clean, shared_dirty, \
private_clean, private_dirty, referenced, permissions, name):
self.size = size
self.rss = rss
self.shared_clean = shared_clean
self.shared_dirty = shared_dirty
self.private_clean = private_clean
self.private_dirty = private_dirty
self.referenced = referenced
self.permissions = permissions
self.name = name
# Parse /proc/PID/maps file to get the clean memory usage by process,
# we avoid lines with backed-files
class ProcMaps:
clean_size = 0
def __init__(self, pid):
mapfile = "/proc/%s/maps" % pid
try:
infile = open(mapfile, "r")
except:
print "Error trying " + mapfile
return None
sum = 0
to_data_do = {
"[anon]": self.parse_size_line,
"[heap]": self.parse_size_line
}
for line in infile:
arr = line.split()
# Just parse writable mapped areas
if arr[1][1] != "w":
continue
if len(arr) == 6:
# if we got a backed-file we skip this info
if os.path.isfile(arr[5]):
continue
else:
line_size = to_data_do.get(arr[5], self.skip)(line)
sum += line_size
else:
line_size = self.parse_size_line(line)
sum += line_size
infile.close()
self.clean_size = sum
def skip(self, line):
return 0
# Parse a maps line and return the mapped size
def parse_size_line(self, line):
start, end = line.split()[0].split('-')
size = int(end, 16) - int(start, 16)
return size

@ -1,256 +0,0 @@
#!/usr/bin/env python
# Copyright (C) 2007, 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
from ctypes import *
# XText Property
class _XTextProperty(Structure):
pass
_XTextProperty._fields_ = [("value", c_char_p),\
("encoding", c_ulong),\
("format", c_int),\
("nitems", c_ulong)]
# XResType Structure
class _XResTypeStruct(Structure):
pass
_XResTypeStruct._fields_ = [("resource_type", c_ulong),\
("count", c_uint)]
_ATOMNAMES = ["PIXMAP",\
"WINDOW",\
"GC",\
"FONT",\
"GLYPHSET",\
"PICTURE",\
"COLORMAP ENTRY",\
"PASSIVE GRAB",\
"CURSOR",\
"_NET_CLIENT_LIST",\
"_NET_WM_PID",\
"_NET_WM_NAME",\
"UTF8_STRING",\
"WM_NAME", # FIXME!
"CARDINAL" # FIXME!
]
_ATOM_PIXMAP = 0
_ATOM_WINDOW = 1
_ATOM_GC = 2
_ATOM_FONT = 3
_ATOM_GLYPHSET = 4
_ATOM_PICTURE = 5
_ATOM_COLORMAP_ENTRY = 6
_ATOM_PASSIVE_GRAB = 7
_ATOM_CURSOR = 8
_ATOM_NET_CLIENT_LIST = 9
_ATOM_NET_WM_PID = 10
_ATOM_NET_WM_NAME = 11
_ATOM_UTF8_STRING = 12
_ATOM_WM_NAME = 13
_ATOM_CARDINAL = 14
# XText Property
class _XTextProperty(Structure):
pass
_XTextProperty._fields_ = [("value", c_char_p),\
("encoding", c_ulong),\
("format", c_int),\
("nitems", c_ulong)]
class XRes(object):
_XRESLIB = "libXRes.so"
_XMULIB = "libXmu.so.6"
def __init__(self):
self._lib = CDLL(self._XRESLIB)
self._lib_xmu = CDLL(self._XMULIB)
def _set_atoms(self, display):
self.atoms = []
for atom in _ATOMNAMES:
atom_value = self._lib.XInternAtom(display, atom, True)
self.atoms.append(atom_value)
def open_display(self, display=None):
display = self._lib.XOpenDisplay(display)
self._set_atoms(display)
return display
# Return an array with XRestTypes:
#
# XResType.resource_type (Atom_type)
# XResTyoe.count
def get_resources(self, display, resource_base):
n_types = c_long()
types = pointer(_XResTypeStruct())
self._lib.XResQueryClientResources(display, resource_base, \
byref(n_types), byref(types))
pytypes = []
for t in types[:n_types.value]:
pytypes.append(t)
return pytypes
def get_windows(self, display):
self._windows = []
root = self._lib.XDefaultRootWindow(display)
self._lookat(display, root)
return self._windows
def _lookat(self, display, win_root):
wp = self._get_window_properties (display, win_root)
if wp:
self._windows.append(wp)
w = None
dummy = self._Window()
children = self._Window()
nchildren = c_uint()
r = self._lib.XQueryTree(display, win_root, byref(dummy), \
byref(dummy), byref(children), byref(nchildren))
for client in children[:nchildren.value]:
cli = self._lib_xmu.XmuClientWindow (display, client)
if client is not None:
wp = self._get_window_properties (display, cli)
if wp:
self._windows.append(wp)
def _get_window_properties(self, display, w):
cliargv = c_char_p()
cliargc = c_long()
machtp = pointer(_XTextProperty())
nametp = _XTextProperty()
w_name = None
if not self._lib.XGetWMClientMachine (display, w, byref(machtp)):
machtp.value = None
machtp.encoding = None
if not self._lib.XGetCommand(display, w, byref(cliargv), byref(cliargc)):
return
if self._lib.XGetWMName(display, w, byref(nametp)):
w_name = nametp.value
bytes = c_ulong()
self._lib.XResQueryClientPixmapBytes(display, w, byref(bytes))
w_pixmaps = bytes.value
type = self._Atom()
format = c_int()
n_items = c_ulong()
bytes_after = c_int()
w_pid = pointer(c_long())
wname = c_char_p()
self._lib.XGetWindowProperty(display, w,\
self.atoms[_ATOM_NET_WM_PID],
0, 2L,\
False, self.atoms[_ATOM_CARDINAL],\
byref(type), byref(format), \
byref(n_items), byref(bytes_after), \
byref(w_pid))
# Calc aditional X resources by window
res = self.get_resources(display, w)
n_windows = 0
n_gcs = 0
n_pictures = 0
n_glyphsets = 0
n_fonts = 0
n_colormaps = 0
n_passive_grabs = 0
n_cursors = 0
n_other = 0
for r in res:
if r.resource_type == self.atoms[_ATOM_WINDOW]:
n_windows += r.count
elif r.resource_type == self.atoms[_ATOM_GC]:
n_gcs += r.count
elif r.resource_type == self.atoms[_ATOM_PICTURE]:
n_pictures += r.count
elif r.resource_type == self.atoms[_ATOM_GLYPHSET]:
n_glyphsets += r.count
elif r.resource_type == self.atoms[_ATOM_FONT]:
n_fonts += r.count
elif r.resource_type == self.atoms[_ATOM_COLORMAP_ENTRY]:
n_colormaps += r.count
elif r.resource_type == self.atoms[_ATOM_PASSIVE_GRAB]:
n_passive_grabs += r.count
elif r.resource_type == self.atoms[_ATOM_CURSOR]:
n_cursors += r.count
else:
n_other += r.count
other_bytes = n_windows * 24
other_bytes += n_gcs * 24
other_bytes += n_pictures * 24
other_bytes += n_glyphsets * 24
other_bytes += n_fonts * 1024
other_bytes += n_colormaps * 24
other_bytes += n_passive_grabs * 24
other_bytes += n_cursors * 24
other_bytes += n_other * 24
window = Window(w, w_pid.contents.value, w_pixmaps, \
n_windows, n_gcs, n_fonts, n_glyphsets, n_pictures,\
n_colormaps, n_passive_grabs, n_cursors, n_other,\
other_bytes, w_name)
return window
# Data types
def _Window(self):
return pointer(c_ulong())
def _Atom(self, data=0):
return pointer(c_ulong(data))
class Window(object):
def __init__(self, resource_base, pid, pixmap_bytes=0,\
n_windows=0, n_gcs=0, n_fonts=0, n_glyphsets=0, n_pictures=0,\
n_colormaps=0, n_passive_grabs=0, n_cursors=0, n_other=0,\
other_bytes=0, wm_name=None):
self.resource_base = resource_base
self.pid = pid
self.pixmap_bytes = pixmap_bytes
self.n_windows = n_windows
self.n_gcs = n_gcs
self.n_fonts = n_fonts
self.n_glyphsets = n_glyphsets
self.n_pictures = n_pictures
self.n_colormaps = n_colormaps
self.n_passive_grabs = n_passive_grabs
self.n_cursors = n_cursors
self.n_other = n_other
self.other_bytes = other_bytes
self.wm_name = wm_name

@ -1,5 +0,0 @@
sugardir = $(pkgdatadir)/services/console/lib/ui
sugar_PYTHON = \
__init__.py \
treeview.py

@ -1,73 +0,0 @@
# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import gtk
class TreeView(gtk.ScrolledWindow):
iters = [] # Iters index
# Create a window with a treeview object
#
# cols = List of dicts, ex:
#
# cols = []
# cols.append({'index': integer_index_position, 'name': string_col_name})
def __init__(self, cols_def, cols_name):
gtk.ScrolledWindow.__init__(self)
self._iters = []
self._treeview = gtk.TreeView()
# Creating column data types
self._store = gtk.TreeStore(*cols_def)
# Columns definition
cell = gtk.CellRendererText()
tv_cols = []
i=0
for col in cols_name:
col_tv = gtk.TreeViewColumn(col['name'], cell, text=i)
col_tv.set_reorderable(True)
col_tv.set_resizable(True)
tv_cols.append(col_tv)
i+=1
# Setting treeview properties
self._treeview.set_model(self._store)
self._treeview.set_enable_search(True)
self._treeview.set_rules_hint(True)
for col in tv_cols:
self._treeview.append_column(col)
self.add(self._treeview)
def add_row(self, cols_data):
iter = self._store.insert_after(None, None)
for col in cols_data:
print col['index'],col['info']
self._store.set_value(iter, int(col['index']) , col['info'])
self.iters.append(iter)
return iter
def update_row(self, iter, cols_data):
for col in cols_data:
self._store.set_value(iter, int(col['index']) , str(col['info']))
def remove_row(self, iter):
self._store.remove(iter)

@ -1,4 +0,0 @@
[D-BUS Service]
Name = org.laptop.sugar.Console
Exec = @bindir@/sugar-console

@ -1,20 +0,0 @@
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import os
import sys
from sugar import env
from sugar import util
sys.path.append(env.get_service_path('console'))
# change to the user's home directory if it is set
# root if not
os.chdir(os.environ.get('HOME', '/'))
#set the process title so it shows up as sugar-console not python
util.set_proc_title('sugar-console')
import console

@ -45,8 +45,6 @@ _actions_table = {
'<ctrl>F11' : 'volume_min',
'<ctrl>F12' : 'volume_max',
'<alt>1' : 'screenshot',
'<alt>equal' : 'console',
'<alt>0' : 'console',
'<alt>f' : 'frame',
'0x93' : 'frame',
'<alt>o' : 'overlay',
@ -156,9 +154,6 @@ class KeyHandler(object):
def handle_screenshot(self):
self._shell.take_screenshot()
def handle_console(self):
gobject.idle_add(self._toggle_console_visibility_cb)
def handle_frame(self):
self._shell.get_frame().notify_key_press()
@ -222,10 +217,3 @@ class KeyHandler(object):
return True
return False
def _toggle_console_visibility_cb(self):
bus = dbus.SessionBus()
proxy = bus.get_object('org.laptop.sugar.Console',
'/org/laptop/sugar/Console')
console = dbus.Interface(proxy, 'org.laptop.sugar.Console')
console.ToggleVisibility()

Loading…
Cancel
Save