#!/usr/bin/env python # USP Meminfo Plugin Version 1.0 ##Description:Simple resources monitor (CPU,memory,etc) import gtk from gtk import gdk import gtk.glade import sys import os import subprocess import gobject from datetime import datetime import math import gconf import pango import commands import cairo import re import gtop import time from execute import Execute from easygconf import SetGconf from easygconf import WriteGconf class CpuSensor : def __init__(self,cpu="cpu"): pass self.c=cpu self.u=[0,0] self.s=[0,0] self.n=[0,0] self.i=[0,0] self.t=0 self.update() def update(self): pass f=open("/proc/stat","r") buf=f.readlines() f.close() for i in range(len(buf)): st=re.match(self.c+"\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)",buf[i]) if st!=None: self.u[0]=self.u[1] self.s[0]=self.s[1] self.n[0]=self.n[1] self.i[0]=self.i[1] self.u[1]=long(st.group(1)) self.s[1]=long(st.group(2)) self.n[1]=long(st.group(3)) self.i[1]=long(st.group(4)) self.t=float((self.u[1]-self.u[0])+(self.s[1]-self.s[0])+(self.n[1]-self.n[0])+(self.i[1]-self.i[0])) break def get(self,st) : pass st=st.replace("%t",str(int(100*self.getLoad()))) st=st.replace("%u",str(int(100*self.getUser()))) st=st.replace("%s",str(int(100*self.getSystem()))) st=st.replace("%n",str(int(100*self.getNice()))) st=st.replace("%i",str(int(100*self.getIdle()))) return st def getLoad(self): pass return ((self.u[1]+self.s[1]+self.n[1])-(self.u[0]+self.s[0]+self.n[0]))/self.t def getUser(self): pass return (self.u[1]-self.u[0])/self.t def getSystem(self): pass return (self.s[1]-self.s[0])/self.t def getNice(self): pass return (self.n[1]-self.n[0])/self.t def getIdle(self): pass return (self.i[1]-self.i[0])/self.t class ProgBar(gtk.DrawingArea): def __init__(self): super(ProgBar, self).__init__() self.connect("expose_event", self.expose) # make it private self._time = None self.gconf_dir = '/apps/usp/plugins/resources' self.client = gconf.client_get_default() try: self.backcol = gdk.color_parse(SetGconf(self.client,'string','/apps/usp/plugins/resources/bar_back_color', "white")) self.forecol = gdk.color_parse(SetGconf(self.client,'string','/apps/usp/plugins/resources/bar_fore_color', "black")) self.fontcol = gdk.color_parse(SetGconf(self.client,'string','/apps/usp/plugins/resources/bar_font_color', "red")) except: print "Color Parse Error" self.backcol = gdk.color_parse("white") self.forecol = gdk.color_parse("black") self.fontcol = gdk.color_parse("red") self.update() # update the clock once a second gobject.timeout_add(1000, self.update) def expose(self, widget, event): global supports_alpha context = widget.window.cairo_create() if supports_alpha == True: context.set_source_rgba(1.0, 0.0, 0.0, 0.0) # Transparent else: context.set_source_rgb(1.0, 1.0, 1.0) # Opaque white context.set_operator(cairo.OPERATOR_SOURCE) context.paint() # set a clip region for the expose event context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) context.clip() self.draw(context) return False def draw(self, context): rect = self.get_allocation() x = rect.width / 2.0 y = rect.height / 2.0 #x = rect.x + rect.width / 2.0 #y = rect.y + rect.height / 2.0 radius = min(rect.width / 2.0, rect.height / 2.0) - 20 # clock back context.arc(x, y, radius, 0, 2.0 * math.pi) context.set_source_rgb(self.backcol.red,self.backcol.green,self.backcol.blue) # face colour context.fill_preserve() context.set_source_rgb(self.forecol.red,self.forecol.green,self.forecol.blue) # "numbers" & hands colour context.stroke() # clock ticks for i in xrange(12): context.save() if i % 3 == 0: inset = 0.2 * radius else: inset = 0.1 * radius context.set_line_width(0.7 * context.get_line_width()) context.move_to(x + (radius - inset) * math.cos(i * math.pi / 6.0), y + (radius - inset) * math.sin(i * math.pi / 6.0)) context.line_to(x + radius * math.cos(i * math.pi / 6.0), y + radius * math.sin(i * math.pi / 6.0)) context.stroke() context.restore() # clock hands hours = self._time.hour minutes = self._time.minute seconds = self._time.second # hour hand: # the hour hand is rotated 30 degrees (pi/6 r) per hour + # 1/2 a degree (pi/360) per minute context.save() context.set_line_width(1.5 * context.get_line_width()) context.move_to(x, y) context.line_to(x + radius / 2 * math.sin( math.pi / 6 * hours + math.pi / 360 * minutes), y + radius / 2 * -math.cos( math.pi / 6 * hours + math.pi / 360 * minutes)) context.stroke() context.restore() # minute hand: # the minute hand is rotated 6 degrees (pi/30 r) per minute context.move_to(x, y) context.line_to(x + radius * 0.75 * math.sin(math.pi / 30 * minutes), y + radius * 0.75 * -math.cos(math.pi / 30 * minutes)) context.stroke() # seconds hand: # operates identically to the minute hand if self.hidesec==False: context.save() context.set_source_rgb(self.secondcol.red,self.secondcol.green,self.secondcol.blue) # seconds hand colour context.move_to(x, y) context.line_to(x + radius * 0.9 * math.sin(math.pi / 30 * seconds), y + radius * 0.9 * -math.cos(math.pi / 30 * seconds)) context.stroke() context.restore() def redraw_canvas(self): if self.window: alloc = self.get_allocation() rect = gdk.Rectangle(alloc.x, alloc.y, alloc.width, alloc.height) self.window.invalidate_rect(rect, True) self.window.process_updates(True) def update(self): # update the time self.time = datetime.now() return True # keep running this event # public access to the time member def _get_time(self): return self._time def _set_time(self, datetime): self._time = datetime self.redraw_canvas() time = property(_get_time, _set_time) class pluginclass: TARGET_TYPE_TEXT = 80 toButton = [ ( "text/uri-list", 0, TARGET_TYPE_TEXT ) ] """This is the main class for the plugin""" """It MUST be named pluginclass""" def __init__(self, USPWin): self.USPWin = USPWin #The Glade file for the plugin self.gladefile = os.path.join(os.path.dirname(__file__), "resources.glade") #Read GLADE file self.wTree = gtk.glade.XML(self.gladefile,"window1") #These properties are NECESSARY to maintain consistency #throughout USP #Set 'window' property for the plugin (Must be the root widget) self.window = self.wTree.get_widget("window1") self.window.set_app_paintable(True) #Set 'heading' property for plugin self.heading = "Resources" #This should be the first item added to the window in glade self.content_holder = self.wTree.get_widget("eventbox1") #Specify plugin width self.width = 250 #Plugin icon self.icon = 'computer' self.gconf_dir = '/apps/usp/plugins/resources' self.client = gconf.client_get_default() self.client.add_dir('/apps/usp/plugins/resources', gconf.CLIENT_PRELOAD_NONE) self.client.notify_add('/apps/usp/plugins/resources/sticky',self.RegenPlugin) self.client.notify_add('/apps/usp/plugins/resources/icon',self.RegenPlugin) self.client.notify_add('/apps/usp/plugins/resources/width',self.RegenPlugin) self.client.notify_add('/apps/usp/plugins/resources/height',self.RegenPlugin) self.client.notify_add('/apps/usp/plugins/resources/hide_average_load',self.RegenPlugin) self.client.notify_add('/apps/usp/plugins/resources/hide_cpu_process',self.RegenPlugin) self.client.notify_add('/apps/usp/plugins/resources/hide_memory',self.RegenPlugin) self.client.notify_add('/apps/usp/plugins/resources/hide_swap',self.RegenPlugin) self.client.notify_add('/apps/usp/plugins/resources/hide_vmalloc',self.RegenPlugin) self.RegenPlugin() self.UserVal = 0 self.NiceVal = 0 self.SysVal = 0 self.IdleVal = 0 self.allow_top = True do_msv = False if self.hidemem == True: self.wTree.get_widget('hbox2').hide() self.wTree.get_widget('MemBar').hide() else: self.wTree.get_widget('hbox2').show() self.wTree.get_widget('MemBar').show() do_msv = True if self.hideswap == True: self.wTree.get_widget('hbox3').hide() self.wTree.get_widget('SwapBar').hide() else: self.wTree.get_widget('hbox3').show() self.wTree.get_widget('SwapBar').show() do_msv = True if self.hidealloc == True: self.wTree.get_widget('hbox4').hide() self.wTree.get_widget('AllocBar').hide() else: self.wTree.get_widget('hbox4').show() self.wTree.get_widget('AllocBar').show() do_msv = True if do_msv == True: gobject.timeout_add(1000, self.do_mem) if self.hideavg == True: self.wTree.get_widget('LoadAvgLabel').hide() self.wTree.get_widget('hbox6').hide() else: self.wTree.get_widget('LoadAvgLabel').show() self.wTree.get_widget('hbox6').show() self.do_load() gobject.timeout_add(60000, self.do_load) if self.hidecpu == True: self.wTree.get_widget('hbox5').hide() self.wTree.get_widget('hbox7').hide() self.wTree.get_widget('CPUBar').hide() else: self.wTree.get_widget('hbox5').show() self.wTree.get_widget('hbox7').show() self.wTree.get_widget('CPUBar').show() gobject.timeout_add(1000, self.do_cpu_process) if self.hidemem == True and self.hideavg == True and self.hidecpu == True: self.wTree.get_widget('WarnLabel').set_text('All Items are Hidden in Preferences.') else: self.wTree.get_widget('WarnLabel').set_text('') self.SetSystemStyle(["TotMemLabel","MemLabel","TotSwapLabel","SwapLabel","TotVMLabel","VMLabel","TopProcLabel","TopCPULabel","LoadAvgLabel","Min1Label","Min5Label","Min15Label","Min1Read","Min5Read","Min15Read"]) HeadingStyle = pango.AttrList() attr = pango.AttrSize(10000,0,-1) HeadingStyle.insert(attr) self.wTree.get_widget('WarnLabel').set_attributes(HeadingStyle) def RegenPlugin(self, *args, **kargs): self.GetGconfEntries() try: self.wTree.get_widget('vbox1').set_size_request( self.width, self.height ) except: pass def GetGconfEntries(self): self.client = gconf.client_get_default() self.sticky = SetGconf( self.client, "bool", "/apps/usp/plugins/resources/sticky", False ) self.minimized = SetGconf( self.client, "bool", "/apps/usp/plugins/resources/minimized", False ) self.icon = SetGconf( self.client, "string", "/apps/usp/plugins/resources/icon", "utilities-system-monitor" ) self.width = SetGconf( self.client, "int", "/apps/usp/plugins/resources/width", 250 ) self.height = SetGconf( self.client, "int", "/apps/usp/plugins/resources/height", 250 ) self.hideavg = SetGconf( self.client, "bool", "/apps/usp/plugins/resources/hide_average_load", False ) self.hidecpu = SetGconf( self.client, "bool", "/apps/usp/plugins/resources/hide_cpu_process", False ) self.hidemem = SetGconf( self.client, "bool", "/apps/usp/plugins/resources/hide_memory", False ) self.hideswap = SetGconf( self.client, "bool", "/apps/usp/plugins/resources/hide_swap", False ) self.hidealloc = SetGconf( self.client, "bool", "/apps/usp/plugins/resources/hide_vmalloc", False ) def SetHidden( self, state ): if state == True: WriteGconf( self.client, "bool", "/apps/usp/plugins/resources/minimized", True ) else: WriteGconf( self.client, "bool", "/apps/usp/plugins/resources/minimized", False ) def SetSystemStyle(self,items): HeadingStyle = pango.AttrList() attr = pango.AttrSize(7000,0,-1) HeadingStyle.insert(attr) for item in items: self.wTree.get_widget(item).set_attributes(HeadingStyle) #Actually do something with the plugin def do_mem(self): retval = True try: output = commands.getoutput('cat /proc/meminfo') lines = output.split ('\n') # Have to find the indexes as the values are in different places on different systems. for i in range(len(lines)): if lines[i].split()[0] == "MemTotal:": MEMTOT = i if lines[i].split()[0] == "MemFree:": MEMFREE = i if lines[i].split()[0] == "SwapTotal:": SWAPTOT = i if lines[i].split()[0] == "SwapFree:": SWAPFREE = i if lines[i].split()[0] == "VmallocTotal:": VMTOT = i if lines[i].split()[0] == "VmallocUsed:": VMUSED = i memory = 1.00-float(lines[MEMFREE].split()[1])/float(lines[MEMTOT].split()[1]) if float(lines[SWAPTOT].split()[1]) > 0.00: swap = 1.00-float(lines[SWAPFREE].split()[1])/float(lines[SWAPTOT].split()[1]) else: swap = 0.00 if float(lines[VMTOT].split()[1]) > 0.00: vmalloc = float(lines[VMUSED].split()[1])/float(lines[VMTOT].split()[1]) else: vmalloc = 0.00 if memory < 0.10: memtext = str(memory*100)[0:4] else: memtext = str(memory*100)[0:5] if swap < 0.10: swaptext = str(swap*100)[0:4] else: swaptext = str(swap*100)[0:5] if vmalloc < 0.10: alloctext = str("%02.02f"%(vmalloc*100)) else: alloctext = str("%02.02f"%(vmalloc*100)) except: try: self.wTree.get_widget('WarnLabel').set_text('Error :\nMemory Information\nCollection.') except: pass print "Error : Memory Information Collection." pass try: if self.hidemem == False: self.wTree.get_widget('MemBar').set_fraction(memory) self.wTree.get_widget('MemBar').set_text("Memory "+memtext+"%") self.wTree.get_widget('MemLabel').set_text(str(int(lines[MEMTOT].split()[1])/1024)+" MB") if self.hideswap == False: self.wTree.get_widget('SwapBar').set_fraction(swap) self.wTree.get_widget('SwapBar').set_text("Swap "+swaptext+"%") self.wTree.get_widget('SwapLabel').set_text(str(int(lines[SWAPTOT].split()[1])/1024)+" MB") if self.hidealloc == False: self.wTree.get_widget('AllocBar').set_fraction(vmalloc) self.wTree.get_widget('AllocBar').set_text("VMAlloc "+alloctext+"%") self.wTree.get_widget('VMLabel').set_text(str("%02.f"%(float(lines[VMTOT].split()[1])/1024.00)+" MB")) except: pass return retval def do_load(self): retval = True try: output = commands.getoutput('cat /proc/loadavg') lines = output.split() output = "" except: try: self.wTree.get_widget('WarnLabel').set_text('Error :\nLoad Information\nCollection.') except: pass retval = False print "Error : Load Information Collection." pass try: self.wTree.get_widget('Min1Read').set_text(lines[0]) self.wTree.get_widget('Min5Read').set_text(lines[1]) self.wTree.get_widget('Min15Read').set_text(lines[2]) except: pass return retval def do_cpu_process(self): try: output = commands.getoutput('ps r --no-heading -eo pcpu,comm,args | sort -k 1 -r') lines = output.split('\n') searchusp = "/usr/bin/usp" topprocess = "" topcpu = '0.0' totalcpu = 0.0 for top_one in lines: top_one = top_one.split() if len(top_one) > 3: # Don't count USP itself as check activity takes precedence. if (top_one[3].find(searchusp) == -1):# and (top_one[1] != 'Xorg'): if topprocess == "": topprocess = top_one[1] topcpu = top_one[0] totalcpu = totalcpu + float(top_one[0]) else: totalcpu = totalcpu + float(top_one[0]) if topprocess == "": topprocess = top_one[1] topcpu = top_one[0] try: self.wTree.get_widget('WarnLabel').set_text('') except: pass except: try: self.wTree.get_widget('WarnLabel').set_text('Error :\nCPU Information\nCollection.') except: pass print "Error : CPU Information Collection." pass try: if topcpu != '0.0': self.wTree.get_widget('TopProcLabel').set_text("Top Process : "+topprocess) self.wTree.get_widget('TopCPULabel').set_text("Top Process CPU Usage : "+topcpu+"%") else: self.wTree.get_widget('TopProcLabel').set_text("Top Process : ") self.wTree.get_widget('TopCPULabel').set_text("Top Process CPU Usage : 0.0%") if totalcpu < 0.0: percent = 0.0 elif totalcpu > 100.0: percent = 100.0 else: percent = totalcpu self.wTree.get_widget('CPUBar').set_fraction(percent/100.0) self.wTree.get_widget('CPUBar').set_text("Total CPU Usage : "+str("%02.02f"%percent)+"%") except: pass return True def do_cpu(self): retval = True process = 'top' processcpu = 0.0 nextprocess = '' nextprocesscpu = 0.0 total = 0.0 #try: if self.allow_top == True: self.allow_top = False self.output = commands.getoutput('top -b -d1 -n1') #output = subprocess.Popen(["top", "top -b -n1"],stdin=1).communicate()[0] #print output, "OUTPUT" #print stderr,"STDERR" lines = self.output.split('\n') if self.USPWin.VERBOSE == True: print "\nProcess Information\n-------------------" for line in lines: print line # Set Return Value to False to stop timeout, so we don't keep repeating list. retval = False process = lines[7].split()[11] processcpu = lines[7].split()[8] nextprocess = lines[8].split()[11] nextprocesscpu = lines[8].split()[8] # # Total up CPU Percents i = 7 total = 0.0 while i < (len(lines)-1): if lines[i].split()[11] != 'top': total = total + float(lines[i].split()[8]) #except: # try: # self.wTree.get_widget('WarnLabel').set_text('Error :\nCPU Information\nCollection.\nIs \"top\" installed?') # except: # pass ## retval = False i+=1 if total > 100.0: total = 100.0 #except: # try: # self.wTree.get_widget('WarnLabel').set_text('Error :\nCPU Information\nCollection.\nIs \"top\" installed?') # except: # pass ## retval = False print "Error : CPU Information Collection. Is \"top\" installed?" pass try: if process != 'top': if processcpu != '0.0': self.wTree.get_widget('TopProcLabel').set_text("Top Process : "+process) self.wTree.get_widget('totcpuLabel').set_text("Process CPU Usage : "+processcpu+"%") else: self.wTree.get_widget('TopProcLabel').set_text("Top Process : ") self.wTree.get_widget('totcpuLabel').set_text("Process CPU Usage : 0.0%") else: if nextprocesscpu != '0.0': self.wTree.get_widget('TopProcLabel').set_text("Top Process : "+nextprocess) self.wTree.get_widget('totcpuLabel').set_text("Process CPU Usage : "+nextprocesscpu+"%") else: self.wTree.get_widget('TopProcLabel').set_text("Top Process : ") self.wTree.get_widget('totcpuLabel').set_text("Process CPU Usage : 0.0%") self.wTree.get_widget('CPUBar').set_fraction(total/100.0) self.wTree.get_widget('CPUBar').set_text("Total CPU Usage : "+str(total)+"%") except: pass self.allow_top = True return retval #---------------------------------------------------------------------------------------# # USPconfig Section Below #---------------------------------------------------------------------------------------# # This is the Config Class it must be called "cfgpluginclass' class cfgpluginclass: def __init__(self): # The Gladefile for the plugins USPconfig Tab self.gladefile = os.path.join(os.path.dirname(__file__), "resources.glade") # Read GLADE file self.wTree = gtk.glade.XML(self.gladefile,"config") # Set 'window' property for the plugin (Must be the root widget) self.window = self.wTree.get_widget("config") # Set Heading, this will be used for the tab label in USPconfig self.heading = "Resources" # Content Place Holder must be eventbox1 self.content_holder = self.wTree.get_widget("eventbox2") # GConf Stuff - This just makes sure a gconf path is there. self.gconf_dir = '/apps/usp/plugins/resources' self.client = gconf.client_get_default() self.client.add_dir('/apps/usp/plugins/resources', gconf.CLIENT_PRELOAD_NONE) # Setup the Functions of the Glade files spin controls or entry boxes for Value Changes # Tip: For spinbutton controls use the "_value_changed" event not the "_changed" event. dic = { "on_window1_destroy" : gtk.main_quit, "on_HideAvgChkBtn_toggled" : self.hideavgload, "on_HideMemChkBtn_toggled" : self.hidemem, "on_HideSwapChkBtn_toggled" : self.hideswap, "on_HideAllocChkBtn_toggled" : self.hidealloc, "on_HideProcChkBtn_toggled" : self.hidecpuproc, "on_WSpin_changed" : self.wspin, "on_HSpin_changed" : self.hspin, "on_IconEntry_changed" : self.iconchange, "on_StickyChkBtn_toggled" : self.sticky} self.wTree.signal_autoconnect(dic) # Read Values from Gconf and Set Default Values if they don't exist. self.wTree.get_widget("IconEntry").set_text(SetGconf(self.client,'string','/apps/usp/plugins/resources/icon','utilities-system-monitor')) self.wTree.get_widget("StickyChkBtn").set_active(SetGconf(self.client,'bool','/apps/usp/plugins/resources/sticky',False)) self.wTree.get_widget("HideMemChkBtn").set_active(SetGconf(self.client,'bool','/apps/usp/plugins/resources/hide_memory',False)) self.wTree.get_widget("HideSwapChkBtn").set_active(SetGconf(self.client,'bool','/apps/usp/plugins/resources/hide_swap',False)) self.wTree.get_widget("HideAllocChkBtn").set_active(SetGconf(self.client,'bool','/apps/usp/plugins/resources/hide_vmalloc',False)) self.wTree.get_widget("HideProcChkBtn").set_active(SetGconf(self.client,'bool','/apps/usp/plugins/resources/hide_cpu_process',False)) self.wTree.get_widget("HideAvgChkBtn").set_active(SetGconf(self.client,'bool','/apps/usp/plugins/resources/hide_average_load',False)) self.wTree.get_widget("WSpin").set_value(SetGconf(self.client,'int','/apps/usp/plugins/resources/width',250)) self.wTree.get_widget("HSpin").set_value(SetGconf(self.client,'int','/apps/usp/plugins/resources/height',250)) # Functions for Changing Values when items checked or altered Section def iconchange(self, widget, **kargs): self.icon=self.wTree.get_widget("IconEntry").get_text() self.client.set_string('/apps/usp/plugins/resources/icon',self.wTree.get_widget('IconEntry').get_text()) def sticky(self, widget, **kargs): if self.wTree.get_widget("StickyChkBtn").get_active() == True: self.client.set_bool('/apps/usp/plugins/resources/sticky',True) else: self.client.set_bool('/apps/usp/plugins/resources/sticky',False) def wspin(self, widget, **kargs): self.client.set_int('/apps/usp/plugins/resources/width',int(self.wTree.get_widget("WSpin").get_value())) def hspin(self, widget, **kargs): self.client.set_int('/apps/usp/plugins/resources/height',int(self.wTree.get_widget("HSpin").get_value())) def hideavgload(self, widget, **kargs): if self.wTree.get_widget("HideAvgChkBtn").get_active() == True: self.client.set_bool('/apps/usp/plugins/resources/hide_average_load',True) else: self.client.set_bool('/apps/usp/plugins/resources/hide_average_load',False) def hidemem(self, widget, **kargs): if self.wTree.get_widget("HideMemChkBtn").get_active() == True: self.client.set_bool('/apps/usp/plugins/resources/hide_memory',True) else: self.client.set_bool('/apps/usp/plugins/resources/hide_memory',False) def hideswap(self, widget, **kargs): if self.wTree.get_widget("HideSwapChkBtn").get_active() == True: self.client.set_bool('/apps/usp/plugins/resources/hide_swap',True) else: self.client.set_bool('/apps/usp/plugins/resources/hide_swap',False) def hidealloc(self, widget, **kargs): if self.wTree.get_widget("HideAllocChkBtn").get_active() == True: self.client.set_bool('/apps/usp/plugins/resources/hide_vmalloc',True) else: self.client.set_bool('/apps/usp/plugins/resources/hide_vmalloc',False) def hidecpuproc(self, widget, **kargs): if self.wTree.get_widget("HideProcChkBtn").get_active() == True: self.client.set_bool('/apps/usp/plugins/resources/hide_cpu_process',True) else: self.client.set_bool('/apps/usp/plugins/resources/hide_cpu_process',False)