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