#!/usr/bin/env python
# -*- coding: utf-8 -*-

#    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 3 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, see <http://www.gnu.org/licenses/>.

# (C) 2010 boamaod@gmail.com, saweden@hotmail.com
#
#  Provided by the gCal Screenlet Team
#
#  Originally based on and inspired by the GDocs Screenlet by Alexandre freret
#  and eventcal/eigencal screenlet by Lukas K. and Wolfgang Arlt  
#
#  Using modified Google icon from FREE Handy Icon Set by Webdesigner Depot
#  http://www.webdesignerdepot.com/2009/04/24-free-exclusive-vector-icons-handy/
#
# INFO:
# This screenlet puts your Google calendar on your desktop.
# 


import screenlets
from screenlets.options import StringOption , BoolOption , IntOption , FileOption , DirectoryOption , ListOption , AccountOption , TimeOption , FontOption, ColorOption , ImageOption, FloatOption
from screenlets.options import create_option_from_node
from screenlets import DefaultMenuItem
import cairo
import pango
import gobject
import threading
import traceback
import gtk
import time
import datetime
import pygtk
pygtk.require('2.0')
import sys
import locale
import re
import urllib
from operator import itemgetter
import os
import string
import math

try:
	import gdata.calendar.service
	import gdata.service
	import atom.service
	import gdata.calendar
	import atom
except:
	print "Importing gdata failed."

X_SIZE = 440
Y_SIZE = 155

# use gettext for translation
import gettext

_ = screenlets.utils.get_translator(__file__)

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

@tdoc
class GoogleCalendarScreenlet (screenlets.Screenlet):
	"""Puts all your Google calendars on your desktop. Very customizable."""
	
	# default meta-info for Screenlets (should be remofved and put into metainfo)
	__name__	= 'GoogleCalendarScreenlet'
	__version__	= '0.4.12'
	__author__	= 'boamaod@gmail.com'
	__requires__	= ['python-gdata (>= 2.0.10)']
	__desc__	= __doc__	# set description to docstring of class
	
	# a list of google calendar events
	__calendarevents = [ ]
	# current index of the displayed documents
	__currentIndex = 0
	# Id of the selected row
	__selectedRow = 0
	
	# Are we handling a search right now?
	__onSearch = False
	# Search String
	__searchW = ''
	# Variable to keep search results
	__resultsCalendaritems = [ ]
	
	__connected = False
	__connected_prev = True
	__update_prev = True

	__events_area = None
	__all_area = None

	__events_ctx = None
	__events_test_ctx = None
	__events_buffer = None
	__events_test_buffer = None
	__events_layout = None
	__events_test_layout = None

	__text_height = 131

	__cal_client = None

	__customDateFormat = None
	__customTimeFormat = None

	__notifier = None

	__lock = threading.Lock()
	retrieving = False

	date_bg_file = None
	full_bg_file = None
	events_bg_file = None
	bg_type = 0

	good_login = False
	
	themes_dir = sys.path[0] + '/themes/'

	# editable options (options that are editable through the UI)
	loginCredentials =  ('','')
	# Documents list's font color - default white
#	font_color =(255.0, 255.0, 255.0, 1)
	exportDirectory= '/'

	# START Copied var defs from eventCalScreenlet
	# internals
	__timeout = None
	__timeout_net = None
	__first_day = 0
	__day_names = []
	rgba_color = (255, 255, 255, 1)
	date_day_color = (255, 255, 255, 1)
	date_weekday_color = (255, 255, 255, 1)
	date_month_color = (255, 255, 255, 1)
	event_weekday_color = (255, 255, 255, 1)
	event_time_color = (255, 255, 255, 1)
	bg_rgba_color = (0, 0, 0, 0.5)
	todaytxt = _('Today')
	tomorrowtxt = _('Tomorrow')
	dayaftertomorrowtxt = ''
	themeBehind = False
	scaleTheme = True
	roundCorner = True

	# DIY overkill
	CustomDateFormat = _('%d.%m')
	CustomTimeFormat = _('%H:%M')

	tabs = [16,55,60,99]

	dt_before = '\\t<b>'
	dt_after = '</b>'

	ind_prefix = '\\t'
	prefix_title = '\\t\\t'
	allday_prefix = '<i>'
	allday_suffix = '</i>'

	prefix_far_notime = '\\t'
	prefix_far_time = '\\t'
	prefix_far_title = '\\t'
	far_allday_prefix = '\\t<i>'
	far_allday_suffix = '</i>'

	ret = '\\n'

	# width of calendar date panel
	dateWidth = 130
	dateHeight = 131

	# width of events panel
	eventsWidth = 270
	eventsHeight = 131

	# padding for all the panels, as well as margin
	padding = 10

	# for scrolling the event list with the mouse wheel	
	scroll_step = 15
	scroll_offset = 0
	scroll_tooltip = _("Use mouse wheel to scroll up/down the event list")
	
	# settings
	update_interval = 10
	first_weekday = ''
	p_layout = None
	day = ''
	showEvents = True
	showDate = True
	autoHide = False
	eventDaysToShow = 21
	farAwayFuture = 6

	# normal event text buffer
	txt = ''
	# in far away future buffer
	txtExtra = ''

	demo_number = ''
	int_example = 1
	bool_example = True
	time_example =  (7, 30, 0)
	account_example =  ('','')
	color_example =(0.0, 0.0, 0.0, 1)

	text_font="Sans 9"

	date_big_font="Sans Bold 56"
	date_big_pos=0.16
	date_month_year_font="Sans 10"
	date_month_year_pos=0.09
	date_weekday_font="Sans 10"
	date_weekday_pos=0.75

	image_example = ''
	file_example = ''
	directory_example = ''
	list_example = ('','')
	hover = False
	number = 0

	calendar_indicator_char= "●"

	# to let drawing routine know if createEventList found any events or not
	eventsFound = False

	# END Copied var defs from eventCalScreenlet

	# constructor
	def __init__(self, **keyword_args):
		"""Init"""
		print 'Running __init__'
		screenlets.Screenlet.__init__(self, width=X_SIZE, height=Y_SIZE, uses_theme=True, **keyword_args) 
		# get localized day names
		locale.setlocale(locale.LC_ALL, '');
		# we convert to unicode here for the first letter extraction to work well
		self.__day_names = [locale.nl_langinfo(locale.DAY_1 + i).decode() for i in range(7)] 
		self.first_weekday = self.__day_names[self.__first_day]
		# call super (and not show window yet)
		# set theme
		self.theme_name = "default"

		self.width = X_SIZE
		self.height = Y_SIZE
		''' -----------------------------------------
		Properties
		----------------------------------------- '''
		# add option group
		self.add_options_group(_('gCal essential'), _('Please fill in the gCal essential properties ...'))

		# TODO: add to __setattr__ which are needed
		
		# add editable option to the group
