Thanks for reviewing this patch. I think I have addressed all issues raised by tomeu, silbe and quozl.
Additionally, I've put the portion of code that accesses the /proc/stat and /proc/meminfo files in a try...except block. When an exception occurs, all the widgets barring _cpu_text are removed and _cpu_text displays an error message "Cannot compute CPU and memory usage statistics!" in the palette. -- Anish On Sat, Jul 10, 2010 at 1:04 PM, anishmangal2002 <anishmangal2...@gmail.com> wrote: > This patch adds an icon to the frame, whose palette > menu displays the memory and cpu resources. For computing > free memory, the code reads the /proc/meminfo file (thanks > quozl) and for computing cpu usage, the code reads the > /proc/stat file. > > The palette menu entries are only updated (in one second > intervals) when the palette menu is visible thus > possibly saving cpu cycles. > > Signed-off-by: anishmangal2002 <anishmangal2...@gmail.com> > --- > extensions/deviceicon/Makefile.am | 3 +- > extensions/deviceicon/resources.py | 188 > ++++++++++++++++++++++++++++++++++++ > 2 files changed, 190 insertions(+), 1 deletions(-) > create mode 100644 extensions/deviceicon/resources.py > > diff --git a/extensions/deviceicon/Makefile.am > b/extensions/deviceicon/Makefile.am > index 8a2e765..038c059 100644 > --- a/extensions/deviceicon/Makefile.am > +++ b/extensions/deviceicon/Makefile.am > @@ -5,4 +5,5 @@ sugar_PYTHON = \ > battery.py \ > network.py \ > speaker.py \ > - volume.py > + volume.py \ > + resources.py > diff --git a/extensions/deviceicon/resources.py > b/extensions/deviceicon/resources.py > new file mode 100644 > index 0000000..7503bef > --- /dev/null > +++ b/extensions/deviceicon/resources.py > @@ -0,0 +1,188 @@ > +# Copyright (C) Anish Mangal <anishmangal2...@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 gettext import gettext as _ > +import logging > +import os > + > +import gobject > +import gtk > +import gconf > + > +from sugar.graphics.tray import TrayIcon > +from sugar.graphics.xocolor import XoColor > +from sugar.graphics.palette import Palette > +from sugar.graphics import style > + > +from jarabe.frame.frameinvoker import FrameWidgetInvoker > + > +class DeviceView(TrayIcon): > + > + FRAME_POSITION_RELATIVE = 500 > + > + def __init__(self): > + client = gconf.client_get_default() > + color = XoColor(client.get_string('/desktop/sugar/user/color')) > + TrayIcon.__init__(self, icon_name='computer', xo_color=color) > + self.set_palette_invoker(FrameWidgetInvoker(self)) > + > + def create_palette(self): > + palette = ResourcePalette(_('System resources')) > + palette.set_group_id('frame') > + return palette > + > +class ResourcePalette(Palette): > + > + def __init__(self, primary_text): > + Palette.__init__(self, label=primary_text) > + > + self._popup_cb_id = self.connect('popup', self._popup_cb) > + self._popdown_cb_id = self.connect('popdown', self._popdown_cb) > + > + self.vbox = gtk.VBox() > + self.set_content(self.vbox) > + > + self._cpu_text = gtk.Label() > + self.vbox.pack_start(self._cpu_text, padding=style.DEFAULT_PADDING) > + self._cpu_text.show() > + > + self._cpu_bar = gtk.ProgressBar() > + self._cpu_bar.set_size_request( > + style.zoom(style.GRID_CELL_SIZE * 4), -1) > + self.vbox.pack_start(self._cpu_bar, padding=style.DEFAULT_PADDING) > + self._cpu_bar.show() > + > + self._memory_text = gtk.Label() > + self.vbox.pack_start(self._memory_text, > padding=style.DEFAULT_PADDING) > + self._memory_text.show() > + > + self._memory_bar = gtk.ProgressBar() > + self._memory_bar.set_size_request( > + style.zoom(style.GRID_CELL_SIZE * 4), -1) > + self.vbox.pack_start(self._memory_bar, padding=style.DEFAULT_PADDING) > + self._memory_bar.show() > + > + self.vbox.show() > + > + try: > + self._cpu_times = self._get_cpu_times_list() > + except Exception: > + logging.exception('An error ocurred while attempting to ' > + 'read /proc/stat') > + self._remove_callbacks() > + > + def _get_cpu_times_list(self): > + """Return various cpu times as read from /proc/stat > + > + This method returns the following cpu times measured > + in jiffies (1/100 of a second for x86 systems) > + as an ordered list of numbers - [user, nice, > + system, idle, iowait] where, > + > + user: normal processes executing in user mode > + nice: niced processes executing in user mode > + system: processes executing in kernel mode > + idle: twiddling thumbs > + iowait: waiting for I/O to complete > + > + Note: For systems having 2 or more CPU's, the above > + numbers would be the cumulative sum of these times > + for all CPU's present in the system. > + > + """ > + return [int(count) > + for count in file('/proc/stat').readline().split()[1:6]] > + > + def _percentage_cpu_available(self): > + """ > + Return free CPU resources as a percentage > + > + """ > + _cpu_times_new = self._get_cpu_times_list() > + _cpu_times_current = [(new - old) > + for new, old in zip(_cpu_times_new, self._cpu_times)] > + user, nice, system, idle, iowait = _cpu_times_current > + cpu_free = (idle + iowait) * 100.0 / sum(_cpu_times_current) > + self._cpu_times = self._get_cpu_times_list() > + return cpu_free > + > + def _percentage_memory_available(self): > + """ > + Return free memory as a percentage > + > + """ > + for line in file('/proc/meminfo'): > + name, value, unit = line.split()[:3] > + if 'MemTotal:' == name: > + total = int(value) > + elif 'MemFree:' == name: > + free = int(value) > + elif 'Buffers:' == name: > + buffers = int(value) > + elif 'Cached:' == name: > + cached = int(value) > + elif 'Active:' == name: > + break > + return (free + buffers + cached) * 100.0 / total > + > + def __timer_cb(self): > + try: > + cpu_free = self._percentage_cpu_available() > + memory_free = self._percentage_memory_available() > + self._cpu_text.set_label(_('CPU free: %d%%' % cpu_free)) > + self._cpu_bar.set_fraction(cpu_free/100.0) > + self._memory_text.set_label(_('Memory free: %d%%' % memory_free)) > + self._memory_bar.set_fraction(memory_free/100.0) > + return True > + except Exception: > + logging.exception('An error ocurred while trying to ' > + 'retrieve resource usage statistics') > + self._remove_callbacks() > + return False > + > + def _remove_callbacks(self): > + """ > + Stop computing usage statistics and display and error message > + since we've hit an exception. > + > + """ > + self.disconnect(self._popup_cb_id) > + self.disconnect(self._popdown_cb_id) > + > + # Use the existing _cpu_text label to display the error. Remove > + # everything else. > + self._cpu_text.set_size_request( > + style.zoom(style.GRID_CELL_SIZE * 4), -1) > + self._cpu_text.set_line_wrap(True) > + self._cpu_text.set_text(_('Cannot compute CPU and memory usage ' > + 'statistics!')) > + self.vbox.remove(self._cpu_bar) > + self.vbox.remove(self._memory_text) > + self.vbox.remove(self._memory_bar) > + > + def _popup_cb(self, gobject_ref): > + self.__timer_cb() > + self._timer = gobject.timeout_add(2000, self.__timer_cb) > + > + def _popdown_cb(self, gobject_ref): > + gobject.source_remove(self._timer) > + > +def setup(tray): > + if not (os.path.exists('/proc/stat') and > os.path.exists('/proc/meminfo')): > + logging.warning('Either /proc/stat or /proc/meminfo not present. Not > ' > + 'adding the CPU and memory usage icon to the frame') > + return > + tray.add_device(DeviceView()) > -- > 1.7.1 > > _______________________________________________ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel