#!/usr/bin/env python

#  WirelessScreenlet (c) Nemanja Jovicic 2008 <nemanja.jovicic@hotmail.com> 
#  based on Patrik Kullman screenlet 
#
#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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
#

import screenlets
from screenlets.options import StringOption, BoolOption, ColorOption
from screenlets import sensors
import cairo
import gtk
import pango
from os import popen
import gobject
import commands
# use gettext for translation
import gettext

_ = screenlets.utils.get_translator(__file__)

def tdoc(obj):
	obj.__doc__ = _(obj.__doc__)
	return obj

@tdoc
class WirelessScreenlet(screenlets.Screenlet):
	
	# default meta-info for Screenlets
	__name__ = 'WirelessScreenlet'
	__version__ = '0.4.21'
	__author__ = ' Jovicic Nemanja aka drxnele based on Patrik Kullman screenlet '
	__desc__ = _('Display wireles link quality and ESSID')


	__timeout = None
	__icon = 'link-0'
	__stats = {"essid": _("Not updated"), "percentage": 0,"signal":0,"noise":0,"local_ip":"127.0.0.1"}
	__not_connected_stats = {"essid": _("Not connected"),"percentage": 0,"signal":0,"noise":0,"local_ip":"127.0.0.1"}
	__update_interval = 3 # every 3 seconds
	show_signal_noise = True
	show_ip = True
	
	interface = ''
	text_color = (1,1,1, 0.8)

	# constructor
	def __init__(self, **keyword_args):
		# call super
		screenlets.Screenlet.__init__(self, width=200, height=100, **keyword_args)
		# set theme
		self.theme_name = "default"

		self.add_menuitem("show_signal_noise", _("Show signal and noise"))
		self.add_menuitem("show_ip", _("Show ip"))
		# add default menu items
		self.add_default_menuitems()
		# add option groups
		self.__update_interval = self.__update_interval
		self.add_options_group(_('Wireless'), _('Wireless settings'))
		self.add_option(StringOption(_('Wireless'),
			'interface', 						# attribute-name
			self.interface,						# default-value
			_('Wireless interface'), 						# widget-label
			_('The wireless interface to use for monitoring'),choices=self.get_wireless_interfaces()	# description
			))
		self.add_option(BoolOption(_('Wireless'), 'show_signal_noise', self.show_signal_noise, _('Show signal and noise'), _('Turn off/on showing of signal link and noise in dBm')))
		self.add_option(BoolOption(_('Wireless'), 'show_ip', self.show_ip, _('Show your IP'), _('Turn off/on showing of your ip')))
		self.add_option(ColorOption(_('Wireless'),'text_color', self.text_color, _('Text color'), _('Text color')))
		if self.interface == '':
			interfaces = self.get_wireless_interfaces()
			if len(interfaces) > 0:
				self.interface = interfaces[0]

	def __setattr__(self, name, value):
		# call Screenlet.__setattr__ in baseclass (ESSENTIAL!!!!)
		screenlets.Screenlet.__setattr__(self, name, value)
		# redraw the canvas when server-info is changed since a server host/ip addition/removal will change the size of the screenlet
		if name == "_WirelessScreenlet__update_interval":
			if value > 0:
				if self.__timeout:
					gobject.source_remove(self.__timeout)
				self.__timeout = gobject.timeout_add(value * 1000, self.update)
			else:
				# TODO: raise exception!!!
				pass
		if name == "interface":
			self.update_stats()

	def update(self):
		gobject.idle_add(self.update_stats)
		return True

	def update_stats(self):
		self.__stats = sensors.get_wireless_stats(self.interface)
		self.__icon = self.get_icon()
		self.redraw_canvas()

	def on_draw(self, ctx):
		# if theme is loaded
		if self.theme:
			# find out how many servers that are configured and force a update_shape() when they're changed from the last draw.
			# apparently the settings doesn't get loaded until the widget is first displayed, and no update_shape is performed at
			# that point
			# make sure that the background covers all the icons
			ctx.save()
			ctx.scale(self.scale, self.scale)
			ctx.translate(0, 0)
			self.theme.render(ctx, 'background')
			ctx.restore()

			ctx.save()
			ctx.scale(self.scale, self.scale)
			
			#place for link icon
			ctx.translate(115, 15)

			self.theme.render(ctx, self.__icon)
			ctx.restore()
			ctx.save()
			ctx.scale(self.scale, self.scale)
			ctx.set_source_rgba(*self.text_color)

			if self.show_signal_noise ==True:

				text='<b>' + self.__stats['essid'] + '</b>'
				self.theme.draw_text(ctx,text, 15, 5, "Sans", 10,  self.width,allignment=pango.ALIGN_LEFT,weight = 0, ellipsize = pango.ELLIPSIZE_NONE)	
						
				text="<b>Signal</b>\n"+str(self.__stats['signal'])
				self.theme.draw_text(ctx,text, 15, 23, "Sans", 8,  self.width,pango.ALIGN_LEFT)

				text="<b>Noise</b>\n"+str(self.__stats['noise'])
				self.theme.draw_text(ctx,text, 75, 23, "Sans", 8,  self.width,pango.ALIGN_LEFT)
			else:
				
				text='<b>' + self.__stats['essid'] + '</b>'
				self.theme.draw_text(ctx,text, 10, 15, "Sans", 10,  self.width,pango.ALIGN_LEFT)

			text='<b>' +  str(self.__stats['percentage']) + '%</b>'
			self.theme.draw_text(ctx,text, 10, 43, "Sans", 32,  self.width,pango.ALIGN_LEFT)

			if self.show_ip ==True:
				text="<b>&lt;ip: "+self.__stats['local_ip']+"&gt;</b>"
				self.theme.draw_text(ctx,text, 8, 86, "Sans", 7,  self.width,pango.ALIGN_LEFT)

			ctx.restore()
			

			ctx.save()
			ctx.scale(self.scale, self.scale)
			ctx.translate(0, 0)
			self.theme.render(ctx, 'glass')
			ctx.restore()

	def on_draw_shape(self, ctx):
		if self.theme:
			self.on_draw(ctx)


	def get_wireless_interfaces(self):
		interfaces = []
		wfd = open("/proc/net/wireless")
		procinfo = wfd.read(1024)
		wfd.close()
		for line in procinfo.splitlines():
			colon = line.find(":")
			if colon > 0:
				interfaces.append(line[:colon].strip())
		return interfaces

