Diffstat (limited to 'libopie/pim/ocontactaccessbackend_xml.h') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie/pim/ocontactaccessbackend_xml.h | 550 |
1 files changed, 550 insertions, 0 deletions
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h new file mode 100644 index 0000000..2cdb45b --- a/dev/null +++ b/libopie/pim/ocontactaccessbackend_xml.h | |||
@@ -0,0 +1,550 @@ | |||
1 | /* | ||
2 | * XML 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: XML-Backend: Automatic reload if something was changed... | ||
13 | * | ||
14 | * | ||
15 | * ===================================================================== | ||
16 | * Version: $Id$ | ||
17 | * ===================================================================== | ||
18 | * History: | ||
19 | * $Log$ | ||
20 | * Revision 1.1 2002/09/27 17:11:44 eilers | ||
21 | * Added API for accessing the Contact-Database ! It is compiling, but | ||
22 | * please do not expect that anything is working ! | ||
23 | * I will debug that stuff in the next time .. | ||
24 | * Please read README_COMPILE for compiling ! | ||
25 | * | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef _OContactAccessBackend_XML_ | ||
30 | #define _OContactAccessBackend_XML_ | ||
31 | |||
32 | #include <qasciidict.h> | ||
33 | #include <qdatetime.h> | ||
34 | #include <qfile.h> | ||
35 | #include <qregexp.h> | ||
36 | #include <qarray.h> | ||
37 | |||
38 | #include <opie/xmltree.h> | ||
39 | #include "ocontactaccessbackend.h" | ||
40 | |||
41 | using namespace Opie; | ||
42 | |||
43 | /* the default xml implementation */ | ||
44 | class OContactAccessBackend_XML : public OContactAccessBackend { | ||
45 | public: | ||
46 | OContactAccessBackend_XML ( QString appname, QString filename = 0l ) | ||
47 | { | ||
48 | m_appName = appname; | ||
49 | |||
50 | /* Set journalfile name ... */ | ||
51 | m_journalName = getenv("HOME"); | ||
52 | m_journalName +="/.abjournal" + appname; | ||
53 | |||
54 | /* Expecting to access the default filename if nothing else is set */ | ||
55 | if ( filename.isEmpty() ){ | ||
56 | m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); | ||
57 | } else | ||
58 | m_fileName = filename; | ||
59 | |||
60 | /* Load Database now */ | ||
61 | load (); | ||
62 | } | ||
63 | |||
64 | bool save() { | ||
65 | QString strNewFile = m_fileName + ".new"; | ||
66 | QFile f( strNewFile ); | ||
67 | if ( !f.open( IO_WriteOnly|IO_Raw ) ) | ||
68 | return false; | ||
69 | |||
70 | int total_written; | ||
71 | QString out; | ||
72 | out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" | ||
73 | " <Groups>\n" | ||
74 | " </Groups>\n" | ||
75 | " <Contacts>\n"; | ||
76 | //QValueList<Contact>::iterator it; | ||
77 | QValueListConstIterator<OContact> it; | ||
78 | for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) { | ||
79 | out += "<Contact "; | ||
80 | (*it).save( out ); | ||
81 | out += "/>\n"; | ||
82 | QCString cstr = out.utf8(); | ||
83 | total_written = f.writeBlock( cstr.data(), cstr.length() ); | ||
84 | if ( total_written != int(cstr.length()) ) { | ||
85 | f.close(); | ||
86 | QFile::remove( strNewFile ); | ||
87 | return false; | ||
88 | } | ||
89 | out = ""; | ||
90 | } | ||
91 | out += " </Contacts>\n</AddressBook>\n"; | ||
92 | |||
93 | QCString cstr = out.utf8(); | ||
94 | total_written = f.writeBlock( cstr.data(), cstr.length() ); | ||
95 | if ( total_written != int( cstr.length() ) ) { | ||
96 | f.close(); | ||
97 | QFile::remove( strNewFile ); | ||
98 | return false; | ||
99 | } | ||
100 | f.close(); | ||
101 | |||
102 | // move the file over, I'm just going to use the system call | ||
103 | // because, I don't feel like using QDir. | ||
104 | if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { | ||
105 | qWarning( "problem renaming file %s to %s, errno: %d", | ||
106 | strNewFile.latin1(), m_journalName.latin1(), errno ); | ||
107 | // remove the tmp file... | ||
108 | QFile::remove( strNewFile ); | ||
109 | } | ||
110 | |||
111 | /* The journalfile should be removed now... */ | ||
112 | removeJournal(); | ||
113 | return true; | ||
114 | } | ||
115 | |||
116 | bool load () { | ||
117 | m_contactList.clear(); | ||
118 | |||
119 | /* Load XML-File and journal if it exists */ | ||
120 | if ( !load ( m_fileName, false ) ) | ||
121 | return false; | ||
122 | /* The returncode of the journalfile is ignored due to the | ||
123 | * fact that it does not exist when this class is instantiated ! | ||
124 | * But there may such a file exist, if the application crashed. | ||
125 | * Therefore we try to load it to get the changes before the # | ||
126 | * crash happened... | ||
127 | */ | ||
128 | load (m_journalName, true); | ||
129 | |||
130 | return true; | ||
131 | } | ||
132 | |||
133 | void clear () { | ||
134 | m_contactList.clear(); | ||
135 | |||
136 | } | ||
137 | |||
138 | bool wasChangedExternally() | ||
139 | { | ||
140 | QFileInfo fi( m_fileName ); | ||
141 | |||
142 | QDateTime lastmod = fi.lastModified (); | ||
143 | |||
144 | return (lastmod != m_readtime); | ||
145 | } | ||
146 | |||
147 | QArray<int> allRecords() const { | ||
148 | QArray<int> uid_list( m_contactList.count() ); | ||
149 | |||
150 | uint counter = 0; | ||
151 | QValueListConstIterator<OContact> it; | ||
152 | for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ | ||
153 | uid_list[counter++] = (*it).uid(); | ||
154 | } | ||
155 | |||
156 | return ( uid_list ); | ||
157 | } | ||
158 | |||
159 | OContact find ( int uid ) const | ||
160 | { | ||
161 | bool found = false; | ||
162 | OContact foundContact; //Create empty contact | ||
163 | |||
164 | QValueListConstIterator<OContact> it; | ||
165 | for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ | ||
166 | if ((*it).uid() == uid){ | ||
167 | found = true; | ||
168 | break; | ||
169 | } | ||
170 | } | ||
171 | if ( found ){ | ||
172 | foundContact = *it; | ||
173 | } | ||
174 | |||
175 | return ( foundContact ); | ||
176 | } | ||
177 | |||
178 | QArray<int> queryByExample ( const OContact &query, int settings ){ | ||
179 | |||
180 | QArray<int> m_currentQuery( m_contactList.count() ); | ||
181 | QValueListConstIterator<OContact> it; | ||
182 | uint arraycounter = 0; | ||
183 | |||
184 | for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ | ||
185 | /* Search all fields and compare them with query object. Store them into list | ||
186 | * if all fields matches. | ||
187 | */ | ||
188 | bool allcorrect = true; | ||
189 | for ( int i = 0; i < Qtopia::rid; i++ ) { | ||
190 | /* Just compare fields which are not empty in the query object */ | ||
191 | if ( !query.field(i).isEmpty() ){ | ||
192 | switch ( settings & ~OContactAccess::query_IgnoreCase ){ | ||
193 | case OContactAccess::query_RegExp:{ | ||
194 | QRegExp expr ( query.field(i), | ||
195 | !(settings & OContactAccess::query_IgnoreCase), | ||
196 | false ); | ||
197 | if ( expr.find ( (*it).field(i), 0 ) == -1 ) | ||
198 | allcorrect = false; | ||
199 | } | ||
200 | break; | ||
201 | case OContactAccess::query_WildCards:{ | ||
202 | QRegExp expr ( query.field(i), | ||
203 | !(settings & OContactAccess::query_IgnoreCase), | ||
204 | true ); | ||
205 | if ( expr.find ( (*it).field(i), 0 ) == -1 ) | ||
206 | allcorrect = false; | ||
207 | } | ||
208 | break; | ||
209 | case OContactAccess::query_ExactMatch:{ | ||
210 | if (settings & OContactAccess::query_IgnoreCase){ | ||
211 | if ( query.field(i).upper() != | ||
212 | (*it).field(i).upper() ) | ||
213 | allcorrect = false; | ||
214 | }else{ | ||
215 | if ( query.field(i) != (*it).field(i) ) | ||
216 | allcorrect = false; | ||
217 | } | ||
218 | } | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | if ( allcorrect ){ | ||
224 | m_currentQuery[arraycounter++] = (*it).uid(); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | // Shrink to fit.. | ||
229 | m_currentQuery.resize(arraycounter); | ||
230 | |||
231 | return m_currentQuery; | ||
232 | } | ||
233 | |||
234 | const uint querySettings() | ||
235 | { | ||
236 | return ( OContactAccess::query_WildCards | ||
237 | & OContactAccess::query_IgnoreCase | ||
238 | & OContactAccess::query_RegExp | ||
239 | & OContactAccess::query_ExactMatch ); | ||
240 | } | ||
241 | |||
242 | bool hasQuerySettings (uint querySettings) const | ||
243 | { | ||
244 | /* OContactAccess::query_IgnoreCase may be added with one | ||
245 | * of the other settings, but never used alone. | ||
246 | * The other settings are just valid alone... | ||
247 | */ | ||
248 | switch ( querySettings & ~OContactAccess::query_IgnoreCase ){ | ||
249 | case OContactAccess::query_RegExp: | ||
250 | return ( true ); | ||
251 | case OContactAccess::query_WildCards: | ||
252 | return ( true ); | ||
253 | case OContactAccess::query_ExactMatch: | ||
254 | return ( true ); | ||
255 | default: | ||
256 | return ( false ); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | bool add ( const OContact &newcontact ) | ||
261 | { | ||
262 | //qWarning("odefaultbackend: ACTION::ADD"); | ||
263 | updateJournal (newcontact, OContact::ACTION_ADD); | ||
264 | addContact_p( newcontact ); | ||
265 | return true; | ||
266 | } | ||
267 | |||
268 | bool replace ( const OContact &contact ) | ||
269 | { | ||
270 | bool found = false; | ||
271 | |||
272 | QValueListIterator<OContact> it; | ||
273 | for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ | ||
274 | if ( (*it).uid() == contact.uid() ){ | ||
275 | found = true; | ||
276 | break; | ||
277 | } | ||
278 | } | ||
279 | if (found) { | ||
280 | updateJournal (contact, OContact::ACTION_REPLACE); | ||
281 | m_contactList.remove (it); | ||
282 | m_contactList.append (contact); | ||
283 | return true; | ||
284 | } else | ||
285 | return false; | ||
286 | } | ||
287 | |||
288 | bool remove ( int uid ) | ||
289 | { | ||
290 | bool found = false; | ||
291 | QValueListIterator<OContact> it; | ||
292 | for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ | ||
293 | if ((*it).uid() == uid){ | ||
294 | found = true; | ||
295 | break; | ||
296 | } | ||
297 | } | ||
298 | if (found) { | ||
299 | updateJournal ( *it, OContact::ACTION_REMOVE); | ||
300 | m_contactList.remove (it); | ||
301 | return true; | ||
302 | } else | ||
303 | return false; | ||
304 | } | ||
305 | |||
306 | bool reload(){ | ||
307 | /* Reload is the same as load in this implementation */ | ||
308 | return ( load() ); | ||
309 | } | ||
310 | |||
311 | private: | ||
312 | void addContact_p( const OContact &newcontact ){ | ||
313 | m_contactList.append (newcontact); | ||
314 | } | ||
315 | |||
316 | /* This function loads the xml-database and the journalfile */ | ||
317 | bool load( const QString filename, bool isJournal ) { | ||
318 | |||
319 | /* We use the time of the last read to check if the file was | ||
320 | * changed externally. | ||
321 | */ | ||
322 | if ( !isJournal ){ | ||
323 | QFileInfo fi( filename ); | ||
324 | m_readtime = fi.lastModified (); | ||
325 | } | ||
326 | |||
327 | const int JOURNALACTION = Qtopia::Notes + 1; | ||
328 | const int JOURNALROW = JOURNALACTION + 1; | ||
329 | |||
330 | bool foundAction = false; | ||
331 | OContact::journal_action action = OContact::ACTION_ADD; | ||
332 | int journalKey = 0; | ||
333 | QMap<int, QString> contactMap; | ||
334 | QMap<QString, QString> customMap; | ||
335 | QMap<QString, QString>::Iterator customIt; | ||
336 | QAsciiDict<int> dict( 47 ); | ||
337 | |||
338 | dict.setAutoDelete( TRUE ); | ||
339 | dict.insert( "Uid", new int(Qtopia::AddressUid) ); | ||
340 | dict.insert( "Title", new int(Qtopia::Title) ); | ||
341 | dict.insert( "FirstName", new int(Qtopia::FirstName) ); | ||
342 | dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); | ||
343 | dict.insert( "LastName", new int(Qtopia::LastName) ); | ||
344 | dict.insert( "Suffix", new int(Qtopia::Suffix) ); | ||
345 | dict.insert( "FileAs", new int(Qtopia::FileAs) ); | ||
346 | dict.insert( "Categories", new int(Qtopia::AddressCategory) ); | ||
347 | dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); | ||
348 | dict.insert( "Emails", new int(Qtopia::Emails) ); | ||
349 | dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); | ||
350 | dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); | ||
351 | dict.insert( "HomeState", new int(Qtopia::HomeState) ); | ||
352 | dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); | ||
353 | dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); | ||
354 | dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); | ||
355 | dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); | ||
356 | dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); | ||
357 | dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); | ||
358 | dict.insert( "Company", new int(Qtopia::Company) ); | ||
359 | dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); | ||
360 | dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); | ||
361 | dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); | ||
362 | dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); | ||
363 | dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); | ||
364 | dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); | ||
365 | dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); | ||
366 | dict.insert( "Department", new int(Qtopia::Department) ); | ||
367 | dict.insert( "Office", new int(Qtopia::Office) ); | ||
368 | dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); | ||
369 | dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); | ||
370 | dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); | ||
371 | dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); | ||
372 | dict.insert( "Profession", new int(Qtopia::Profession) ); | ||
373 | dict.insert( "Assistant", new int(Qtopia::Assistant) ); | ||
374 | dict.insert( "Manager", new int(Qtopia::Manager) ); | ||
375 | dict.insert( "Spouse", new int(Qtopia::Spouse) ); | ||
376 | dict.insert( "Children", new int(Qtopia::Children) ); | ||
377 | dict.insert( "Gender", new int(Qtopia::Gender) ); | ||
378 | dict.insert( "Birthday", new int(Qtopia::Birthday) ); | ||
379 | dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); | ||
380 | dict.insert( "Nickname", new int(Qtopia::Nickname) ); | ||
381 | dict.insert( "Notes", new int(Qtopia::Notes) ); | ||
382 | dict.insert( "action", new int(JOURNALACTION) ); | ||
383 | dict.insert( "actionrow", new int(JOURNALROW) ); | ||
384 | |||
385 | //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); | ||
386 | |||
387 | XMLElement *root = XMLElement::load( filename ); | ||
388 | if(root != 0l ){ // start parsing | ||
389 | /* Parse all XML-Elements and put the data into the | ||
390 | * Contact-Class | ||
391 | */ | ||
392 | XMLElement *element = root->firstChild(); | ||
393 | //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() ); | ||
394 | element = element->firstChild(); | ||
395 | |||
396 | /* Search Tag "Contacts" which is the parent of all Contacts */ | ||
397 | while( element && !isJournal ){ | ||
398 | if( element->tagName() != QString::fromLatin1("Contacts") ){ | ||
399 | //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s", | ||
400 | // element->tagName().latin1()); | ||
401 | element = element->nextChild(); | ||
402 | } else { | ||
403 | element = element->firstChild(); | ||
404 | break; | ||
405 | } | ||
406 | } | ||
407 | /* Parse all Contacts and ignore unknown tags */ | ||
408 | while( element ){ | ||
409 | if( element->tagName() != QString::fromLatin1("Contact") ){ | ||
410 | //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s", | ||
411 | // element->tagName().latin1()); | ||
412 | element = element->nextChild(); | ||
413 | continue; | ||
414 | } | ||
415 | /* Found alement with tagname "contact", now parse and store all | ||
416 | * attributes contained | ||
417 | */ | ||
418 | //qWarning("OContactDefBack::load element tagName() : %s", | ||
419 | // element->tagName().latin1() ); | ||
420 | QString dummy; | ||
421 | foundAction = false; | ||
422 | |||
423 | XMLElement::AttributeMap aMap = element->attributes(); | ||
424 | XMLElement::AttributeMap::Iterator it; | ||
425 | contactMap.clear(); | ||
426 | customMap.clear(); | ||
427 | for( it = aMap.begin(); it != aMap.end(); ++it ){ | ||
428 | // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1()); | ||
429 | |||
430 | int *find = dict[ it.key() ]; | ||
431 | /* Unknown attributes will be stored as "Custom" elements */ | ||
432 | if ( !find ) { | ||
433 | qWarning("Attribute %s not known.", it.key().latin1()); | ||
434 | //contact.setCustomField(it.key(), it.data()); | ||
435 | customMap.insert( it.key(), it.data() ); | ||
436 | continue; | ||
437 | } | ||
438 | |||
439 | /* Check if special conversion is needed and add attribute | ||
440 | * into Contact class | ||
441 | */ | ||
442 | switch( *find ) { | ||
443 | /* | ||
444 | case Qtopia::AddressUid: | ||
445 | contact.setUid( it.data().toInt() ); | ||
446 | break; | ||
447 | case Qtopia::AddressCategory: | ||
448 | contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); | ||
449 | break; | ||
450 | */ | ||
451 | case JOURNALACTION: | ||
452 | action = OContact::journal_action(it.data().toInt()); | ||
453 | foundAction = true; | ||
454 | qWarning ("ODefBack(journal)::ACTION found: %d", action); | ||
455 | break; | ||
456 | case JOURNALROW: | ||
457 | journalKey = it.data().toInt(); | ||
458 | break; | ||
459 | default: // no conversion needed add them to the map | ||
460 | contactMap.insert( *find, it.data() ); | ||
461 | break; | ||
462 | } | ||
463 | } | ||
464 | /* now generate the Contact contact */ | ||
465 | OContact contact( contactMap ); | ||
466 | |||
467 | for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { | ||
468 | contact.setCustomField( customIt.key(), customIt.data() ); | ||
469 | } | ||
470 | |||
471 | if (foundAction){ | ||
472 | foundAction = false; | ||
473 | switch ( action ) { | ||
474 | case OContact::ACTION_ADD: | ||
475 | addContact_p (contact); | ||
476 | break; | ||
477 | case OContact::ACTION_REMOVE: | ||
478 | if ( !remove (contact.uid()) ) | ||
479 | qWarning ("ODefBack(journal)::Unable to remove uid: %d", | ||
480 | contact.uid() ); | ||
481 | break; | ||
482 | case OContact::ACTION_REPLACE: | ||
483 | if ( !replace ( contact ) ) | ||
484 | qWarning ("ODefBack(journal)::Unable to replace uid: %d", | ||
485 | contact.uid() ); | ||
486 | break; | ||
487 | default: | ||
488 | qWarning ("Unknown action: ignored !"); | ||
489 | break; | ||
490 | } | ||
491 | }else{ | ||
492 | /* Add contact to list */ | ||
493 | addContact_p (contact); | ||
494 | } | ||
495 | |||
496 | /* Move to next element */ | ||
497 | element = element->nextChild(); | ||
498 | } | ||
499 | }else { | ||
500 | qWarning("ODefBack::could not load"); | ||
501 | } | ||
502 | delete root; | ||
503 | qWarning("returning from loading" ); | ||
504 | return true; | ||
505 | } | ||
506 | |||
507 | |||
508 | void updateJournal( const OContact& cnt, | ||
509 | OContact::journal_action action ) { | ||
510 | QFile f( m_journalName ); | ||
511 | bool created = !f.exists(); | ||
512 | if ( !f.open(IO_WriteOnly|IO_Append) ) | ||
513 | return; | ||
514 | |||
515 | QString buf; | ||
516 | QCString str; | ||
517 | |||
518 | // if the file was created, we have to set the Tag "<CONTACTS>" to | ||
519 | // get a XML-File which is readable by our parser. | ||
520 | // This is just a cheat, but better than rewrite the parser. | ||
521 | if ( created ){ | ||
522 | buf = "<Contacts>"; | ||
523 | QCString cstr = buf.utf8(); | ||
524 | f.writeBlock( cstr.data(), cstr.length() ); | ||
525 | } | ||
526 | |||
527 | buf = "<Contact "; | ||
528 | cnt.save( buf ); | ||
529 | buf += " action=\"" + QString::number( (int)action ) + "\" "; | ||
530 | buf += "/>\n"; | ||
531 | QCString cstr = buf.utf8(); | ||
532 | f.writeBlock( cstr.data(), cstr.length() ); | ||
533 | } | ||
534 | |||
535 | void removeJournal() | ||
536 | { | ||
537 | QFile f ( m_journalName ); | ||
538 | if ( f.exists() ) | ||
539 | f.remove(); | ||
540 | } | ||
541 | |||
542 | protected: | ||
543 | QString m_journalName; | ||
544 | QString m_fileName; | ||
545 | QString m_appName; | ||
546 | QValueList<OContact> m_contactList; | ||
547 | QDateTime m_readtime; | ||
548 | }; | ||
549 | |||
550 | #endif | ||