#		self.add_option(ColorOption('gCal','font_color', self.font_color, _('Font color'), _('Choose the font color')))
		self.add_option(AccountOption(_('gCal essential'),'loginCredentials',self.loginCredentials, _('Google account'),_('Enter username and password. gCal is using system keyring encryption.')))
		self.add_option(IntOption(_('gCal essential'), 'update_interval', self.update_interval, _('Update interval'), _('The interval for updating info (in minutes)'), min=1, max=120),realtime=True)
		self.add_option(IntOption(_('gCal essential'), 'eventDaysToShow', self.eventDaysToShow, _('Calendar length'), _('How many days to show events for'), min=0, max=60), realtime=False)
		self.add_option(IntOption(_('gCal essential'), 'farAwayFuture', self.farAwayFuture, _('Active interval'), _('Starting from this amount of days towards future, the event data is displayed in compressed format'), min=0, max=60), realtime=True)
		self.add_option(BoolOption(_('gCal essential'), 'showEvents',bool(self.showEvents), _('Show events'),_('Show the event pane')),realtime=True)
		self.add_option(BoolOption(_('gCal essential'), 'autoHide',bool(self.autoHide), _('Auto hide on no events'),_('Auto hide events pane on no events')),realtime=True)
		self.add_option(BoolOption(_('gCal essential'), 'showDate',bool(self.showDate), _('Show date'),_('Show the current date pane')),realtime=True)

		self.add_option(StringOption(_('gCal essential'), 'calendar_indicator_char', self.calendar_indicator_char,_('Indicator character'), _('What character to use for the coloured calendar indicators (leave empty if you don\'t want color indication!)'),),realtime=True)

		self.add_option(StringOption(_('gCal essential'), 'todaytxt', self.todaytxt,_('Today title'), _('Your preferred label for today\'s events section'),),realtime=True)
		self.add_option(StringOption(_('gCal essential'), 'tomorrowtxt', self.tomorrowtxt,_('Tomorrow title'), _('Your preferred label for tomorrows\'s events section'),),realtime=True)
		self.add_option(StringOption(_('gCal essential'), 'dayaftertomorrowtxt', self.dayaftertomorrowtxt,_('Day after tomorrow'), _('Your preferred label for day after tomorrow\'s events section'),),realtime=True)




		self.add_options_group(_('gCal window'), _('Please fill in the gCal window properties ...'))

		self.add_option(IntOption(_('gCal window'), 'dateWidth', self.dateWidth, _('Date panel width'), _('Date panel width'), min=130, max=2000),realtime=True)
		self.add_option(IntOption(_('gCal window'), 'dateHeight', self.dateHeight, _('Date panel height'), _('Date panel height'), min=131, max=3000),realtime=True)
		self.add_option(IntOption(_('gCal window'), 'eventsWidth', self.eventsWidth, _('Events panel width'), _('Events panel width'), min=130, max=2000),realtime=True)
		self.add_option(IntOption(_('gCal window'), 'eventsHeight', self.eventsHeight, _('Events panel height'), _('Events panel height'), min=131, max=3000),realtime=True)


		self.add_option(BoolOption(_('gCal window'), 'roundCorner',bool(self.roundCorner), _('Background round corners'),_('Draw background with round corners')),realtime=True)
		self.add_option(ColorOption(_('gCal window'), 'bg_rgba_color', self.bg_rgba_color, _('Background color'), _('The default color of the background (can be transparent too)')), realtime=True)
		self.add_option(BoolOption(_('gCal window'), 'scaleTheme',bool(self.scaleTheme), _('Scale background images'),_('Scale theme images to fit fully into the background')),realtime=True)
		self.add_option(BoolOption(_('gCal window'), 'themeBehind',bool(self.themeBehind), _('Theme behind background'),_('Theme behind rendered background')),realtime=True)




		self.add_options_group(_('gCal appearance'), _('Please fill in the gCal appearance properties ...'))


		self.add_option(FontOption(_('gCal appearance'), 'text_font', self.text_font, _('Event text font'), _('Font to use for event list')), realtime=True)
		self.add_option(ColorOption(_('gCal appearance'), 'rgba_color', self.rgba_color, _('Event text color'), _('The default color of the text (when no markup is used)')), realtime=True)
		self.add_option(ColorOption(_('gCal appearance'), 'event_weekday_color', self.event_weekday_color, _('Event weekday color'), _('The default color of the weekday name (transparency does not work)')), realtime=True)
		self.add_option(ColorOption(_('gCal appearance'), 'event_time_color', self.event_time_color, _('Event timestamp color'), _('The default color of the date/time displayed in front of events (transparency does not work)')), realtime=True)

		self.add_option(FontOption(_('gCal appearance'), 'date_month_year_font', self.date_month_year_font, _('Date month font'), _('Font to use to display month and year of the current date')), realtime=True)
		self.add_option(ColorOption(_('gCal appearance'), 'date_month_color', self.date_month_color, _('Date month color'), _('The default color for the month name text')), realtime=True)
		self.add_option(FloatOption(_('gCal appearance'), 'date_month_year_pos', self.date_month_year_pos, 
				_('Date month position'), _('Position on the pane'),
				min=0, max=1, increment=0.01, digits=2))

		self.add_option(FontOption(_('gCal appearance'), 'date_big_font', self.date_big_font, _('Date day font'), _('Font to use to display day of the current date')), realtime=True)
		self.add_option(ColorOption(_('gCal appearance'), 'date_day_color', self.date_day_color, _('Date day color'), _('The default color for day')), realtime=True)
		self.add_option(FloatOption(_('gCal appearance'), 'date_big_pos', self.date_big_pos, 
				_('Date day position'), _('Position on the pane'),
				min=0, max=1, increment=0.01, digits=2))

		self.add_option(FontOption(_('gCal appearance'), 'date_weekday_font', self.date_weekday_font, _('Date weekday font'), _('Font to use to display weekday of the current date')), realtime=True)
		self.add_option(ColorOption(_('gCal appearance'), 'date_weekday_color', self.date_weekday_color, _('Date weekday color'), _('The default color for the weekday text')), realtime=True)
		self.add_option(FloatOption(_('gCal appearance'), 'date_weekday_pos', self.date_weekday_pos, 
				_('Date weekday position'), _('Position on the pane'),
				min=0, max=1, increment=0.01, digits=2))


		self.add_options_group(_('DIY overkill'), _('You can change here some of the the strings gCal uses \nto display things. You can use Pango Markup as described \nat http://www.pygtk.org/docs/pygtk/pango-markup-language.html\n and for the date/time formatting have a look at \nhttp://docs.python.org/library/datetime.html#strftime-strptime-behavior'))

		self.add_option(StringOption(_('DIY overkill'), 'CustomDateFormat', self.CustomDateFormat,_('Date formatting'), _('For far away events. Use %m for month as a number, %b for month as text, %d for day. Example: %d/%m. Find more info from http://docs.python.org/library/datetime.html#strftime-strptime-behavior'),),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'CustomTimeFormat', self.CustomTimeFormat,_('Time formatting'), _('Use %H for hours 0-23, %I for hours 0-11, %M for minutes, %p for AM/PM indicator, if that supported by locale. Find more info from http://docs.python.org/library/datetime.html#strftime-strptime-behavior'),),realtime=True)

		self.add_option(ListOption(_('DIY overkill'), 'tabs', self.tabs, _('Tab positions'), _('Tabulator positions')),realtime=True)

		self.add_option(StringOption(_('DIY overkill'), 'dt_before', self.dt_before, _('Day prefix'), _('Before day text'),),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'dt_after', self.dt_after, _('Day suffix'), _('After day text'),),realtime=True)


		self.add_option(StringOption(_('DIY overkill'), 'ind_prefix', self.ind_prefix, _('Indicator suffix'), '' ),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'prefix_title', self.prefix_title, _('Title prefix'), '' ),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'allday_prefix', self.allday_prefix, _('Allday prefix'), _('Before full day event text'),),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'allday_suffix', self.allday_suffix, _('Allday suffix'), _('After full day event text'),),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'prefix_far_notime', self.prefix_far_notime, _('Far no time prefix'), '' ),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'prefix_far_time', self.prefix_far_time, _('Far time prefix'), '' ),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'prefix_far_title', self.prefix_far_title, _('Far title prefix'), '' ),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'far_allday_prefix', self.far_allday_prefix, _('Far allday prefix'), _('Before full day event text'),),realtime=True)
		self.add_option(StringOption(_('DIY overkill'), 'far_allday_suffix', self.far_allday_suffix, _('Far allday suffix'), _('After full day event text'),),realtime=True)

		self.add_option(StringOption(_('DIY overkill'), 'ret', self.ret, _('Return char'), _('Carriage return char'),),realtime=True)


		self.__notifier = screenlets.utils.Notifier(self)

		# scrolling is for events
		self.resize_on_scroll = False

		# this is needed only for the tooltip
		self.__events_area = gtk.Fixed()
		self.__all_area = gtk.Fixed()
		self.__all_area.put(self.__events_area, 0, 0)
		self.window.add(self.__all_area)