#	def get_wireless_stats(self, interface):
#		
#		stats = {}
#		# finding of computers ip
#		#bug with localization fixed by fl0cker
#		ip = commands.getoutput("LANG=\"\" ifconfig "+ interface)
#		#---------------------------------------------------
#	
#		ip = ip[ip.find("inet"):] 
#		ip = ip[ip.find(":")+1:] 
#		ip = ip[:ip.find(" ")] 
#		stats['local_ip'] = ip
#		#print "<ip>"+ip+"</ip>"
#		#if no ip there's no connection...
#		if ip == '127.0.0.1' or ip == None or ip =='1' or ip=="":
#			#print "No connection"
#			return self.__not_connected_stats
#		else:
#
#			iwconfig = commands.getoutput("iwconfig "+ interface) 
#
#			essid = iwconfig[iwconfig.find(_('ESSID:"'))+7:]
#			stats['essid'] = essid[:essid.find('"')]	
#
#			bitrate = iwconfig[iwconfig.find(_("Bit Rate"))+9:]
#			bitrate = bitrate.split('   ')[0]
#			stats['bitrate'] = bitrate
#			#print "bitrate="+bitrate
#			
#			quality = iwconfig[iwconfig.find(_("Link Quality"))+13:]
#			quality = quality[:quality.find(" ")]
#			#print "quality="+quality
#			if quality.find("/") > 0:
#				stats['quality'], stats['quality_max'] = quality.split("/")
#			else:
#				stats['quality'] = quality
#			if stats['quality']=="0":
#				#print "no signal"
#				return self.__not_connected_stats
#
#			stats['percentage'] = self.get_percentage(int(stats['quality']), int(stats['quality_max']))
#			signal = iwconfig[iwconfig.find(_("Signal level"))+13:]
#			signal = signal.split(' Noise')[0];	
#			stats['signal'] = signal
#			#print "signal=="+signal
#
#			noise = iwconfig[iwconfig.find(_("Noise level"))+12:]
#			noise = noise.split('\n')[0]			
#			stats['noise'] = noise
#			#print "noise=="+noise
#			
#			return stats

	def get_percentage(self, quality, quality_max):
		# use log(quality) / log(quality_max) ?
		return int(float(quality) / quality_max * 100)

	def get_icon(self):
		if self.__stats['percentage'] < 1:
			return 'link-0'
		elif self.__stats['percentage'] < 21:
			return 'link-20'
		elif self.__stats['percentage'] < 41:
			return 'link-40'
		elif self.__stats['percentage'] < 61:
			return 'link-60'
		elif self.__stats['percentage'] < 81:
			return 'link-80'
		else:
			return 'link-100'
	
	def menuitem_callback(self, widget, id):
		screenlets.Screenlet.menuitem_callback(self, widget, id)
		if id == "show_signal_noise":
			self.show_signal_noise = not self.show_signal_noise
			self.update()
		if id == "show_ip":
			self.show_ip = not self.show_ip
			self.update()
	
# If the program is run directly or passed as an argument to the python
# interpreter then create a Screenlet instance and show it
if __name__ == "__main__":
	import screenlets.session
	screenlets.session.create_session(WirelessScreenlet)

