diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index 241a36b1051..27b68003aa2 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -1500,6 +1500,7 @@ true, it will allow you to hide the event alarm information without removing it. @param context: A standard dictionary for contextual values @return: List of Dictionary of form [{‘name_of_the_field’: value, ...}, ...] """ + # FIXME This whole id mangling has to go! if not context: context = {} diff --git a/addons/caldav/caldav.py b/addons/caldav/caldav.py index f760421dfe5..3aa5dfd14dc 100644 --- a/addons/caldav/caldav.py +++ b/addons/caldav/caldav.py @@ -26,15 +26,16 @@ import urlparse urlparse.uses_netloc.append('caldav') urlparse.uses_netloc.append('caldavs') super_mk_prop_response = webdav.mk_prop_response -def mk_prop_response(self,uri,good_props,bad_props,doc): - res = super_mk_prop_response(self, uri,good_props,bad_props,doc) - uris = uri.split('/') - calendar = False + +def mk_prop_response(self,uri,good_props,bad_props,doc): + res = super_mk_prop_response(self, uri,good_props,bad_props,doc) + uris = uri.split('/') + calendar = False if 'http://calendarserver.org/ns/' in good_props or 'http://calendarserver.org/ns/' in bad_props: calendar = True if calendar: ad = doc.createElement('calendar') - ad.setAttribute('xmlns', 'urn:ietf:params:xml:ns:caldav') + ad.setAttribute('xmlns', 'urn:ietf:params:xml:ns:caldav') cols = res.getElementsByTagName('D:collection') if cols: cols[0].parentNode.appendChild(ad) diff --git a/addons/caldav/caldav_data.xml b/addons/caldav/caldav_data.xml index e2ae6624979..2394c95d272 100644 --- a/addons/caldav/caldav_data.xml +++ b/addons/caldav/caldav_data.xml @@ -1,385 +1,390 @@ - + Calendars True - + - - comment - vevent - + + comment + vevent + - organizer - vevent - - - - uid - vevent - - - - seq - vevent - - - - recurrence-id - vevent - - - - transp - vevent - - - - attendee - vevent - - - - related - vevent - - - - rrule - vevent - - - - dtend - vevent - - - - valarm - vevent - - - - vtimezone - vevent - - - - priority - vevent - - - - location - vevent - - - - exrule - vevent - - - - resources - vevent - - - - rstatus - vevent - - - - status - vevent - - - - exdate - vevent - - - - dtstamp - vevent - - - - description - vevent - - - - rdate - vevent - - - - dtstart - vevent - - - - class - vevent - - - - x-openobject-model - vevent - - - - created - vevent - - - - url - vevent - - - - summary - vevent - - - - contact - vevent - - - - - - - status - vtodo - - - - comment - vtodo - - - - attendee - vtodo - - - - valarm - vtodo - - - - description - vtodo - - - - seq - vtodo - - - - vtimezone - vtodo - - - - url - vtodo - - - - completed - vtodo - - - - percent - vtodo - - - - due - vtodo - - - - summary - vtodo - - - - priority - vtodo - - - - exdate - vtodo - - - - location - vtodo - - - - exrule - vtodo - - - - duration - vtodo - - - - organizer - vtodo - - - - dtstart - vtodo - - - - rrule - vtodo - - - - class - vtodo - - - - uid - vtodo - - - - - - cn - attendee - - - - sent-by - attendee - - - - language - attendee - - - - delegated-from - attendee - - - - member - attendee - - - - cutype - attendee - - - - role - attendee - - - - partstat - attendee - - - - delegated-to - attendee - - - - dir - attendee - - - - rsvp - attendee - - - - - - attendee - alarm - - - - trigger_duration - alarm - - - - description - alarm - - - - attach - alarm - - - - trigger_occurs - alarm - - - - trigger_interval - alarm - - - - summary - alarm - - - - duration - alarm - - - - repeat - alarm - - - - action - alarm - - - - trigger_related - alarm - - - + organizer + vevent + + + + uid + vevent + + + + seq + vevent + + + + recurrence-id + vevent + + + + transp + vevent + + + + attendee + vevent + + + + related + vevent + + + + rrule + vevent + + + + dtend + vevent + + + + duration + vevent + + + + valarm + vevent + + + + vtimezone + vevent + + + + priority + vevent + + + + location + vevent + + + + exrule + vevent + + + + resources + vevent + + + + rstatus + vevent + + + + status + vevent + + + + exdate + vevent + + + + dtstamp + vevent + + + + description + vevent + + + + rdate + vevent + + + + dtstart + vevent + + + + class + vevent + + + + x-openobject-model + vevent + + + + created + vevent + + + + url + vevent + + + + summary + vevent + + + + contact + vevent + + + + + + + status + vtodo + + + + comment + vtodo + + + + attendee + vtodo + + + + valarm + vtodo + + + + description + vtodo + + + + sequence + vtodo + + + + vtimezone + vtodo + + + + url + vtodo + + + + completed + vtodo + + + + percent-complete + vtodo + + + + due + vtodo + + + + summary + vtodo + + + + priority + vtodo + + + + exdate + vtodo + + + + location + vtodo + + + + exrule + vtodo + + + + duration + vtodo + + + + organizer + vtodo + + + + dtstart + vtodo + + + + rrule + vtodo + + + + class + vtodo + + + + uid + vtodo + + + + + + cn + attendee + + + + sent-by + attendee + + + + language + attendee + + + + delegated-from + attendee + + + + member + attendee + + + + cutype + attendee + + + + role + attendee + + + + partstat + attendee + + + + delegated-to + attendee + + + + dir + attendee + + + + rsvp + attendee + + + + + + attendee + alarm + + + + trigger_duration + alarm + + + + description + alarm + + + + attach + alarm + + + + trigger_occurs + alarm + + + + trigger_interval + alarm + + + + summary + alarm + + + + duration + alarm + + + + repeat + alarm + + + + action + alarm + + + + trigger_related + alarm + + + diff --git a/addons/caldav/caldav_node.py b/addons/caldav/caldav_node.py index 8ec7422a045..3ae37ea3e7e 100644 --- a/addons/caldav/caldav_node.py +++ b/addons/caldav/caldav_node.py @@ -24,7 +24,6 @@ from tools.translate import _ import pooler import tools import time -import base64 from document import nodes import StringIO @@ -38,78 +37,48 @@ class node_database(nodes.node_database): domain = [] domain2 = domain + [('calendar_collection','=', False)] res = super(node_database, self)._child_get(cr, name=name, parent_id=parent_id, domain=domain2) - where = [('parent_id','=',parent_id)] - domain2 = domain + [('calendar_collection','=', True)] + where = [('parent_id','=',parent_id)] + domain2 = domain + [('calendar_collection','=', True)] if name: where.append(('name','=',name)) if domain2: where += domain2 where2 = where + [('type', '=', 'directory')] - ids = dirobj.search(cr, uid, where2, context=ctx) - for dirr in dirobj.browse(cr,uid,ids,context=ctx): + ids = dirobj.search(cr, uid, where2, context=ctx) + for dirr in dirobj.browse(cr,uid,ids,context=ctx): res.append(node_calendar_collection(dirr.name,self,self.context,dirr)) return res -class node_calendar_collection(nodes.node_dir): - PROPS = { - "http://calendarserver.org/ns/" : ('getctag'), - } - M_NS = { +class node_calendar_collection(nodes.node_dir): + DAV_PROPS = { + "http://calendarserver.org/ns/" : ('getctag',), + } + DAV_M_NS = { "http://calendarserver.org/ns/" : '_get_dav', - } + } - - def get_dav_props(self, cr): - return self.PROPS - - - - def get_dav_eprop(self,cr, ns, propname): - if self.M_NS.has_key(ns): - prefix = self.M_NS[ns] - else: - print "No namespace:",ns, "( for prop:", propname,")" - return None - - mname = prefix + "_" + propname - - if not hasattr(self, mname): - return None - - try: - m = getattr(self, mname) - r = m(cr) - return r - except AttributeError, e: - print 'Property %s not supported' % propname - print "Exception:", e - return None + http_options = { 'DAV': ['calendar-access'] } def _file_get(self,cr, nodename=False): return [] - - - - def _child_get(self, cr, name=False, parent_id=False, domain=None): + def _child_get(self, cr, name=False, parent_id=False, domain=None): dirobj = self.context._dirobj uid = self.context.uid ctx = self.context.context.copy() ctx.update(self.dctx) - where = [('collection_id','=',self.dir_id)] - ext = False - if name: - res = name.split('.ics') - if len(res) > 1: - name = res[0] - ext = '.ics' - if name: + where = [('collection_id','=',self.dir_id)] + ext = False + if name and name.endswith('.ics'): + name = name[-4] + ext = '.ics' + if name: where.append(('name','=',name)) if not domain: - domain = [] + domain = [] where = where + domain - fil_obj = dirobj.pool.get('basic.calendar') + fil_obj = dirobj.pool.get('basic.calendar') ids = fil_obj.search(cr,uid,where,context=ctx) res = [] for calender in fil_obj.browse(cr, uid, ids, context=ctx): @@ -120,34 +89,21 @@ class node_calendar_collection(nodes.node_dir): return res def _get_dav_owner(self, cr): + # Todo? return False - - def get_etag(self, cr): - """ Get a tag, unique per object + modification. - - see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """ - return self._get_ttag(cr) + ':' + self._get_wtag(cr) - - def _get_wtag(self, cr): - """ Return the modification time as a unique, compact string """ - if self.write_date: - wtime = time.mktime(time.strptime(self.write_date, '%Y-%m-%d %H:%M:%S')) - else: wtime = time.time() - return str(wtime) - def _get_ttag(self, cr): - return 'calendar collection-%d' % self.dir_id + return 'calen-dir-%d' % self.dir_id def _get_dav_getctag(self, cr): - result = self.get_etag(cr) - return str(result) - + result = self.get_etag(cr) + return str(result) -class node_calendar(nodes.node_class): - our_type = 'collection' - PROPS = { - "http://calendarserver.org/ns/" : ('getctag'), +class node_calendar(nodes.node_class): + our_type = 'collection' + DAV_PROPS = { + "http://calendarserver.org/ns/" : ('getctag',), + 'http://groupdav.org/': ('resourcetype',), "urn:ietf:params:xml:ns:caldav" : ( 'calendar-description', 'calendar-data', @@ -155,10 +111,13 @@ class node_calendar(nodes.node_class): 'calendar-user-address-set', 'schedule-inbox-URL', 'schedule-outbox-URL',)} - M_NS = { - "DAV:" : '_get_dav', + DAV_M_NS = { + "DAV:" : '_get_dav', + 'http://groupdav.org/': '_get_gdav', "http://calendarserver.org/ns/" : '_get_dav', - "urn:ietf:params:xml:ns:caldav" : '_get_caldav'} + "urn:ietf:params:xml:ns:caldav" : '_get_caldav'} + + http_options = { 'DAV': ['calendar-access'] } def __init__(self,path, parent, context, calendar): super(node_calendar,self).__init__(path, parent,context) @@ -170,45 +129,49 @@ class node_calendar(nodes.node_class): self.displayname = calendar.name self.cal_type = calendar.type - def _get_dav_getctag(self, cr): + def _get_dav_getctag(self, cr): result = self._get_ttag(cr) + ':' + str(time.time()) - return str(result) + return str(result) - def match_dav_eprop(self, cr, match, ns, prop): + def _get_gdav_resourcetype(self, cr): + return (str(self.cal_type + '-collection'), 'http://groupdav.org/') + + def removeme_match_dav_eprop(self, cr, match, ns, prop): + # Why? if ns == "DAV:" and prop == "getetag": dirobj = self.context._dirobj uid = self.context.uid - ctx = self.context.context.copy() + ctx = self.context.context.copy() tem, dav_time = tuple(match.split(':')) model, res_id = tuple(tem.split('_')) model_obj = dirobj.pool.get(model) model = model_obj.browse(cr, uid, res_id, context=ctx) write_time = model.write_date or model.create_date - wtime = time.mktime(time.strptime(write_time,'%Y-%m-%d %H:%M:%S')) + wtime = time.mktime(time.strptime(write_time,'%Y-%m-%d %H:%M:%S')) if float(dav_time) == float(wtime): return True return False res = super(node_calendar, self).match_dav_eprop(cr, match, ns, prop) - return res - - - def get_domain(self, cr, filters): + return res + + def get_domain(self, cr, filters): + # TODO: doc. res = [] - dirobj = self.context._dirobj - uid = self.context.uid - ctx = self.context.context.copy() - ctx.update(self.dctx) - calendar_obj = dirobj.pool.get('basic.calendar') + # dirobj = self.context._dirobj + #uid = self.context.uid + #ctx = self.context.context.copy() + #ctx.update(self.dctx) + # calendar_obj = dirobj.pool.get('basic.calendar') if not filters: return res - if filters.localName == 'calendar-query': + if filters.localName == 'calendar-query': res = [] for filter_child in filters.childNodes: if filter_child.nodeType == filter_child.TEXT_NODE: - continue - if filter_child.localName == 'filter': + continue + if filter_child.localName == 'filter': for vcalendar_filter in filter_child.childNodes: - if vcalendar_filter.nodeType == vcalendar_filter.TEXT_NODE: + if vcalendar_filter.nodeType == vcalendar_filter.TEXT_NODE: continue if vcalendar_filter.localName == 'comp-filter': if vcalendar_filter.getAttribute('name') == 'VCALENDAR': @@ -216,10 +179,10 @@ class node_calendar(nodes.node_class): if vevent_filter.nodeType == vevent_filter.TEXT_NODE: continue if vevent_filter.localName == 'comp-filter': - if vevent_filter.getAttribute('name') == 'VEVENT': + if vevent_filter.getAttribute('name') == 'VEVENT': res = [('type','=','vevent')] if vevent_filter.getAttribute('name') == 'VTODO': - res = [('type','=','vtodo')] + res = [('type','=','vtodo')] return res elif filters.localName == 'calendar-multiget': names = [] @@ -229,105 +192,70 @@ class node_calendar(nodes.node_class): if filter_child.localName == 'href': if not filter_child.firstChild: continue - uri = filter_child.firstChild.data + uri = filter_child.firstChild.data caluri = uri.split('/') if len(caluri): caluri = caluri[-2] if caluri not in names : names.append(caluri) res = [('name','in',names)] return res - return res + return res - def children(self, cr, domain=None): + def children(self, cr, domain=None): return self._child_get(cr, domain=domain) - def child(self,cr, name, domain=None): - res = self._child_get(cr, name, domain=domain) + def child(self,cr, name, domain=None): + res = self._child_get(cr, name, domain=domain) if res: return res[0] - return None + return None def _child_get(self, cr, name=False, parent_id=False, domain=None): dirobj = self.context._dirobj uid = self.context.uid ctx = self.context.context.copy() - ctx.update(self.dctx) - where = [] - if name: - where.append(('id','=',int(name))) + ctx.update(self.dctx) + where = [] + if name: + if name.endswith('.ics'): + name = name[:-4] + where.append(('id','=',int(name))) if not domain: domain = [] #for opr1, opt, opr2 in domain: # if opr1 == 'type' and opr2 != self.cal_type: # return [] - fil_obj = dirobj.pool.get('basic.calendar') + fil_obj = dirobj.pool.get('basic.calendar') ids = fil_obj.search(cr, uid, domain) res = [] if self.calendar_id in ids: - res = fil_obj.get_calendar_objects(cr, uid, [self.calendar_id], self, domain=where, context=ctx) - return res + res = fil_obj.get_calendar_objects(cr, uid, [self.calendar_id], self, domain=where, context=ctx) + return res - - - def get_dav_props(self, cr): - return self.PROPS - - def get_dav_eprop(self,cr, ns, propname): - if self.M_NS.has_key(ns): - prefix = self.M_NS[ns] - else: - print "No namespace:",ns, "( for prop:", propname,")" - return None - propname = propname.replace('-','_') - mname = prefix + "_" + propname - if not hasattr(self, mname): - return None - - try: - m = getattr(self, mname) - r = m(cr) - return r - except AttributeError, e: - print 'Property %s not supported' % propname - print "Exception:", e - return None - - - def create_child(self,cr,path,data): + def create_child(self, cr, path, data): """ API function to create a child file object and node Return the node_* created """ - return self.set_data(cr, data) + # we ignore the path, it will be re-generated automatically + res = self.set_data(cr, data) + + # TODO: use the res to create at least one node + return None def set_data(self, cr, data, fil_obj = None): uid = self.context.uid calendar_obj = self.context._dirobj.pool.get('basic.calendar') - return calendar_obj.import_cal(cr, uid, base64.encodestring(data), self.calendar_id) + res = calendar_obj.import_cal(cr, uid, data, self.calendar_id) + return res - def get_data_len(self, cr, fil_obj = None): + def get_data_len(self, cr, fil_obj = None): return self.content_length - def _get_ttag(self,cr): - return 'calendar-%d' % (self.calendar_id,) - - - - def get_etag(self, cr): - """ Get a tag, unique per object + modification. - - see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """ - return self._get_ttag(cr) + ':' + self._get_wtag(cr) - - def _get_wtag(self, cr): - """ Return the modification time as a unique, compact string """ - if self.write_date: - wtime = time.mktime(time.strptime(self.write_date, '%Y-%m-%d %H:%M:%S')) - else: wtime = time.time() - return str(wtime) + return 'calendar-%d' % (self.calendar_id,) def rmcol(self, cr): return False @@ -335,7 +263,7 @@ class node_calendar(nodes.node_class): class res_node_calendar(nodes.node_class): our_type = 'file' - PROPS = { + DAV_PROPS = { "http://calendarserver.org/ns/" : ('getctag'), "urn:ietf:params:xml:ns:caldav" : ( 'calendar-description', @@ -344,76 +272,54 @@ class res_node_calendar(nodes.node_class): 'calendar-user-address-set', 'schedule-inbox-URL', 'schedule-outbox-URL',)} - M_NS = { + DAV_M_NS = { "http://calendarserver.org/ns/" : '_get_dav', - "urn:ietf:params:xml:ns:caldav" : '_get_caldav'} + "urn:ietf:params:xml:ns:caldav" : '_get_caldav'} + + http_options = { 'DAV': ['calendar-access'] } def __init__(self,path, parent, context, res_obj, res_model=None, res_id=None): - super(res_node_calendar,self).__init__(path, parent, context) + super(res_node_calendar,self).__init__(path, parent, context) self.mimetype = 'text/calendar' self.create_date = parent.create_date self.write_date = parent.write_date or parent.create_date self.calendar_id = hasattr(parent, 'calendar_id') and parent.calendar_id or False if res_obj: if not self.calendar_id: self.calendar_id = res_obj.id - self.create_date = res_obj.create_date - self.write_date = res_obj.write_date or res_obj.create_date + pr = res_obj.perm_read()[0] + self.create_date = pr.get('create_date') + self.write_date = pr.get('write_date') or pr.get('create_date') self.displayname = res_obj.name self.content_length = 0 - + self.model = res_model self.res_id = res_id - + def open(self, cr, mode=False): - uid = self.context.uid + uid = self.context.uid if self.type in ('collection','database'): - return False - s = StringIO.StringIO(self.get_data(cr)) + return False + s = StringIO.StringIO(self.get_data(cr)) s.name = self - return s + return s - - - def get_dav_props(self, cr): - return self.PROPS - - def get_dav_eprop(self,cr, ns, propname): - if self.M_NS.has_key(ns): - prefix = self.M_NS[ns] - else: - print "No namespace:",ns, "( for prop:", propname,")" - return None - propname = propname.replace('-','_') - mname = prefix + "_" + propname - if not hasattr(self, mname): - return None - - try: - m = getattr(self, mname) - r = m(cr) - return r - except AttributeError, e: - print 'Property %s not supported' % propname - print "Exception:", e - return None - - - def get_data(self, cr, fil_obj = None): + def get_data(self, cr, fil_obj = None): uid = self.context.uid calendar_obj = self.context._dirobj.pool.get('basic.calendar') - context = self.context.context.copy() - context.update({'model': self.model, 'res_id':self.res_id}) - res = calendar_obj.export_cal(cr, uid, [self.calendar_id], context=context) + context = self.context.context.copy() + context.update({'model': self.model, 'res_id':self.res_id}) + res = calendar_obj.export_cal(cr, uid, [self.calendar_id], context=context) return res - def get_data_len(self, cr, fil_obj = None): + def get_data_len(self, cr, fil_obj = None): return self.content_length def set_data(self, cr, data, fil_obj = None): uid = self.context.uid calendar_obj = self.context._dirobj.pool.get('basic.calendar') - return calendar_obj.import_cal(cr, uid, base64.encodestring(data), self.calendar_id) + res = calendar_obj.import_cal(cr, uid, data, self.calendar_id) + return res def _get_ttag(self,cr): res = False @@ -423,30 +329,28 @@ class res_node_calendar(nodes.node_class): res = '%d' % (self.calendar_id) return res - - - def _get_caldav_calendar_data(self, cr): + def _get_caldav_calendar_data(self, cr): return self.get_data(cr) - + def _get_caldav_calendar_description(self, cr): uid = self.context.uid calendar_obj = self.context._dirobj.pool.get('basic.calendar') ctx = self.context.context.copy() - ctx.update(self.dctx) + ctx.update(self.dctx) calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx) return calendar.description - + def _get_caldav_calendar_home_set(self, cr): import xml.dom.minidom - import urllib + import urllib uid = self.context.uid ctx = self.context.context.copy() ctx.update(self.dctx) - doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None) - - calendar_obj = self.context._dirobj.pool.get('basic.calendar') + doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None) + + calendar_obj = self.context._dirobj.pool.get('basic.calendar') calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx) huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, calendar.collection_id.name))) href = doc.documentElement @@ -461,7 +365,7 @@ class res_node_calendar(nodes.node_class): ctx = self.context.context.copy() ctx.update(self.dctx) user_obj = self.context._dirobj.pool.get('res.users') - user = user_obj.browse(cr, uid, uid, context=ctx) + user = user_obj.browse(cr, uid, uid, context=ctx) doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None) href = doc.documentElement href.tagName = 'D:href' @@ -472,11 +376,11 @@ class res_node_calendar(nodes.node_class): def _get_caldav_schedule_inbox_URL(self, cr): import xml.dom.minidom - import urllib + import urllib uid = self.context.uid ctx = self.context.context.copy() ctx.update(self.dctx) - calendar_obj = self.context._dirobj.pool.get('basic.calendar') + calendar_obj = self.context._dirobj.pool.get('basic.calendar') calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx) res = '%s/%s' %(calendar.name, calendar.collection_id.name) doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None) @@ -491,31 +395,15 @@ class res_node_calendar(nodes.node_class): uid = self.context.uid res = False if self.type in ('collection','database'): - return False - if self.model and self.res_id: + return False + if self.model and self.res_id: document_obj = self.context._dirobj.pool.get(self.model) if document_obj: - res = False - #res = document_obj.unlink(cr, uid, [self.res_id]) #TOFIX - - return res - + res = document_obj.unlink(cr, uid, [self.res_id]) + return res def _get_caldav_schedule_outbox_URL(self, cr): return self._get_caldav_schedule_inbox_URL(cr) - - def get_etag(self, cr): - """ Get a tag, unique per object + modification. - - see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """ - return self._get_ttag(cr) + ':' + self._get_wtag(cr) - - def _get_wtag(self, cr): - """ Return the modification time as a unique, compact string """ - if self.write_date: - wtime = time.mktime(time.strptime(self.write_date, '%Y-%m-%d %H:%M:%S')) - else: wtime = time.time() - return str(wtime) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4 diff --git a/addons/caldav/caldav_view.xml b/addons/caldav/caldav_view.xml index d1cb79a0e4a..9184a0aadd2 100644 --- a/addons/caldav/caldav_view.xml +++ b/addons/caldav/caldav_view.xml @@ -1,6 +1,6 @@ - + Calendar Collections : Form document.directory @@ -17,10 +17,10 @@ Calendar Collections : Tree document.directory - tree + tree - + @@ -73,34 +73,34 @@ - + -
- - - - - - - - - - - - - - - - - - - - +
+ + + + + + + + + + + + + + + + + + + + - - - + + +
@@ -110,11 +110,11 @@ Calendar : Tree basic.calendar - tree + tree - - + + @@ -127,8 +127,8 @@ ir.actions.act_window basic.calendar form - tree,form - + tree,form +
@@ -147,5 +147,5 @@ action="action_caldav_form" id="menu_caldav_directories" parent="menu_calendar"/> -
+
diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py index a45152501cc..c62055554ce 100644 --- a/addons/caldav/calendar.py +++ b/addons/caldav/calendar.py @@ -24,7 +24,6 @@ from dateutil import parser from dateutil.rrule import * from osv import osv, fields from tools.translate import _ -import base64 import math import pooler import pytz @@ -52,6 +51,8 @@ def uid2openobjectid(cr, uidval, oomodel, rdate): @param rdate: Get Recurrent Date """ __rege = re.compile(r'OpenObject-([\w|\.]+)_([0-9]+)@(\w+)$') + if not uidval: + return (False, None) wematch = __rege.match(uidval.encode('utf8')) if not wematch: return (False, None) @@ -133,7 +134,7 @@ def map_data(cr, uid, obj, context=None): continue mapping = obj.__attribute__[map_dict].get('mapping', False) if mapping: - map_val = mapping[map_val.lower()] + map_val = mapping.get(map_val.lower(), False) else: map_val = map_val.lower() if field_type == 'many2many': @@ -381,7 +382,7 @@ class CalDAV(object): raise osv.except_osv(('Error !'), (str(e))) return ids - def export_cal(self, cr, uid, datas, vobj=None, context={}): + def export_cal(self, cr, uid, datas, vobj=None, context=None): """ Export Calendar @param self: The object pointer @param cr: the current row, from the database cursor, @@ -396,7 +397,7 @@ class CalDAV(object): self.create_ics(cr, uid, datas, vobj, ical, context=context) return ical except Exception, e: - raise osv.except_osv(('Error !'), (str(e))) + raise # osv.except_osv(('Error !'), (str(e))) def import_cal(self, cr, uid, content, data_id=None, context=None): """ Import Calendar @@ -407,7 +408,7 @@ class CalDAV(object): @param context: A standard dictionary for contextual values """ - ical_data = base64.decodestring(content) + ical_data = content self.__attribute__ = get_attribute_mapping(cr, uid, self._calname, context) parsedCal = vobject.readOne(ical_data) res = [] @@ -447,8 +448,8 @@ class Calendar(CalDAV, osv.osv): 'type': fields.selection([('vevent', 'Event'), ('vtodo', 'TODO')], \ string="Type", size=64), 'line_ids': fields.one2many('basic.calendar.lines', 'calendar_id', 'Calendar Lines'), - 'create_date': fields.datetime('Created Date'), - 'write_date': fields.datetime('Modifided Date'), + 'create_date': fields.datetime('Created Date', readonly=True), + 'write_date': fields.datetime('Modifided Date', readonly=True), } def get_calendar_objects(self, cr, uid, ids, parent=None, domain=None, context=None): @@ -473,17 +474,16 @@ class Calendar(CalDAV, osv.osv): data_ids = mod_obj.search(cr, uid, line_domain, context=context) for data in mod_obj.browse(cr, uid, data_ids, context): ctx = parent and parent.context or None - node = res_node_calendar('%s' %data.id, parent, ctx, data, line.object_id.model, data.id) + node = res_node_calendar('%s.ics' %data.id, parent, ctx, data, line.object_id.model, data.id) res.append(node) return res def export_cal(self, cr, uid, ids, vobj='vevent', context=None): """ Export Calendar - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, @param ids: List of calendar’s IDs - @param context: A standard dictionary for contextual values + @param vobj: the type of object to export + + @return the ical data. """ if not context: context = {} @@ -521,7 +521,7 @@ class Calendar(CalDAV, osv.osv): if not context: context = {} vals = [] - ical_data = base64.decodestring(content) + ical_data = content parsedCal = vobject.readOne(ical_data) if not data_id: data_id = self.search(cr, uid, [])[0] @@ -541,14 +541,19 @@ class Calendar(CalDAV, osv.osv): val = self.parse_ics(cr, uid, child, cal_children=cal_children, context=context) vals.append(val) objs.append(cal_children[child.name.lower()]) + + res = [] for obj_name in list(set(objs)): obj = self.pool.get(obj_name) if hasattr(obj, 'check_import'): - obj.check_import(cr, uid, vals, context=context) + r = obj.check_import(cr, uid, vals, context=context) checked = True + res.extend(r) + if not checked: - self.check_import(cr, uid, vals, context=context) - return {} + r = self.check_import(cr, uid, vals, context=context) + res.extend(r) + return res Calendar() @@ -632,6 +637,10 @@ class basic_calendar_fields(osv.osv): 'fn': lambda *a: 'field', } + _sql_constraints = [ + ( 'name_type_uniq', 'UNIQUE(name, type_id)', 'Can not map a field more than once'), + ] + def check_line(self, cr, uid, vals, name, context=None): """ check calendar's line @param self: The object pointer @@ -667,12 +676,6 @@ class basic_calendar_fields(osv.osv): name = name[0] if name in ('valarm', 'attendee'): self.check_line(cr, uid, vals, name, context=context) - cr.execute("Select count(id) from basic_calendar_fields \ - where name=%s and type_id=%s" % (vals.get('name'), vals.get('type_id'))) - res = cr.fetchone() - if res: - if res[0] > 0: - raise osv.except_osv(_('Warning !'), _('Can not map the field more than once')) return super(basic_calendar_fields, self).create(cr, uid, vals, context=context) def write(self, cr, uid, ids, vals, context=None): @@ -691,13 +694,6 @@ class basic_calendar_fields(osv.osv): name = field.name.name if name in ('valarm', 'attendee'): self.check_line(cr, uid, vals, name, context=context) - qry = "Select count(id) from basic_calendar_fields \ - where name=%s and type_id=%s" % (field.name.id, field.type_id.id) - cr.execute(qry) - res = cr.fetchone() - if res: - if res[0] > 1: - raise osv.except_osv(_('Warning !'), _('Can not map same field more than once')) return super(basic_calendar_fields, self).write(cr, uid, ids, vals, context) basic_calendar_fields() diff --git a/addons/caldav/wizard/calendar_event_export_view.xml b/addons/caldav/wizard/calendar_event_export_view.xml index cfadf945bf4..3161bb7d45e 100644 --- a/addons/caldav/wizard/calendar_event_export_view.xml +++ b/addons/caldav/wizard/calendar_event_export_view.xml @@ -1,25 +1,25 @@ - + calendar.event.export.form calendar.event.export form
- - - + + + - + -