#		self.window.add(self.__events_area)

	# attribute-"setter", handles setting of attributes
	def __setattr__(self, name, value):
		"""Set attr"""

		# call Screenlet.__setattr__ in baseclass (ESSENTIAL!!!!)
		screenlets.Screenlet.__setattr__(self, name, value)
		# check for this Screenlet's attributes, we are interested in: 

		# TODO: add ALL attributes which make screenlet window to need resizing!!
		if name == "hide_events_panel" or name == "hide_date_panel" or name == "showDate" or name == "showEvents" or name == "autoHide" or name=="dateWidth" or name=="dateHeight" or name=="eventsWidth" or name=="eventsHeight":
			if self.window:
				self.calculateWindow()
				self.calculateTxtHeight()
				self.redraw_canvas()
		# TODO: add ALL attributes which make screenlet window to need redrawing!!
		if name=='CustomTimeFormat' or name=='CustomDateFormat' or name=='date_big_font' or name == 'date_month_year_font' or name == 'date_weekday_font' or name=='date_big_pos' or name == 'date_month_year_pos' or name == 'date_weekday_pos' or name == 'rgba_color' or name == "date_day_color" or name == "date_month_color" or name == "date_weekday_color" or name == 'bg_rgba_color' or name == "text_font" or name == "calendar_indicator_char" or name == "event_weekday_color" or name == "event_time_color" or name == "todaytxt" or name == "tomorrowtxt" or name == "dayaftertomorrowtxt" or name == 'tab' or name == 'ret' or name == 'dt_before' or name == 'dt_after' or name=="farAwayFuture" or name == 'tabs' or name.find("prefix") >= 0:
			if self.window:
				self.createEventList()
				self.redraw_canvas()
		if name == "update_interval":
			if value > 0:
				self.__dict__['update_interval'] = value
				if self.__timeout:
					gobject.source_remove(self.__timeout)
				self.__timeout = gobject.timeout_add(value 
						* 60000, self.update)
			else:
				# TODO: raise exception!!!
				pass

	def get_date_info(self):
		"""Date info"""

		today = datetime.datetime.now()
		day = today.strftime(_("%d"))
		month = today.month
		year = today.year

		# apply month shift
		# get first day of the updated month
		first_day = datetime.date(year, month, 1)
		# get the month name
		month_name = first_day.strftime(_("%B"))
        # get the day name
		day_name = today.strftime(_("%A"))
		# get the day count
		if month in [1, 3, 5, 7, 8, 10, 12]:
			days_in_month = 31
		elif month != 2:
			days_in_month = 30
		elif year % 4 == 0:
			days_in_month = 29
		else:
			days_in_month = 28
		# find the first day of the month
		start_day = (int(first_day.strftime("%u")) % 7) + 1
		# return as array
		return [day, year, month_name, days_in_month, start_day, day_name]
	

	def update (self):
		"""Update login and calendar data"""
		print "Running update"

		self.bg_rgba_color = self.bg_rgba_color

		try:

			if not self.checkConnected():
				raise NameError('Not connected exception')

			if self.__timeout_net:
 				gobject.source_remove(self.__timeout_net)

			if self.__cal_client is None:
				self.loginGAccount()

			# this updates the calendar data, screen is refreshed in on_draw
			self.retrieveEventsOnAllCalendars()

		except Exception:

			if self.checkConnected():
				self.__connected_prev = self.__connected
				self.__connected = True

 				if self.__timeout_net:
	 				gobject.source_remove(self.__timeout_net)

				self.loginGAccount()

				return True

			else:
				if self.__connected is not self.__connected_prev:
					self.__notifier.notify(_("Internet connection failed."))
					print "Not connected to internet."
					self.__connected_prev = self.__connected

				if self.__timeout_net:
					gobject.source_remove(self.__timeout_net)
				self.__timeout_net = gobject.timeout_add(10000, self.update)

				return True

			# still try to force repairing connection etc
#			try:
#				self.loginGAccount()
#			except Exception:
#				print "Couldn't fix."

#		if self.__timeout:
#			gobject.source_remove(self.__timeout)
		if not self.__timeout:
			self.__timeout = gobject.timeout_add(int(self.update_interval)
					* 60000, self.update)

		return True # keep running this event	


	def on_after_set_atribute(self,name, value):
		"""Called after setting screenlet atributes"""
		if name == 'loginCredentials' or name == 'eventDaysToShow':
#			print "*** Running on_after_set_atribute for name: " + name
			if self.__connected and self.loginCredentials[0] and self.loginCredentials[1] and self.loginGAccount():
				if name == 'loginCredentials':
					self.__notifier.notify(_("Login successful."))
				self.retrieveEventsOnAllCalendars()
		if name == 'CustomDateFormat' or name == 'CustomTimeFormat':
#			print "*** Running on_after_set_atribute for name: " + name
			# Hmmm... better check if the user entered something that won't cause the
			# screenlet to stop working. If so, - reset to default.
			try:
				__tmpdate = datetime.now()
				print __tmpdate.strftime(value)
			except Exception:
				if name == 'CustomDateFormat':
					CustomDateFormat = ''
				elif name == 'CustomTimeFormat':
					CustomTimeFormat = ''
				print 'Bad custom ' + name + ' rules entered'
			self.redraw_canvas()
		pass

	def menuitem_callback(self, widget, id):
		"""Deal with menu choices using widget object????"""
		screenlets.Screenlet.menuitem_callback(self, widget, id)

	def on_before_set_atribute(self,name, value):
		"""Called before setting screenlet atributes"""
		pass

	def on_create_drag_icon (self):
		"""Called when the screenlet's drag-icon is created. You can supply
		your own icon and mask by returning them as a 2-tuple."""
		return (None, None)

	def on_composite_changed(self):
		"""Called when composite state has changed"""
		pass

	def on_drag_begin (self, drag_context):
		"""Called when the Screenlet gets dragged."""
		pass
	
	def on_drag_enter (self, drag_context, x, y, timestamp):
		"""Called when something gets dragged into the Screenlets area."""
		pass
	
	def on_drag_leave (self, drag_context, timestamp):
		"""Called when something gets dragged out of the Screenlets area."""
		pass

	def on_drop (self, x, y, sel_data, timestamp):
		"""Called when a selection is dropped on this Screenlet."""
		return False
		
	def on_focus (self, event):
		"""Called when the Screenlet's window receives focus."""
		self.__has_focus = True
		pass
	
	def on_hide (self):
		"""Called when the Screenlet gets hidden."""
		pass
	
	def on_init (self):
		"""Called when the Screenlet's options have been applied and the 
		screenlet finished its initialization. If you want to have your
		Screenlet do things on startup you should use this handler."""

		''' -----------------------------------------
		Menu items
		----------------------------------------- '''
		print '*** Running on_init'
		self.add_menuitem("hide_events_panel", _("Toggle hide/view calendar events"))
		self.add_menuitem("hide_date_panel", _("Toggle hide/view current date"))
		self.add_menuitem("update", _("Update events now"))
