import datetime
import gobject
from gettext import gettext as _
import logging
log = logging.getLogger("modules.Evolution")
import conduit
import conduit.dataproviders.DataProvider as DataProvider
import conduit.utils as Utils
import conduit.Exceptions as Exceptions
import conduit.datatypes.Contact as Contact
import conduit.datatypes.Event as Event
import conduit.datatypes.Note as Note
MODULES = {}
try:
import evolution
if evolution.__version__ >= (0,0,4):
MODULES = {
"EvoContactTwoWay" : { "type": "dataprovider" },
"EvoCalendarTwoWay" : { "type": "dataprovider" },
"EvoTasksTwoWay" : { "type": "dataprovider" },
"EvoMemoTwoWay" : { "type": "dataprovider" },
}
log.info("Module Information: %s" % Utils.get_module_information(evolution, '__version__'))
except ImportError:
log.info("Evolution support disabled")
class EvoBase(DataProvider.TwoWay):
_configurable_ = True
def __init__(self, sourceURI, *args):
DataProvider.TwoWay.__init__(self)
self.defaultSourceURI = sourceURI
self.selectedSourceURI = sourceURI
self.allSourceURIs = []
self.uids = None
def _get_object(self, uid):
raise NotImplementedError
def _create_object(self, obj):
raise NotImplementedError
def _update_object(self, uid, obj):
if self._delete_object(uid):
uid = self._create_object(obj)
return uid
else:
raise Exceptions.SyncronizeError("Error updating object (uid: %s)" % uid)
def _delete_object(self, uid):
raise NotImplementedError
def refresh(self):
DataProvider.TwoWay.refresh(self)
self.uids = []
def get_all(self):
DataProvider.TwoWay.get_all(self)
return self.uids
def get(self, LUID):
DataProvider.TwoWay.get(self, LUID)
return self._get_object(LUID)
def put(self, obj, overwrite, LUID=None):
DataProvider.TwoWay.put(self, obj, overwrite, LUID)
if LUID != None:
existing = self._get_object(LUID)
if existing != None:
if overwrite == True:
rid = self._update_object(LUID, obj)
return rid
else:
comp = obj.compare(existing)
if comp != conduit.datatypes.COMPARISON_NEWER:
raise Exceptions.SynchronizeConflictError(comp, existing, obj)
else:
rid = self._update_object(LUID, obj)
return rid
log.info("Creating new object")
rid = self._create_object(obj)
return rid
def delete(self, LUID):
if not self._delete_object(LUID):
log.warn("Error deleting event (uid: %s)" % LUID)
def finish(self, aborted, error, conflict):
DataProvider.TwoWay.finish(self)
self.uids = None
def configure(self, window, name):
import gtk
tree = Utils.dataprovider_glade_get_widget(
__file__,
"config.glade",
"EvolutionConfigDialog"
)
sourceComboBox = tree.get_widget("sourceComboBox")
sourceLabel = tree.get_widget("sourceLabel")
sourceLabel.set_text(_("Select %s:") % name)
store = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING)
sourceComboBox.set_model(store)
cell = gtk.CellRendererText()
sourceComboBox.pack_start(cell, True)
sourceComboBox.add_attribute(cell, 'text', 0)
sourceComboBox.set_active(0)
for name,uri in self.allSourceURIs:
rowref = store.append( (name, uri) )
if uri == self.selectedSourceURI:
sourceComboBox.set_active_iter(rowref)
dlg = tree.get_widget("EvolutionConfigDialog")
response = Utils.run_dialog (dlg, window)
if response == True:
self.selectedSourceURI = store.get_value(sourceComboBox.get_active_iter(), 1)
dlg.destroy()
def get_configuration(self):
return {
"sourceURI" : self.selectedSourceURI
}
def set_configuration(self, config):
self.selectedSourceURI = config.get("sourceURI", self.defaultSourceURI)
def get_UID(self):
return self.selectedSourceURI
class EvoContactTwoWay(EvoBase):
DEFAULT_ADDRESSBOOK_URI = "default"
_name_ = _("Evolution Contacts")
_description_ = _("Sync your contacts")
_category_ = conduit.dataproviders.CATEGORY_OFFICE
_module_type_ = "twoway"
_in_type_ = "contact"
_out_type_ = "contact"
_icon_ = "contact-new"
def __init__(self, *args):
EvoBase.__init__(self, EvoContactTwoWay.DEFAULT_ADDRESSBOOK_URI)
self.allSourceURIs = evolution.ebook.list_addressbooks()
def _get_object(self, LUID):
"""
Retrieve a specific contact object from evolution
"""
obj = self.book.get_contact(LUID)
contact = Contact.Contact()
contact.set_from_vcard_string(obj.get_vcard_string())
contact.set_UID(obj.get_uid())
contact.set_mtime(datetime.datetime.fromtimestamp(obj.get_modified()))
return contact
def _create_object(self, contact):
obj = evolution.ebook.EContact(vcard=contact.get_vcard_string())
if self.book.add_contact(obj):
return self._get_object(obj.get_uid()).get_rid()
else:
raise Exceptions.SyncronizeError("Error creating contact")
def _delete_object(self, uid):
try:
return self.book.remove_contact_by_id(uid)
except:
return False
def refresh(self):
EvoBase.refresh(self)
self.book = evolution.ebook.open_addressbook(self.selectedSourceURI)
for i in self.book.get_all_contacts():
self.uids.append(i.get_uid())
def configure(self, window):
EvoBase.configure(self, window, "Addressbook")
class EvoCalendarTwoWay(EvoBase):
DEFAULT_CALENDAR_URI = "default"
_name_ = _("Evolution Calendar")
_description_ = _("Sync your calendar")
_category_ = conduit.dataproviders.CATEGORY_OFFICE
_module_type_ = "twoway"
_in_type_ = "event"
_out_type_ = "event"
_icon_ = "appointment-new"
def __init__(self, *args):
EvoBase.__init__(self, EvoCalendarTwoWay.DEFAULT_CALENDAR_URI)
self.allSourceURIs = evolution.ecal.list_calendars()
def _get_object(self, LUID):
"""
Get an event from Evolution.
"""
raw = self.calendar.get_object(LUID, "")
event = Event.Event()
event.set_from_ical_string(self.calendar.get_object_as_string(raw))
event.set_UID(raw.get_uid())
event.set_mtime(datetime.datetime.fromtimestamp(raw.get_modified()))
return event
def _create_object(self, event):
if "UID" in [x.name for x in list(event.iCal.lines())]:
event.iCal.remove(event.iCal.uid)
obj = evolution.ecal.ECalComponent(evolution.ecal.CAL_COMPONENT_EVENT, event.get_ical_string())
if self.calendar.add_object(obj):
mtime = datetime.datetime.fromtimestamp(obj.get_modified())
return conduit.datatypes.Rid(uid=obj.get_uid(), mtime=mtime, hash=mtime)
else:
raise Exceptions.SyncronizeError("Error creating event")
def _delete_object(self, uid):
try:
return self.calendar.remove_object(self.calendar.get_object(uid, ""))
except:
return False
def refresh(self):
EvoBase.refresh(self)
self.calendar = evolution.ecal.open_calendar_source(
self.selectedSourceURI,
evolution.ecal.CAL_SOURCE_TYPE_EVENT
)
for i in self.calendar.get_all_objects():
self.uids.append(i.get_uid())
def configure(self, window):
EvoBase.configure(self, window, "Calendar")
class EvoTasksTwoWay(EvoBase):
DEFAULT_TASK_URI = "default"
_name_ = _("Evolution Tasks")
_description_ = _("Sync your tasks")
_category_ = conduit.dataproviders.CATEGORY_OFFICE
_module_type_ = "twoway"
_in_type_ = "event"
_out_type_ = "event"
_icon_ = "tomboy"
def __init__(self, *args):
EvoBase.__init__(self, EvoTasksTwoWay.DEFAULT_TASK_URI)
self.allSourceURIs = evolution.ecal.list_task_sources()
def _get_object(self, LUID):
raw = self.tasks.get_object(LUID, "")
task = Event.Event()
task.set_from_ical_string(raw.get_as_string())
task.set_UID(raw.get_uid())
task.set_mtime(datetime.datetime.fromtimestamp(raw.get_modified()))
return task
def _create_object(self, event):
if "UID" in [x.name for x in list(event.iCal.lines())]:
event.iCal.remove(event.iCal.uid)
obj = evolution.ecal.ECalComponent(
evolution.ecal.CAL_COMPONENT_TODO,
event.get_ical_string()
)
if self.tasks.add_object(obj):
mtime = datetime.datetime.fromtimestamp(obj.get_modified())
return conduit.datatypes.Rid(uid=obj.get_uid(), mtime=mtime, hash=mtime)
else:
raise Exceptions.SyncronizeError("Error creating event")
def _delete_object(self, uid):
try:
return self.tasks.remove_object(self.tasks.get_object(uid, ""))
except:
return False
def refresh(self):
EvoBase.refresh(self)
self.tasks = evolution.ecal.open_calendar_source(
self.selectedSourceURI,
evolution.ecal.CAL_SOURCE_TYPE_TODO
)
for i in self.tasks.get_all_objects():
self.uids.append(i.get_uid())
def configure(self, window):
EvoBase.configure(self, window, "Tasks")
class EvoMemoTwoWay(EvoBase):
DEFAULT_MEMO_URI = ""
_name_ = _("Evolution Memos")
_description_ = _("Sync your memos")
_category_ = conduit.dataproviders.CATEGORY_OFFICE
_module_type_ = "twoway"
_in_type_ = "note"
_out_type_ = "note"
_icon_ = "tomboy"
def __init__(self, *args):
EvoBase.__init__(self, EvoMemoTwoWay.DEFAULT_MEMO_URI)
self.allSourceURIs = evolution.ecal.list_memo_sources()
def _get_object(self, LUID):
"""
Retrieve a specific contact object from evolution
FIXME: In 0.5 this will replace get(...)
"""
obj = self.memos.get_object(LUID, "")
mtime = datetime.datetime.fromtimestamp(obj.get_modified())
note = Note.Note(
title=obj.get_summary(),
mtime=mtime,
contents=obj.get_description()
)
if note.contents == None:
note.contents = ""
note.set_UID(obj.get_uid())
note.set_mtime(mtime)
print note.get_note_string()
return note
def _create_object(self, note):
obj = evolution.ecal.ECalComponent(evolution.ecal.CAL_COMPONENT_JOURNAL)
obj.set_summary(note.title)
if note.contents != None:
obj.set_description(note.contents)
uid = self.memos.add_object(obj)
if uid != None:
mtime = datetime.datetime.fromtimestamp(obj.get_modified())
return conduit.datatypes.Rid(uid=uid, mtime=mtime, hash=mtime)
else:
raise Exceptions.SyncronizeError("Error creating memo")
def _delete_object(self, uid):
try:
return self.memos.remove_object(self.memos.get_object(uid, ""))
except:
return False
def refresh(self):
EvoBase.refresh(self)
self.memos = evolution.ecal.open_calendar_source(
self.selectedSourceURI,
evolution.ecal.CAL_SOURCE_TYPE_JOURNAL
)
for i in self.memos.get_all_objects():
self.uids.append(i.get_uid())
def configure(self, window):
EvoBase.configure(self, window, "Memos")