summaryrefslogtreecommitdiff
path: root/libopie
authoreilers <eilers>2002-10-16 10:52:40 (UTC)
committer eilers <eilers>2002-10-16 10:52:40 (UTC)
commitf9756ca203a06fa60413ef1a96416d87b9dc1a6b (patch) (unidiff)
tree0b67c3c485349a1c31ea82e7c12526b990654d58 /libopie
parent9eba62fc184260f1a0455a6dd057e2ccebf4bdac (diff)
downloadopie-f9756ca203a06fa60413ef1a96416d87b9dc1a6b.zip
opie-f9756ca203a06fa60413ef1a96416d87b9dc1a6b.tar.gz
opie-f9756ca203a06fa60413ef1a96416d87b9dc1a6b.tar.bz2
Added some docu to the interface and now using the cache infrastucture by zecke.. :)
Diffstat (limited to 'libopie') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/ocontactaccess.cpp57
-rw-r--r--libopie/pim/ocontactaccess.h43
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h21
-rw-r--r--libopie/pim/opimaccesstemplate.h27
4 files changed, 55 insertions, 93 deletions
diff --git a/libopie/pim/ocontactaccess.cpp b/libopie/pim/ocontactaccess.cpp
index e8c0a45..2ca0283 100644
--- a/libopie/pim/ocontactaccess.cpp
+++ b/libopie/pim/ocontactaccess.cpp
@@ -1,188 +1,153 @@
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.5 2002/10/16 10:52:40 eilers
25 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
26 *
24 * Revision 1.4 2002/10/14 16:21:54 eilers 27 * Revision 1.4 2002/10/14 16:21:54 eilers
25 * Some minor interface updates 28 * Some minor interface updates
26 * 29 *
27 * Revision 1.3 2002/10/07 17:34:24 eilers 30 * Revision 1.3 2002/10/07 17:34:24 eilers
28 * added OBackendFactory for advanced backend access 31 * added OBackendFactory for advanced backend access
29 * 32 *
30 * Revision 1.2 2002/10/02 16:18:11 eilers 33 * Revision 1.2 2002/10/02 16:18:11 eilers
31 * debugged and seems to work almost perfectly .. 34 * debugged and seems to work almost perfectly ..
32 * 35 *
33 * Revision 1.1 2002/09/27 17:11:44 eilers 36 * Revision 1.1 2002/09/27 17:11:44 eilers
34 * Added API for accessing the Contact-Database ! It is compiling, but 37 * Added API for accessing the Contact-Database ! It is compiling, but
35 * please do not expect that anything is working ! 38 * please do not expect that anything is working !
36 * I will debug that stuff in the next time .. 39 * I will debug that stuff in the next time ..
37 * Please read README_COMPILE for compiling ! 40 * Please read README_COMPILE for compiling !
38 * 41 *
39 * 42 *
40 */ 43 */
41 44
42#include "ocontactaccess.h" 45#include "ocontactaccess.h"
43#include "obackendfactory.h" 46#include "obackendfactory.h"
44 47
45#include <qasciidict.h> 48#include <qasciidict.h>
46#include <qdatetime.h> 49#include <qdatetime.h>
47#include <qfile.h> 50#include <qfile.h>
48#include <qregexp.h> 51#include <qregexp.h>
49#include <qlist.h> 52#include <qlist.h>
50#include <qcopchannel_qws.h> 53#include <qcopchannel_qws.h>
51 54
52//#include <qpe/qcopenvelope_qws.h> 55//#include <qpe/qcopenvelope_qws.h>
53#include <qpe/global.h> 56#include <qpe/global.h>
54 57
55#include <errno.h> 58#include <errno.h>
56#include <fcntl.h> 59#include <fcntl.h>
57#include <unistd.h> 60#include <unistd.h>
58#include <stdlib.h> 61#include <stdlib.h>
59 62
60#include "ocontactaccessbackend_xml.h" 63#include "ocontactaccessbackend_xml.h"
61 64
62 65
63OContactAccess::OContactAccess ( const QString appname, const QString , 66OContactAccess::OContactAccess ( const QString appname, const QString ,
64 OContactAccessBackend* end, bool autosync ): 67 OContactAccessBackend* end, bool autosync ):
65 OPimAccessTemplate<OContact>( end ), 68 OPimAccessTemplate<OContact>( end )
66 m_changed ( false )
67{ 69{
68 /* take care of the backend. If there is no one defined, we 70 /* take care of the backend. If there is no one defined, we
69 * will use the XML-Backend as default (until we have a cute SQL-Backend..). 71 * will use the XML-Backend as default (until we have a cute SQL-Backend..).
70 */ 72 */
71 if( end == 0 ) { 73 if( end == 0 ) {
72 qWarning ("Using BackendFactory !"); 74 qWarning ("Using BackendFactory !");
73 end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname ); 75 end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname );
74 } 76 }
75 // Set backend locally and in template 77 // Set backend locally and in template
76 m_backEnd = end; 78 m_backEnd = end;
77 OPimAccessTemplate<OContact>::setBackEnd (end); 79 OPimAccessTemplate<OContact>::setBackEnd (end);
78 80
79 81
80 /* Connect signal of external db change to function */ 82 /* Connect signal of external db change to function */
81 QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this ); 83 QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this );
82 connect( dbchannel, SIGNAL(received(const QCString &, const QByteArray &)), 84 connect( dbchannel, SIGNAL(received(const QCString &, const QByteArray &)),
83 this, SLOT(copMessage( const QCString &, const QByteArray &)) ); 85 this, SLOT(copMessage( const QCString &, const QByteArray &)) );
84 if ( autosync ){ 86 if ( autosync ){
85 QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this ); 87 QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this );
86 connect( syncchannel, SIGNAL(received(const QCString &, const QByteArray &)), 88 connect( syncchannel, SIGNAL(received(const QCString &, const QByteArray &)),
87 this, SLOT(copMessage( const QCString &, const QByteArray &)) ); 89 this, SLOT(copMessage( const QCString &, const QByteArray &)) );
88 } 90 }
89 91
90 92
91} 93}
92OContactAccess::~OContactAccess () 94OContactAccess::~OContactAccess ()
93{ 95{
94 /* The user may forget to save the changed database, therefore try to 96 /* The user may forget to save the changed database, therefore try to
95 * do it for him.. 97 * do it for him..
96 */ 98 */
97 if ( m_changed ) 99 save();
98 save();
99 // delete m_backEnd; is done by template.. 100 // delete m_backEnd; is done by template..
100} 101}
101 102
102bool OContactAccess::load()
103{
104 return ( m_backEnd->load() );
105}
106 103
107bool OContactAccess::save () 104bool OContactAccess::save ()
108{ 105{
109 /* If the database was changed externally, we could not save the 106 /* If the database was changed externally, we could not save the
110 * Data. This will remove added items which is unacceptable ! 107 * Data. This will remove added items which is unacceptable !
111 * Therefore: Reload database and merge the data... 108 * Therefore: Reload database and merge the data...
112 */ 109 */
113 if ( m_backEnd->wasChangedExternally() ) 110 if ( OPimAccessTemplate<OContact>::wasChangedExternally() )
114 reload(); 111 reload();
115 112
116 if ( m_changed ){ 113 bool status = OPimAccessTemplate<OContact>::save();
117 bool status = m_backEnd->save(); 114 if ( !status ) return false;
118 if ( !status ) return false;
119 115
120 m_changed = false; 116 /* Now tell everyone that new data is available.
121 /* Now tell everyone that new data is available. 117 */
122 */ 118 QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
123 QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
124
125 }
126 119
127 return true; 120 return true;
128} 121}
129 122
130const uint OContactAccess::querySettings() 123const uint OContactAccess::querySettings()
131{ 124{
132 return ( m_backEnd->querySettings() ); 125 return ( m_backEnd->querySettings() );
133} 126}
134 127
135bool OContactAccess::hasQuerySettings ( int querySettings ) const 128bool OContactAccess::hasQuerySettings ( int querySettings ) const
136{ 129{
137 return ( m_backEnd->hasQuerySettings ( querySettings ) ); 130 return ( m_backEnd->hasQuerySettings ( querySettings ) );
138} 131}
139 132
140bool OContactAccess::add ( const OContact& newcontact )
141{
142 m_changed = true;
143 return ( m_backEnd->add ( newcontact ) );
144}
145
146bool OContactAccess::replace ( const OContact& contact )
147{
148 m_changed = true;
149 return ( m_backEnd->replace ( contact ) );
150}
151
152bool OContactAccess::remove ( const OContact& t )
153{
154 m_changed = true;
155 return ( m_backEnd->remove ( t.uid() ) );
156}
157
158bool OContactAccess::remove ( int uid )
159{
160 m_changed = true;
161 return ( m_backEnd->remove ( uid ) );
162}
163 133
164bool OContactAccess::wasChangedExternally()const 134bool OContactAccess::wasChangedExternally()const
165{ 135{
166 return ( m_backEnd->wasChangedExternally() ); 136 return ( m_backEnd->wasChangedExternally() );
167} 137}
168 138
169 139
170bool OContactAccess::reload()
171{
172 return ( m_backEnd->reload() );
173}
174
175void OContactAccess::copMessage( const QCString &msg, const QByteArray & ) 140void OContactAccess::copMessage( const QCString &msg, const QByteArray & )
176{ 141{
177 if ( msg == "addressbookUpdated()" ){ 142 if ( msg == "addressbookUpdated()" ){
178 qWarning ("OContactAccess: Received addressbokUpdated()"); 143 qWarning ("OContactAccess: Received addressbokUpdated()");
179 emit signalChanged ( this ); 144 emit signalChanged ( this );
180 } else if ( msg == "flush()" ) { 145 } else if ( msg == "flush()" ) {
181 qWarning ("OContactAccess: Received flush()"); 146 qWarning ("OContactAccess: Received flush()");
182 save (); 147 save ();
183 } else if ( msg == "reload()" ) { 148 } else if ( msg == "reload()" ) {
184 qWarning ("OContactAccess: Received reload()"); 149 qWarning ("OContactAccess: Received reload()");
185 reload (); 150 reload ();
186 emit signalChanged ( this ); 151 emit signalChanged ( this );
187 } 152 }
188} 153}
diff --git a/libopie/pim/ocontactaccess.h b/libopie/pim/ocontactaccess.h
index adc66cf..da9c942 100644
--- a/libopie/pim/ocontactaccess.h
+++ b/libopie/pim/ocontactaccess.h
@@ -1,168 +1,131 @@
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 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org) 5 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
6 * 6 *
7 * ===================================================================== 7 * =====================================================================
8 *This program is free software; you can redistribute it and/or 8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public 9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; 10 * License as published by the Free Software Foundation;
11 * either version 2 of the License, or (at your option) any later 11 * either version 2 of the License, or (at your option) any later
12 * version. 12 * version.
13 * ===================================================================== 13 * =====================================================================
14 * ToDo: Define enum for query settings 14 * ToDo: Define enum for query settings
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.3 2002/10/16 10:52:40 eilers
21 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
22 *
20 * Revision 1.2 2002/10/14 16:21:54 eilers 23 * Revision 1.2 2002/10/14 16:21:54 eilers
21 * Some minor interface updates 24 * Some minor interface updates
22 * 25 *
23 * Revision 1.1 2002/09/27 17:11:44 eilers 26 * Revision 1.1 2002/09/27 17:11:44 eilers
24 * Added API for accessing the Contact-Database ! It is compiling, but 27 * Added API for accessing the Contact-Database ! It is compiling, but
25 * please do not expect that anything is working ! 28 * please do not expect that anything is working !
26 * I will debug that stuff in the next time .. 29 * I will debug that stuff in the next time ..
27 * Please read README_COMPILE for compiling ! 30 * Please read README_COMPILE for compiling !
28 * 31 *
29 * ===================================================================== 32 * =====================================================================
30 */ 33 */
31#ifndef _OCONTACTACCESS_H 34#ifndef _OCONTACTACCESS_H
32#define _OCONTACTACCESS_H 35#define _OCONTACTACCESS_H
33 36
34#include <qobject.h> 37#include <qobject.h>
35 38
36#include <qpe/qcopenvelope_qws.h> 39#include <qpe/qcopenvelope_qws.h>
37 40
38#include <qvaluelist.h> 41#include <qvaluelist.h>
39#include <qfileinfo.h> 42#include <qfileinfo.h>
40 43
41#include "ocontact.h" 44#include "ocontact.h"
42#include "ocontactaccessbackend.h" 45#include "ocontactaccessbackend.h"
43#include "opimaccesstemplate.h" 46#include "opimaccesstemplate.h"
44 47
45/** Class to access the contacts database. 48/** Class to access the contacts database.
46 * This is just a frontend for the real database handling which is 49 * This is just a frontend for the real database handling which is
47 * done by the backend. 50 * done by the backend.
48 */ 51 */
49class OContactAccess: public QObject, public OPimAccessTemplate<OContact> 52class OContactAccess: public QObject, public OPimAccessTemplate<OContact>
50{ 53{
51 Q_OBJECT 54 Q_OBJECT
52 55
53 public: 56 public:
54 /** Create Database with contacts (addressbook). 57 /** Create Database with contacts (addressbook).
55 * @param appname Name of application which wants access to the database 58 * @param appname Name of application which wants access to the database
56 * (i.e. "todolist") 59 * (i.e. "todolist")
57 * @param filename The name of the database file. If not set, the default one 60 * @param filename The name of the database file. If not set, the default one
58 * is used. 61 * is used.
59 * @param backend Pointer to an alternative Backend. If not set, we will use 62 * @param backend Pointer to an alternative Backend. If not set, we will use
60 * the default backend. 63 * the default backend.
61 * @param handlesync If <b>true</b> the database stores the current state 64 * @param handlesync If <b>true</b> the database stores the current state
62 * automatically if it receives the signals <i>flush()</i> and <i>reload()</i> 65 * automatically if it receives the signals <i>flush()</i> and <i>reload()</i>
63 * which are used before and after synchronisation. If the application wants 66 * which are used before and after synchronisation. If the application wants
64 * to react itself, it should be disabled by setting it to <b>false</b> 67 * to react itself, it should be disabled by setting it to <b>false</b>
65 * @see OContactAccessBackend 68 * @see OContactAccessBackend
66 */ 69 */
67 OContactAccess (const QString appname, const QString filename = 0l, 70 OContactAccess (const QString appname, const QString filename = 0l,
68 OContactAccessBackend* backend = 0l, bool handlesync = true); 71 OContactAccessBackend* backend = 0l, bool handlesync = true);
69 ~OContactAccess (); 72 ~OContactAccess ();
70 73
71 /** Constants for query. 74 /** Constants for query.
72 * Use this constants to set the query parameters. 75 * Use this constants to set the query parameters.
73 * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes ! 76 * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes !
74 * @see queryByExample() 77 * @see queryByExample()
75 */ 78 */
76 enum QuerySettings { 79 enum QuerySettings {
77 WildCards = 0x0001, 80 WildCards = 0x0001,
78 IgnoreCase = 0x0002, 81 IgnoreCase = 0x0002,
79 RegExp = 0x0004, 82 RegExp = 0x0004,
80 ExactMatch = 0x0008, 83 ExactMatch = 0x0008,
81 }; 84 };
82 85
83 /** Return all possible settings. 86 /** Return all possible settings.
84 * @return All settings provided by the current backend 87 * @return All settings provided by the current backend
85 * (i.e.: query_WildCards & query_IgnoreCase) 88 * (i.e.: query_WildCards & query_IgnoreCase)
86 */ 89 */
87 const uint querySettings(); 90 const uint querySettings();
88 91
89 /** Check whether settings are correct. 92 /** Check whether settings are correct.
90 * @return <i>true</i> if the given settings are correct and possible. 93 * @return <i>true</i> if the given settings are correct and possible.
91 */ 94 */
92 bool hasQuerySettings ( int querySettings ) const; 95 bool hasQuerySettings ( int querySettings ) const;
93 96
94 /** Add Contact to database.
95 * @param newcontact The contact to add.
96 * @return <i>true</i> if added successfully.
97 */
98 bool add (const OContact& newcontact);
99
100 /** Replace contact.
101 * Replaces given contact with contact with the user id <i>uid</i>.
102 * @param uid The user ID
103 * @param contact The new contact
104 * @return <i>true</i> if successful.
105 */
106 bool replace ( const OContact& contact );
107
108 /** Remove contact.
109 * Removes contact with the user id <i>uid</i>.
110 * @param The contact to remove
111 * @return <i>true</i> if successful.
112 */
113 bool remove ( const OContact& t );
114
115 /** Remove contact.
116 * Removes contact with the user id <i>uid</i>.
117 * @param The user id of the contact to remove
118 * @return <i>true</i> if successful.
119 */
120 bool remove ( int uid );
121
122 /** Load Database *
123 */
124 bool load();
125
126 /** 97 /**
127 * if the resource was changed externally. 98 * if the resource was changed externally.
128 * You should use the signal instead of polling possible changes ! 99 * You should use the signal instead of polling possible changes !
129 */ 100 */
130 bool wasChangedExternally()const; 101 bool wasChangedExternally()const;
131 102
132 /** Reload database.
133 * You should execute this function if the external database
134 * was changed.
135 * This function will load the external database and afterwards
136 * rejoin the local changes. Therefore the local database will be set consistent.
137 */
138 bool reload();
139 103
140 /** Save contacts database. 104 /** Save contacts database.
141 * Save is more a "commit". After calling this function, all changes are public available. 105 * Save is more a "commit". After calling this function, all changes are public available.
142 * @return true if successful 106 * @return true if successful
143 */ 107 */
144 bool save(); 108 bool save();
145 109
146 signals: 110 signals:
147 /* Signal is emitted if the database was changed. Therefore 111 /* Signal is emitted if the database was changed. Therefore
148 * we may need to reload to stay consistent. 112 * we may need to reload to stay consistent.
149 * @param which Pointer to the database who created this event. This pointer 113 * @param which Pointer to the database who created this event. This pointer
150 * is useful if an application has to handle multiple databases at the same time. 114 * is useful if an application has to handle multiple databases at the same time.
151 * @see reload() 115 * @see reload()
152 */ 116 */
153 void signalChanged ( const OContactAccess *which ); 117 void signalChanged ( const OContactAccess *which );
154 118
155 119
156 private: 120 private:
157 // class OContactAccessPrivate; 121 // class OContactAccessPrivate;
158 // OContactAccessPrivate* d; 122 // OContactAccessPrivate* d;
159 OContactAccessBackend *m_backEnd; 123 OContactAccessBackend *m_backEnd;
160 bool m_loading:1; 124 bool m_loading:1;
161 bool m_changed;
162 125
163 private slots: 126 private slots:
164 void copMessage( const QCString &msg, const QByteArray &data ); 127 void copMessage( const QCString &msg, const QByteArray &data );
165 128
166 129
167}; 130};
168#endif 131#endif
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
index 50ea329..12a75ba 100644
--- a/libopie/pim/ocontactaccessbackend_xml.h
+++ b/libopie/pim/ocontactaccessbackend_xml.h
@@ -1,398 +1,416 @@
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.4 2002/10/16 10:52:40 eilers
21 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
22 *
20 * Revision 1.3 2002/10/14 16:21:54 eilers 23 * Revision 1.3 2002/10/14 16:21:54 eilers
21 * Some minor interface updates 24 * Some minor interface updates
22 * 25 *
23 * Revision 1.2 2002/10/07 17:34:24 eilers 26 * Revision 1.2 2002/10/07 17:34:24 eilers
24 * added OBackendFactory for advanced backend access 27 * added OBackendFactory for advanced backend access
25 * 28 *
26 * Revision 1.1 2002/09/27 17:11:44 eilers 29 * Revision 1.1 2002/09/27 17:11:44 eilers
27 * Added API for accessing the Contact-Database ! It is compiling, but 30 * Added API for accessing the Contact-Database ! It is compiling, but
28 * please do not expect that anything is working ! 31 * please do not expect that anything is working !
29 * I will debug that stuff in the next time .. 32 * I will debug that stuff in the next time ..
30 * Please read README_COMPILE for compiling ! 33 * Please read README_COMPILE for compiling !
31 * 34 *
32 * 35 *
33 */ 36 */
34 37
35#ifndef _OContactAccessBackend_XML_ 38#ifndef _OContactAccessBackend_XML_
36#define _OContactAccessBackend_XML_ 39#define _OContactAccessBackend_XML_
37 40
38#include <qasciidict.h> 41#include <qasciidict.h>
39#include <qdatetime.h> 42#include <qdatetime.h>
40#include <qfile.h> 43#include <qfile.h>
41#include <qfileinfo.h> 44#include <qfileinfo.h>
42#include <qregexp.h> 45#include <qregexp.h>
43#include <qarray.h> 46#include <qarray.h>
44 47
45#include <qpe/global.h> 48#include <qpe/global.h>
46 49
47#include <opie/xmltree.h> 50#include <opie/xmltree.h>
48#include "ocontactaccessbackend.h" 51#include "ocontactaccessbackend.h"
49#include "ocontactaccess.h" 52#include "ocontactaccess.h"
50 53
51#include <stdlib.h> 54#include <stdlib.h>
52#include <errno.h> 55#include <errno.h>
53 56
54using namespace Opie; 57using namespace Opie;
55 58
56/* the default xml implementation */ 59/* the default xml implementation */
57class OContactAccessBackend_XML : public OContactAccessBackend { 60class OContactAccessBackend_XML : public OContactAccessBackend {
58 public: 61 public:
59 OContactAccessBackend_XML ( QString appname, QString filename = 0l ) 62 OContactAccessBackend_XML ( QString appname, QString filename = 0l ):
63 m_changed( false )
60 { 64 {
61 m_appName = appname; 65 m_appName = appname;
62 66
63 /* Set journalfile name ... */ 67 /* Set journalfile name ... */
64 m_journalName = getenv("HOME"); 68 m_journalName = getenv("HOME");
65 m_journalName +="/.abjournal" + appname; 69 m_journalName +="/.abjournal" + appname;
66 70
67 /* Expecting to access the default filename if nothing else is set */ 71 /* Expecting to access the default filename if nothing else is set */
68 if ( filename.isEmpty() ){ 72 if ( filename.isEmpty() ){
69 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); 73 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
70 } else 74 } else
71 m_fileName = filename; 75 m_fileName = filename;
72 76
73 /* Load Database now */ 77 /* Load Database now */
74 load (); 78 load ();
75 } 79 }
76 80
77 bool save() { 81 bool save() {
82
83 if ( !m_changed )
84 return true;
85
78 QString strNewFile = m_fileName + ".new"; 86 QString strNewFile = m_fileName + ".new";
79 QFile f( strNewFile ); 87 QFile f( strNewFile );
80 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 88 if ( !f.open( IO_WriteOnly|IO_Raw ) )
81 return false; 89 return false;
82 90
83 int total_written; 91 int total_written;
84 QString out; 92 QString out;
85 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 93 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
86 " <Groups>\n" 94 " <Groups>\n"
87 " </Groups>\n" 95 " </Groups>\n"
88 " <Contacts>\n"; 96 " <Contacts>\n";
89 //QValueList<Contact>::iterator it; 97 //QValueList<Contact>::iterator it;
90 QValueListConstIterator<OContact> it; 98 QValueListConstIterator<OContact> it;
91 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) { 99 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
92 out += "<Contact "; 100 out += "<Contact ";
93 (*it).save( out ); 101 (*it).save( out );
94 out += "/>\n"; 102 out += "/>\n";
95 QCString cstr = out.utf8(); 103 QCString cstr = out.utf8();
96 total_written = f.writeBlock( cstr.data(), cstr.length() ); 104 total_written = f.writeBlock( cstr.data(), cstr.length() );
97 if ( total_written != int(cstr.length()) ) { 105 if ( total_written != int(cstr.length()) ) {
98 f.close(); 106 f.close();
99 QFile::remove( strNewFile ); 107 QFile::remove( strNewFile );
100 return false; 108 return false;
101 } 109 }
102 out = ""; 110 out = "";
103 } 111 }
104 out += " </Contacts>\n</AddressBook>\n"; 112 out += " </Contacts>\n</AddressBook>\n";
105 113
106 QCString cstr = out.utf8(); 114 QCString cstr = out.utf8();
107 total_written = f.writeBlock( cstr.data(), cstr.length() ); 115 total_written = f.writeBlock( cstr.data(), cstr.length() );
108 if ( total_written != int( cstr.length() ) ) { 116 if ( total_written != int( cstr.length() ) ) {
109 f.close(); 117 f.close();
110 QFile::remove( strNewFile ); 118 QFile::remove( strNewFile );
111 return false; 119 return false;
112 } 120 }
113 f.close(); 121 f.close();
114 122
115 // move the file over, I'm just going to use the system call 123 // move the file over, I'm just going to use the system call
116 // because, I don't feel like using QDir. 124 // because, I don't feel like using QDir.
117 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 125 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
118 qWarning( "problem renaming file %s to %s, errno: %d", 126 qWarning( "problem renaming file %s to %s, errno: %d",
119 strNewFile.latin1(), m_journalName.latin1(), errno ); 127 strNewFile.latin1(), m_journalName.latin1(), errno );
120 // remove the tmp file... 128 // remove the tmp file...
121 QFile::remove( strNewFile ); 129 QFile::remove( strNewFile );
122 } 130 }
123 131
124 /* The journalfile should be removed now... */ 132 /* The journalfile should be removed now... */
125 removeJournal(); 133 removeJournal();
134
135 m_changed = false;
126 return true; 136 return true;
127 } 137 }
128 138
129 bool load () { 139 bool load () {
130 m_contactList.clear(); 140 m_contactList.clear();
131 141
132 /* Load XML-File and journal if it exists */ 142 /* Load XML-File and journal if it exists */
133 if ( !load ( m_fileName, false ) ) 143 if ( !load ( m_fileName, false ) )
134 return false; 144 return false;
135 /* The returncode of the journalfile is ignored due to the 145 /* The returncode of the journalfile is ignored due to the
136 * fact that it does not exist when this class is instantiated ! 146 * fact that it does not exist when this class is instantiated !
137 * But there may such a file exist, if the application crashed. 147 * But there may such a file exist, if the application crashed.
138 * Therefore we try to load it to get the changes before the # 148 * Therefore we try to load it to get the changes before the #
139 * crash happened... 149 * crash happened...
140 */ 150 */
141 load (m_journalName, true); 151 load (m_journalName, true);
142 152
143 return true; 153 return true;
144 } 154 }
145 155
146 void clear () { 156 void clear () {
147 m_contactList.clear(); 157 m_contactList.clear();
158 m_changed = false;
148 159
149 } 160 }
150 161
151 bool wasChangedExternally() 162 bool wasChangedExternally()
152 { 163 {
153 QFileInfo fi( m_fileName ); 164 QFileInfo fi( m_fileName );
154 165
155 QDateTime lastmod = fi.lastModified (); 166 QDateTime lastmod = fi.lastModified ();
156 167
157 return (lastmod != m_readtime); 168 return (lastmod != m_readtime);
158 } 169 }
159 170
160 QArray<int> allRecords() const { 171 QArray<int> allRecords() const {
161 QArray<int> uid_list( m_contactList.count() ); 172 QArray<int> uid_list( m_contactList.count() );
162 173
163 uint counter = 0; 174 uint counter = 0;
164 QValueListConstIterator<OContact> it; 175 QValueListConstIterator<OContact> it;
165 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 176 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
166 uid_list[counter++] = (*it).uid(); 177 uid_list[counter++] = (*it).uid();
167 } 178 }
168 179
169 return ( uid_list ); 180 return ( uid_list );
170 } 181 }
171 182
172 OContact find ( int uid ) const 183 OContact find ( int uid ) const
173 { 184 {
174 bool found = false; 185 bool found = false;
175 OContact foundContact; //Create empty contact 186 OContact foundContact; //Create empty contact
176 187
177 QValueListConstIterator<OContact> it; 188 QValueListConstIterator<OContact> it;
178 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 189 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
179 if ((*it).uid() == uid){ 190 if ((*it).uid() == uid){
180 found = true; 191 found = true;
181 break; 192 break;
182 } 193 }
183 } 194 }
184 if ( found ){ 195 if ( found ){
185 foundContact = *it; 196 foundContact = *it;
186 } 197 }
187 198
188 return ( foundContact ); 199 return ( foundContact );
189 } 200 }
190 201
191 QArray<int> queryByExample ( const OContact &query, int settings ){ 202 QArray<int> queryByExample ( const OContact &query, int settings ){
192 203
193 QArray<int> m_currentQuery( m_contactList.count() ); 204 QArray<int> m_currentQuery( m_contactList.count() );
194 QValueListConstIterator<OContact> it; 205 QValueListConstIterator<OContact> it;
195 uint arraycounter = 0; 206 uint arraycounter = 0;
196 207
197 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 208 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
198 /* Search all fields and compare them with query object. Store them into list 209 /* Search all fields and compare them with query object. Store them into list
199 * if all fields matches. 210 * if all fields matches.
200 */ 211 */
201 bool allcorrect = true; 212 bool allcorrect = true;
202 for ( int i = 0; i < Qtopia::rid; i++ ) { 213 for ( int i = 0; i < Qtopia::rid; i++ ) {
203 /* Just compare fields which are not empty in the query object */ 214 /* Just compare fields which are not empty in the query object */
204 if ( !query.field(i).isEmpty() ){ 215 if ( !query.field(i).isEmpty() ){
205 switch ( settings & ~OContactAccess::IgnoreCase ){ 216 switch ( settings & ~OContactAccess::IgnoreCase ){
206 case OContactAccess::RegExp:{ 217 case OContactAccess::RegExp:{
207 QRegExp expr ( query.field(i), 218 QRegExp expr ( query.field(i),
208 !(settings & OContactAccess::IgnoreCase), 219 !(settings & OContactAccess::IgnoreCase),
209 false ); 220 false );
210 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 221 if ( expr.find ( (*it).field(i), 0 ) == -1 )
211 allcorrect = false; 222 allcorrect = false;
212 } 223 }
213 break; 224 break;
214 case OContactAccess::WildCards:{ 225 case OContactAccess::WildCards:{
215 QRegExp expr ( query.field(i), 226 QRegExp expr ( query.field(i),
216 !(settings & OContactAccess::IgnoreCase), 227 !(settings & OContactAccess::IgnoreCase),
217 true ); 228 true );
218 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 229 if ( expr.find ( (*it).field(i), 0 ) == -1 )
219 allcorrect = false; 230 allcorrect = false;
220 } 231 }
221 break; 232 break;
222 case OContactAccess::ExactMatch:{ 233 case OContactAccess::ExactMatch:{
223 if (settings & OContactAccess::IgnoreCase){ 234 if (settings & OContactAccess::IgnoreCase){
224 if ( query.field(i).upper() != 235 if ( query.field(i).upper() !=
225 (*it).field(i).upper() ) 236 (*it).field(i).upper() )
226 allcorrect = false; 237 allcorrect = false;
227 }else{ 238 }else{
228 if ( query.field(i) != (*it).field(i) ) 239 if ( query.field(i) != (*it).field(i) )
229 allcorrect = false; 240 allcorrect = false;
230 } 241 }
231 } 242 }
232 break; 243 break;
233 } 244 }
234 } 245 }
235 } 246 }
236 if ( allcorrect ){ 247 if ( allcorrect ){
237 m_currentQuery[arraycounter++] = (*it).uid(); 248 m_currentQuery[arraycounter++] = (*it).uid();
238 } 249 }
239 } 250 }
240 251
241 // Shrink to fit.. 252 // Shrink to fit..
242 m_currentQuery.resize(arraycounter); 253 m_currentQuery.resize(arraycounter);
243 254
244 return m_currentQuery; 255 return m_currentQuery;
245 } 256 }
246 257
247 const uint querySettings() 258 const uint querySettings()
248 { 259 {
249 return ( OContactAccess::WildCards 260 return ( OContactAccess::WildCards
250 & OContactAccess::IgnoreCase 261 & OContactAccess::IgnoreCase
251 & OContactAccess::RegExp 262 & OContactAccess::RegExp
252 & OContactAccess::ExactMatch ); 263 & OContactAccess::ExactMatch );
253 } 264 }
254 265
255 bool hasQuerySettings (uint querySettings) const 266 bool hasQuerySettings (uint querySettings) const
256 { 267 {
257 /* OContactAccess::IgnoreCase may be added with one 268 /* OContactAccess::IgnoreCase may be added with one
258 * of the other settings, but never used alone. 269 * of the other settings, but never used alone.
259 * The other settings are just valid alone... 270 * The other settings are just valid alone...
260 */ 271 */
261 switch ( querySettings & ~OContactAccess::IgnoreCase ){ 272 switch ( querySettings & ~OContactAccess::IgnoreCase ){
262 case OContactAccess::RegExp: 273 case OContactAccess::RegExp:
263 return ( true ); 274 return ( true );
264 case OContactAccess::WildCards: 275 case OContactAccess::WildCards:
265 return ( true ); 276 return ( true );
266 case OContactAccess::ExactMatch: 277 case OContactAccess::ExactMatch:
267 return ( true ); 278 return ( true );
268 default: 279 default:
269 return ( false ); 280 return ( false );
270 } 281 }
271 } 282 }
272 283
273 bool add ( const OContact &newcontact ) 284 bool add ( const OContact &newcontact )
274 { 285 {
275 //qWarning("odefaultbackend: ACTION::ADD"); 286 //qWarning("odefaultbackend: ACTION::ADD");
276 updateJournal (newcontact, OContact::ACTION_ADD); 287 updateJournal (newcontact, OContact::ACTION_ADD);
277 addContact_p( newcontact ); 288 addContact_p( newcontact );
289
290 m_changed = true;
291
278 return true; 292 return true;
279 } 293 }
280 294
281 bool replace ( const OContact &contact ) 295 bool replace ( const OContact &contact )
282 { 296 {
297 m_changed = true;
298
283 bool found = false; 299 bool found = false;
284 300
285 QValueListIterator<OContact> it; 301 QValueListIterator<OContact> it;
286 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 302 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
287 if ( (*it).uid() == contact.uid() ){ 303 if ( (*it).uid() == contact.uid() ){
288 found = true; 304 found = true;
289 break; 305 break;
290 } 306 }
291 } 307 }
292 if (found) { 308 if (found) {
293 updateJournal (contact, OContact::ACTION_REPLACE); 309 updateJournal (contact, OContact::ACTION_REPLACE);
294 m_contactList.remove (it); 310 m_contactList.remove (it);
295 m_contactList.append (contact); 311 m_contactList.append (contact);
296 return true; 312 return true;
297 } else 313 } else
298 return false; 314 return false;
299 } 315 }
300 316
301 bool remove ( int uid ) 317 bool remove ( int uid )
302 { 318 {
319 m_changed = true;
320
303 bool found = false; 321 bool found = false;
304 QValueListIterator<OContact> it; 322 QValueListIterator<OContact> it;
305 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 323 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
306 if ((*it).uid() == uid){ 324 if ((*it).uid() == uid){
307 found = true; 325 found = true;
308 break; 326 break;
309 } 327 }
310 } 328 }
311 if (found) { 329 if (found) {
312 updateJournal ( *it, OContact::ACTION_REMOVE); 330 updateJournal ( *it, OContact::ACTION_REMOVE);
313 m_contactList.remove (it); 331 m_contactList.remove (it);
314 return true; 332 return true;
315 } else 333 } else
316 return false; 334 return false;
317 } 335 }
318 336
319 bool reload(){ 337 bool reload(){
320 /* Reload is the same as load in this implementation */ 338 /* Reload is the same as load in this implementation */
321 return ( load() ); 339 return ( load() );
322 } 340 }
323 341
324 private: 342 private:
325 void addContact_p( const OContact &newcontact ){ 343 void addContact_p( const OContact &newcontact ){
326 m_contactList.append (newcontact); 344 m_contactList.append (newcontact);
327 } 345 }
328 346
329 /* This function loads the xml-database and the journalfile */ 347 /* This function loads the xml-database and the journalfile */
330 bool load( const QString filename, bool isJournal ) { 348 bool load( const QString filename, bool isJournal ) {
331 349
332 /* We use the time of the last read to check if the file was 350 /* We use the time of the last read to check if the file was
333 * changed externally. 351 * changed externally.
334 */ 352 */
335 if ( !isJournal ){ 353 if ( !isJournal ){
336 QFileInfo fi( filename ); 354 QFileInfo fi( filename );
337 m_readtime = fi.lastModified (); 355 m_readtime = fi.lastModified ();
338 } 356 }
339 357
340 const int JOURNALACTION = Qtopia::Notes + 1; 358 const int JOURNALACTION = Qtopia::Notes + 1;
341 const int JOURNALROW = JOURNALACTION + 1; 359 const int JOURNALROW = JOURNALACTION + 1;
342 360
343 bool foundAction = false; 361 bool foundAction = false;
344 OContact::journal_action action = OContact::ACTION_ADD; 362 OContact::journal_action action = OContact::ACTION_ADD;
345 int journalKey = 0; 363 int journalKey = 0;
346 QMap<int, QString> contactMap; 364 QMap<int, QString> contactMap;
347 QMap<QString, QString> customMap; 365 QMap<QString, QString> customMap;
348 QMap<QString, QString>::Iterator customIt; 366 QMap<QString, QString>::Iterator customIt;
349 QAsciiDict<int> dict( 47 ); 367 QAsciiDict<int> dict( 47 );
350 368
351 dict.setAutoDelete( TRUE ); 369 dict.setAutoDelete( TRUE );
352 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 370 dict.insert( "Uid", new int(Qtopia::AddressUid) );
353 dict.insert( "Title", new int(Qtopia::Title) ); 371 dict.insert( "Title", new int(Qtopia::Title) );
354 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 372 dict.insert( "FirstName", new int(Qtopia::FirstName) );
355 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 373 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
356 dict.insert( "LastName", new int(Qtopia::LastName) ); 374 dict.insert( "LastName", new int(Qtopia::LastName) );
357 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 375 dict.insert( "Suffix", new int(Qtopia::Suffix) );
358 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 376 dict.insert( "FileAs", new int(Qtopia::FileAs) );
359 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 377 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
360 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 378 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
361 dict.insert( "Emails", new int(Qtopia::Emails) ); 379 dict.insert( "Emails", new int(Qtopia::Emails) );
362 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 380 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
363 dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); 381 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
364 dict.insert( "HomeState", new int(Qtopia::HomeState) ); 382 dict.insert( "HomeState", new int(Qtopia::HomeState) );
365 dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); 383 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
366 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); 384 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
367 dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); 385 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
368 dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); 386 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
369 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); 387 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
370 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); 388 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
371 dict.insert( "Company", new int(Qtopia::Company) ); 389 dict.insert( "Company", new int(Qtopia::Company) );
372 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); 390 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
373 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); 391 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
374 dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); 392 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
375 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); 393 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
376 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); 394 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
377 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); 395 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
378 dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); 396 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
379 dict.insert( "Department", new int(Qtopia::Department) ); 397 dict.insert( "Department", new int(Qtopia::Department) );
380 dict.insert( "Office", new int(Qtopia::Office) ); 398 dict.insert( "Office", new int(Qtopia::Office) );
381 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); 399 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
382 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); 400 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
383 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); 401 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
384 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); 402 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
385 dict.insert( "Profession", new int(Qtopia::Profession) ); 403 dict.insert( "Profession", new int(Qtopia::Profession) );
386 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 404 dict.insert( "Assistant", new int(Qtopia::Assistant) );
387 dict.insert( "Manager", new int(Qtopia::Manager) ); 405 dict.insert( "Manager", new int(Qtopia::Manager) );
388 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 406 dict.insert( "Spouse", new int(Qtopia::Spouse) );
389 dict.insert( "Children", new int(Qtopia::Children) ); 407 dict.insert( "Children", new int(Qtopia::Children) );
390 dict.insert( "Gender", new int(Qtopia::Gender) ); 408 dict.insert( "Gender", new int(Qtopia::Gender) );
391 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 409 dict.insert( "Birthday", new int(Qtopia::Birthday) );
392 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 410 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
393 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 411 dict.insert( "Nickname", new int(Qtopia::Nickname) );
394 dict.insert( "Notes", new int(Qtopia::Notes) ); 412 dict.insert( "Notes", new int(Qtopia::Notes) );
395 dict.insert( "action", new int(JOURNALACTION) ); 413 dict.insert( "action", new int(JOURNALACTION) );
396 dict.insert( "actionrow", new int(JOURNALROW) ); 414 dict.insert( "actionrow", new int(JOURNALROW) );
397 415
398 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); 416 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
@@ -460,104 +478,105 @@ class OContactAccessBackend_XML : public OContactAccessBackend {
460 case Qtopia::AddressCategory: 478 case Qtopia::AddressCategory:
461 contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); 479 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
462 break; 480 break;
463 */ 481 */
464 case JOURNALACTION: 482 case JOURNALACTION:
465 action = OContact::journal_action(it.data().toInt()); 483 action = OContact::journal_action(it.data().toInt());
466 foundAction = true; 484 foundAction = true;
467 qWarning ("ODefBack(journal)::ACTION found: %d", action); 485 qWarning ("ODefBack(journal)::ACTION found: %d", action);
468 break; 486 break;
469 case JOURNALROW: 487 case JOURNALROW:
470 journalKey = it.data().toInt(); 488 journalKey = it.data().toInt();
471 break; 489 break;
472 default: // no conversion needed add them to the map 490 default: // no conversion needed add them to the map
473 contactMap.insert( *find, it.data() ); 491 contactMap.insert( *find, it.data() );
474 break; 492 break;
475 } 493 }
476 } 494 }
477 /* now generate the Contact contact */ 495 /* now generate the Contact contact */
478 OContact contact( contactMap ); 496 OContact contact( contactMap );
479 497
480 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { 498 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
481 contact.setCustomField( customIt.key(), customIt.data() ); 499 contact.setCustomField( customIt.key(), customIt.data() );
482 } 500 }
483 501
484 if (foundAction){ 502 if (foundAction){
485 foundAction = false; 503 foundAction = false;
486 switch ( action ) { 504 switch ( action ) {
487 case OContact::ACTION_ADD: 505 case OContact::ACTION_ADD:
488 addContact_p (contact); 506 addContact_p (contact);
489 break; 507 break;
490 case OContact::ACTION_REMOVE: 508 case OContact::ACTION_REMOVE:
491 if ( !remove (contact.uid()) ) 509 if ( !remove (contact.uid()) )
492 qWarning ("ODefBack(journal)::Unable to remove uid: %d", 510 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
493 contact.uid() ); 511 contact.uid() );
494 break; 512 break;
495 case OContact::ACTION_REPLACE: 513 case OContact::ACTION_REPLACE:
496 if ( !replace ( contact ) ) 514 if ( !replace ( contact ) )
497 qWarning ("ODefBack(journal)::Unable to replace uid: %d", 515 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
498 contact.uid() ); 516 contact.uid() );
499 break; 517 break;
500 default: 518 default:
501 qWarning ("Unknown action: ignored !"); 519 qWarning ("Unknown action: ignored !");
502 break; 520 break;
503 } 521 }
504 }else{ 522 }else{
505 /* Add contact to list */ 523 /* Add contact to list */
506 addContact_p (contact); 524 addContact_p (contact);
507 } 525 }
508 526
509 /* Move to next element */ 527 /* Move to next element */
510 element = element->nextChild(); 528 element = element->nextChild();
511 } 529 }
512 }else { 530 }else {
513 qWarning("ODefBack::could not load"); 531 qWarning("ODefBack::could not load");
514 } 532 }
515 delete root; 533 delete root;
516 qWarning("returning from loading" ); 534 qWarning("returning from loading" );
517 return true; 535 return true;
518 } 536 }
519 537
520 538
521 void updateJournal( const OContact& cnt, 539 void updateJournal( const OContact& cnt,
522 OContact::journal_action action ) { 540 OContact::journal_action action ) {
523 QFile f( m_journalName ); 541 QFile f( m_journalName );
524 bool created = !f.exists(); 542 bool created = !f.exists();
525 if ( !f.open(IO_WriteOnly|IO_Append) ) 543 if ( !f.open(IO_WriteOnly|IO_Append) )
526 return; 544 return;
527 545
528 QString buf; 546 QString buf;
529 QCString str; 547 QCString str;
530 548
531 // if the file was created, we have to set the Tag "<CONTACTS>" to 549 // if the file was created, we have to set the Tag "<CONTACTS>" to
532 // get a XML-File which is readable by our parser. 550 // get a XML-File which is readable by our parser.
533 // This is just a cheat, but better than rewrite the parser. 551 // This is just a cheat, but better than rewrite the parser.
534 if ( created ){ 552 if ( created ){
535 buf = "<Contacts>"; 553 buf = "<Contacts>";
536 QCString cstr = buf.utf8(); 554 QCString cstr = buf.utf8();
537 f.writeBlock( cstr.data(), cstr.length() ); 555 f.writeBlock( cstr.data(), cstr.length() );
538 } 556 }
539 557
540 buf = "<Contact "; 558 buf = "<Contact ";
541 cnt.save( buf ); 559 cnt.save( buf );
542 buf += " action=\"" + QString::number( (int)action ) + "\" "; 560 buf += " action=\"" + QString::number( (int)action ) + "\" ";
543 buf += "/>\n"; 561 buf += "/>\n";
544 QCString cstr = buf.utf8(); 562 QCString cstr = buf.utf8();
545 f.writeBlock( cstr.data(), cstr.length() ); 563 f.writeBlock( cstr.data(), cstr.length() );
546 } 564 }
547 565
548 void removeJournal() 566 void removeJournal()
549 { 567 {
550 QFile f ( m_journalName ); 568 QFile f ( m_journalName );
551 if ( f.exists() ) 569 if ( f.exists() )
552 f.remove(); 570 f.remove();
553 } 571 }
554 572
555 protected: 573 protected:
574 bool m_changed;
556 QString m_journalName; 575 QString m_journalName;
557 QString m_fileName; 576 QString m_fileName;
558 QString m_appName; 577 QString m_appName;
559 QValueList<OContact> m_contactList; 578 QValueList<OContact> m_contactList;
560 QDateTime m_readtime; 579 QDateTime m_readtime;
561}; 580};
562 581
563#endif 582#endif
diff --git a/libopie/pim/opimaccesstemplate.h b/libopie/pim/opimaccesstemplate.h
index 3e1f393..50cb1e4 100644
--- a/libopie/pim/opimaccesstemplate.h
+++ b/libopie/pim/opimaccesstemplate.h
@@ -1,239 +1,254 @@
1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H 1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
2#define OPIE_PIM_ACCESS_TEMPLATE_H 2#define OPIE_PIM_ACCESS_TEMPLATE_H
3 3
4#include <qarray.h> 4#include <qarray.h>
5 5
6#include <opie/opimrecord.h> 6#include <opie/opimrecord.h>
7#include <opie/opimaccessbackend.h> 7#include <opie/opimaccessbackend.h>
8#include <opie/orecordlist.h> 8#include <opie/orecordlist.h>
9 9
10#include "opimcache.h" 10#include "opimcache.h"
11#include "otemplatebase.h" 11#include "otemplatebase.h"
12 12
13/** 13/**
14 * Thats the frontend to our OPIE PIM 14 * Thats the frontend to our OPIE PIM
15 * Library. Either you want to use it's 15 * Library. Either you want to use it's
16 * interface or you want to implement 16 * interface or you want to implement
17 * your own Access lib 17 * your own Access lib
18 * Just create a OPimRecord and inherit from 18 * Just create a OPimRecord and inherit from
19 * the plugins 19 * the plugins
20 */ 20 */
21 21
22template <class T = OPimRecord > 22template <class T = OPimRecord >
23class OPimAccessTemplate : public OTemplateBase<T> { 23class OPimAccessTemplate : public OTemplateBase<T> {
24public: 24public:
25 typedef ORecordList<T> List; 25 typedef ORecordList<T> List;
26 typedef OPimAccessBackend<T> BackEnd; 26 typedef OPimAccessBackend<T> BackEnd;
27 typedef OPimCache<T> Cache; 27 typedef OPimCache<T> Cache;
28 28
29 /** 29 /**
30 * c'tor BackEnd 30 * c'tor BackEnd
31 */ 31 */
32 OPimAccessTemplate( BackEnd* end); 32 OPimAccessTemplate( BackEnd* end);
33 virtual ~OPimAccessTemplate(); 33 virtual ~OPimAccessTemplate();
34 34
35 /** 35 /**
36 * load from the backend 36 * load from the backend
37 */ 37 */
38 virtual bool load(); 38 virtual bool load();
39 39
40 /** 40 /** Reload database.
41 * reload from the backend 41 * You should execute this function if the external database
42 * was changed.
43 * This function will load the external database and afterwards
44 * rejoin the local changes. Therefore the local database will be set consistent.
42 */ 45 */
43 virtual bool reload(); 46 virtual bool reload();
44 47
45 /** 48 /** Save contacts database.
46 * save to the backend 49 * Save is more a "commit". After calling this function, all changes are public available.
50 * @return true if successful
47 */ 51 */
48 virtual bool save(); 52 virtual bool save();
49 53
50 /** 54 /**
51 * if the resource was changed externally 55 * if the resource was changed externally
56 * You should use the signal handling instead of polling possible changes !
57 * zecke: Do you implement a signal for otodoaccess ?
52 */ 58 */
53 bool wasChangedExternally()const; 59 bool wasChangedExternally()const;
54 60
55 /** 61 /**
56 * return a List of records 62 * return a List of records
57 * you can iterate over them 63 * you can iterate over them
58 */ 64 */
59 virtual List allRecords()const; 65 virtual List allRecords()const;
60 66
61 /** 67 /**
62 * queryByExample) 68 * queryByExample.
63 * @see otodoaccess, ocontactaccess 69 * @see otodoaccess, ocontactaccess
64 */ 70 */
65 virtual List queryByExample( const T& t, int querySettings ); 71 virtual List queryByExample( const T& t, int querySettings );
66 72
67 /** 73 /**
68 * find the OPimRecord uid 74 * find the OPimRecord uid
69 */ 75 */
70 virtual T find( int uid )const; 76 virtual T find( int uid )const;
71 77
72 /** 78 /**
73 * read ahead cache find method ;) 79 * read ahead cache find method ;)
74 */ 80 */
75 virtual T find( int uid, const QArray<int>&, 81 virtual T find( int uid, const QArray<int>&,
76 uint current, CacheDirection dir = Forward )const; 82 uint current, CacheDirection dir = Forward )const;
77 83
78 /* invalidate cache here */ 84 /* invalidate cache here */
79 /** 85 /**
80 * clears the backend and invalidates the backend 86 * clears the backend and invalidates the backend
81 */ 87 */
82 virtual void clear() ; 88 virtual void clear() ;
83 89
84 /** 90 /**
85 * add T to the backend 91 * add T to the backend
92 * @param t The item to add.
93 * @return <i>true</i> if added successfully.
86 */ 94 */
87 virtual bool add( const T& t ) ; 95 virtual bool add( const T& t ) ;
88 96
89 /* only the uid matters */ 97 /* only the uid matters */
90 /** 98 /**
91 * remove T from the backend 99 * remove T from the backend
100 * @param t The item to remove
101 * @return <i>true</i> if successful.
92 */ 102 */
93 virtual bool remove( const T& t ); 103 virtual bool remove( const T& t );
94 104
95 /** 105 /**
96 * remove the OPimRecord with uid 106 * remove the OPimRecord with uid
107 * @param uid The ID of the item to remove
108 * @return <i>true</i> if successful.
97 */ 109 */
98 virtual bool remove( int uid ); 110 virtual bool remove( int uid );
99 111
100 /** 112 /**
101 * replace T from backend 113 * replace T from backend
114 * @param t The item to replace
115 * @return <i>true</i> if successful.
102 */ 116 */
103 virtual bool replace( const T& t) ; 117 virtual bool replace( const T& t) ;
104 118
105 /** 119 /**
106 * @internal 120 * @internal
107 */ 121 */
108 void cache( const T& )const; 122 void cache( const T& )const;
109 void setSaneCacheSize( int ); 123 void setSaneCacheSize( int );
110protected: 124protected:
111 /** 125 /**
112 * invalidate the cache 126 * invalidate the cache
113 */ 127 */
114 void invalidateCache(); 128 void invalidateCache();
115 129
116 void setBackEnd( BackEnd* end ); 130 void setBackEnd( BackEnd* end );
117 /** 131 /**
118 * returns the backend 132 * returns the backend
119 */ 133 */
120 BackEnd* backEnd(); 134 BackEnd* backEnd();
121 BackEnd* m_backEnd; 135 BackEnd* m_backEnd;
122 Cache m_cache; 136 Cache m_cache;
123 137
124}; 138};
125 139
126template <class T> 140template <class T>
127OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) 141OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
128 : OTemplateBase<T>(), m_backEnd( end ) 142 : OTemplateBase<T>(), m_backEnd( end )
129{ 143{
130 if (end ) 144 if (end )
131 end->setFrontend( this ); 145 end->setFrontend( this );
132} 146}
133template <class T> 147template <class T>
134OPimAccessTemplate<T>::~OPimAccessTemplate() { 148OPimAccessTemplate<T>::~OPimAccessTemplate() {
135 qWarning("~OPimAccessTemplate<T>"); 149 qWarning("~OPimAccessTemplate<T>");
136 delete m_backEnd; 150 delete m_backEnd;
137} 151}
138template <class T> 152template <class T>
139bool OPimAccessTemplate<T>::load() { 153bool OPimAccessTemplate<T>::load() {
140 invalidateCache(); 154 invalidateCache();
141 return m_backEnd->load(); 155 return m_backEnd->load();
142} 156}
143template <class T> 157template <class T>
144bool OPimAccessTemplate<T>::reload() { 158bool OPimAccessTemplate<T>::reload() {
145 return m_backEnd->reload(); 159 invalidateCache(); // zecke: I think this should be added (se)
160 return m_backEnd->reload();
146} 161}
147template <class T> 162template <class T>
148bool OPimAccessTemplate<T>::save() { 163bool OPimAccessTemplate<T>::save() {
149 return m_backEnd->save(); 164 return m_backEnd->save();
150} 165}
151template <class T> 166template <class T>
152OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { 167OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
153 QArray<int> ints = m_backEnd->allRecords(); 168 QArray<int> ints = m_backEnd->allRecords();
154 List lis(ints, this ); 169 List lis(ints, this );
155 return lis; 170 return lis;
156} 171}
157template <class T> 172template <class T>
158OPimAccessTemplate<T>::List 173OPimAccessTemplate<T>::List
159OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) { 174OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) {
160 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder ); 175 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder );
161 176
162 List lis(ints, this ); 177 List lis(ints, this );
163 return lis; 178 return lis;
164} 179}
165template <class T> 180template <class T>
166T OPimAccessTemplate<T>::find( int uid ) const{ 181T OPimAccessTemplate<T>::find( int uid ) const{
167 T t = m_backEnd->find( uid ); 182 T t = m_backEnd->find( uid );
168 cache( t ); 183 cache( t );
169 return t; 184 return t;
170} 185}
171template <class T> 186template <class T>
172T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar, 187T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
173 uint current, CacheDirection dir )const { 188 uint current, CacheDirection dir )const {
174 /* 189 /*
175 * better do T.isEmpty() 190 * better do T.isEmpty()
176 * after a find this way we would 191 * after a find this way we would
177 * avoid two finds in QCache... 192 * avoid two finds in QCache...
178 */ 193 */
179 // qWarning("find it now %d", uid ); 194 // qWarning("find it now %d", uid );
180 if (m_cache.contains( uid ) ) { 195 if (m_cache.contains( uid ) ) {
181 return m_cache.find( uid ); 196 return m_cache.find( uid );
182 } 197 }
183 198
184 T t = m_backEnd->find( uid, ar, current, dir ); 199 T t = m_backEnd->find( uid, ar, current, dir );
185 cache( t ); 200 cache( t );
186 return t; 201 return t;
187} 202}
188template <class T> 203template <class T>
189void OPimAccessTemplate<T>::clear() { 204void OPimAccessTemplate<T>::clear() {
190 invalidateCache(); 205 invalidateCache();
191 m_backEnd->clear(); 206 m_backEnd->clear();
192} 207}
193template <class T> 208template <class T>
194bool OPimAccessTemplate<T>::add( const T& t ) { 209bool OPimAccessTemplate<T>::add( const T& t ) {
195 cache( t ); 210 cache( t );
196 return m_backEnd->add( t ); 211 return m_backEnd->add( t );
197} 212}
198template <class T> 213template <class T>
199bool OPimAccessTemplate<T>::remove( const T& t ) { 214bool OPimAccessTemplate<T>::remove( const T& t ) {
200 return remove( t.uid() ); 215 return remove( t.uid() );
201} 216}
202template <class T> 217template <class T>
203bool OPimAccessTemplate<T>::remove( int uid ) { 218bool OPimAccessTemplate<T>::remove( int uid ) {
204 m_cache.remove( uid ); 219 m_cache.remove( uid );
205 return m_backEnd->remove( uid ); 220 return m_backEnd->remove( uid );
206} 221}
207template <class T> 222template <class T>
208bool OPimAccessTemplate<T>::replace( const T& t ) { 223bool OPimAccessTemplate<T>::replace( const T& t ) {
209 m_cache.replace( t ); 224 m_cache.replace( t );
210 return m_backEnd->replace( t ); 225 return m_backEnd->replace( t );
211} 226}
212template <class T> 227template <class T>
213void OPimAccessTemplate<T>::invalidateCache() { 228void OPimAccessTemplate<T>::invalidateCache() {
214 m_cache.invalidate(); 229 m_cache.invalidate();
215} 230}
216template <class T> 231template <class T>
217OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() { 232OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() {
218 return m_backEnd; 233 return m_backEnd;
219} 234}
220template <class T> 235template <class T>
221bool OPimAccessTemplate<T>::wasChangedExternally()const { 236bool OPimAccessTemplate<T>::wasChangedExternally()const {
222 return false; 237 return false;
223} 238}
224template <class T> 239template <class T>
225void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) { 240void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) {
226 m_backEnd = end; 241 m_backEnd = end;
227 if (m_backEnd ) 242 if (m_backEnd )
228 m_backEnd->setFrontend( this ); 243 m_backEnd->setFrontend( this );
229} 244}
230template <class T> 245template <class T>
231void OPimAccessTemplate<T>::cache( const T& t ) const{ 246void OPimAccessTemplate<T>::cache( const T& t ) const{
232 /* hacky we need to work around the const*/ 247 /* hacky we need to work around the const*/
233 ((OPimAccessTemplate<T>*)this)->m_cache.add( t ); 248 ((OPimAccessTemplate<T>*)this)->m_cache.add( t );
234} 249}
235template <class T> 250template <class T>
236void OPimAccessTemplate<T>::setSaneCacheSize( int size ) { 251void OPimAccessTemplate<T>::setSaneCacheSize( int size ) {
237 m_cache.setSize( size ); 252 m_cache.setSize( size );
238} 253}
239#endif 254#endif