-rw-r--r-- | libopie/pim/ocontactaccessbackend_vcard.cpp | 549 | ||||
-rw-r--r-- | libopie/pim/ocontactaccessbackend_vcard.h | 65 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp | 549 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_vcard.h | 65 |
4 files changed, 1228 insertions, 0 deletions
diff --git a/libopie/pim/ocontactaccessbackend_vcard.cpp b/libopie/pim/ocontactaccessbackend_vcard.cpp new file mode 100644 index 0000000..903c0b7 --- a/dev/null +++ b/libopie/pim/ocontactaccessbackend_vcard.cpp | |||
@@ -0,0 +1,549 @@ | |||
1 | /* | ||
2 | * VCard Backend for the OPIE-Contact Database. | ||
3 | * | ||
4 | * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) | ||
5 | * | ||
6 | * ===================================================================== | ||
7 | *This program is free software; you can redistribute it and/or | ||
8 | *modify it under the terms of the GNU Library General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2 of the License, or (at your option) any later version. | ||
11 | * ===================================================================== | ||
12 | * ToDo: | ||
13 | * | ||
14 | * ===================================================================== | ||
15 | * Version: $Id$ | ||
16 | * ===================================================================== | ||
17 | * History: | ||
18 | * $Log$ | ||
19 | * Revision 1.1 2002/11/09 14:34:52 eilers | ||
20 | * Added VCard Backend. | ||
21 | * | ||
22 | */ | ||
23 | #include "ocontactaccessbackend_vcard.h" | ||
24 | #include "../../library/backend/vobject_p.h" | ||
25 | #include "../../library/backend/qfiledirect_p.h" | ||
26 | |||
27 | #include <qpe/timeconversion.h> | ||
28 | |||
29 | #include <qfile.h> | ||
30 | |||
31 | OContactAccessBackend_VCard::OContactAccessBackend_VCard ( QString , QString filename = 0l ): | ||
32 | m_dirty( false ), | ||
33 | m_file( filename ) | ||
34 | {} | ||
35 | |||
36 | |||
37 | bool OContactAccessBackend_VCard::load () | ||
38 | { | ||
39 | m_map.clear(); | ||
40 | m_dirty = false; | ||
41 | |||
42 | VObject* obj = 0l; | ||
43 | obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() ); | ||
44 | if ( !obj ) | ||
45 | return false; | ||
46 | |||
47 | while ( obj ) { | ||
48 | OContact con = parseVObject( obj ); | ||
49 | /* | ||
50 | * if uid is 0 assign a new one | ||
51 | * this at least happens on | ||
52 | * Nokia6210 | ||
53 | */ | ||
54 | if ( con.uid() == 0 ){ | ||
55 | con.setUid( 1 ); | ||
56 | qWarning("assigned new uid %d",con.uid() ); | ||
57 | } | ||
58 | |||
59 | m_map.insert( con.uid(), con ); | ||
60 | |||
61 | VObject *t = obj; | ||
62 | obj = nextVObjectInList(obj); | ||
63 | cleanVObject( t ); | ||
64 | } | ||
65 | |||
66 | return true; | ||
67 | |||
68 | } | ||
69 | bool OContactAccessBackend_VCard::reload() | ||
70 | { | ||
71 | return load(); | ||
72 | } | ||
73 | bool OContactAccessBackend_VCard::save() | ||
74 | { | ||
75 | if (!m_dirty ) | ||
76 | return true; | ||
77 | |||
78 | QFileDirect file( m_file ); | ||
79 | if (!file.open(IO_WriteOnly ) ) | ||
80 | return false; | ||
81 | |||
82 | VObject *obj; | ||
83 | obj = newVObject( VCCalProp ); | ||
84 | addPropValue( obj, VCVersionProp, "1.0" ); | ||
85 | |||
86 | VObject *vo; | ||
87 | for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){ | ||
88 | vo = createVObject( *it ); | ||
89 | addVObjectProp( obj, vo ); | ||
90 | } | ||
91 | writeVObject( file.directHandle() , obj ); | ||
92 | cleanVObject( obj ); | ||
93 | |||
94 | cleanStrTbl(); | ||
95 | |||
96 | m_dirty = false; | ||
97 | return true; | ||
98 | |||
99 | |||
100 | } | ||
101 | void OContactAccessBackend_VCard::clear () | ||
102 | { | ||
103 | m_map.clear(); | ||
104 | m_dirty = true; // ??? sure ? (se) | ||
105 | } | ||
106 | |||
107 | bool OContactAccessBackend_VCard::add ( const OContact& newcontact ) | ||
108 | { | ||
109 | m_map.insert( newcontact.uid(), newcontact ); | ||
110 | m_dirty = true; | ||
111 | return true; | ||
112 | } | ||
113 | |||
114 | bool OContactAccessBackend_VCard::remove ( int uid ) | ||
115 | { | ||
116 | m_map.remove( uid ); | ||
117 | m_dirty = true; | ||
118 | return true; | ||
119 | } | ||
120 | |||
121 | bool OContactAccessBackend_VCard::replace ( const OContact &contact ) | ||
122 | { | ||
123 | m_map.replace( contact.uid(), contact ); | ||
124 | m_dirty = true; | ||
125 | return true; | ||
126 | } | ||
127 | |||
128 | OContact OContactAccessBackend_VCard::find ( int uid ) const | ||
129 | { | ||
130 | return m_map[uid]; | ||
131 | } | ||
132 | |||
133 | QArray<int> OContactAccessBackend_VCard::allRecords() const | ||
134 | { | ||
135 | QArray<int> ar( m_map.count() ); | ||
136 | QMap<int, OContact>::ConstIterator it; | ||
137 | int i = 0; | ||
138 | for ( it = m_map.begin(); it != m_map.end(); ++it ) { | ||
139 | ar[i] = it.key(); | ||
140 | i++; | ||
141 | } | ||
142 | return ar; | ||
143 | } | ||
144 | |||
145 | // Not implemented | ||
146 | QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int ) | ||
147 | { | ||
148 | QArray<int> ar(0); | ||
149 | return ar; | ||
150 | } | ||
151 | |||
152 | // Not implemented | ||
153 | QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const | ||
154 | { | ||
155 | QArray<int> ar(0); | ||
156 | return ar; | ||
157 | } | ||
158 | |||
159 | const uint OContactAccessBackend_VCard::querySettings() | ||
160 | { | ||
161 | return 0; // No search possible | ||
162 | } | ||
163 | |||
164 | bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const | ||
165 | { | ||
166 | return false; // No search possible, therefore all settings invalid ;) | ||
167 | } | ||
168 | |||
169 | |||
170 | // *** Private stuff *** | ||
171 | |||
172 | |||
173 | OContact OContactAccessBackend_VCard::parseVObject( VObject *obj ) | ||
174 | { | ||
175 | OContact c; | ||
176 | |||
177 | VObjectIterator it; | ||
178 | initPropIterator( &it, obj ); | ||
179 | while( moreIteration( &it ) ) { | ||
180 | VObject *o = nextVObject( &it ); | ||
181 | QCString name = vObjectName( o ); | ||
182 | QCString value = vObjectStringZValue( o ); | ||
183 | if ( name == VCNameProp ) { | ||
184 | VObjectIterator nit; | ||
185 | initPropIterator( &nit, o ); | ||
186 | while( moreIteration( &nit ) ) { | ||
187 | VObject *o = nextVObject( &nit ); | ||
188 | QCString name = vObjectTypeInfo( o ); | ||
189 | QString value = vObjectStringZValue( o ); | ||
190 | if ( name == VCNamePrefixesProp ) | ||
191 | c.setTitle( value ); | ||
192 | else if ( name == VCNameSuffixesProp ) | ||
193 | c.setSuffix( value ); | ||
194 | else if ( name == VCFamilyNameProp ) | ||
195 | c.setLastName( value ); | ||
196 | else if ( name == VCGivenNameProp ) | ||
197 | c.setFirstName( value ); | ||
198 | else if ( name == VCAdditionalNamesProp ) | ||
199 | c.setMiddleName( value ); | ||
200 | } | ||
201 | } | ||
202 | else if ( name == VCAdrProp ) { | ||
203 | bool work = TRUE; // default address is work address | ||
204 | QString street; | ||
205 | QString city; | ||
206 | QString region; | ||
207 | QString postal; | ||
208 | QString country; | ||
209 | |||
210 | VObjectIterator nit; | ||
211 | initPropIterator( &nit, o ); | ||
212 | while( moreIteration( &nit ) ) { | ||
213 | VObject *o = nextVObject( &nit ); | ||
214 | QCString name = vObjectName( o ); | ||
215 | QString value = vObjectStringZValue( o ); | ||
216 | if ( name == VCHomeProp ) | ||
217 | work = FALSE; | ||
218 | else if ( name == VCWorkProp ) | ||
219 | work = TRUE; | ||
220 | else if ( name == VCStreetAddressProp ) | ||
221 | street = value; | ||
222 | else if ( name == VCCityProp ) | ||
223 | city = value; | ||
224 | else if ( name == VCRegionProp ) | ||
225 | region = value; | ||
226 | else if ( name == VCPostalCodeProp ) | ||
227 | postal = value; | ||
228 | else if ( name == VCCountryNameProp ) | ||
229 | country = value; | ||
230 | } | ||
231 | if ( work ) { | ||
232 | c.setBusinessStreet( street ); | ||
233 | c.setBusinessCity( city ); | ||
234 | c.setBusinessCountry( country ); | ||
235 | c.setBusinessZip( postal ); | ||
236 | c.setBusinessState( region ); | ||
237 | } else { | ||
238 | c.setHomeStreet( street ); | ||
239 | c.setHomeCity( city ); | ||
240 | c.setHomeCountry( country ); | ||
241 | c.setHomeZip( postal ); | ||
242 | c.setHomeState( region ); | ||
243 | } | ||
244 | } | ||
245 | else if ( name == VCTelephoneProp ) { | ||
246 | enum { | ||
247 | HOME = 0x01, | ||
248 | WORK = 0x02, | ||
249 | VOICE = 0x04, | ||
250 | CELL = 0x08, | ||
251 | FAX = 0x10, | ||
252 | PAGER = 0x20, | ||
253 | UNKNOWN = 0x80 | ||
254 | }; | ||
255 | int type = 0; | ||
256 | |||
257 | VObjectIterator nit; | ||
258 | initPropIterator( &nit, o ); | ||
259 | while( moreIteration( &nit ) ) { | ||
260 | VObject *o = nextVObject( &nit ); | ||
261 | QCString name = vObjectTypeInfo( o ); | ||
262 | if ( name == VCHomeProp ) | ||
263 | type |= HOME; | ||
264 | else if ( name == VCWorkProp ) | ||
265 | type |= WORK; | ||
266 | else if ( name == VCVoiceProp ) | ||
267 | type |= VOICE; | ||
268 | else if ( name == VCCellularProp ) | ||
269 | type |= CELL; | ||
270 | else if ( name == VCFaxProp ) | ||
271 | type |= FAX; | ||
272 | else if ( name == VCPagerProp ) | ||
273 | type |= PAGER; | ||
274 | else if ( name == VCPreferredProp ) | ||
275 | ; | ||
276 | else | ||
277 | type |= UNKNOWN; | ||
278 | } | ||
279 | if ( (type & UNKNOWN) != UNKNOWN ) { | ||
280 | if ( ( type & (HOME|WORK) ) == 0 ) // default | ||
281 | type |= HOME; | ||
282 | if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default | ||
283 | type |= VOICE; | ||
284 | |||
285 | if ( (type & (VOICE|HOME) ) == (VOICE|HOME) ) | ||
286 | c.setHomePhone( value ); | ||
287 | if ( ( type & (FAX|HOME) ) == (FAX|HOME) ) | ||
288 | c.setHomeFax( value ); | ||
289 | if ( ( type & (CELL|HOME) ) == (CELL|HOME) ) | ||
290 | c.setHomeMobile( value ); | ||
291 | if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) ) | ||
292 | c.setBusinessPhone( value ); | ||
293 | if ( ( type & (FAX|WORK) ) == (FAX|WORK) ) | ||
294 | c.setBusinessFax( value ); | ||
295 | if ( ( type & (CELL|WORK) ) == (CELL|WORK) ) | ||
296 | c.setBusinessMobile( value ); | ||
297 | if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) ) | ||
298 | c.setBusinessPager( value ); | ||
299 | } | ||
300 | } | ||
301 | else if ( name == VCEmailAddressProp ) { | ||
302 | QString email = vObjectStringZValue( o ); | ||
303 | bool valid = TRUE; | ||
304 | VObjectIterator nit; | ||
305 | initPropIterator( &nit, o ); | ||
306 | while( moreIteration( &nit ) ) { | ||
307 | VObject *o = nextVObject( &nit ); | ||
308 | QCString name = vObjectTypeInfo( o ); | ||
309 | if ( name != VCInternetProp && name != VCHomeProp && | ||
310 | name != VCWorkProp && | ||
311 | name != VCPreferredProp ) | ||
312 | // ### preffered should map to default email | ||
313 | valid = FALSE; | ||
314 | } | ||
315 | if ( valid ) { | ||
316 | c.insertEmail( email ); | ||
317 | } | ||
318 | } | ||
319 | else if ( name == VCURLProp ) { | ||
320 | VObjectIterator nit; | ||
321 | initPropIterator( &nit, o ); | ||
322 | while( moreIteration( &nit ) ) { | ||
323 | VObject *o = nextVObject( &nit ); | ||
324 | QCString name = vObjectTypeInfo( o ); | ||
325 | if ( name == VCHomeProp ) | ||
326 | c.setHomeWebpage( value ); | ||
327 | else if ( name == VCWorkProp ) | ||
328 | c.setBusinessWebpage( value ); | ||
329 | } | ||
330 | } | ||
331 | else if ( name == VCOrgProp ) { | ||
332 | VObjectIterator nit; | ||
333 | initPropIterator( &nit, o ); | ||
334 | while( moreIteration( &nit ) ) { | ||
335 | VObject *o = nextVObject( &nit ); | ||
336 | QCString name = vObjectName( o ); | ||
337 | QString value = vObjectStringZValue( o ); | ||
338 | if ( name == VCOrgNameProp ) | ||
339 | c.setCompany( value ); | ||
340 | else if ( name == VCOrgUnitProp ) | ||
341 | c.setDepartment( value ); | ||
342 | else if ( name == VCOrgUnit2Prop ) | ||
343 | c.setOffice( value ); | ||
344 | } | ||
345 | } | ||
346 | else if ( name == VCTitleProp ) { | ||
347 | c.setJobTitle( value ); | ||
348 | } | ||
349 | else if ( name == "X-Qtopia-Profession" ) { | ||
350 | c.setProfession( value ); | ||
351 | } | ||
352 | else if ( name == "X-Qtopia-Manager" ) { | ||
353 | c.setManager( value ); | ||
354 | } | ||
355 | else if ( name == "X-Qtopia-Assistant" ) { | ||
356 | c.setAssistant( value ); | ||
357 | } | ||
358 | else if ( name == "X-Qtopia-Spouse" ) { | ||
359 | c.setSpouse( value ); | ||
360 | } | ||
361 | else if ( name == "X-Qtopia-Gender" ) { | ||
362 | c.setGender( value ); | ||
363 | } | ||
364 | else if ( name == "X-Qtopia-Anniversary" ) { | ||
365 | c.setAnniversary( TimeConversion::fromString( value ) ); | ||
366 | } | ||
367 | else if ( name == "X-Qtopia-Nickname" ) { | ||
368 | c.setNickname( value ); | ||
369 | } | ||
370 | else if ( name == "X-Qtopia-Children" ) { | ||
371 | c.setChildren( value ); | ||
372 | } | ||
373 | else if ( name == VCBirthDateProp ) { | ||
374 | // Reading Birthdate regarding RFC 2425 (5.8.4) | ||
375 | c.setBirthday( convVCardDateToDate( value ) ); | ||
376 | |||
377 | } | ||
378 | |||
379 | #if 0 | ||
380 | else { | ||
381 | printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); | ||
382 | VObjectIterator nit; | ||
383 | initPropIterator( &nit, o ); | ||
384 | while( moreIteration( &nit ) ) { | ||
385 | VObject *o = nextVObject( &nit ); | ||
386 | QCString name = vObjectName( o ); | ||
387 | QString value = vObjectStringZValue( o ); | ||
388 | printf(" subprop: %s = %s\n", name.data(), value.latin1() ); | ||
389 | } | ||
390 | } | ||
391 | #endif | ||
392 | } | ||
393 | c.setFileAs(); | ||
394 | return c; | ||
395 | } | ||
396 | |||
397 | |||
398 | VObject* OContactAccessBackend_VCard::createVObject( const OContact &c ) | ||
399 | { | ||
400 | VObject *vcard = newVObject( VCCardProp ); | ||
401 | safeAddPropValue( vcard, VCVersionProp, "2.1" ); | ||
402 | safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) ); | ||
403 | safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) ); | ||
404 | |||
405 | // full name | ||
406 | safeAddPropValue( vcard, VCFullNameProp, c.fullName() ); | ||
407 | |||
408 | // name properties | ||
409 | VObject *name = safeAddProp( vcard, VCNameProp ); | ||
410 | safeAddPropValue( name, VCFamilyNameProp, c.lastName() ); | ||
411 | safeAddPropValue( name, VCGivenNameProp, c.firstName() ); | ||
412 | safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() ); | ||
413 | safeAddPropValue( name, VCNamePrefixesProp, c.title() ); | ||
414 | safeAddPropValue( name, VCNameSuffixesProp, c.suffix() ); | ||
415 | |||
416 | // home properties | ||
417 | VObject *home_adr= safeAddProp( vcard, VCAdrProp ); | ||
418 | safeAddProp( home_adr, VCHomeProp ); | ||
419 | safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() ); | ||
420 | safeAddPropValue( home_adr, VCCityProp, c.homeCity() ); | ||
421 | safeAddPropValue( home_adr, VCRegionProp, c.homeState() ); | ||
422 | safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() ); | ||
423 | safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() ); | ||
424 | |||
425 | VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() ); | ||
426 | safeAddProp( home_phone, VCHomeProp ); | ||
427 | home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() ); | ||
428 | safeAddProp( home_phone, VCHomeProp ); | ||
429 | safeAddProp( home_phone, VCCellularProp ); | ||
430 | home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() ); | ||
431 | safeAddProp( home_phone, VCHomeProp ); | ||
432 | safeAddProp( home_phone, VCFaxProp ); | ||
433 | |||
434 | VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() ); | ||
435 | safeAddProp( url, VCHomeProp ); | ||
436 | |||
437 | // work properties | ||
438 | VObject *work_adr= safeAddProp( vcard, VCAdrProp ); | ||
439 | safeAddProp( work_adr, VCWorkProp ); | ||
440 | safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() ); | ||
441 | safeAddPropValue( work_adr, VCCityProp, c.businessCity() ); | ||
442 | safeAddPropValue( work_adr, VCRegionProp, c.businessState() ); | ||
443 | safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() ); | ||
444 | safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() ); | ||
445 | |||
446 | VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() ); | ||
447 | safeAddProp( work_phone, VCWorkProp ); | ||
448 | work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() ); | ||
449 | safeAddProp( work_phone, VCWorkProp ); | ||
450 | safeAddProp( work_phone, VCCellularProp ); | ||
451 | work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() ); | ||
452 | safeAddProp( work_phone, VCWorkProp ); | ||
453 | safeAddProp( work_phone, VCFaxProp ); | ||
454 | work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() ); | ||
455 | safeAddProp( work_phone, VCWorkProp ); | ||
456 | safeAddProp( work_phone, VCPagerProp ); | ||
457 | |||
458 | url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() ); | ||
459 | safeAddProp( url, VCWorkProp ); | ||
460 | |||
461 | VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() ); | ||
462 | safeAddProp( title, VCWorkProp ); | ||
463 | |||
464 | |||
465 | QStringList emails = c.emailList(); | ||
466 | emails.prepend( c.defaultEmail() ); | ||
467 | for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) { | ||
468 | VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it ); | ||
469 | safeAddProp( email, VCInternetProp ); | ||
470 | } | ||
471 | |||
472 | safeAddPropValue( vcard, VCNoteProp, c.notes() ); | ||
473 | |||
474 | // Exporting Birthday regarding RFC 2425 (5.8.4) | ||
475 | if ( c.birthday().isValid() ){ | ||
476 | QString birthd_rfc2425 = QString("%1-%2-%3") | ||
477 | .arg( c.birthday().year() ) | ||
478 | .arg( c.birthday().month(), 2 ) | ||
479 | .arg( c.birthday().day(), 2 ); | ||
480 | // Now replace spaces with "0"... | ||
481 | int pos = 0; | ||
482 | while ( ( pos = birthd_rfc2425.find (' ') ) > 0 ) | ||
483 | birthd_rfc2425.replace( pos, 1, "0" ); | ||
484 | |||
485 | qWarning("Exporting birthday as: %s", birthd_rfc2425.latin1()); | ||
486 | safeAddPropValue( vcard, VCBirthDateProp, birthd_rfc2425.latin1() ); | ||
487 | } | ||
488 | |||
489 | if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) { | ||
490 | VObject *org = safeAddProp( vcard, VCOrgProp ); | ||
491 | safeAddPropValue( org, VCOrgNameProp, c.company() ); | ||
492 | safeAddPropValue( org, VCOrgUnitProp, c.department() ); | ||
493 | safeAddPropValue( org, VCOrgUnit2Prop, c.office() ); | ||
494 | } | ||
495 | |||
496 | // some values we have to export as custom fields | ||
497 | safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() ); | ||
498 | safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() ); | ||
499 | safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() ); | ||
500 | |||
501 | safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() ); | ||
502 | safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() ); | ||
503 | safeAddPropValue( vcard, "X-Qtopia-Anniversary", TimeConversion::toString( c.anniversary() ) ); | ||
504 | safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() ); | ||
505 | safeAddPropValue( vcard, "X-Qtopia-Children", c.children() ); | ||
506 | |||
507 | return vcard; | ||
508 | } | ||
509 | |||
510 | QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr ) | ||
511 | { | ||
512 | int monthPos = datestr.find('-'); | ||
513 | int dayPos = datestr.find('-', monthPos+1 ); | ||
514 | int sep_ignore = 1; | ||
515 | if ( monthPos == -1 || dayPos == -1 ) { | ||
516 | qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos ); | ||
517 | // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD ) | ||
518 | if ( datestr.length() == 8 ){ | ||
519 | monthPos = 4; | ||
520 | dayPos = 6; | ||
521 | sep_ignore = 0; | ||
522 | qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos ); | ||
523 | } else { | ||
524 | return QDate(); | ||
525 | } | ||
526 | } | ||
527 | int y = datestr.left( monthPos ).toInt(); | ||
528 | int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt(); | ||
529 | int d = datestr.mid( dayPos + sep_ignore ).toInt(); | ||
530 | qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos); | ||
531 | QDate date ( y,m,d ); | ||
532 | return date; | ||
533 | } | ||
534 | |||
535 | VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value ) | ||
536 | { | ||
537 | VObject *ret = 0; | ||
538 | if ( o && !value.isEmpty() ) | ||
539 | ret = addPropValue( o, prop, value.latin1() ); | ||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop) | ||
544 | { | ||
545 | VObject *ret = 0; | ||
546 | if ( o ) | ||
547 | ret = addProp( o, prop ); | ||
548 | return ret; | ||
549 | } | ||
diff --git a/libopie/pim/ocontactaccessbackend_vcard.h b/libopie/pim/ocontactaccessbackend_vcard.h new file mode 100644 index 0000000..c1422b0 --- a/dev/null +++ b/libopie/pim/ocontactaccessbackend_vcard.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * VCard Backend for the OPIE-Contact Database. | ||
3 | * | ||
4 | * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) | ||
5 | * | ||
6 | * ===================================================================== | ||
7 | *This program is free software; you can redistribute it and/or | ||
8 | *modify it under the terms of the GNU Library General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2 of the License, or (at your option) any later version. | ||
11 | * ===================================================================== | ||
12 | * ToDo: | ||
13 | * | ||
14 | * ===================================================================== | ||
15 | * Version: $Id$ | ||
16 | * ===================================================================== | ||
17 | * History: | ||
18 | * $Log$ | ||
19 | * Revision 1.1 2002/11/09 14:34:52 eilers | ||
20 | * Added VCard Backend. | ||
21 | * | ||
22 | */ | ||
23 | #ifndef __OCONTACTACCESSBACKEND_VCARD_H_ | ||
24 | #define __OCONTACTACCESSBACKEND_VCARD_H_ | ||
25 | |||
26 | #include <opie/ocontact.h> | ||
27 | |||
28 | #include "ocontactaccessbackend.h" | ||
29 | |||
30 | class VObject; | ||
31 | |||
32 | class OContactAccessBackend_VCard : public OContactAccessBackend { | ||
33 | public: | ||
34 | OContactAccessBackend_VCard ( QString appname, QString filename = 0l ); | ||
35 | |||
36 | bool load (); | ||
37 | bool reload(); | ||
38 | bool save(); | ||
39 | void clear (); | ||
40 | |||
41 | bool add ( const OContact& newcontact ); | ||
42 | bool remove ( int uid ); | ||
43 | bool replace ( const OContact& contact ); | ||
44 | |||
45 | OContact find ( int uid ) const; | ||
46 | QArray<int> allRecords() const; | ||
47 | QArray<int> queryByExample ( const OContact &query, int settings ); | ||
48 | QArray<int> matchRegexp( const QRegExp &r ) const; | ||
49 | |||
50 | const uint querySettings(); | ||
51 | bool hasQuerySettings (uint querySettings) const; | ||
52 | |||
53 | private: | ||
54 | OContact parseVObject( VObject* obj ); | ||
55 | VObject* createVObject( const OContact& c ); | ||
56 | QDate convVCardDateToDate( const QString& datestr ); | ||
57 | VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value ); | ||
58 | VObject *safeAddProp( VObject* o, const char* prop); | ||
59 | |||
60 | bool m_dirty : 1; | ||
61 | QString m_file; | ||
62 | QMap<int, OContact> m_map; | ||
63 | }; | ||
64 | |||
65 | #endif | ||
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp new file mode 100644 index 0000000..903c0b7 --- a/dev/null +++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp | |||
@@ -0,0 +1,549 @@ | |||
1 | /* | ||
2 | * VCard Backend for the OPIE-Contact Database. | ||
3 | * | ||
4 | * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) | ||
5 | * | ||
6 | * ===================================================================== | ||
7 | *This program is free software; you can redistribute it and/or | ||
8 | *modify it under the terms of the GNU Library General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2 of the License, or (at your option) any later version. | ||
11 | * ===================================================================== | ||
12 | * ToDo: | ||
13 | * | ||
14 | * ===================================================================== | ||
15 | * Version: $Id$ | ||
16 | * ===================================================================== | ||
17 | * History: | ||
18 | * $Log$ | ||
19 | * Revision 1.1 2002/11/09 14:34:52 eilers | ||
20 | * Added VCard Backend. | ||
21 | * | ||
22 | */ | ||
23 | #include "ocontactaccessbackend_vcard.h" | ||
24 | #include "../../library/backend/vobject_p.h" | ||
25 | #include "../../library/backend/qfiledirect_p.h" | ||
26 | |||
27 | #include <qpe/timeconversion.h> | ||
28 | |||
29 | #include <qfile.h> | ||
30 | |||
31 | OContactAccessBackend_VCard::OContactAccessBackend_VCard ( QString , QString filename = 0l ): | ||
32 | m_dirty( false ), | ||
33 | m_file( filename ) | ||
34 | {} | ||
35 | |||
36 | |||
37 | bool OContactAccessBackend_VCard::load () | ||
38 | { | ||
39 | m_map.clear(); | ||
40 | m_dirty = false; | ||
41 | |||
42 | VObject* obj = 0l; | ||
43 | obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() ); | ||
44 | if ( !obj ) | ||
45 | return false; | ||
46 | |||
47 | while ( obj ) { | ||
48 | OContact con = parseVObject( obj ); | ||
49 | /* | ||
50 | * if uid is 0 assign a new one | ||
51 | * this at least happens on | ||
52 | * Nokia6210 | ||
53 | */ | ||
54 | if ( con.uid() == 0 ){ | ||
55 | con.setUid( 1 ); | ||
56 | qWarning("assigned new uid %d",con.uid() ); | ||
57 | } | ||
58 | |||
59 | m_map.insert( con.uid(), con ); | ||
60 | |||
61 | VObject *t = obj; | ||
62 | obj = nextVObjectInList(obj); | ||
63 | cleanVObject( t ); | ||
64 | } | ||
65 | |||
66 | return true; | ||
67 | |||
68 | } | ||
69 | bool OContactAccessBackend_VCard::reload() | ||
70 | { | ||
71 | return load(); | ||
72 | } | ||
73 | bool OContactAccessBackend_VCard::save() | ||
74 | { | ||
75 | if (!m_dirty ) | ||
76 | return true; | ||
77 | |||
78 | QFileDirect file( m_file ); | ||
79 | if (!file.open(IO_WriteOnly ) ) | ||
80 | return false; | ||
81 | |||
82 | VObject *obj; | ||
83 | obj = newVObject( VCCalProp ); | ||
84 | addPropValue( obj, VCVersionProp, "1.0" ); | ||
85 | |||
86 | VObject *vo; | ||
87 | for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){ | ||
88 | vo = createVObject( *it ); | ||
89 | addVObjectProp( obj, vo ); | ||
90 | } | ||
91 | writeVObject( file.directHandle() , obj ); | ||
92 | cleanVObject( obj ); | ||
93 | |||
94 | cleanStrTbl(); | ||
95 | |||
96 | m_dirty = false; | ||
97 | return true; | ||
98 | |||
99 | |||
100 | } | ||
101 | void OContactAccessBackend_VCard::clear () | ||
102 | { | ||
103 | m_map.clear(); | ||
104 | m_dirty = true; // ??? sure ? (se) | ||
105 | } | ||
106 | |||
107 | bool OContactAccessBackend_VCard::add ( const OContact& newcontact ) | ||
108 | { | ||
109 | m_map.insert( newcontact.uid(), newcontact ); | ||
110 | m_dirty = true; | ||
111 | return true; | ||
112 | } | ||
113 | |||
114 | bool OContactAccessBackend_VCard::remove ( int uid ) | ||
115 | { | ||
116 | m_map.remove( uid ); | ||
117 | m_dirty = true; | ||
118 | return true; | ||
119 | } | ||
120 | |||
121 | bool OContactAccessBackend_VCard::replace ( const OContact &contact ) | ||
122 | { | ||
123 | m_map.replace( contact.uid(), contact ); | ||
124 | m_dirty = true; | ||
125 | return true; | ||
126 | } | ||
127 | |||
128 | OContact OContactAccessBackend_VCard::find ( int uid ) const | ||
129 | { | ||
130 | return m_map[uid]; | ||
131 | } | ||
132 | |||
133 | QArray<int> OContactAccessBackend_VCard::allRecords() const | ||
134 | { | ||
135 | QArray<int> ar( m_map.count() ); | ||
136 | QMap<int, OContact>::ConstIterator it; | ||
137 | int i = 0; | ||
138 | for ( it = m_map.begin(); it != m_map.end(); ++it ) { | ||
139 | ar[i] = it.key(); | ||
140 | i++; | ||
141 | } | ||
142 | return ar; | ||
143 | } | ||
144 | |||
145 | // Not implemented | ||
146 | QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int ) | ||
147 | { | ||
148 | QArray<int> ar(0); | ||
149 | return ar; | ||
150 | } | ||
151 | |||
152 | // Not implemented | ||
153 | QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const | ||
154 | { | ||
155 | QArray<int> ar(0); | ||
156 | return ar; | ||
157 | } | ||
158 | |||
159 | const uint OContactAccessBackend_VCard::querySettings() | ||
160 | { | ||
161 | return 0; // No search possible | ||
162 | } | ||
163 | |||
164 | bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const | ||
165 | { | ||
166 | return false; // No search possible, therefore all settings invalid ;) | ||
167 | } | ||
168 | |||
169 | |||
170 | // *** Private stuff *** | ||
171 | |||
172 | |||
173 | OContact OContactAccessBackend_VCard::parseVObject( VObject *obj ) | ||
174 | { | ||
175 | OContact c; | ||
176 | |||
177 | VObjectIterator it; | ||
178 | initPropIterator( &it, obj ); | ||
179 | while( moreIteration( &it ) ) { | ||
180 | VObject *o = nextVObject( &it ); | ||
181 | QCString name = vObjectName( o ); | ||
182 | QCString value = vObjectStringZValue( o ); | ||
183 | if ( name == VCNameProp ) { | ||
184 | VObjectIterator nit; | ||
185 | initPropIterator( &nit, o ); | ||
186 | while( moreIteration( &nit ) ) { | ||
187 | VObject *o = nextVObject( &nit ); | ||
188 | QCString name = vObjectTypeInfo( o ); | ||
189 | QString value = vObjectStringZValue( o ); | ||
190 | if ( name == VCNamePrefixesProp ) | ||
191 | c.setTitle( value ); | ||
192 | else if ( name == VCNameSuffixesProp ) | ||
193 | c.setSuffix( value ); | ||
194 | else if ( name == VCFamilyNameProp ) | ||
195 | c.setLastName( value ); | ||
196 | else if ( name == VCGivenNameProp ) | ||
197 | c.setFirstName( value ); | ||
198 | else if ( name == VCAdditionalNamesProp ) | ||
199 | c.setMiddleName( value ); | ||
200 | } | ||
201 | } | ||
202 | else if ( name == VCAdrProp ) { | ||
203 | bool work = TRUE; // default address is work address | ||
204 | QString street; | ||
205 | QString city; | ||
206 | QString region; | ||
207 | QString postal; | ||
208 | QString country; | ||
209 | |||
210 | VObjectIterator nit; | ||
211 | initPropIterator( &nit, o ); | ||
212 | while( moreIteration( &nit ) ) { | ||
213 | VObject *o = nextVObject( &nit ); | ||
214 | QCString name = vObjectName( o ); | ||
215 | QString value = vObjectStringZValue( o ); | ||
216 | if ( name == VCHomeProp ) | ||
217 | work = FALSE; | ||
218 | else if ( name == VCWorkProp ) | ||
219 | work = TRUE; | ||
220 | else if ( name == VCStreetAddressProp ) | ||
221 | street = value; | ||
222 | else if ( name == VCCityProp ) | ||
223 | city = value; | ||
224 | else if ( name == VCRegionProp ) | ||
225 | region = value; | ||
226 | else if ( name == VCPostalCodeProp ) | ||
227 | postal = value; | ||
228 | else if ( name == VCCountryNameProp ) | ||
229 | country = value; | ||
230 | } | ||
231 | if ( work ) { | ||
232 | c.setBusinessStreet( street ); | ||
233 | c.setBusinessCity( city ); | ||
234 | c.setBusinessCountry( country ); | ||
235 | c.setBusinessZip( postal ); | ||
236 | c.setBusinessState( region ); | ||
237 | } else { | ||
238 | c.setHomeStreet( street ); | ||
239 | c.setHomeCity( city ); | ||
240 | c.setHomeCountry( country ); | ||
241 | c.setHomeZip( postal ); | ||
242 | c.setHomeState( region ); | ||
243 | } | ||
244 | } | ||
245 | else if ( name == VCTelephoneProp ) { | ||
246 | enum { | ||
247 | HOME = 0x01, | ||
248 | WORK = 0x02, | ||
249 | VOICE = 0x04, | ||
250 | CELL = 0x08, | ||
251 | FAX = 0x10, | ||
252 | PAGER = 0x20, | ||
253 | UNKNOWN = 0x80 | ||
254 | }; | ||
255 | int type = 0; | ||
256 | |||
257 | VObjectIterator nit; | ||
258 | initPropIterator( &nit, o ); | ||
259 | while( moreIteration( &nit ) ) { | ||
260 | VObject *o = nextVObject( &nit ); | ||
261 | QCString name = vObjectTypeInfo( o ); | ||
262 | if ( name == VCHomeProp ) | ||
263 | type |= HOME; | ||
264 | else if ( name == VCWorkProp ) | ||
265 | type |= WORK; | ||
266 | else if ( name == VCVoiceProp ) | ||
267 | type |= VOICE; | ||
268 | else if ( name == VCCellularProp ) | ||
269 | type |= CELL; | ||
270 | else if ( name == VCFaxProp ) | ||
271 | type |= FAX; | ||
272 | else if ( name == VCPagerProp ) | ||
273 | type |= PAGER; | ||
274 | else if ( name == VCPreferredProp ) | ||
275 | ; | ||
276 | else | ||
277 | type |= UNKNOWN; | ||
278 | } | ||
279 | if ( (type & UNKNOWN) != UNKNOWN ) { | ||
280 | if ( ( type & (HOME|WORK) ) == 0 ) // default | ||
281 | type |= HOME; | ||
282 | if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default | ||
283 | type |= VOICE; | ||
284 | |||
285 | if ( (type & (VOICE|HOME) ) == (VOICE|HOME) ) | ||
286 | c.setHomePhone( value ); | ||
287 | if ( ( type & (FAX|HOME) ) == (FAX|HOME) ) | ||
288 | c.setHomeFax( value ); | ||
289 | if ( ( type & (CELL|HOME) ) == (CELL|HOME) ) | ||
290 | c.setHomeMobile( value ); | ||
291 | if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) ) | ||
292 | c.setBusinessPhone( value ); | ||
293 | if ( ( type & (FAX|WORK) ) == (FAX|WORK) ) | ||
294 | c.setBusinessFax( value ); | ||
295 | if ( ( type & (CELL|WORK) ) == (CELL|WORK) ) | ||
296 | c.setBusinessMobile( value ); | ||
297 | if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) ) | ||
298 | c.setBusinessPager( value ); | ||
299 | } | ||
300 | } | ||
301 | else if ( name == VCEmailAddressProp ) { | ||
302 | QString email = vObjectStringZValue( o ); | ||
303 | bool valid = TRUE; | ||
304 | VObjectIterator nit; | ||
305 | initPropIterator( &nit, o ); | ||
306 | while( moreIteration( &nit ) ) { | ||
307 | VObject *o = nextVObject( &nit ); | ||
308 | QCString name = vObjectTypeInfo( o ); | ||
309 | if ( name != VCInternetProp && name != VCHomeProp && | ||
310 | name != VCWorkProp && | ||
311 | name != VCPreferredProp ) | ||
312 | // ### preffered should map to default email | ||
313 | valid = FALSE; | ||
314 | } | ||
315 | if ( valid ) { | ||
316 | c.insertEmail( email ); | ||
317 | } | ||
318 | } | ||
319 | else if ( name == VCURLProp ) { | ||
320 | VObjectIterator nit; | ||
321 | initPropIterator( &nit, o ); | ||
322 | while( moreIteration( &nit ) ) { | ||
323 | VObject *o = nextVObject( &nit ); | ||
324 | QCString name = vObjectTypeInfo( o ); | ||
325 | if ( name == VCHomeProp ) | ||
326 | c.setHomeWebpage( value ); | ||
327 | else if ( name == VCWorkProp ) | ||
328 | c.setBusinessWebpage( value ); | ||
329 | } | ||
330 | } | ||
331 | else if ( name == VCOrgProp ) { | ||
332 | VObjectIterator nit; | ||
333 | initPropIterator( &nit, o ); | ||
334 | while( moreIteration( &nit ) ) { | ||
335 | VObject *o = nextVObject( &nit ); | ||
336 | QCString name = vObjectName( o ); | ||
337 | QString value = vObjectStringZValue( o ); | ||
338 | if ( name == VCOrgNameProp ) | ||
339 | c.setCompany( value ); | ||
340 | else if ( name == VCOrgUnitProp ) | ||
341 | c.setDepartment( value ); | ||
342 | else if ( name == VCOrgUnit2Prop ) | ||
343 | c.setOffice( value ); | ||
344 | } | ||
345 | } | ||
346 | else if ( name == VCTitleProp ) { | ||
347 | c.setJobTitle( value ); | ||
348 | } | ||
349 | else if ( name == "X-Qtopia-Profession" ) { | ||
350 | c.setProfession( value ); | ||
351 | } | ||
352 | else if ( name == "X-Qtopia-Manager" ) { | ||
353 | c.setManager( value ); | ||
354 | } | ||
355 | else if ( name == "X-Qtopia-Assistant" ) { | ||
356 | c.setAssistant( value ); | ||
357 | } | ||
358 | else if ( name == "X-Qtopia-Spouse" ) { | ||
359 | c.setSpouse( value ); | ||
360 | } | ||
361 | else if ( name == "X-Qtopia-Gender" ) { | ||
362 | c.setGender( value ); | ||
363 | } | ||
364 | else if ( name == "X-Qtopia-Anniversary" ) { | ||
365 | c.setAnniversary( TimeConversion::fromString( value ) ); | ||
366 | } | ||
367 | else if ( name == "X-Qtopia-Nickname" ) { | ||
368 | c.setNickname( value ); | ||
369 | } | ||
370 | else if ( name == "X-Qtopia-Children" ) { | ||
371 | c.setChildren( value ); | ||
372 | } | ||
373 | else if ( name == VCBirthDateProp ) { | ||
374 | // Reading Birthdate regarding RFC 2425 (5.8.4) | ||
375 | c.setBirthday( convVCardDateToDate( value ) ); | ||
376 | |||
377 | } | ||
378 | |||
379 | #if 0 | ||
380 | else { | ||
381 | printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); | ||
382 | VObjectIterator nit; | ||
383 | initPropIterator( &nit, o ); | ||
384 | while( moreIteration( &nit ) ) { | ||
385 | VObject *o = nextVObject( &nit ); | ||
386 | QCString name = vObjectName( o ); | ||
387 | QString value = vObjectStringZValue( o ); | ||
388 | printf(" subprop: %s = %s\n", name.data(), value.latin1() ); | ||
389 | } | ||
390 | } | ||
391 | #endif | ||
392 | } | ||
393 | c.setFileAs(); | ||
394 | return c; | ||
395 | } | ||
396 | |||
397 | |||
398 | VObject* OContactAccessBackend_VCard::createVObject( const OContact &c ) | ||
399 | { | ||
400 | VObject *vcard = newVObject( VCCardProp ); | ||
401 | safeAddPropValue( vcard, VCVersionProp, "2.1" ); | ||
402 | safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) ); | ||
403 | safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) ); | ||
404 | |||
405 | // full name | ||
406 | safeAddPropValue( vcard, VCFullNameProp, c.fullName() ); | ||
407 | |||
408 | // name properties | ||
409 | VObject *name = safeAddProp( vcard, VCNameProp ); | ||
410 | safeAddPropValue( name, VCFamilyNameProp, c.lastName() ); | ||
411 | safeAddPropValue( name, VCGivenNameProp, c.firstName() ); | ||
412 | safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() ); | ||
413 | safeAddPropValue( name, VCNamePrefixesProp, c.title() ); | ||
414 | safeAddPropValue( name, VCNameSuffixesProp, c.suffix() ); | ||
415 | |||
416 | // home properties | ||
417 | VObject *home_adr= safeAddProp( vcard, VCAdrProp ); | ||
418 | safeAddProp( home_adr, VCHomeProp ); | ||
419 | safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() ); | ||
420 | safeAddPropValue( home_adr, VCCityProp, c.homeCity() ); | ||
421 | safeAddPropValue( home_adr, VCRegionProp, c.homeState() ); | ||
422 | safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() ); | ||
423 | safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() ); | ||
424 | |||
425 | VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() ); | ||
426 | safeAddProp( home_phone, VCHomeProp ); | ||
427 | home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() ); | ||
428 | safeAddProp( home_phone, VCHomeProp ); | ||
429 | safeAddProp( home_phone, VCCellularProp ); | ||
430 | home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() ); | ||
431 | safeAddProp( home_phone, VCHomeProp ); | ||
432 | safeAddProp( home_phone, VCFaxProp ); | ||
433 | |||
434 | VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() ); | ||
435 | safeAddProp( url, VCHomeProp ); | ||
436 | |||
437 | // work properties | ||
438 | VObject *work_adr= safeAddProp( vcard, VCAdrProp ); | ||
439 | safeAddProp( work_adr, VCWorkProp ); | ||
440 | safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() ); | ||
441 | safeAddPropValue( work_adr, VCCityProp, c.businessCity() ); | ||
442 | safeAddPropValue( work_adr, VCRegionProp, c.businessState() ); | ||
443 | safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() ); | ||
444 | safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() ); | ||
445 | |||
446 | VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() ); | ||
447 | safeAddProp( work_phone, VCWorkProp ); | ||
448 | work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() ); | ||
449 | safeAddProp( work_phone, VCWorkProp ); | ||
450 | safeAddProp( work_phone, VCCellularProp ); | ||
451 | work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() ); | ||
452 | safeAddProp( work_phone, VCWorkProp ); | ||
453 | safeAddProp( work_phone, VCFaxProp ); | ||
454 | work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() ); | ||
455 | safeAddProp( work_phone, VCWorkProp ); | ||
456 | safeAddProp( work_phone, VCPagerProp ); | ||
457 | |||
458 | url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() ); | ||
459 | safeAddProp( url, VCWorkProp ); | ||
460 | |||
461 | VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() ); | ||
462 | safeAddProp( title, VCWorkProp ); | ||
463 | |||
464 | |||
465 | QStringList emails = c.emailList(); | ||
466 | emails.prepend( c.defaultEmail() ); | ||
467 | for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) { | ||
468 | VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it ); | ||
469 | safeAddProp( email, VCInternetProp ); | ||
470 | } | ||
471 | |||
472 | safeAddPropValue( vcard, VCNoteProp, c.notes() ); | ||
473 | |||
474 | // Exporting Birthday regarding RFC 2425 (5.8.4) | ||
475 | if ( c.birthday().isValid() ){ | ||
476 | QString birthd_rfc2425 = QString("%1-%2-%3") | ||
477 | .arg( c.birthday().year() ) | ||
478 | .arg( c.birthday().month(), 2 ) | ||
479 | .arg( c.birthday().day(), 2 ); | ||
480 | // Now replace spaces with "0"... | ||
481 | int pos = 0; | ||
482 | while ( ( pos = birthd_rfc2425.find (' ') ) > 0 ) | ||
483 | birthd_rfc2425.replace( pos, 1, "0" ); | ||
484 | |||
485 | qWarning("Exporting birthday as: %s", birthd_rfc2425.latin1()); | ||
486 | safeAddPropValue( vcard, VCBirthDateProp, birthd_rfc2425.latin1() ); | ||
487 | } | ||
488 | |||
489 | if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) { | ||
490 | VObject *org = safeAddProp( vcard, VCOrgProp ); | ||
491 | safeAddPropValue( org, VCOrgNameProp, c.company() ); | ||
492 | safeAddPropValue( org, VCOrgUnitProp, c.department() ); | ||
493 | safeAddPropValue( org, VCOrgUnit2Prop, c.office() ); | ||
494 | } | ||
495 | |||
496 | // some values we have to export as custom fields | ||
497 | safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() ); | ||
498 | safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() ); | ||
499 | safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() ); | ||
500 | |||
501 | safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() ); | ||
502 | safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() ); | ||
503 | safeAddPropValue( vcard, "X-Qtopia-Anniversary", TimeConversion::toString( c.anniversary() ) ); | ||
504 | safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() ); | ||
505 | safeAddPropValue( vcard, "X-Qtopia-Children", c.children() ); | ||
506 | |||
507 | return vcard; | ||
508 | } | ||
509 | |||
510 | QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr ) | ||
511 | { | ||
512 | int monthPos = datestr.find('-'); | ||
513 | int dayPos = datestr.find('-', monthPos+1 ); | ||
514 | int sep_ignore = 1; | ||
515 | if ( monthPos == -1 || dayPos == -1 ) { | ||
516 | qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos ); | ||
517 | // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD ) | ||
518 | if ( datestr.length() == 8 ){ | ||
519 | monthPos = 4; | ||
520 | dayPos = 6; | ||
521 | sep_ignore = 0; | ||
522 | qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos ); | ||
523 | } else { | ||
524 | return QDate(); | ||
525 | } | ||
526 | } | ||
527 | int y = datestr.left( monthPos ).toInt(); | ||
528 | int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt(); | ||
529 | int d = datestr.mid( dayPos + sep_ignore ).toInt(); | ||
530 | qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos); | ||
531 | QDate date ( y,m,d ); | ||
532 | return date; | ||
533 | } | ||
534 | |||
535 | VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value ) | ||
536 | { | ||
537 | VObject *ret = 0; | ||
538 | if ( o && !value.isEmpty() ) | ||
539 | ret = addPropValue( o, prop, value.latin1() ); | ||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop) | ||
544 | { | ||
545 | VObject *ret = 0; | ||
546 | if ( o ) | ||
547 | ret = addProp( o, prop ); | ||
548 | return ret; | ||
549 | } | ||
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h new file mode 100644 index 0000000..c1422b0 --- a/dev/null +++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * VCard Backend for the OPIE-Contact Database. | ||
3 | * | ||
4 | * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) | ||
5 | * | ||
6 | * ===================================================================== | ||
7 | *This program is free software; you can redistribute it and/or | ||
8 | *modify it under the terms of the GNU Library General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2 of the License, or (at your option) any later version. | ||
11 | * ===================================================================== | ||
12 | * ToDo: | ||
13 | * | ||
14 | * ===================================================================== | ||
15 | * Version: $Id$ | ||
16 | * ===================================================================== | ||
17 | * History: | ||
18 | * $Log$ | ||
19 | * Revision 1.1 2002/11/09 14:34:52 eilers | ||
20 | * Added VCard Backend. | ||
21 | * | ||
22 | */ | ||
23 | #ifndef __OCONTACTACCESSBACKEND_VCARD_H_ | ||
24 | #define __OCONTACTACCESSBACKEND_VCARD_H_ | ||
25 | |||
26 | #include <opie/ocontact.h> | ||
27 | |||
28 | #include "ocontactaccessbackend.h" | ||
29 | |||
30 | class VObject; | ||
31 | |||
32 | class OContactAccessBackend_VCard : public OContactAccessBackend { | ||
33 | public: | ||
34 | OContactAccessBackend_VCard ( QString appname, QString filename = 0l ); | ||
35 | |||
36 | bool load (); | ||
37 | bool reload(); | ||
38 | bool save(); | ||
39 | void clear (); | ||
40 | |||
41 | bool add ( const OContact& newcontact ); | ||
42 | bool remove ( int uid ); | ||
43 | bool replace ( const OContact& contact ); | ||
44 | |||
45 | OContact find ( int uid ) const; | ||
46 | QArray<int> allRecords() const; | ||
47 | QArray<int> queryByExample ( const OContact &query, int settings ); | ||
48 | QArray<int> matchRegexp( const QRegExp &r ) const; | ||
49 | |||
50 | const uint querySettings(); | ||
51 | bool hasQuerySettings (uint querySettings) const; | ||
52 | |||
53 | private: | ||
54 | OContact parseVObject( VObject* obj ); | ||
55 | VObject* createVObject( const OContact& c ); | ||
56 | QDate convVCardDateToDate( const QString& datestr ); | ||
57 | VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value ); | ||
58 | VObject *safeAddProp( VObject* o, const char* prop); | ||
59 | |||
60 | bool m_dirty : 1; | ||
61 | QString m_file; | ||
62 | QMap<int, OContact> m_map; | ||
63 | }; | ||
64 | |||
65 | #endif | ||