#		self.add_menuitem("RefreshCalendar", "Refresh calendar")
#		self.add_menuitem("Reconnect", "Reconnect to Google Calendar")
		self.add_default_menuitems()
		
		print '\033[0;36mGoogleCalendarScreenlet started.\033[0m'

		# this is the most stupidest thing to do, but it won't work ok otherwise
		self.bg_rgba_color = self.bg_rgba_color
#		self.bg_rgba_color = [0,0,0,0.5]

		self.calculateWindow()
		self.redraw_canvas()

#		if not self.checkConnected():
#			# ADD a 10 seconds (10000) TIMER
#			# to check the internet connection
#			if(self.__timer_net):
#				gobject.source_remove(self.__timer_net)
#			self.__timeout_net = gobject.timeout_add(10000, self.update)
#		else:
#		self.__connected = True
		self.update()

		if not self.__timeout:
			self.__timeout = gobject.timeout_add(int(self.update_interval)
					* 60000, self.update)

#		print self.width, ", ", self.height

		
	def on_key_down(self, keycode, keyvalue, event):
		"""Called when a keypress-event occured in Screenlet's window."""
		key = gtk.gdk.keyval_name(event.keyval)
#		self.redraw_canvas()
		pass
	
	def on_load_theme (self):
		"""Called when the theme is reloaded (after loading, before redraw)."""

		print self.themes_dir + self.theme_name

		# theme file name first parts
		self.full_bg_file = self.themes_dir + self.theme_name + '/calendar1'
		self.date_bg_file = self.themes_dir + self.theme_name + '/calendar'
		self.events_bg_file = self.themes_dir + self.theme_name + '/calendar2'

		# check the contents
		if os.path.isfile(self.full_bg_file + ".svg"):
			self.full_bg_file = self.full_bg_file + ".svg"
		elif os.path.isfile(self.full_bg_file + ".png"):
			self.full_bg_file = self.full_bg_file + ".png"
		else:
			self.full_bg_file = None
		if os.path.isfile(self.date_bg_file + ".svg"):
			self.date_bg_file = self.date_bg_file + ".svg"
		elif os.path.isfile(self.date_bg_file + ".png"):
			self.date_bg_file = self.date_bg_file + ".png"
		else:
			self.date_bg_file = None
		if os.path.isfile(self.events_bg_file + ".svg"):
			self.events_bg_file = self.events_bg_file + ".svg"
		elif os.path.isfile(self.events_bg_file + ".png"):
			self.events_bg_file = self.events_bg_file + ".png"
		else:
			self.events_bg_file = None

		print "THEME FILES AVAILABLE"

		print "Full", self.full_bg_file
		print "Date", self.date_bg_file
		print "Events", self.events_bg_file

		self.findOutThemingOptions()

	
	def on_menuitem_select (self, id):
		"""Called when a menuitem is selected."""

		if id == "hide_events_panel":
			self.showEvents = not self.showEvents
		if id == "hide_date_panel":
			self.showDate = not self.showDate
		if id == "hide_events_panel" or id == "hide_date_panel":
			self.calculateWindow()
			self.redraw_canvas()
		if id=="update":
			self.update()

#		if id == "update":
#			self.update()

#		if id == "RefreshCalendar":
#			self.retrieveEventsOnAllCalendars()
#			self.redraw_canvas()
#		elif id =="Reconnect":
			
#			print 'trying to log in'
			
			#if successful
#			if self.__connected and self.loginGAccount():
#				self.retrieveEventsOnAllCalendars()
#				self.redraw_canvas()

#		pass
	
	def on_mouse_down (self, event):
		"""Called when a buttonpress-event occured in Screenlet's window. 
		Returning True causes the event to be not further propagated."""
		
	
	def on_mouse_enter (self, event):
		"""Called when the mouse enters the Screenlet's window."""
		self.hover = True
		
		
	def on_mouse_leave (self, event):
		"""Called when the mouse leaves the Screenlet's window."""
		self.hover = False


	def on_mouse_move(self, event):
		"""Called when the mouse moves in the Screenlet's window."""
		pass

	def on_mouse_up (self, event):
		"""Called when a buttonrelease-event occured in Screenlet's window. 
		Returning True causes the event to be not further propagated."""
		return False
	
	def on_quit (self):
		"""Callback for handling destroy-event. Perform your cleanup here!"""
		if self.__timeout_net:
			gobject.source_remove(self.__timeout_net)
		if self.__timeout:
			gobject.source_remove(self.__timeout)
		return True
		
	def on_realize (self):
		""""Callback for handling the realize-event."""
	
	def on_scale (self):
		"""Called when Screenlet.scale is changed."""
		pass
	
	def on_scroll_up (self):
		"""Called when mousewheel is scrolled up (button4)."""

		self.scroll_offset -= self.scroll_step
		if self.scroll_offset < 0 : self.scroll_offset = 0
		self.redraw_canvas()
		return True
		
	def on_scroll_down (self):
		"""Called when mousewheel is scrolled down (button5)."""

		self.scroll_offset += self.scroll_step
		if self.scroll_offset > self.__text_height - self.eventsHeight: self.scroll_offset = self.__text_height - self.eventsHeight
		self.redraw_canvas()
		return True
	
	def on_show (self):
		"""Called when the Screenlet gets shown after being hidden."""
		pass
	
	def on_switch_widget_state (self, state):
		"""Called when the Screenlet enters/leaves "Widget"-state."""
		pass
	
	def on_unfocus (self, event):
		"""Called when the Screenlet's window loses focus."""
		self.__has_focus = False
		pass

	# from drawing.py for debugging reasons
	def draw_rounded_rectangle_not_needed(self,ctx,x,y,rounded_angle,width,height,round_top_left = True ,round_top_right = True,round_bottom_left = True,round_bottom_right = True, fill=True):
		"""Draws a rounded rectangle"""
		ctx.save()
		ctx.translate(x, y)
		padding=0 # Padding from the edges of the window
        	rounded=rounded_angle # How round to make the edges 20 is ok
        	w = width
		h = height

        	# Move to top corner
        	ctx.move_to(0+padding+rounded, 0+padding)
        	
        	# Top right corner and round the edge
		if round_top_right:
	        	ctx.line_to(w-padding-rounded, 0+padding)
	        	ctx.arc(w-padding-rounded, 0+padding+rounded, rounded, (math.pi/2 )+(math.pi) , 0)
		else:
			ctx.line_to(w-padding, 0+padding)

        	# Bottom right corner and round the edge
		if round_bottom_right:
		       	ctx.line_to(w-padding, h-padding-rounded)
	        	ctx.arc(w-padding-rounded, h-padding-rounded, rounded, 0, math.pi/2)
		else:
	        	ctx.line_to(w-padding, h-padding)       	
        	# Bottom left corner and round the edge.
		if round_bottom_left:
	        	ctx.line_to(0+padding+rounded, h-padding)
	        	ctx.arc(0+padding+rounded, h-padding-rounded, rounded,math.pi/2, math.pi)
		else:	
	        	ctx.line_to(0+padding, h-padding)
        	# Top left corner and round the edge
		if round_top_left:
	        	ctx.line_to(0+padding, 0+padding+rounded)
	        	ctx.arc(0+padding+rounded, 0+padding+rounded, rounded, math.pi, (math.pi/2 )+(math.pi))
		else:
			ctx.line_to(0+padding, 0+padding)
        	# Fill in the shape.
