diff -uprN hamster-applet-2.24.1/hamster/gcal.py hamster-gcal-applet-2.24.1/hamster/gcal.py
--- hamster-applet-2.24.1/hamster/gcal.py	1970-01-01 03:00:00.000000000 +0300
+++ hamster-gcal-applet-2.24.1/hamster/gcal.py	2008-11-24 18:58:31.000000000 +0300
@@ -0,0 +1,429 @@
+# - coding: utf-8 -
+
+# Copyright (C) 2007, 2008 Toms Bauģis <toms.baugis at gmail.com>
+# Copyright (C) 2007 Patryk Zawadzki <patrys at pld-linux.org>
+
+# This file is part of Project Hamster.
+
+# Project Hamster 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.
+
+# Project Hamster 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 Project Hamster.  If not, see <http://www.gnu.org/licenses/>.
+
+try:
+  from xml.etree import ElementTree
+except ImportError:
+  from elementtree import ElementTree
+
+import os, time
+import datetime
+import calendar
+import hamster
+import hamster.storage
+import datetime as dt
+
+import gdata.calendar.service
+import gdata.service
+import atom.service
+import gdata.calendar
+import atom
+import xml.utils.iso8601
+
+#http://code.google.com/apis/calendar/docs/1.0/developers_guide_python.html#
+# http://calendar.google.com
+#	--> Settings --> Calendars --> Select One/Or create it --> Calendar Address: Calendar ID
+CAL_ID = ""
+USERNAME = "" # Google Acount ID, usually mail
+PASSWORD = "" # Password for your Google Account
+
+TIMEFORMAT = "%Y-%m-%dT%H:%M:%S.000Z"
+
+def dt_to_loc(dt):
+	secs = calendar.timegm(dt.timetuple())
+	return time.localtime(secs)
+
+def dt_to_utc(dt):
+	secs = time.mktime(dt.timetuple())
+	return time.gmtime(secs)
+
+def iso8601_to_loc(iso_str):
+	sec = xml.utils.iso8601.parse(iso_str)
+	return datetime.datetime.fromtimestamp(sec)
+
+def dt_to_iso8601(dt):
+	utc = dt_to_utc(dt)
+	return time.strftime(TIMEFORMAT, utc)
+
+
+class Storage(hamster.storage.Storage):
+	con = None # Connection will be created on demand
+	fid_hashtable = {}
+	aid_hashtable = {}
+
+	def cal_uri(self):
+		return "/calendar/feeds/" + CAL_ID + "/private/full"
+
+	def event_when_to_datetime(self, when_list):
+		""" Convert Event When field to datetime value """
+
+		if len(when_list) == 0:
+			return (None, None)
+
+		wn = when_list[0]
+		start_time = iso8601_to_loc(wn.start_time)
+		end_time = iso8601_to_loc(wn.end_time)
+		return (start_time, end_time)
+
+	def event_to_fact(self, event):
+		""" Convert Google Calendar Event to Hamster Fact """
+
+		eid = event.id.text
+		if self.fid_hashtable.has_key(eid):
+			fid = self.fid_hashtable[eid]
+		else:
+			fid = len(self.fid_hashtable) + 1
+			self.fid_hashtable[eid] = fid
+
+		start_time, end_time = self.event_when_to_datetime(event.when)
+
+		if not self.is_event_finished(event):
+			end_time = None
+
+		fact = {
+			"id" : fid,
+			"name" : event.title.text,
+			"start_time" : start_time,
+			"end_time" : end_time,
+			"category" : 2,
+			"eid" : eid,
+		}
+		return fact
+
+	def event_to_activity(self, event):
+
+		eid = event.id.text
+		if self.aid_hashtable.has_key(eid):
+			aid = self.aid_hashtable[eid]
+		else:
+			aid = len(self.aid_hashtable) + 1
+			self.aid_hashtable[eid] = aid
+
+		start_time, end_time = self.event_when_to_datetime(event.when)
+
+		act = {
+			"id" : aid,
+			"name" : event.title.text,
+			"activity_order" : 1,
+			"category_id" : 2,
+			"start_time" : start_time,
+			"end_time" : end_time,
+			"eid" : eid,
+		}
+		return act
+
+	def __get_category_list(self):
+		c = {
+			"id" : 2,
+			"name" : "domain",
+			"category_order" : 1,
+			"color_code" : "#00FF00",
+		}
+		return (c, )
+
+	def __change_category(self, id, category_id):
+		print "Category changed to", category_id
+
+	def __insert_category(self, name):
+		print "Insert new category:", name
+		return 1
+
+	def __update_category(self, id,  name):
+		print "Update category:", name
+
+	def __move_activity(self, source_id, target_order, insert_after = True):
+		print "Move activity:", source_id
+
+	def __get_activity_by_name(self, name):
+		events = self.get_all_events()
+		for e in events:
+			if name.lover() == e.title.text.lower():
+				return e.id.text
+		return None
+
+	def __get_fact(self, fact_id):
+		event = self.get_event_by_id(fact_id)
+		if event != None:
+			fact = self.event_to_fact(event)
+			return fact
+		return None
+
+	def __get_last_activity(self):
+		last_a = None
+		events = self.get_all_events()
+		if len(events) != 0:
+			e = events[0]
+			last_a = self.event_to_activity(e)
+		return last_a
+
+	def __touch_fact(self, fact, end_time):
+		# tasks under five minutes do not count
+		if end_time - fact['start_time'] < datetime.timedelta(minutes = 5):
+			self.__remove_fact(fact['eid'])
+		else:
+			self.set_event_time(fact['eid'], end_time = end_time)
+
+	def __add_fact(self, activity_name, start_time = None, end_time = None):
+		start_time = start_time or datetime.datetime.now()
+
+		# now fetch facts for the specified day and check if we have to
+		# split or change span 
+		day_facts = self.__get_facts(start_time.date())
+		for fact in day_facts:
+			# first check if maybe we are overlapping end
+			if fact['end_time'] and fact['start_time'] < start_time < fact['end_time']:
+				#set fact's end time to our start one
+				self.set_event_time(fact["eid"], end_time = start_time)
+
+				# now check - maybe we are inside the fact. in that case
+				# we should create another task after our one
+				if end_time and end_time < fact['end_time']:
+					self.__add_fact(fact['name'], end_time, fact['end_time'])
+
+			else: #end's fine? what about start then?
+				if fact['end_time'] and end_time and fact['start_time'] < end_time < fact['end_time'] \
+					or not fact['end_time'] and end_time and fact['start_time'] < end_time: # case for the entry before the last one
+					#set fact's start time to our end one
+					self.set_event_time(fact["eid"], start_time = end_time)
+
+		# now check if maybe we are at the last task, and if that's true
+		# look if we maybe have to finish it or delete if it was too short
+		if day_facts:
+			last_fact = day_facts[0]
+
+			if last_fact['end_time'] == None and start_time > last_fact['start_time']:
+				delta = (start_time - last_fact['start_time'])
+
+				if 60 >= delta.seconds >= 0:
+					self.__remove_fact(last_fact['eid'])
+					start_time = last_fact['start_time']
+
+					# go further now and check, maybe task before the last one
+					# is the same we have now. If that happened before less
+					# than a minute - remove end time!
+					if len(day_facts) > 2 and day_facts[-2]['name'] == activity_name:
+						print day_facts[-2]['name'], activity_name, day_facts[-2]['end_time'], start_time
+						delta = (start_time - day_facts[-2]['end_time'])
+						if 60 >= delta.seconds >= 0:
+							self.set_event_state(fact["eid"], False)
+							return day_facts[-2]
+					else:
+						#set previous fact end time
+						self.set_event_time(fact["eid"], end_time = start_time)
+
+        # finally add the new entry
+		new_event = self.insert_event(activity_name, start_time, end_time)
+		fact = self.event_to_fact(new_event)
+		return fact
+
+	def __get_facts(self, date, end_date = None):
+		print "Get facts..."
+		end_date = end_date or (date + dt.timedelta(days=1))
+		events = self.get_events_range(date, end_date)
+		print "...found", len(events)
+		facts = []
+		for e in events:
+			f = self.event_to_fact(e)
+			facts.append(f)
+		facts.reverse()
+		return facts
+
+	def __remove_fact(self, event_id):
+		print "Remove fact:", event_id
+		self.remove_event(event_id)
+
+	def __get_sorted_activities(self):
+		print "Get sorted activities..."
+		return self.__get_activities()
+
+	def __get_activities(self, category_id = None):
+		print "Get activities..."
+		events = self.get_all_events()
+		a_list = []
+		for e in events:
+			a = self.event_to_activity(e)
+			a_list.append(a)
+		return a_list
+
+	def __remove_activity(self, id):
+		""" check if we have any facts with this activity and behave accordingly
+			if there are facts - sets activity to deleted = True
+			else, just remove it"""
+		print "Remove activity:", id
+
+	def __remove_category(self, id):
+		"""move all activities to unsorted and remove category"""
+		print "Remove catecory:", id
+
+	def __swap_activities(self, id1, id2):
+		""" swaps nearby activities """
+		print "Swap activities..."
+
+	def __insert_activity(self, name, category_id = -1):
+		print "Insert activity...", name
+		return 2
+
+	def __update_activity(self, id, name, category_id):
+		print "Update activity...", name
+
+	def insert_event(self, title, start_time, end_time = None):
+		""" Added Event to Google Calendar """
+
+		event = gdata.calendar.CalendarEventEntry()
+		event.title = atom.Title(text=title)
+
+		#If Event is running then mark it
+		if end_time == None:
+			end_time = (start_time + dt.timedelta(minutes=5))
+			event.extended_property.append(gdata.calendar.ExtendedProperty(name="finished", value="false"))
+
+		s = dt_to_iso8601(start_time)
+		e = dt_to_iso8601(end_time)
+		w = gdata.calendar.When(start_time=s, end_time=e)
+		event.when.append(w)
+
+		print "Added event: %s (%s - %s)" % (title, s, e)
+		new_event = self.connection.InsertEvent(event, self.cal_uri())
+		return new_event
+
+	def remove_event(self, ev_id):
+		""" Remove Event from Google Calendar """
+
+		event = self.get_event_by_id(ev_id)
+		if event == None:
+			print "Warning: Event no found!"
+			return
+
+		print "Removing event from Calendar..."
+		self.connection.DeleteEvent(event.GetEditLink().href)
+
+	def __set_event_state(self, event, state):
+		""" Mark Event as Finished or not """
+
+		found = False
+		if event.extended_property:
+			for num, p in enumerate(event.extended_property):
+				if p.name == "finished":
+					found = True
+					p.value = state
+		if not found:
+			event.extended_property.append(gdata.calendar.ExtendedProperty(name="finished", value=state))
+
+	def set_event_state(self, ev_id, state):
+		""" state = True = Finished """
+
+		event = self.get_event_by_id(ev_id)
+		if event == None:
+			print "Warning: Event not found!"
+			return
+
+		bool_str = state and "true" or "false"
+		self.__set_event_state(event, bool_str)
+
+		self.connection.UpdateEvent(event.GetEditLink().href, event)
+
+	def set_event_time(self, ev_id, start_time = None, end_time = None):
+		""" Adjust start_time or end_time of Event and apply to Google Calendar """
+
+		if start_time == end_time:
+			print "Warning: Times is equals!" 
+			return
+
+		time_val = start_time or end_time
+		time_str = dt_to_iso8601(time_val)
+		print "Adjust Event time to:", time_str
+
+		event = self.get_event_by_id(ev_id)
+		if event == None:
+			print "Warning: Event not found!"
+			return
+
+		if start_time is not None:
+			event.when[0].start_time = time_str
+		else:
+			event.when[0].end_time = time_str
+			self.__set_event_state(event, "true")
+
+		print "Updating event..."
+		self.connection.UpdateEvent(event.GetEditLink().href, event)
+
+	def is_event_finished(self, event):
+		""" Return state(running, finished) of event """
+
+		retval = True
+		if event.extended_property:
+			for num, p in enumerate(event.extended_property):
+				if p.name == "finished":
+					retval = (p.value == "true")
+					break
+		return retval
+
+	def get_event_by_id(self, ev_id):
+		""" Find Event in Calendar by ID """
+
+		events = self.get_all_events()
+		for e in events:
+			if ev_id == e.id.text:
+				return e
+		return None
+
+	def get_all_events(self):
+		""" Return list of all events from Google Calendar """
+
+		feed = self.connection.GetCalendarEventFeed(self.cal_uri())
+		if feed == None:
+			print "Warning: Calendar nof found!"
+		else:
+			events = [ x for i, x in enumerate(feed.entry) ]
+			return events
+		return []
+
+	def get_events_range(self, start_date, end_date):
+		""" Return list of all event in range[star_date, end_date) """
+
+		start_date_s = start_date.strftime("%Y-%m-%d")
+		end_date_s = end_date.strftime('%Y-%m-%d')
+
+		events = []
+		query = gdata.calendar.service.CalendarEventQuery(CAL_ID, 'private', 'full')
+		query.start_min = start_date_s
+		query.start_max = end_date_s
+		feed = self.connection.CalendarQuery(query)
+		if feed == None:
+			print "Warning: Calendar nof found!"
+		else:
+			events = [ x for i, x in enumerate(feed.entry) ]
+		return events
+
+	def get_connection(self):
+		if self.con == None:
+			self.con = gdata.calendar.service.CalendarService()
+			self.con.source = 'Hamster-Applet-GCal-1.0'
+			self.con.email = USERNAME
+			self.con.password = PASSWORD
+			try:
+				print "Create conection..."
+				self.con.ProgrammaticLogin()
+			except gdata.service.BadAuthentication, e:
+				print "Error:", e
+		return self.con
+
+	connection = property(get_connection, None)
+
diff -uprN hamster-applet-2.24.1/hamster/__init__.py hamster-gcal-applet-2.24.1/hamster/__init__.py
--- hamster-applet-2.24.1/hamster/__init__.py	2008-10-20 13:38:33.000000000 +0400
+++ hamster-gcal-applet-2.24.1/hamster/__init__.py	2008-11-24 15:35:37.000000000 +0300
@@ -30,7 +30,8 @@ import gettext
 import locale
 
 # Autotools set the actual data_dir in defs.py
-from db import Storage
+#from db import Storage
+from gcal import Storage
 from defs import *
 from dispatcher import Dispatcher
 
diff -uprN hamster-applet-2.24.1/hamster/Makefile.in hamster-gcal-applet-2.24.1/hamster/Makefile.in
--- hamster-applet-2.24.1/hamster/Makefile.in	2008-10-20 13:50:16.000000000 +0400
+++ hamster-gcal-applet-2.24.1/hamster/Makefile.in	2008-11-21 16:55:04.000000000 +0300
@@ -260,6 +260,7 @@ hamster_PYTHON = \
 	dispatcher.py \
 	storage.py \
 	db.py \
+	gcal.py \
 	eds.py \
 	stats.py \
 	reports.py \
