| Trees | Indices | Help |
|
|---|
|
|
1 ### BITPIM
2 ###
3 ### Copyright (C) 2004 Roger Binns <rogerb@rogerbinns.com>
4 ### Copyright (C) 2004 Peter Pletcher <peterpl@pacbell.net>
5 ###
6 ### This program is free software; you can redistribute it and/or modify
7 ### it under the terms of the BitPim license as detailed in the LICENSE file.
8 ###
9 ### $Id: evolution.py 1442 2004-07-14 05:14:24Z rogerb $
10
11 "Be at one with Evolution"
12
13 # Evolution mostly sucks when compared to Outlook. The UI and functionality
14 # for the address book is a literal copy. There is no API as such and we
15 # just have to delve around the filesystem
16
17 # root directory is ~/evolution
18 # folders are any directory containing a file named folder-metadata.xml
19 # note that folders can be nested
20 #
21 # the folder name is the directory name. The folder-metadata.xml file
22 # does contain description tag, but it isn't normally displayed and
23 # is usually empty for user created folders
24 #
25 # if the folder contains any addressbook entries, then there will
26 # be an addressbook.db file
27 #
28 # the file should be opened using bsddb
29 # import bsddb
30 # db=bsddb.hashopen("addressbook.db", "r")
31 # db.keys() lists keys, db[key] gets item
32 #
33 # the item contains exactly one field which is a null terminated string
34 # containing a vcard
35
36
37 import sys
38 import os
39 import re
40
41 if sys.platform!="linux2":
42 raise ImportError()
43
44 try:
45 import bsddb
46 except:
47 raise ImportError()
48
49
50 userdir=os.path.expanduser("~")
51 evolutionpath="evolution/local"
52 evolutionbasedir=os.path.join(userdir, evolutionpath)
53 evolutionexporter = {
54 'command' : "evolution-addressbook-export",
55 'folderid' : "<Evolution Addressbook Exporter>",
56 'name' : "<Evolution Addressbook Exporter>",
57 'type' : ["address book"]
58 }
59
61 """Returns the contacts as a list of string vcards
62
63 Note that the Windows EOL convention is used"""
64
65 if folder == evolutionexporter['folderid']:
66 return getcontacts_evoexporter()
67
68 dir=os.path.expanduser(folder)
69 p=os.path.join(dir, "addressbook.db")
70 if not os.path.isfile(p):
71 # ok, this is not an address book folder
72 if not os.path.isfile(os.path.join(dir, "folder-metadata.xml")):
73 raise ValueError("Supplied folder is not a folder! "+folder)
74 raise ValueError("Folder does not contain contacts! "+folder)
75 res=[]
76 db=bsddb.hashopen(p, 'r')
77 for key in db.keys():
78 if key.startswith("PAS-DB-VERSION"): # no need for this field
79 continue
80 data=db[key]
81 while data[-1]=="\x00": # often has actual null on the end
82 data=data[:-1]
83 res.append(data)
84 db.close()
85 return res
86
89
91 """Get the cards by running evolution-addressbook-export
92
93 Note that this code returns all the contacts as a single
94 string item. It seemed silly to split them apart when
95 the caller then just puts them back together as one
96 string"""
97 evo_export = os.popen(evolutionexporter['command'])
98 evo_cards = evo_export.read()
99 evo_export_status = evo_export.close()
100 if evo_export_status is not None:
101 raise EvolutionExportException("%s failed with code %s" % (evolutionexporter['command'], `evo_export_status`))
102 return [evo_cards]
103
105
106 res={}
107 children=[]
108
109 for f in os.listdir(basedir):
110 p=os.path.join(basedir, f)
111
112 # deal with child folders (depth first)
113 if os.path.isdir(p):
114 f=getfsfolders(p)
115 if len(f):
116 children.extend(f)
117 continue
118
119 # if we have any children, sort them
120 if len(children):
121 lc=[ (child['name'], child) for child in children] # decorate
122 lc.sort() # sort
123 children=[child for _, child in lc] # un-decorate
124
125
126 # do we have a meta-data file?
127 if not os.path.isfile(os.path.join(basedir, "folder-metadata.xml")):
128 return children
129
130 # ok, what type is this folder
131 t=[]
132 for file,type in ( ("mbox", "mailbox"), ("calendar.ics", "calendar"), ("addressbook.db", "address book"),
133 ("tasks.ics", "tasks") ):
134 if os.path.isfile(os.path.join(basedir, file)):
135 t.append(type)
136
137 entry={}
138 entry['dirpath']=basedir
139 entry['name']=os.path.basename(basedir)
140 entry['folderid']=basedir.replace(userdir, "~", 1)
141 entry['type']=t
142 if len(children):
143 entry['children']=children
144 # tell children who their daddy is
145 for c in children:
146 c['parent']=entry
147
148 return [entry]
149
151 "Return a list of any special folders"
152
153 # the only one we look for currently is evolution-addressbook-export
154 # command
155 evo_version = os.popen(evolutionexporter['command'] + " --version")
156 evo_version_result = evo_version.read()
157 evo_version_status = evo_version.close()
158 if evo_version_status is not None:
159 return []
160 # it doesn't work with earlier versions of evolution, so we do a version
161 # check
162 if evo_version_result.startswith("Gnome evolution 1.4"):
163 return [evolutionexporter]
164 else:
165 return []
166
169
171 # we do the imports etc in the function so that this file won't
172 # require gui code unless this function is called
173
174 import wx
175 import wx.gizmos
176
177 dlg=wx.Dialog(parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER, size=(450,350))
178 vbs=wx.BoxSizer(wx.VERTICAL)
179
180 tl=wx.gizmos.TreeListCtrl(dlg, -1, style=wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT)
181
182 tl.AddColumn("Name")
183 tl.SetMainColumn(0)
184 tl.AddColumn("Type")
185 tl.SetColumnWidth(0, 300)
186
187
188
189 def addnode(parent, item, selected):
190 node=tl.AppendItem(parent, item['name'])
191 if selected==item['folderid']:
192 tl.SelectItem(node)
193 tl.SetItemText(node, ", ".join(item['type']), 1)
194 tl.SetPyData(node, item)
195 if item.has_key("children"):
196 for child in item['children']:
197 addnode(node, child, selected)
198 tl.Expand(node)
199
200 root=tl.AddRoot("?")
201 tl.SetPyData(root, None)
202
203 for f in getfolders():
204 addnode(root, f, selectedid)
205
206 # select first folder if nothing is selected
207 if tl.GetPyData(tl.GetSelection()) is None:
208 child,_=tl.GetFirstChild(root, 1234)
209 tl.SelectItem(child)
210
211 vbs.Add(tl, 1, wx.EXPAND|wx.ALL, 5)
212
213 vbs.Add(wx.StaticLine(dlg, -1, style=wx.LI_HORIZONTAL), 0, wx.EXPAND|wx.ALL, 5)
214
215 vbs.Add(dlg.CreateButtonSizer(wx.OK|wx.CANCEL|wx.HELP), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
216
217 dlg.SetSizer(vbs)
218 dlg.SetAutoLayout(True)
219
220 if dlg.ShowModal()==wx.ID_OK:
221 folderid=tl.GetPyData(tl.GetSelection())['folderid']
222 else:
223 folderid=None
224 dlg.Destroy()
225 return folderid
226
227 # we use a pathname like "~/evolution/local/Contacts" as the folder id
228 # and the same as a "folder"
229
233
235 "Return a folder object given the id"
236
237 f=_findfolder(id)
238 if f is not None:
239 return f['folderid']
240
241 if default:
242 # look for a default
243 for f in getfolders():
244 if "address book" in f['type']:
245 return f["folderid"]
246 # brute force
247 return getfolders()[0]['folderid']
248
249 return None
250
252 "Recursive function to locate a folder, using Match exception to return the found folder"
253 if node['folderid']==id:
254 raise Match(node)
255 for c in node.get("children", []):
256 __findfolder(c, id)
257
259 for f in getfolders():
260 try:
261 __findfolder(f, id)
262 except Match,m:
263 return m.folder # we found it
264 return None
265
266
268 f=_findfolder(id)
269 if f is None:
270 raise AttributeError("No such folder "+id)
271
272 n=[]
273 while f:
274 n=[f['name']]+n
275 f=f.get('parent',None)
276
277 return " / ".join(n)
278
280 return folder
281
282
283 if __name__=="__main__":
284 # a folder selector
285 import wx
286 import wx.gizmos
287
288 app=wx.PySimpleApp()
289
290 folder=pickfolder()
291 print folder
292
293 print "\n".join(getcontacts(folder))
294
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sun Jan 24 16:25:37 2010 | http://epydoc.sourceforge.net |