#		if fill:ctx.fill()
#		else: ctx.stroke()
		ctx.fill()
		ctx.restore()

	def on_draw(self, ctx):
		"""on_draw"""

		if not self.window:
			return
			
		if not self.has_started:
			return

#		print '*** Running on_draw'

		# get data
		date = self.get_date_info() # [day, year, month_name, days_in_month, start_day]

		# draw bg (if theme available)
		ctx.set_operator(cairo.OPERATOR_OVER)

		# set size
		ctx.scale(self.scale, self.scale)

		if self.themeBehind:
			self.drawTheme(ctx)

#		print self.bg_rgba_color
		# draw the normal background
#		a = self.bg_rgba_color[0]
#		b = self.bg_rgba_color[1]
#		c = self.bg_rgba_color[2]
#		d = self.bg_rgba_color[3]
#		print a,b,c,d
#		ctx.set_source_rgba(0,0,0.5,0.5)
#		ctx.set_source_rgba(a,b,c,d)
#		ctx.set_source_rgba(1,2,3,4)
		ctx.set_source_rgba(self.bg_rgba_color[0], self.bg_rgba_color[1], self.bg_rgba_color[2], self.bg_rgba_color[3])
#		ctx.set_source_rgba(0.3,0.5,0.5,0.5)
		if self.roundCorner:
			self.draw_rounded_rectangle(ctx,0,0, self.padding,self.width, self.height)
		else:
			self.draw_rectangle(ctx,0,0, self.width, self.height)


		if not self.themeBehind:
			self.drawTheme(ctx)

		if self.showEvents:

			# if the credentials haven't been set
			if self.loginCredentials[0] == '':

					ctx.set_source_rgba(self.rgba_color[0], self.rgba_color[1], self.rgba_color[2], self.rgba_color[3])
					self.draw_text(ctx, _("\nCan't display events, because no login credentials are provided. Please provide the credentials using the configuration dialog. Your credentials are stored safely into system keyring and reloaded from keyring every time the screenlet is started."), self.xpos(), self.padding , self.text_font , 9, self.eventsWidth, self.width,pango.ALIGN_LEFT)

			elif self.__cal_client is None and not self.__connected:

				ctx.set_source_rgba(self.rgba_color[0], self.rgba_color[1], self.rgba_color[2], self.rgba_color[3])
				self.draw_text(ctx, _("\nWaiting for the connection..."), self.xpos(), self.padding , self.text_font , 9, self.eventsWidth, self.width,pango.ALIGN_LEFT)

			elif self.eventsFound:

				self. drawEvents(ctx);

					
		if self.showDate:

			self.drawDate(ctx, date)		

		if not self.showEvents and not self.showDate:

			self.theme.draw_scaled_image(ctx, 0, 0, sys.path[0] + '/icon.svg', self.width, self.height)

		self.window.resize(int(self.width * self.scale), int(self.height * self.scale))
		ctx.scale(self.scale, self.scale)
		ctx.stroke ()

	def drawTheme(self, ctx):
		"""Draws the theme pictures"""
		if not self.theme:
			return

		if self.bg_type == 1: # full
			if self.scaleTheme == True:
					self.theme.draw_scaled_image(ctx, 0, 0, self.full_bg_file, self.width, self.height)
			else:
				self.theme.render(ctx, 'calendar1')
		if self.bg_type == 2 or self.bg_type == 4: # date
			if self.scaleTheme == True:
					self.theme.draw_scaled_image(ctx, 0, 0, self.date_bg_file, self.dateWidth + self.padding*2, self.dateHeight + self.padding*2)
			else:
				self.theme.render(ctx, 'calendar')
		if self.bg_type == 3 or self.bg_type == 4: # events
			if self.scaleTheme == True:
					self.theme.draw_scaled_image(ctx, self.xpos() - self.padding, 0, self.events_bg_file, self.eventsWidth + self.padding*2, self.eventsHeight + self.padding*2)
			else:
				self.theme.draw_image(ctx, self.xpos() - self.padding, 0, self.events_bg_file)

	def xpos(self):
		"""returns presumable x position of the events pane"""
		if self.showDate:
			xpos = self.dateWidth +  self.padding*3
		else:
			xpos = self.padding

		return xpos

	def calculateWindow(self):
		"""calculates window size from the elements present, sets tooltip position, updates theming variables"""
#		print "*** Running calculateWindow"

		h=0
		w=0
		if (self.showEvents and not self.autoHide) or (self.showEvents and self.autoHide and self.eventsFound):
			h = max(self.eventsHeight, h)
			w += self.eventsWidth
		if self.showDate:
			h = max(self.dateHeight, h)
			w += self.dateWidth

		if w == 0 or h == 0:
			w = self.dateHeight
			h = self.dateWidth

		if self.showDate and ((self.showEvents and not self.autoHide) or (self.showEvents and self.autoHide and self.eventsFound)):
			w += self.padding*2 # line between

		# margin=padding
		w += self.padding*2
		h += self.padding*2

		self.height= h
		self.width = w

		self.findOutThemingOptions()

		# events pane tooltip area
		if (self.showEvents and not self.autoHide) or (self.showEvents and self.autoHide and self.eventsFound):
			if self.__events_area:
				self.__events_area.set_size_request(int(self.eventsWidth * self.scale), int(self.eventsHeight * self.scale))
			if self.__all_area:
				self.__all_area.move(self.__events_area, int(self.xpos() * self.scale), int(self.padding * self.scale))
			self.__events_area.set_tooltip_text(self.scroll_tooltip)
			self.window.show_all()        
		else:
			self.__events_area.set_tooltip_text("")


	def findOutThemingOptions(self):
		"""Detects which theming option should be used for current pane configuration
		 bg_type: 0 - none, 1 - full, 2 - date, 3 - events, 4 - both"""

		self.bg_type = 0

		# detect which kind of theming is recommended
		if self.theme:
			if self.showDate and (self.showEvents and not self.autoHide) or (self.showEvents and self.autoHide and self.eventsFound):
				if self.full_bg_file is not None: # one full image
					self.bg_type = 1
				if self.bg_type != 1: # try both other parts
					if self.date_bg_file is not None:
						self.bg_type = 2
					if self.events_bg_file is not None:
						if self.bg_type == 2:
							self.bg_type = 4
						else:
							self.bg_type = 3
			elif self.showDate:
				if self.date_bg_file is not None:
					self.bg_type = 2
			elif (self.showEvents and not self.autoHide) or (self.showEvents and self.autoHide and self.eventsFound):
				if self.events_bg_file is not None:
					self.bg_type = 3



	def createEventList(self):
		"""create the list into self.txt ja self.txtExtra, set self.eventsFound"""
		# The calentries list has the following named keys: googleid, calenderid, color, title, 
		# content, start_time, end_time, updated

		if not self.showEvents:
			return

		IND_PREFIX = self.ind_prefix.decode("string_escape")
		PREFIX_TITLE = self.prefix_title.decode("string_escape")
		PREFIX_FAR_TIME = self.prefix_far_time.decode("string_escape")
		PREFIX_FAR_NOTIME = self.prefix_far_notime.decode("string_escape")
		PREFIX_FAR_TITLE = self.prefix_far_title.decode("string_escape")
		ALLDAY_PREFIX = self.allday_prefix.decode("string_escape")
		FAR_ALLDAY_PREFIX = self.far_allday_prefix.decode("string_escape")
		ALLDAY_SUFFIX = self.allday_suffix.decode("string_escape")
		FAR_ALLDAY_SUFFIX = self.far_allday_suffix.decode("string_escape")
		RET = self.ret.decode("string_escape")
		DT_BEFORE = self.dt_before.decode("string_escape")
		DT_AFTER = self.dt_after.decode("string_escape")

		# for autohide
		prev_ev_f=self.eventsFound			

		# normal event text
		self.txt = ''
		# in far away future
		self.txtExtra = ''

		daycount=0
		runningDate = ""

		calentries = self.__calendarevents

		# get data
		date = self.get_date_info() # [day, year, month_name, days_in_month, start_day]

		if len(calentries) != 0:
			today=datetime.date.today()
			for calentry in calentries:
				if calentry['title'] == None: # had this problem, just added this check here!
					continue

				startDate = datetime.date.fromordinal(calentry['start_time'].toordinal())
				strStartTime = str(calentry['start_time'])[11:16]
				strEndTime = str(calentry['end_time'])[11:16]

				alldayevent = False
				if strStartTime == '00:00' and strEndTime == '00:00':
					alldayevent = True
