1 """
2 Syncronize with an iCalendar file
3
4 This file is part of Pisi.
5
6 ICalendar support is based on the VOBJECT library by skyhouseconsulting (U{http://vobject.skyhouseconsulting.com/}).
7 Consequently, the vobject site-package has to be installed for utilizing ICS support in PISI.
8
9 Pisi is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Pisi is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Pisi. If not, see <http://www.gnu.org/licenses/>
21 """
22
23 from events import events
24 import datetime,time
25 import pisiprogress
26 import datetime
27 import os.path
28 import os
29 from pisiconstants import *
30
31 from vobjecttools import *
32
33 FIELD_PISI = "X-PISI-ID"
34 """Name of additional field in ICS file for PISI ID (must start with X-)"""
35
37 """
38 The implementation of the interface L{events.AbstractCalendarSynchronizationModule} for the ICalendar file backend
39 """
40 - def __init__( self, modulesString, config, configsection, folder, verbose=False, soft=False):
41 """
42 Constructor
43
44 Super class constructor (L{events.AbstractCalendarSynchronizationModule.__init__}) is called.
45 Local variables are initialized.
46 The settings from the configuration file are loaded.
47 """
48 events.AbstractCalendarSynchronizationModule.__init__(self, verbose, soft, modulesString, config, configsection, "ICalendar file")
49 self._folder = folder
50 self._path = config.get(configsection,'path')
51 pisiprogress.getCallback().verbose('ics-module using file %s' % (self._path))
52 self._rawData = {}
53
54
56 """
57 Try to determine roughly how many entries are in this file (we can't know prior to parsing; but we have a guess using the file size)
58 """
59 info = os.stat(self._path)
60 return info.st_size / ICS_BYTES_PER_ENTRY
61
63 """
64 Load all data from local ICS file
65
66 File is opened and the entries are parsed. For each entry an L{events.events.Event} instance is created and stored in the instance dictionary.
67 """
68 pisiprogress.getCallback().verbose("ICalendar: Loading")
69 file = None
70 try:
71 file = open(self._path, "r")
72 except IOError, e:
73 pisiprogress.getCallback().error("--> Error: Could not load ICS file - we still carry on with processing:\n\t%s" %(e))
74 return
75 pisiprogress.getCallback().progress.push(0, 100)
76 vcal = vobject.readOne(file)
77 pisiprogress.getCallback().progress.setProgress(20)
78 pisiprogress.getCallback().update("Loading")
79 amount = self._guessAmount()
80 i = 0
81 if vcal.contents.has_key('vevent'):
82 for x in vcal.contents['vevent']:
83 atts, globalId, updated = extractICSEntry(x)
84 if not globalId or globalId == "":
85 globalId = events.assembleID()
86 tmpEvent = events.Event( globalId, updated, atts)
87 tmpEvent.attributes['globalid'] = globalId
88 self.replaceEvent(globalId, tmpEvent)
89 else:
90 tmpEvent = events.Event(globalId, updated, atts)
91 tmpEvent.attributes['globalid'] = globalId
92
93 self._allEvents[globalId] = tmpEvent
94 self._rawData[globalId] = x
95
96 if i < amount:
97 i += 1
98 pisiprogress.getCallback().progress.setProgress(20 + ((i*80) / amount))
99 pisiprogress.getCallback().update('Loading')
100
101 file.close()
102 pisiprogress.getCallback().progress.drop()
103
104
152