Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAjay Garg <ajay@activitycentral.com>2012-10-17 06:43:06 (GMT)
committer Ajay Garg <ajay@activitycentral.com>2012-10-17 06:46:52 (GMT)
commitc01d6f8f23822fada1d59efe65a0aad87bb3c20c (patch)
treeeb0dfbfd4c99344e47966ddca03aac35c2b6b264
parent5079cf047328b2f83f3d2a3fc859b40e36759158 (diff)
System-Resources feature (gconf-controllable).
Signed-off-by: Ajay Garg <ajay@activitycentral.com>
-rw-r--r--extensions/deviceicon/Makefile.am1
-rw-r--r--extensions/deviceicon/resources.py217
-rw-r--r--po/POTFILES.in1
3 files changed, 219 insertions, 0 deletions
diff --git a/extensions/deviceicon/Makefile.am b/extensions/deviceicon/Makefile.am
index 96a1753..42f3a4b 100644
--- a/extensions/deviceicon/Makefile.am
+++ b/extensions/deviceicon/Makefile.am
@@ -5,6 +5,7 @@ sugar_PYTHON = \
battery.py \
frame.py \
network.py \
+ resources.py \
speaker.py \
speech.py \
touchpad.py \
diff --git a/extensions/deviceicon/resources.py b/extensions/deviceicon/resources.py
new file mode 100644
index 0000000..ef4adac
--- /dev/null
+++ b/extensions/deviceicon/resources.py
@@ -0,0 +1,217 @@
+# Copyright (C) Anish Mangal <anishmangal2002@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
+
+from gi.repository import GObject
+from gi.repository import Gtk
+from gi.repository import GConf
+
+from sugar3.graphics.tray import TrayIcon
+from sugar3.graphics.xocolor import XoColor
+from sugar3.graphics.palette import Palette
+from sugar3.graphics import style
+
+
+_SYSTEM_MOODS = ['-sad', '-normal', '-happy']
+_ICON_NAME = 'computer'
+_UPDATE_INTERVAL = 5 * 1000
+
+
+class DeviceView(TrayIcon):
+
+ FRAME_POSITION_RELATIVE = 500
+
+ def __init__(self):
+ client = GConf.Client.get_default()
+ self._color = XoColor(client.get_string('/desktop/sugar/user/color'))
+ TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color)
+ self.create_palette()
+ self._icon_widget.connect('button-release-event', self._click_cb)
+
+ def create_palette(self):
+ self.palette = ResourcePalette(_('System resources'))
+ self.palette.set_group_id('frame')
+ self.palette.add_timer()
+ self.palette.connect('system-mood-changed',
+ self._system_mood_changed_cb)
+ return self.palette
+
+ def _system_mood_changed_cb(self, palette_, mood):
+ self.icon.props.icon_name = _ICON_NAME + mood
+
+ def _click_cb(self, widget, event):
+ self.palette_invoker.notify_right_click()
+
+
+class ResourcePalette(Palette):
+ __gsignals__ = {
+ 'system-mood-changed': (GObject.SignalFlags.RUN_FIRST, None, ([str])),
+ }
+
+ def __init__(self, primary_text):
+ Palette.__init__(self, label=primary_text)
+
+ self.vbox = Gtk.VBox()
+ self.set_content(self.vbox)
+
+ self._cpu_text = Gtk.Label()
+ self.vbox.pack_start(self._cpu_text, True, True, 0)
+ 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, True, True, 0)
+
+ self._memory_text = Gtk.Label()
+ self.vbox.pack_start(self._memory_text, True, True, 0)
+ 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, True, True, 0)
+
+ self._system_mood = None
+ try:
+ self._cpu_times = self._get_cpu_times_list()
+ except IOError:
+ logging.exception('An error ocurred while attempting to '
+ 'read /proc/stat')
+ self._stop_computing_statistics()
+
+ self.vbox.show()
+ self._cpu_text.show()
+ self._cpu_bar.show()
+ self._memory_text.show()
+ self._memory_bar.show()
+
+ def add_timer(self):
+ GObject.timeout_add(_UPDATE_INTERVAL, self.__timer_cb)
+
+ 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_in_use = 100 - self._percentage_cpu_available()
+ memory_in_use = 100 - self._percentage_memory_available()
+ except IOError:
+ logging.exception('An error ocurred while trying to '
+ 'retrieve resource usage statistics')
+ self._stop_and_show_error()
+ return False
+ else:
+ self._cpu_text.set_label(_('CPU in use: %d%%' % cpu_in_use))
+ self._cpu_bar.set_fraction(float(cpu_in_use) / 100)
+ self._memory_text.set_label(_('Memory in use: %d%%' %
+ memory_in_use))
+ self._memory_bar.set_fraction(float(memory_in_use) / 100)
+
+ # both cpu_free and memory_free lie between 0-100
+ system_mood = _SYSTEM_MOODS[
+ int(300 - (cpu_in_use + 2 * memory_in_use)) // 100]
+
+ # check if self._system_mood exists
+ try:
+ if self._system_mood != system_mood:
+ self.emit('system-mood-changed', system_mood)
+ self._system_mood = system_mood
+ except AttributeError:
+ self.emit('system-mood-changed', system_mood)
+ self._system_mood = system_mood
+
+ return True
+
+ def _stop_and_show_error(self):
+ """
+ Stop computing usage statistics and display an error message
+ since we've hit an exception.
+
+ """
+ # 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)
+ self.emit('system-mood-changed', '-error')
+
+
+def setup(tray):
+ client = GConf.Client.get_default()
+ if not client.get_bool('/desktop/sugar/frame/show_network_resources'):
+ return
+
+ 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())
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 17c10c3..2408820 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -28,6 +28,7 @@ extensions/cpsection/updater/view.py
extensions/deviceicon/battery.py
extensions/deviceicon/frame.py
extensions/deviceicon/network.py
+extensions/deviceicon/resources.py
extensions/deviceicon/speech.py
extensions/deviceicon/speaker.py
extensions/deviceicon/touchpad.py