#					strStartTime = strEndTime = TAB  
#				print 'drawCalEntryList: ' + str(startDate) + ' ' + strStartTime + TAB +'   ' + calentry['title']

#				print str(today) + " ---" + str(startDate)






				if(len(self.CustomTimeFormat) > 0 and not alldayevent):

#					print "==================================>>>>"
#					print self.CustomTimeFormat + ": " + strStartTime + " -> " + time.strftime(self.CustomTimeFormat, time.strptime(strStartTime, "%H:%M"))
#					print strStartTime
#					ts = time.strptime(strStartTime, "%H:%M")
#					print self.CustomTimeFormat
#					print time.strftime(self.CustomTimeFormat, ts)

#					self.__customTimeFormat = re.sub(r_("\b0"),"",time.strftime(self.CustomTimeFormat, time.strptime(strStartTime, "%H:%M")))
					self.__customTimeFormat = time.strftime(self.CustomTimeFormat, time.strptime(strStartTime, _("%H:%M")))
				else:
					self.__customTimeFormat = strStartTime = strEndTime = ""

				# this is not really normal way to convert different color representations, but does the job quite universally
				if isinstance(self.event_weekday_color[0], int):
					dayTxtColor = "<span foreground='" + gtk.gdk.Color(self.event_weekday_color[0]*0x101, self.event_weekday_color[1]*0x101, self.event_weekday_color[2]*0x101).to_string() + "'>"
				else:
					dayTxtColor = "<span foreground='" + gtk.gdk.Color(int(self.event_weekday_color[0]*0xffff), int(self.event_weekday_color[1]*0xffff), int(self.event_weekday_color[2]*0xffff)).to_string() + "'>"
				if isinstance(self.event_time_color[0], int):
					dayTimeColor = "<span foreground='" + gtk.gdk.Color(self.event_time_color[0]*0x101, self.event_time_color[1]*0x101, self.event_time_color[2]*0x101).to_string() + "'>"
				else:
					dayTimeColor = "<span foreground='" + gtk.gdk.Color(int(self.event_time_color[0]*0xffff), int(self.event_time_color[1]*0xffff), int(self.event_time_color[2]*0xffff)).to_string() + "'>"
		
				if runningDate == startDate:
					daytxt = ""
				elif today == startDate and self.todaytxt.strip() != "":
					daytxt = dayTxtColor + self.todaytxt.strip()  + "</span>"
					runningDate=startDate
				elif today == startDate - datetime.timedelta(days=1) and self.tomorrowtxt.strip() != "":
					daytxt = dayTxtColor + self.tomorrowtxt.strip()  + "</span>"
					runningDate=startDate
				elif today == startDate - datetime.timedelta(days=2) and self.dayaftertomorrowtxt.strip() != "":
					daytxt = dayTxtColor + self.dayaftertomorrowtxt.strip()  + "</span>"
					runningDate=startDate
				else:
					delta = startDate - today

					daytxt = dayTxtColor + (today + datetime.timedelta(days=delta.days)).strftime(_('%A')).strip() + "</span>"

					runningDate=startDate
					daycount += 1
					
				# choose whether to display in compressed or normal calendar mode
				if startDate > today + datetime.timedelta(days=self.farAwayFuture):
				# far away display
				
					if(len(self.CustomDateFormat) > 0):
						self.__customDateFormat = re.sub(r"\b0","",startDate.strftime(self.CustomDateFormat))
					else:
						self.__customDateFormat = str(startDate)
						# TODO: this does not work since some widths of characters are variable!!!
						#__customDateFormat = __customDateFormat # Pad string with spaces at the end 
						
					self.txtExtra += "<span foreground='" + calentry['color'] + "'>" + self.calendar_indicator_char + "</span>" + IND_PREFIX
					if self.__customTimeFormat.strip()=="":
						add_time = PREFIX_FAR_NOTIME
					else:
						add_time = PREFIX_FAR_TIME + self.__customTimeFormat
					if alldayevent:
						titletodisplay = FAR_ALLDAY_PREFIX +calentry['title'] + FAR_ALLDAY_SUFFIX
					else:
						titletodisplay = PREFIX_FAR_TITLE + calentry['title']
					self.txtExtra +=  dayTimeColor + self.__customDateFormat + add_time + '</span>' + titletodisplay + RET
					
				else:
				# normal display
					if daytxt:
						self.txt += DT_BEFORE+ daytxt + DT_AFTER + RET
					self.txt += "<span foreground='" + calentry['color'] + "'>" + self.calendar_indicator_char + "</span>" + IND_PREFIX
					if alldayevent:
						titletodisplay = ALLDAY_PREFIX + calentry['title'] + ALLDAY_SUFFIX
					else:
						titletodisplay = PREFIX_TITLE + calentry['title']
					self.txt += dayTimeColor + self.__customTimeFormat.strip()  + '</span>' + titletodisplay + RET


			if self.txt == '' and self.txtExtra == '':
				print 'no events found'
				self.eventsFound = False
			else:
				self.eventsFound = True

		if self.autoHide and prev_ev_f != self.eventsFound:
			self.calculateWindow()

		self.__text_height = self.calculateTxtHeight()


#		print self.txt + RET + self.txtExtra

	# TODO: should return the height of events list text (self. 
	def calculateTxtHeight(self):
		"""should return the height of events list text"""
