-rw-r--r-- | libopie/pim/obackendfactory.h | 88 | ||||
-rw-r--r-- | libopie/pim/ocontactaccess.cpp | 10 | ||||
-rw-r--r-- | libopie/pim/ocontactaccessbackend.h | 4 | ||||
-rw-r--r-- | libopie/pim/ocontactaccessbackend_xml.h | 10 | ||||
-rw-r--r-- | libopie2/opiepim/backend/obackendfactory.h | 88 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend.h | 4 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_xml.h | 10 | ||||
-rw-r--r-- | libopie2/opiepim/core/ocontactaccess.cpp | 10 |
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 | |||
37 | template<class T> | ||
38 | class 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 | ||
56 | OContactAccess::OContactAccess ( const QString appname, const QString filename, | 60 | OContactAccess::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 | } |
84 | OContactAccess::~OContactAccess () | 90 | OContactAccess::~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 | ||
94 | bool OContactAccess::load() | 100 | bool OContactAccess::load() |
95 | { | 101 | { |
96 | return ( m_backEnd->load() ); | 102 | return ( m_backEnd->load() ); |
97 | } | 103 | } |
98 | 104 | ||
99 | bool OContactAccess::save () | 105 | bool 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 | ||
122 | const uint OContactAccess::querySettings() | 128 | const uint OContactAccess::querySettings() |
123 | { | 129 | { |
124 | return ( m_backEnd->querySettings() ); | 130 | return ( m_backEnd->querySettings() ); |
125 | } | 131 | } |
126 | 132 | ||
127 | bool OContactAccess::hasQuerySettings ( int querySettings ) const | 133 | bool OContactAccess::hasQuerySettings ( int querySettings ) const |
128 | { | 134 | { |
129 | return ( m_backEnd->hasQuerySettings ( querySettings ) ); | 135 | return ( m_backEnd->hasQuerySettings ( querySettings ) ); |
130 | } | 136 | } |
131 | 137 | ||
132 | bool OContactAccess::add ( const OContact& newcontact ) | 138 | bool 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 | ||
138 | bool OContactAccess::replace ( const OContact& contact ) | 144 | bool 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 | ||
144 | bool OContactAccess::remove ( const OContact& t ) | 150 | bool 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 | ||
150 | bool OContactAccess::remove ( int uid ) | 156 | bool 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 | ||
156 | bool OContactAccess::wasChangedExternally()const | 162 | bool OContactAccess::wasChangedExternally()const |
157 | { | 163 | { |
158 | return ( m_backEnd->wasChangedExternally() ); | 164 | return ( m_backEnd->wasChangedExternally() ); |
159 | } | 165 | } |
160 | 166 | ||
161 | 167 | ||
162 | bool OContactAccess::reload() | 168 | bool OContactAccess::reload() |
163 | { | 169 | { |
164 | return ( m_backEnd->reload() ); | 170 | return ( m_backEnd->reload() ); |
165 | } | 171 | } |
166 | 172 | ||
167 | void OContactAccess::copMessage( const QCString &msg, const QByteArray & ) | 173 | void 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 | ||
37 | class OContactAccessBackend: public OPimAccessBackend<OContact> { | 41 | class 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,423 +1,433 @@ | |||
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 | ||
41 | using namespace Opie; | 51 | using namespace Opie; |
42 | 52 | ||
43 | /* the default xml implementation */ | 53 | /* the default xml implementation */ |
44 | class OContactAccessBackend_XML : public OContactAccessBackend { | 54 | class 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(); |
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 | |||
37 | template<class T> | ||
38 | class 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 | ||
37 | class OContactAccessBackend: public OPimAccessBackend<OContact> { | 41 | class 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,423 +1,433 @@ | |||
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 | ||
41 | using namespace Opie; | 51 | using namespace Opie; |
42 | 52 | ||
43 | /* the default xml implementation */ | 53 | /* the default xml implementation */ |
44 | class OContactAccessBackend_XML : public OContactAccessBackend { | 54 | class 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(); |
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 | ||
56 | OContactAccess::OContactAccess ( const QString appname, const QString filename, | 60 | OContactAccess::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 | } |
84 | OContactAccess::~OContactAccess () | 90 | OContactAccess::~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 | ||
94 | bool OContactAccess::load() | 100 | bool OContactAccess::load() |
95 | { | 101 | { |
96 | return ( m_backEnd->load() ); | 102 | return ( m_backEnd->load() ); |
97 | } | 103 | } |
98 | 104 | ||
99 | bool OContactAccess::save () | 105 | bool 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 | ||
122 | const uint OContactAccess::querySettings() | 128 | const uint OContactAccess::querySettings() |
123 | { | 129 | { |
124 | return ( m_backEnd->querySettings() ); | 130 | return ( m_backEnd->querySettings() ); |
125 | } | 131 | } |
126 | 132 | ||
127 | bool OContactAccess::hasQuerySettings ( int querySettings ) const | 133 | bool OContactAccess::hasQuerySettings ( int querySettings ) const |
128 | { | 134 | { |
129 | return ( m_backEnd->hasQuerySettings ( querySettings ) ); | 135 | return ( m_backEnd->hasQuerySettings ( querySettings ) ); |
130 | } | 136 | } |
131 | 137 | ||
132 | bool OContactAccess::add ( const OContact& newcontact ) | 138 | bool 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 | ||
138 | bool OContactAccess::replace ( const OContact& contact ) | 144 | bool 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 | ||
144 | bool OContactAccess::remove ( const OContact& t ) | 150 | bool 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 | ||
150 | bool OContactAccess::remove ( int uid ) | 156 | bool 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 | ||
156 | bool OContactAccess::wasChangedExternally()const | 162 | bool OContactAccess::wasChangedExternally()const |
157 | { | 163 | { |
158 | return ( m_backEnd->wasChangedExternally() ); | 164 | return ( m_backEnd->wasChangedExternally() ); |
159 | } | 165 | } |
160 | 166 | ||
161 | 167 | ||
162 | bool OContactAccess::reload() | 168 | bool OContactAccess::reload() |
163 | { | 169 | { |
164 | return ( m_backEnd->reload() ); | 170 | return ( m_backEnd->reload() ); |
165 | } | 171 | } |
166 | 172 | ||
167 | void OContactAccess::copMessage( const QCString &msg, const QByteArray & ) | 173 | void 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 | } |