#		print "*** Running calculateTxtHeight"
		
		if not self.window.window:
			return

		RET = self.ret.decode("string_escape")

		if self.__events_test_buffer == None:
			self.__events_test_buffer = gtk.gdk.Pixmap(self.window.window, self.eventsWidth, 5000, -1)

		buffer = self.__events_test_buffer

		if self.__events_test_ctx == None:
			text_ctx = __events_test_ctx = buffer.cairo_create()
			text_ctx.rectangle(0,0,self.eventsWidth,5000)
			text_ctx.clip()
			text_ctx.set_operator(cairo.OPERATOR_OVER)
		else:
			text_ctx = __events_test_ctx

		if self.__events_test_layout == None:
			p_layout = self.__events_test_layout = text_ctx.create_layout()
		else:
			text_ctx.update_layout(self.__events_test_layout)
			p_layout = self.__events_test_layout

		text_ctx.set_source_rgba(self.rgba_color[0], self.rgba_color[1], self.rgba_color[2], self.rgba_color[3])
		self.draw_text(text_ctx, self.txt + RET + self.txtExtra, 0, 0, self.text_font , 9, self.eventsWidth, pango.ALIGN_LEFT, ellipsize=pango.ELLIPSIZE_NONE, tabs = self.tabs)

		extents, lextents = self.p_layout.get_pixel_extents()

		return extents[3]




	def on_draw_shape (self, ctx):
		"""on draw shape"""
		self.on_draw(ctx)




	def drawEvents (self, ctx):
		"""Draws the event list"""


#		if not self.window.window:
#			return

		RET = self.ret.decode("string_escape")

# TODO: i believe it should create new objects only when it's resized!!!!!!!!!!!!!

#		if self.__events_buffer == None:
		self.__events_buffer = gtk.gdk.Pixmap(self.window.window, self.eventsWidth, self.__text_height, -1)

		buffer = self.__events_buffer

#		if self.__events_ctx == None:

		text_ctx = __events_ctx = buffer.cairo_create()
		text_ctx.rectangle(0,0,self.eventsWidth, self.__text_height)
		text_ctx.clip()
		text_ctx.set_operator(cairo.OPERATOR_OVER)

#		else:
#			text_ctx = __events_ctx

		self.clear_cairo_context(text_ctx)

#		if self.__events_layout == None:
#			p_layout = self.__events_layout = text_ctx.create_layout()
#		else:
#			text_ctx.update_layout(self.__events_layout)
#			p_layout = self.__events_layout

		text_ctx.set_source_rgba(self.rgba_color[0], self.rgba_color[1], self.rgba_color[2], self.rgba_color[3])
		self.draw_text(text_ctx, self.txt + RET + self.txtExtra, 0, 0, self.text_font , 9, self.eventsWidth, pango.ALIGN_LEFT, ellipsize=pango.ELLIPSIZE_NONE, tabs = self.tabs)

		ctx.save()
		ctx.set_operator(cairo.OPERATOR_OVER)
		ctx.set_source_pixmap(buffer, self.xpos(), self.padding -self.scroll_offset)
		ctx.rectangle(self.xpos(),self.padding, self.eventsWidth, self.eventsHeight)
		ctx.clip()
		ctx.paint()
		ctx.restore()



	def drawDate (self, ctx, date):
		"""Draws the date"""

		ctx.set_source_rgba(self.date_month_color[0], self.date_month_color[1], self.date_month_color[2], self.date_month_color[3])
		self.draw_text(ctx, str(date[2]) + ' ' + str(date[1]), self.padding, self.padding + self.dateHeight*self.date_month_year_pos, self.date_month_year_font, 10, self.dateWidth,pango.ALIGN_CENTER)
		ctx.set_source_rgba(self.date_day_color[0], self.date_day_color[1], self.date_day_color[2], self.date_day_color[3])
		self.draw_text(ctx, str(date[0]), self.padding, self.padding + self.dateHeight*self.date_big_pos, self.date_big_font, 54, self.dateWidth,pango.ALIGN_CENTER)
		ctx.set_source_rgba(self.date_weekday_color[0], self.date_weekday_color[1], self.date_weekday_color[2], self.date_weekday_color[3])
		self.draw_text(ctx, str(date[5]), self.padding, self.padding + self.dateHeight*self.date_weekday_pos, self.date_weekday_font , 10, self.dateWidth ,pango.ALIGN_CENTER)

	def checkConnected(self):
		"""Check the internet connection"""
		print "Checking the Internet connection"
		try:
			# Check the connection by opening a socket to a URL
			connection = urllib.urlopen('http://www.google.com/robots.txt')
			# Connected successfully so close the socket
			connection.close()
			self.__connected = True
			return True
		except Exception:
			# We are not connected
			self.__connected = False
			return False
		
	def loginGAccount(self):
		"""Logs into Google account"""
		if self.__connected == True:

			try:
				self.__cal_client = gdata.calendar.service.CalendarService()
				self.__cal_client.email = self.loginCredentials[0]
				self.__cal_client.password = self.loginCredentials[1]
				self.__cal_client.source = 'gCal_Screenlet-' + self.__version__
				self.__cal_client.ProgrammaticLogin()
				print 'Valid Programmatic login'
				self.good_login = True
				return True
			except Exception:
				self.good_login = False
				if len(self.loginCredentials[0]) > 0:
					self.__notifier.notify(_("Invalid login, check username and password."))
				return False

	def date_internet(date):
		d = date.strftime('%Y-%m-%dT%H:%M:%S%z')
		return d[:-2] + ':' + d[-2:]


	def draw_text(self, ctx, text, x, y,  font, size, width, allignment=pango.ALIGN_LEFT,alignment=None,justify = False,weight = 0, ellipsize = pango.ELLIPSIZE_NONE, tabs= []):
		"""Draws text"""
		ctx.save()
		ctx.translate(x, y)
		if self.p_layout == None :
	
			self.p_layout = ctx.create_layout()
		else:
			
			ctx.update_layout(self.p_layout)
		self.p_fdesc = pango.FontDescription(font)
#		self.p_fdesc.set_family_static(font)
#		self.p_fdesc.set_size(size * pango.SCALE)
#		self.p_fdesc.set_weight(weight)
		self.p_layout.set_font_description(self.p_fdesc)
		self.p_layout.set_width(width * pango.SCALE)
		self.p_layout.set_alignment(allignment)
		if alignment != None:self.p_layout.set_alignment(alignment)
		self.p_layout.set_justify(justify)
		self.p_layout.set_ellipsize(ellipsize)

		tabarray = self.p_layout.get_tabs()
		if tabarray is None:
			tabarray = pango.TabArray(len(tabs), True)
		if tabarray.get_size() < len(tabs):
			tabarray.resize(len(tabs))
		for i in range(0, len(tabs)):
			tabarray.set_tab(i, pango.TAB_LEFT, int(tabs[i]))
#			print i, int(tabs[i])
		self.p_layout.set_tabs(tabarray)

		self.p_layout.set_markup(text)

#		print text

		ctx.show_layout(self.p_layout)
		ctx.restore()


	def retrieveEventsOnAllCalendars(self):
		if not self.retrieving:
			self.retrieving = True
			threading.Thread(target=self.__retrieveEventsOnAllCalendars).start()

	def __retrieveEventsOnAllCalendars(self):
 		"""Retrieves the list of calendars to which the authenticated user either
		owns or subscribes to.  This is the same list as is represented in the 
		Google Calendar GUI.  Although we are only printing the title of the 
		calendar in this case, other information, including the color of the
		calendar, the timezone, and more.  See CalendarListEntry for more details
		on available attributes."""
		
		print "*** START RETRIEVE"
		
		err = False

		try:
			self.__lock.acquire()

			if self.__cal_client is None:
				print "No client"
				return


	 		if self.__connected:
				self.__calendarevents = [ ]

				sig = "+"
				if time.timezone >= 0:
					sig = "-"
				ttt = sig + string.zfill(abs(time.timezone/3600), 2) + ":" + string.zfill(abs(time.timezone/60)-abs(time.timezone/3600*60), 2)

				#start_date='2010-05-24T00:00:00+09:00', end_date='2010-05-24T23:59:59+09:00'
				__first_date_to_fetch = str(datetime.date.today())+"T00:00:00" + ttt
				__last_date_to_fetch = str(datetime.date.today() + datetime.timedelta(days=self.eventDaysToShow)) + "T23:59:59" + ttt

	#			from datetime import datetime

				todaysdate = datetime.datetime.now()
	
				start_datetime_fetch = datetime.datetime(todaysdate.year, todaysdate.month, todaysdate.day)

				print 'Fetching events in calendars from: %s to %s.' % (__first_date_to_fetch, __last_date_to_fetch,)
				all_calendars_feed = self.__cal_client.GetAllCalendarsFeed()
				print 'Printing allcalendars: %s' % all_calendars_feed.title.text
	#			for i, a_calendar in zip(xrange(len(all_calendars_feed.entry)), all_calendars_feed.entry):
	#				print '%s. %s' % (i, a_calendar.title.text,)
				
				#Now loop through all of the CalendarListEntry items.
				for (index, cal) in enumerate(all_calendars_feed.entry):
					print "----------------------------------"
					if (cal.hidden.value == "true"):
						print "Calendar %s is hidden. Events are not included." % (cal.title.text)
					else:
						#Print out the title and the summary if there is one
						if (cal.summary is not None):
							print "%d) %s - Summary: %s" % (index, cal.title.text, cal.summary.text)
						else:
							print "%d) %s" % (index, cal.title.text)
						#Print out the authors
						alreadyPrintedAuthor = False
						for author in cal.author:
							if (alreadyPrintedAuthor is True):
								print ", %s" % (author.name.text)
							else:
								print "  Author(s): %s" % (author.name.text)
						#Print out other information
						print "  PUB: %s | UPD: %s | TZ: %s" % (cal.published.text, cal.updated.text, cal.timezone.value)
						print "  CLR: %s | SEL: %s | ACS: %s" % (cal.color.value, cal.selected.value, cal.access_level.value)
						# Now Print out the events
#						print "  Events:"
						a_link = cal.GetAlternateLink()
						if (a_link is not None):
							#print "\tA link: %s" % (a_link)
							# See http://jebbeich.blogspot.com/search?updated-min=2009-01-01T00%3A00%3A00-08%3A00&updated-max=2010-01-01T00%3A00%3A00-08%3A00&max-results=6
							query = gdata.calendar.service.CalendarEventQuery('default', 'private', 'full')
							query.start_min = __first_date_to_fetch
							query.start_max = __last_date_to_fetch
							query.__dict__['feed'] = a_link.href
							query.max_results = 200 
							event_feed = self.__cal_client.CalendarQuery(query) 
							print 'Events on calendar: %s' % (event_feed.title.text,)
#							print 'Event feed entry\t%s' % (event_feed.entry,)
		    				for i, an_event in zip(xrange(len(event_feed.entry)), event_feed.entry):
								print '\t%s. %s %s' % (i, an_event.title.text, an_event.uid.value)
								__start_time = 0
								__end_time = 0
								#for p, a_participant in zip(xrange(len(an_event.who)), an_event.who):
									#print '\t\t%s. %s' % (p, a_participant.email,)
									#print '\t\t\t%s' % (a_participant.name,)
									#if a_participant.attendee_status:
										#print '\t\t\t%s' % (a_participant.attendee_status.value,)

								for a_when in an_event.when:
									# If the event is recurring, there may be several occurances here
									print '\t%s - %s' % (a_when.start_time, a_when.end_time)

									__start_time = a_when.start_time
									__end_time = a_when.end_time
									try:
										if __start_time[10:11] == "T":
											start_eventdate = datetime.datetime(*time.strptime(__start_time[:19], "%Y-%m-%dT%H:%M:%S")[0:5])
										else:
											start_eventdate = datetime.datetime(*time.strptime(__start_time[:10], "%Y-%m-%d")[0:5])
									except Exception:
										start_eventdate = datetime.datetime(2010, 1, 1)
										print '*** START DATE MISSING!'
									try:
										if __end_time[10:11] == "T":
											end_eventdate = datetime.datetime(*time.strptime(__end_time[:19], "%Y-%m-%dT%H:%M:%S")[0:5])
										else:
											end_eventdate = datetime.datetime(*time.strptime(__end_time[:10], "%Y-%m-%d")[0:5])
									except Exception:
										end_eventdate = datetime.datetime(2010, 1, 1)
										print '*** END DATE MISSING!'

									if start_eventdate < start_datetime_fetch:
										continue

									add_this_event = True

									# handles modifications of events (ex. when repeated event is modified for one occurrence)
									if len(self.__calendarevents) > 0:
										index = next((i for i in xrange(len(self.__calendarevents)) if self.__calendarevents[i]["googleid"] == an_event.uid.value and self.__calendarevents[i]["start_time"] == start_eventdate), None)
										if index is not None:
											an_id_event=self.__calendarevents[index]

											if an_event.updated >= an_id_event["updated"]:
												an_id_event.update([{"googleid": an_event.uid.value, "calenderid": i, "color": cal.color.value, "title": an_event.title.text, "content": an_event.content.text, "start_time": start_eventdate, "end_time": end_eventdate, "updated": an_event.updated.text}])
												print "\t\tEvent description updated"
											else:
												print "\t\tEvent skipped because a newer mod exists"

											add_this_event = False

									if add_this_event:
										self.__calendarevents.extend([{"googleid": an_event.uid.value, "calenderid": i, "color": cal.color.value, "title": an_event.title.text, "content": an_event.content.text, "start_time": start_eventdate, "end_time": end_eventdate, "updated": an_event.updated.text}])
										print "\t\tEvent added"

				self.__calendarevents.sort(key=itemgetter('start_time'), reverse=False)
				self.createEventList()

		except:
			traceback.print_exc()
			err = True
		finally:
			self.__lock.release()

		print "END RETRIEVE"
		
		# register that everything went fine for the next time
		if not err:

			if not self.__connected_prev:
 				if self.__timeout_net:
	 				gobject.source_remove(self.__timeout_net)
				self.__notifier.notify(_("Connected to internet and updating again."))
				self.__connected = True
				self.__connected_prev = self.__connected

			self.__update_prev = True
		else:
			if self.__update_prev and self.good_login:
				self.__notifier.notify(_("Update failed for some unknown reason."))

			self.__update_prev = False

			print "Update failed for some unknown reason."

		self.retrieving = False

		self.redraw_canvas()


# 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__":
	"""Starts the screenlet"""
	# create new session
	import screenlets.session
	screenlets.session.create_session(GoogleCalendarScreenlet, threading=True)
