summaryrefslogtreecommitdiff
authoreilers <eilers>2002-10-14 16:21:54 (UTC)
committer eilers <eilers>2002-10-14 16:21:54 (UTC)
commitf48ddfb53e49550f9fe8e9502f2a44aeb8b359cc (patch) (unidiff)
tree7972f3fc9a1d61e22fe57ff0fa96fd9a0badb55d
parentda3868438e739310862bf65b0d0c8ffa864392e8 (diff)
downloadopie-f48ddfb53e49550f9fe8e9502f2a44aeb8b359cc.zip
opie-f48ddfb53e49550f9fe8e9502f2a44aeb8b359cc.tar.gz
opie-f48ddfb53e49550f9fe8e9502f2a44aeb8b359cc.tar.bz2
Some minor interface updates
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/DESIGN6
-rw-r--r--libopie/pim/ocontactaccess.cpp4
-rw-r--r--libopie/pim/ocontactaccess.h49
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h35
-rw-r--r--libopie/pim/opimaccesstemplate.h12
-rw-r--r--libopie/pim/otodoaccessxml.cpp2
-rw-r--r--libopie/pim/otodoaccessxml.h2
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.h35
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.cpp2
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.h2
-rw-r--r--libopie2/opiepim/core/ocontactaccess.cpp4
-rw-r--r--libopie2/opiepim/core/ocontactaccess.h49
-rw-r--r--libopie2/opiepim/core/opimaccesstemplate.h12
13 files changed, 74 insertions, 140 deletions
diff --git a/libopie/pim/DESIGN b/libopie/pim/DESIGN
index 4def7b9..bd92b1b 100644
--- a/libopie/pim/DESIGN
+++ b/libopie/pim/DESIGN
@@ -1,62 +1,56 @@
1Hija to the DESIGN of our OPIE PIM stuff 1Hija to the DESIGN of our OPIE PIM stuff
2 2
3This design was firstly discussed in the train 3This design was firstly discussed in the train
4from Frankfurt to Hannover between me (zecke ) and eilers. 4from Frankfurt to Hannover between me (zecke ) and eilers.
5 5
6We had a look at our pim implementation and the one from 6We had a look at our pim implementation and the one from
7trolltech and we looked what was missing. 7trolltech and we looked what was missing.
8 8
9GOALS: 9GOALS:
10 - clean implementation 10 - clean implementation
11 - share code 11 - share code
12 - ObjectOriented Design 12 - ObjectOriented Design
13 - Scalable 13 - Scalable
14 - Integration into common solutions like STL and Qt 14 - Integration into common solutions like STL and Qt
15 - Addition 15 - Addition
16 - Ease of Use 16 - Ease of Use
17 17
18GENERAL: 18GENERAL:
19 - use templates 19 - use templates
20 - have a common base class for all Records OPimRecord 20 - have a common base class for all Records OPimRecord
21 - use references instead of pointers 21 - use references instead of pointers
22 - make use of QShared internally memory consumption 22 - make use of QShared internally memory consumption
23 23
24We've a 'public' and 'private' part in our lib 24We've a 'public' and 'private' part in our lib
25OPimAccessTemplate is the public part. This will be used 25OPimAccessTemplate is the public part. This will be used
26by 3rd party developers to access the PIMs. 26by 3rd party developers to access the PIMs.
27OPimAccessBackend is the backend. You could also call it 27OPimAccessBackend is the backend. You could also call it
28resource. 28resource.
29 29
30Both things need to be implemented for different kind of records. 30Both things need to be implemented for different kind of records.
31By using templates we can make sure we share code and the reason 31By using templates we can make sure we share code and the reason
32not to use simple inheretance is that we can specialise quite easy. 32not to use simple inheretance is that we can specialise quite easy.
33 33
34For example we have OTodoAccess : public OPimAccessTemplate<OTodo>; 34For example we have OTodoAccess : public OPimAccessTemplate<OTodo>;
35the we would do 35the we would do
36OTodoAccess::List list = otodoAccess.all(); 36OTodoAccess::List list = otodoAccess.all();
37OTodoAccess::List::Iterator it; 37OTodoAccess::List::Iterator it;
38for( it = list.begin(); it != list.end(); ++it ); 38for( it = list.begin(); it != list.end(); ++it );
39 39
40 40
41as you can see from here it just behaves like you expect from Qt or STL. 41as you can see from here it just behaves like you expect from Qt or STL.
42 42
43The kewlest thing is that List and List::Iterator is free to use if you 43The kewlest thing is that List and List::Iterator is free to use if you
44want to implement your own OPimAccessTemplate. 44want to implement your own OPimAccessTemplate.
45You just have to sub class it and voila you're done 45You just have to sub class it and voila you're done
46 46
47 47
48Hope you enjoy using OPIE PIM 48Hope you enjoy using OPIE PIM
49 49
50regards Holger 'zecke' Freyther 50regards Holger 'zecke' Freyther
51 51
52 52
53Comment by Stefan Eilers:
54
55The opimaccesstemplate defines "SortOrder":
56I think sortorder is the wrong name for the meaning of it and
57it should be defined by the childs of opimaccesstemplate (every
58implementation may use different values for this..)
59 53
60 54
61 55
62 56
diff --git a/libopie/pim/ocontactaccess.cpp b/libopie/pim/ocontactaccess.cpp
index b5f358b..e8c0a45 100644
--- a/libopie/pim/ocontactaccess.cpp
+++ b/libopie/pim/ocontactaccess.cpp
@@ -1,165 +1,167 @@
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.4 2002/10/14 16:21:54 eilers
25 * Some minor interface updates
26 *
24 * Revision 1.3 2002/10/07 17:34:24 eilers 27 * Revision 1.3 2002/10/07 17:34:24 eilers
25 * added OBackendFactory for advanced backend access 28 * added OBackendFactory for advanced backend access
26 * 29 *
27 * Revision 1.2 2002/10/02 16:18:11 eilers 30 * Revision 1.2 2002/10/02 16:18:11 eilers
28 * debugged and seems to work almost perfectly .. 31 * debugged and seems to work almost perfectly ..
29 * 32 *
30 * Revision 1.1 2002/09/27 17:11:44 eilers 33 * Revision 1.1 2002/09/27 17:11:44 eilers
31 * Added API for accessing the Contact-Database ! It is compiling, but 34 * Added API for accessing the Contact-Database ! It is compiling, but
32 * please do not expect that anything is working ! 35 * please do not expect that anything is working !
33 * I will debug that stuff in the next time .. 36 * I will debug that stuff in the next time ..
34 * Please read README_COMPILE for compiling ! 37 * Please read README_COMPILE for compiling !
35 * 38 *
36 * 39 *
37 */ 40 */
38 41
39#include "ocontactaccess.h" 42#include "ocontactaccess.h"
40#include "obackendfactory.h" 43#include "obackendfactory.h"
41 44
42#include <qasciidict.h> 45#include <qasciidict.h>
43#include <qdatetime.h> 46#include <qdatetime.h>
44#include <qfile.h> 47#include <qfile.h>
45#include <qregexp.h> 48#include <qregexp.h>
46#include <qlist.h> 49#include <qlist.h>
47#include <qcopchannel_qws.h> 50#include <qcopchannel_qws.h>
48 51
49//#include <qpe/qcopenvelope_qws.h> 52//#include <qpe/qcopenvelope_qws.h>
50#include <qpe/global.h> 53#include <qpe/global.h>
51 54
52#include <errno.h> 55#include <errno.h>
53#include <fcntl.h> 56#include <fcntl.h>
54#include <unistd.h> 57#include <unistd.h>
55#include <stdlib.h> 58#include <stdlib.h>
56 59
57#include "ocontactaccessbackend_xml.h" 60#include "ocontactaccessbackend_xml.h"
58 61
59 62
60OContactAccess::OContactAccess ( const QString appname, const QString , 63OContactAccess::OContactAccess ( const QString appname, const QString ,
61 OContactAccessBackend* end, bool autosync ): 64 OContactAccessBackend* end, bool autosync ):
62 OPimAccessTemplate<OContact>( end ), 65 OPimAccessTemplate<OContact>( end ),
63 m_changed ( false ) 66 m_changed ( false )
64{ 67{
65 /* take care of the backend. If there is no one defined, we 68 /* take care of the backend. If there is no one defined, we
66 * will use the XML-Backend as default (until we have a cute SQL-Backend..). 69 * will use the XML-Backend as default (until we have a cute SQL-Backend..).
67 */ 70 */
68 if( end == 0 ) { 71 if( end == 0 ) {
69 // __asm__("int3");
70 qWarning ("Using BackendFactory !"); 72 qWarning ("Using BackendFactory !");
71 end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname ); 73 end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname );
72 } 74 }
73 // Set backend locally and in template 75 // Set backend locally and in template
74 m_backEnd = end; 76 m_backEnd = end;
75 OPimAccessTemplate<OContact>::setBackEnd (end); 77 OPimAccessTemplate<OContact>::setBackEnd (end);
76 78
77 79
78 /* Connect signal of external db change to function */ 80 /* Connect signal of external db change to function */
79 QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this ); 81 QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this );
80 connect( dbchannel, SIGNAL(received(const QCString &, const QByteArray &)), 82 connect( dbchannel, SIGNAL(received(const QCString &, const QByteArray &)),
81 this, SLOT(copMessage( const QCString &, const QByteArray &)) ); 83 this, SLOT(copMessage( const QCString &, const QByteArray &)) );
82 if ( autosync ){ 84 if ( autosync ){
83 QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this ); 85 QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this );
84 connect( syncchannel, SIGNAL(received(const QCString &, const QByteArray &)), 86 connect( syncchannel, SIGNAL(received(const QCString &, const QByteArray &)),
85 this, SLOT(copMessage( const QCString &, const QByteArray &)) ); 87 this, SLOT(copMessage( const QCString &, const QByteArray &)) );
86 } 88 }
87 89
88 90
89} 91}
90OContactAccess::~OContactAccess () 92OContactAccess::~OContactAccess ()
91{ 93{
92 /* The user may forget to save the changed database, therefore try to 94 /* The user may forget to save the changed database, therefore try to
93 * do it for him.. 95 * do it for him..
94 */ 96 */
95 if ( m_changed ) 97 if ( m_changed )
96 save(); 98 save();
97 // delete m_backEnd; is done by template.. 99 // delete m_backEnd; is done by template..
98} 100}
99 101
100bool OContactAccess::load() 102bool OContactAccess::load()
101{ 103{
102 return ( m_backEnd->load() ); 104 return ( m_backEnd->load() );
103} 105}
104 106
105bool OContactAccess::save () 107bool OContactAccess::save ()
106{ 108{
107 /* If the database was changed externally, we could not save the 109 /* If the database was changed externally, we could not save the
108 * Data. This will remove added items which is unacceptable ! 110 * Data. This will remove added items which is unacceptable !
109 * Therefore: Reload database and merge the data... 111 * Therefore: Reload database and merge the data...
110 */ 112 */
111 if ( m_backEnd->wasChangedExternally() ) 113 if ( m_backEnd->wasChangedExternally() )
112 reload(); 114 reload();
113 115
114 if ( m_changed ){ 116 if ( m_changed ){
115 bool status = m_backEnd->save(); 117 bool status = m_backEnd->save();
116 if ( !status ) return false; 118 if ( !status ) return false;
117 119
118 m_changed = false; 120 m_changed = false;
119 /* Now tell everyone that new data is available. 121 /* Now tell everyone that new data is available.
120 */ 122 */
121 QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" ); 123 QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
122 124
123 } 125 }
124 126
125 return true; 127 return true;
126} 128}
127 129
128const uint OContactAccess::querySettings() 130const uint OContactAccess::querySettings()
129{ 131{
130 return ( m_backEnd->querySettings() ); 132 return ( m_backEnd->querySettings() );
131} 133}
132 134
133bool OContactAccess::hasQuerySettings ( int querySettings ) const 135bool OContactAccess::hasQuerySettings ( int querySettings ) const
134{ 136{
135 return ( m_backEnd->hasQuerySettings ( querySettings ) ); 137 return ( m_backEnd->hasQuerySettings ( querySettings ) );
136} 138}
137 139
138bool OContactAccess::add ( const OContact& newcontact ) 140bool OContactAccess::add ( const OContact& newcontact )
139{ 141{
140 m_changed = true; 142 m_changed = true;
141 return ( m_backEnd->add ( newcontact ) ); 143 return ( m_backEnd->add ( newcontact ) );
142} 144}
143 145
144bool OContactAccess::replace ( const OContact& contact ) 146bool OContactAccess::replace ( const OContact& contact )
145{ 147{
146 m_changed = true; 148 m_changed = true;
147 return ( m_backEnd->replace ( contact ) ); 149 return ( m_backEnd->replace ( contact ) );
148} 150}
149 151
150bool OContactAccess::remove ( const OContact& t ) 152bool OContactAccess::remove ( const OContact& t )
151{ 153{
152 m_changed = true; 154 m_changed = true;
153 return ( m_backEnd->remove ( t.uid() ) ); 155 return ( m_backEnd->remove ( t.uid() ) );
154} 156}
155 157
156bool OContactAccess::remove ( int uid ) 158bool OContactAccess::remove ( int uid )
157{ 159{
158 m_changed = true; 160 m_changed = true;
159 return ( m_backEnd->remove ( uid ) ); 161 return ( m_backEnd->remove ( uid ) );
160} 162}
161 163
162bool OContactAccess::wasChangedExternally()const 164bool OContactAccess::wasChangedExternally()const
163{ 165{
164 return ( m_backEnd->wasChangedExternally() ); 166 return ( m_backEnd->wasChangedExternally() );
165} 167}
diff --git a/libopie/pim/ocontactaccess.h b/libopie/pim/ocontactaccess.h
index 54f7f07..adc66cf 100644
--- a/libopie/pim/ocontactaccess.h
+++ b/libopie/pim/ocontactaccess.h
@@ -1,197 +1,168 @@
1/* 1/*
2 * Class to manage the Contacts. 2 * Class to manage the Contacts.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org) 5 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
6 * 6 *
7 * ===================================================================== 7 * =====================================================================
8 *This program is free software; you can redistribute it and/or 8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public 9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; 10 * License as published by the Free Software Foundation;
11 * either version 2 of the License, or (at your option) any later 11 * either version 2 of the License, or (at your option) any later
12 * version. 12 * version.
13 * ===================================================================== 13 * =====================================================================
14 * ToDo: Define enum for query settings 14 * ToDo: Define enum for query settings
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.2 2002/10/14 16:21:54 eilers
21 * Some minor interface updates
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#ifndef _OCONTACTACCESS_H 31#ifndef _OCONTACTACCESS_H
29#define _OCONTACTACCESS_H 32#define _OCONTACTACCESS_H
30 33
31#include <qobject.h> 34#include <qobject.h>
32 35
33#include <qpe/qcopenvelope_qws.h> 36#include <qpe/qcopenvelope_qws.h>
34 37
35#include <qvaluelist.h> 38#include <qvaluelist.h>
36#include <qfileinfo.h> 39#include <qfileinfo.h>
37 40
38#include "ocontact.h" 41#include "ocontact.h"
39#include "ocontactaccessbackend.h" 42#include "ocontactaccessbackend.h"
40#include "opimaccesstemplate.h" 43#include "opimaccesstemplate.h"
41 44
42/** Class to access the contacts database. 45/** Class to access the contacts database.
43 * This is just a frontend for the real database handling which is 46 * This is just a frontend for the real database handling which is
44 * done by the backend. 47 * done by the backend.
45 */ 48 */
46class OContactAccess: public QObject, public OPimAccessTemplate<OContact> 49class OContactAccess: public QObject, public OPimAccessTemplate<OContact>
47{ 50{
48 Q_OBJECT 51 Q_OBJECT
49 52
50
51 /* class Iterator{
52 friend OContactAccess;
53 public:
54 Iterator();
55 Iterator ( const Iterator& copy );
56
57 bool operator== ( const Iterator& it );
58 bool operator!= ( const Iterator& it );
59 Iterator& operator= ( const Iterator& it );
60 Iterator& operator++ (); // prefix
61 Iterator operator++ ( int ); // postfix
62 Iterator& operator-- (); // prefix
63 Iterator operator-- ( int ); // postfix
64 Contact operator*() const;
65 Contact operator->() const;
66
67 Iterator begin();
68 Iterator end();
69
70 uint count() const;
71
72 private:
73 QValueList<int> m_uids;
74 int m_cur_position;
75 bool m_end_reached;
76 OContactAccess *m_db;
77
78 };
79
80 */
81
82 public: 53 public:
83 /** Create Database with contacts (addressbook). 54 /** Create Database with contacts (addressbook).
84 * @param appname Name of application which wants access to the database 55 * @param appname Name of application which wants access to the database
85 * (i.e. "todolist") 56 * (i.e. "todolist")
86 * @param filename The name of the database file. If not set, the default one 57 * @param filename The name of the database file. If not set, the default one
87 * is used. 58 * is used.
88 * @param backend Pointer to an alternative Backend. If not set, we will use 59 * @param backend Pointer to an alternative Backend. If not set, we will use
89 * the default backend. 60 * the default backend.
90 * @param handlesync If <b>true</b> the database stores the current state 61 * @param handlesync If <b>true</b> the database stores the current state
91 * automatically if it receives the signals <i>flush()</i> and <i>reload()</i> 62 * automatically if it receives the signals <i>flush()</i> and <i>reload()</i>
92 * which are used before and after synchronisation. If the application wants 63 * which are used before and after synchronisation. If the application wants
93 * to react itself, it should be disabled by setting it to <b>false</b> 64 * to react itself, it should be disabled by setting it to <b>false</b>
94 * @see OContactBackend 65 * @see OContactAccessBackend
95 */ 66 */
96 OContactAccess (const QString appname, const QString filename = 0l, 67 OContactAccess (const QString appname, const QString filename = 0l,
97 OContactAccessBackend* backend = 0l, bool handlesync = true); 68 OContactAccessBackend* backend = 0l, bool handlesync = true);
98 ~OContactAccess (); 69 ~OContactAccess ();
99 70
100 /** Constants for query. 71 /** Constants for query.
101 * Use this constants to set the query parameters. 72 * Use this constants to set the query parameters.
102 * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes ! 73 * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes !
103 * @see queryByExample() 74 * @see queryByExample()
104 * - why not enum - zecke?
105 * -> Had some implementation problems .. Will use enum soon ! .. (se)
106 */ 75 */
107 static const int query_WildCards = 0x0001; 76 enum QuerySettings {
108 static const int query_IgnoreCase = 0x0002; 77 WildCards = 0x0001,
109 static const int query_RegExp = 0x0004; 78 IgnoreCase = 0x0002,
110 static const int query_ExactMatch = 0x0008; 79 RegExp = 0x0004,
80 ExactMatch = 0x0008,
81 };
111 82
112 /** Return all possible settings. 83 /** Return all possible settings.
113 * @return All settings provided by the current backend 84 * @return All settings provided by the current backend
114 * (i.e.: query_WildCards & query_IgnoreCase) 85 * (i.e.: query_WildCards & query_IgnoreCase)
115 */ 86 */
116 const uint querySettings(); 87 const uint querySettings();
117 88
118 /** Check whether settings are correct. 89 /** Check whether settings are correct.
119 * @return <i>true</i> if the given settings are correct and possible. 90 * @return <i>true</i> if the given settings are correct and possible.
120 */ 91 */
121 bool hasQuerySettings ( int querySettings ) const; 92 bool hasQuerySettings ( int querySettings ) const;
122 93
123 /** Add Contact to database. 94 /** Add Contact to database.
124 * @param newcontact The contact to add. 95 * @param newcontact The contact to add.
125 * @return <i>true</i> if added successfully. 96 * @return <i>true</i> if added successfully.
126 */ 97 */
127 bool add (const OContact& newcontact); 98 bool add (const OContact& newcontact);
128 99
129 /** Replace contact. 100 /** Replace contact.
130 * Replaces given contact with contact with the user id <i>uid</i>. 101 * Replaces given contact with contact with the user id <i>uid</i>.
131 * @param uid The user ID 102 * @param uid The user ID
132 * @param contact The new contact 103 * @param contact The new contact
133 * @return <i>true</i> if successful. 104 * @return <i>true</i> if successful.
134 */ 105 */
135 bool replace ( const OContact& contact ); 106 bool replace ( const OContact& contact );
136 107
137 /** Remove contact. 108 /** Remove contact.
138 * Removes contact with the user id <i>uid</i>. 109 * Removes contact with the user id <i>uid</i>.
139 * @param The contact to remove 110 * @param The contact to remove
140 * @return <i>true</i> if successful. 111 * @return <i>true</i> if successful.
141 */ 112 */
142 bool remove ( const OContact& t ); 113 bool remove ( const OContact& t );
143 114
144 /** Remove contact. 115 /** Remove contact.
145 * Removes contact with the user id <i>uid</i>. 116 * Removes contact with the user id <i>uid</i>.
146 * @param The user id of the contact to remove 117 * @param The user id of the contact to remove
147 * @return <i>true</i> if successful. 118 * @return <i>true</i> if successful.
148 */ 119 */
149 bool remove ( int uid ); 120 bool remove ( int uid );
150 121
151 /** Load Database * 122 /** Load Database *
152 */ 123 */
153 bool load(); 124 bool load();
154 125
155 /** 126 /**
156 * if the resource was changed externally. 127 * if the resource was changed externally.
157 * You should use the signal instead of polling possible changes ! 128 * You should use the signal instead of polling possible changes !
158 */ 129 */
159 bool wasChangedExternally()const; 130 bool wasChangedExternally()const;
160 131
161 /** Reload database. 132 /** Reload database.
162 * You should execute this function if the external database 133 * You should execute this function if the external database
163 * was changed. 134 * was changed.
164 * This function will load the external database and afterwards 135 * This function will load the external database and afterwards
165 * rejoin the local changes. Therefore the local database will be set consistent. 136 * rejoin the local changes. Therefore the local database will be set consistent.
166 */ 137 */
167 bool reload(); 138 bool reload();
168 139
169 /** Save contacts database. 140 /** Save contacts database.
170 * Save is more a "commit". After calling this function, all changes are public available. 141 * Save is more a "commit". After calling this function, all changes are public available.
171 * @return true if successful 142 * @return true if successful
172 */ 143 */
173 bool save(); 144 bool save();
174 145
175 signals: 146 signals:
176 /* Signal is emitted if the database was changed. Therefore 147 /* Signal is emitted if the database was changed. Therefore
177 * we may need to reload to stay consistent. 148 * we may need to reload to stay consistent.
178 * @param which Pointer to the database who created this event. This pointer 149 * @param which Pointer to the database who created this event. This pointer
179 * is useful if an application has to handle multiple databases at the same time. 150 * is useful if an application has to handle multiple databases at the same time.
180 * @see reload() 151 * @see reload()
181 */ 152 */
182 void signalChanged ( const OContactAccess *which ); 153 void signalChanged ( const OContactAccess *which );
183 154
184 155
185 private: 156 private:
186 // class OContactAccessPrivate; 157 // class OContactAccessPrivate;
187 // OContactAccessPrivate* d; 158 // OContactAccessPrivate* d;
188 OContactAccessBackend *m_backEnd; 159 OContactAccessBackend *m_backEnd;
189 bool m_loading:1; 160 bool m_loading:1;
190 bool m_changed; 161 bool m_changed;
191 162
192 private slots: 163 private slots:
193 void copMessage( const QCString &msg, const QByteArray &data ); 164 void copMessage( const QCString &msg, const QByteArray &data );
194 165
195 166
196}; 167};
197#endif 168#endif
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
index 97ef40f..50ea329 100644
--- a/libopie/pim/ocontactaccessbackend_xml.h
+++ b/libopie/pim/ocontactaccessbackend_xml.h
@@ -1,359 +1,362 @@
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.3 2002/10/14 16:21:54 eilers
21 * Some minor interface updates
22 *
20 * Revision 1.2 2002/10/07 17:34:24 eilers 23 * Revision 1.2 2002/10/07 17:34:24 eilers
21 * added OBackendFactory for advanced backend access 24 * added OBackendFactory for advanced backend access
22 * 25 *
23 * Revision 1.1 2002/09/27 17:11:44 eilers 26 * Revision 1.1 2002/09/27 17:11:44 eilers
24 * Added API for accessing the Contact-Database ! It is compiling, but 27 * Added API for accessing the Contact-Database ! It is compiling, but
25 * please do not expect that anything is working ! 28 * please do not expect that anything is working !
26 * I will debug that stuff in the next time .. 29 * I will debug that stuff in the next time ..
27 * Please read README_COMPILE for compiling ! 30 * Please read README_COMPILE for compiling !
28 * 31 *
29 * 32 *
30 */ 33 */
31 34
32#ifndef _OContactAccessBackend_XML_ 35#ifndef _OContactAccessBackend_XML_
33#define _OContactAccessBackend_XML_ 36#define _OContactAccessBackend_XML_
34 37
35#include <qasciidict.h> 38#include <qasciidict.h>
36#include <qdatetime.h> 39#include <qdatetime.h>
37#include <qfile.h> 40#include <qfile.h>
38#include <qfileinfo.h> 41#include <qfileinfo.h>
39#include <qregexp.h> 42#include <qregexp.h>
40#include <qarray.h> 43#include <qarray.h>
41 44
42#include <qpe/global.h> 45#include <qpe/global.h>
43 46
44#include <opie/xmltree.h> 47#include <opie/xmltree.h>
45#include "ocontactaccessbackend.h" 48#include "ocontactaccessbackend.h"
46#include "ocontactaccess.h" 49#include "ocontactaccess.h"
47 50
48#include <stdlib.h> 51#include <stdlib.h>
49#include <errno.h> 52#include <errno.h>
50 53
51using namespace Opie; 54using namespace Opie;
52 55
53/* the default xml implementation */ 56/* the default xml implementation */
54class OContactAccessBackend_XML : public OContactAccessBackend { 57class OContactAccessBackend_XML : public OContactAccessBackend {
55 public: 58 public:
56 OContactAccessBackend_XML ( QString appname, QString filename = 0l ) 59 OContactAccessBackend_XML ( QString appname, QString filename = 0l )
57 { 60 {
58 m_appName = appname; 61 m_appName = appname;
59 62
60 /* Set journalfile name ... */ 63 /* Set journalfile name ... */
61 m_journalName = getenv("HOME"); 64 m_journalName = getenv("HOME");
62 m_journalName +="/.abjournal" + appname; 65 m_journalName +="/.abjournal" + appname;
63 66
64 /* Expecting to access the default filename if nothing else is set */ 67 /* Expecting to access the default filename if nothing else is set */
65 if ( filename.isEmpty() ){ 68 if ( filename.isEmpty() ){
66 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); 69 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
67 } else 70 } else
68 m_fileName = filename; 71 m_fileName = filename;
69 72
70 /* Load Database now */ 73 /* Load Database now */
71 load (); 74 load ();
72 } 75 }
73 76
74 bool save() { 77 bool save() {
75 QString strNewFile = m_fileName + ".new"; 78 QString strNewFile = m_fileName + ".new";
76 QFile f( strNewFile ); 79 QFile f( strNewFile );
77 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 80 if ( !f.open( IO_WriteOnly|IO_Raw ) )
78 return false; 81 return false;
79 82
80 int total_written; 83 int total_written;
81 QString out; 84 QString out;
82 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 85 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
83 " <Groups>\n" 86 " <Groups>\n"
84 " </Groups>\n" 87 " </Groups>\n"
85 " <Contacts>\n"; 88 " <Contacts>\n";
86 //QValueList<Contact>::iterator it; 89 //QValueList<Contact>::iterator it;
87 QValueListConstIterator<OContact> it; 90 QValueListConstIterator<OContact> it;
88 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) { 91 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
89 out += "<Contact "; 92 out += "<Contact ";
90 (*it).save( out ); 93 (*it).save( out );
91 out += "/>\n"; 94 out += "/>\n";
92 QCString cstr = out.utf8(); 95 QCString cstr = out.utf8();
93 total_written = f.writeBlock( cstr.data(), cstr.length() ); 96 total_written = f.writeBlock( cstr.data(), cstr.length() );
94 if ( total_written != int(cstr.length()) ) { 97 if ( total_written != int(cstr.length()) ) {
95 f.close(); 98 f.close();
96 QFile::remove( strNewFile ); 99 QFile::remove( strNewFile );
97 return false; 100 return false;
98 } 101 }
99 out = ""; 102 out = "";
100 } 103 }
101 out += " </Contacts>\n</AddressBook>\n"; 104 out += " </Contacts>\n</AddressBook>\n";
102 105
103 QCString cstr = out.utf8(); 106 QCString cstr = out.utf8();
104 total_written = f.writeBlock( cstr.data(), cstr.length() ); 107 total_written = f.writeBlock( cstr.data(), cstr.length() );
105 if ( total_written != int( cstr.length() ) ) { 108 if ( total_written != int( cstr.length() ) ) {
106 f.close(); 109 f.close();
107 QFile::remove( strNewFile ); 110 QFile::remove( strNewFile );
108 return false; 111 return false;
109 } 112 }
110 f.close(); 113 f.close();
111 114
112 // move the file over, I'm just going to use the system call 115 // move the file over, I'm just going to use the system call
113 // because, I don't feel like using QDir. 116 // because, I don't feel like using QDir.
114 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 117 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
115 qWarning( "problem renaming file %s to %s, errno: %d", 118 qWarning( "problem renaming file %s to %s, errno: %d",
116 strNewFile.latin1(), m_journalName.latin1(), errno ); 119 strNewFile.latin1(), m_journalName.latin1(), errno );
117 // remove the tmp file... 120 // remove the tmp file...
118 QFile::remove( strNewFile ); 121 QFile::remove( strNewFile );
119 } 122 }
120 123
121 /* The journalfile should be removed now... */ 124 /* The journalfile should be removed now... */
122 removeJournal(); 125 removeJournal();
123 return true; 126 return true;
124 } 127 }
125 128
126 bool load () { 129 bool load () {
127 m_contactList.clear(); 130 m_contactList.clear();
128 131
129 /* Load XML-File and journal if it exists */ 132 /* Load XML-File and journal if it exists */
130 if ( !load ( m_fileName, false ) ) 133 if ( !load ( m_fileName, false ) )
131 return false; 134 return false;
132 /* The returncode of the journalfile is ignored due to the 135 /* The returncode of the journalfile is ignored due to the
133 * fact that it does not exist when this class is instantiated ! 136 * fact that it does not exist when this class is instantiated !
134 * But there may such a file exist, if the application crashed. 137 * But there may such a file exist, if the application crashed.
135 * Therefore we try to load it to get the changes before the # 138 * Therefore we try to load it to get the changes before the #
136 * crash happened... 139 * crash happened...
137 */ 140 */
138 load (m_journalName, true); 141 load (m_journalName, true);
139 142
140 return true; 143 return true;
141 } 144 }
142 145
143 void clear () { 146 void clear () {
144 m_contactList.clear(); 147 m_contactList.clear();
145 148
146 } 149 }
147 150
148 bool wasChangedExternally() 151 bool wasChangedExternally()
149 { 152 {
150 QFileInfo fi( m_fileName ); 153 QFileInfo fi( m_fileName );
151 154
152 QDateTime lastmod = fi.lastModified (); 155 QDateTime lastmod = fi.lastModified ();
153 156
154 return (lastmod != m_readtime); 157 return (lastmod != m_readtime);
155 } 158 }
156 159
157 QArray<int> allRecords() const { 160 QArray<int> allRecords() const {
158 QArray<int> uid_list( m_contactList.count() ); 161 QArray<int> uid_list( m_contactList.count() );
159 162
160 uint counter = 0; 163 uint counter = 0;
161 QValueListConstIterator<OContact> it; 164 QValueListConstIterator<OContact> it;
162 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 165 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
163 uid_list[counter++] = (*it).uid(); 166 uid_list[counter++] = (*it).uid();
164 } 167 }
165 168
166 return ( uid_list ); 169 return ( uid_list );
167 } 170 }
168 171
169 OContact find ( int uid ) const 172 OContact find ( int uid ) const
170 { 173 {
171 bool found = false; 174 bool found = false;
172 OContact foundContact; //Create empty contact 175 OContact foundContact; //Create empty contact
173 176
174 QValueListConstIterator<OContact> it; 177 QValueListConstIterator<OContact> it;
175 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 178 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
176 if ((*it).uid() == uid){ 179 if ((*it).uid() == uid){
177 found = true; 180 found = true;
178 break; 181 break;
179 } 182 }
180 } 183 }
181 if ( found ){ 184 if ( found ){
182 foundContact = *it; 185 foundContact = *it;
183 } 186 }
184 187
185 return ( foundContact ); 188 return ( foundContact );
186 } 189 }
187 190
188 QArray<int> queryByExample ( const OContact &query, int settings ){ 191 QArray<int> queryByExample ( const OContact &query, int settings ){
189 192
190 QArray<int> m_currentQuery( m_contactList.count() ); 193 QArray<int> m_currentQuery( m_contactList.count() );
191 QValueListConstIterator<OContact> it; 194 QValueListConstIterator<OContact> it;
192 uint arraycounter = 0; 195 uint arraycounter = 0;
193 196
194 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 197 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
195 /* Search all fields and compare them with query object. Store them into list 198 /* Search all fields and compare them with query object. Store them into list
196 * if all fields matches. 199 * if all fields matches.
197 */ 200 */
198 bool allcorrect = true; 201 bool allcorrect = true;
199 for ( int i = 0; i < Qtopia::rid; i++ ) { 202 for ( int i = 0; i < Qtopia::rid; i++ ) {
200 /* Just compare fields which are not empty in the query object */ 203 /* Just compare fields which are not empty in the query object */
201 if ( !query.field(i).isEmpty() ){ 204 if ( !query.field(i).isEmpty() ){
202 switch ( settings & ~OContactAccess::query_IgnoreCase ){ 205 switch ( settings & ~OContactAccess::IgnoreCase ){
203 case OContactAccess::query_RegExp:{ 206 case OContactAccess::RegExp:{
204 QRegExp expr ( query.field(i), 207 QRegExp expr ( query.field(i),
205 !(settings & OContactAccess::query_IgnoreCase), 208 !(settings & OContactAccess::IgnoreCase),
206 false ); 209 false );
207 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 210 if ( expr.find ( (*it).field(i), 0 ) == -1 )
208 allcorrect = false; 211 allcorrect = false;
209 } 212 }
210 break; 213 break;
211 case OContactAccess::query_WildCards:{ 214 case OContactAccess::WildCards:{
212 QRegExp expr ( query.field(i), 215 QRegExp expr ( query.field(i),
213 !(settings & OContactAccess::query_IgnoreCase), 216 !(settings & OContactAccess::IgnoreCase),
214 true ); 217 true );
215 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 218 if ( expr.find ( (*it).field(i), 0 ) == -1 )
216 allcorrect = false; 219 allcorrect = false;
217 } 220 }
218 break; 221 break;
219 case OContactAccess::query_ExactMatch:{ 222 case OContactAccess::ExactMatch:{
220 if (settings & OContactAccess::query_IgnoreCase){ 223 if (settings & OContactAccess::IgnoreCase){
221 if ( query.field(i).upper() != 224 if ( query.field(i).upper() !=
222 (*it).field(i).upper() ) 225 (*it).field(i).upper() )
223 allcorrect = false; 226 allcorrect = false;
224 }else{ 227 }else{
225 if ( query.field(i) != (*it).field(i) ) 228 if ( query.field(i) != (*it).field(i) )
226 allcorrect = false; 229 allcorrect = false;
227 } 230 }
228 } 231 }
229 break; 232 break;
230 } 233 }
231 } 234 }
232 } 235 }
233 if ( allcorrect ){ 236 if ( allcorrect ){
234 m_currentQuery[arraycounter++] = (*it).uid(); 237 m_currentQuery[arraycounter++] = (*it).uid();
235 } 238 }
236 } 239 }
237 240
238 // Shrink to fit.. 241 // Shrink to fit..
239 m_currentQuery.resize(arraycounter); 242 m_currentQuery.resize(arraycounter);
240 243
241 return m_currentQuery; 244 return m_currentQuery;
242 } 245 }
243 246
244 const uint querySettings() 247 const uint querySettings()
245 { 248 {
246 return ( OContactAccess::query_WildCards 249 return ( OContactAccess::WildCards
247 & OContactAccess::query_IgnoreCase 250 & OContactAccess::IgnoreCase
248 & OContactAccess::query_RegExp 251 & OContactAccess::RegExp
249 & OContactAccess::query_ExactMatch ); 252 & OContactAccess::ExactMatch );
250 } 253 }
251 254
252 bool hasQuerySettings (uint querySettings) const 255 bool hasQuerySettings (uint querySettings) const
253 { 256 {
254 /* OContactAccess::query_IgnoreCase may be added with one 257 /* OContactAccess::IgnoreCase may be added with one
255 * of the other settings, but never used alone. 258 * of the other settings, but never used alone.
256 * The other settings are just valid alone... 259 * The other settings are just valid alone...
257 */ 260 */
258 switch ( querySettings & ~OContactAccess::query_IgnoreCase ){ 261 switch ( querySettings & ~OContactAccess::IgnoreCase ){
259 case OContactAccess::query_RegExp: 262 case OContactAccess::RegExp:
260 return ( true ); 263 return ( true );
261 case OContactAccess::query_WildCards: 264 case OContactAccess::WildCards:
262 return ( true ); 265 return ( true );
263 case OContactAccess::query_ExactMatch: 266 case OContactAccess::ExactMatch:
264 return ( true ); 267 return ( true );
265 default: 268 default:
266 return ( false ); 269 return ( false );
267 } 270 }
268 } 271 }
269 272
270 bool add ( const OContact &newcontact ) 273 bool add ( const OContact &newcontact )
271 { 274 {
272 //qWarning("odefaultbackend: ACTION::ADD"); 275 //qWarning("odefaultbackend: ACTION::ADD");
273 updateJournal (newcontact, OContact::ACTION_ADD); 276 updateJournal (newcontact, OContact::ACTION_ADD);
274 addContact_p( newcontact ); 277 addContact_p( newcontact );
275 return true; 278 return true;
276 } 279 }
277 280
278 bool replace ( const OContact &contact ) 281 bool replace ( const OContact &contact )
279 { 282 {
280 bool found = false; 283 bool found = false;
281 284
282 QValueListIterator<OContact> it; 285 QValueListIterator<OContact> it;
283 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 286 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
284 if ( (*it).uid() == contact.uid() ){ 287 if ( (*it).uid() == contact.uid() ){
285 found = true; 288 found = true;
286 break; 289 break;
287 } 290 }
288 } 291 }
289 if (found) { 292 if (found) {
290 updateJournal (contact, OContact::ACTION_REPLACE); 293 updateJournal (contact, OContact::ACTION_REPLACE);
291 m_contactList.remove (it); 294 m_contactList.remove (it);
292 m_contactList.append (contact); 295 m_contactList.append (contact);
293 return true; 296 return true;
294 } else 297 } else
295 return false; 298 return false;
296 } 299 }
297 300
298 bool remove ( int uid ) 301 bool remove ( int uid )
299 { 302 {
300 bool found = false; 303 bool found = false;
301 QValueListIterator<OContact> it; 304 QValueListIterator<OContact> it;
302 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 305 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
303 if ((*it).uid() == uid){ 306 if ((*it).uid() == uid){
304 found = true; 307 found = true;
305 break; 308 break;
306 } 309 }
307 } 310 }
308 if (found) { 311 if (found) {
309 updateJournal ( *it, OContact::ACTION_REMOVE); 312 updateJournal ( *it, OContact::ACTION_REMOVE);
310 m_contactList.remove (it); 313 m_contactList.remove (it);
311 return true; 314 return true;
312 } else 315 } else
313 return false; 316 return false;
314 } 317 }
315 318
316 bool reload(){ 319 bool reload(){
317 /* Reload is the same as load in this implementation */ 320 /* Reload is the same as load in this implementation */
318 return ( load() ); 321 return ( load() );
319 } 322 }
320 323
321 private: 324 private:
322 void addContact_p( const OContact &newcontact ){ 325 void addContact_p( const OContact &newcontact ){
323 m_contactList.append (newcontact); 326 m_contactList.append (newcontact);
324 } 327 }
325 328
326 /* This function loads the xml-database and the journalfile */ 329 /* This function loads the xml-database and the journalfile */
327 bool load( const QString filename, bool isJournal ) { 330 bool load( const QString filename, bool isJournal ) {
328 331
329 /* We use the time of the last read to check if the file was 332 /* We use the time of the last read to check if the file was
330 * changed externally. 333 * changed externally.
331 */ 334 */
332 if ( !isJournal ){ 335 if ( !isJournal ){
333 QFileInfo fi( filename ); 336 QFileInfo fi( filename );
334 m_readtime = fi.lastModified (); 337 m_readtime = fi.lastModified ();
335 } 338 }
336 339
337 const int JOURNALACTION = Qtopia::Notes + 1; 340 const int JOURNALACTION = Qtopia::Notes + 1;
338 const int JOURNALROW = JOURNALACTION + 1; 341 const int JOURNALROW = JOURNALACTION + 1;
339 342
340 bool foundAction = false; 343 bool foundAction = false;
341 OContact::journal_action action = OContact::ACTION_ADD; 344 OContact::journal_action action = OContact::ACTION_ADD;
342 int journalKey = 0; 345 int journalKey = 0;
343 QMap<int, QString> contactMap; 346 QMap<int, QString> contactMap;
344 QMap<QString, QString> customMap; 347 QMap<QString, QString> customMap;
345 QMap<QString, QString>::Iterator customIt; 348 QMap<QString, QString>::Iterator customIt;
346 QAsciiDict<int> dict( 47 ); 349 QAsciiDict<int> dict( 47 );
347 350
348 dict.setAutoDelete( TRUE ); 351 dict.setAutoDelete( TRUE );
349 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 352 dict.insert( "Uid", new int(Qtopia::AddressUid) );
350 dict.insert( "Title", new int(Qtopia::Title) ); 353 dict.insert( "Title", new int(Qtopia::Title) );
351 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 354 dict.insert( "FirstName", new int(Qtopia::FirstName) );
352 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 355 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
353 dict.insert( "LastName", new int(Qtopia::LastName) ); 356 dict.insert( "LastName", new int(Qtopia::LastName) );
354 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 357 dict.insert( "Suffix", new int(Qtopia::Suffix) );
355 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 358 dict.insert( "FileAs", new int(Qtopia::FileAs) );
356 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 359 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
357 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 360 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
358 dict.insert( "Emails", new int(Qtopia::Emails) ); 361 dict.insert( "Emails", new int(Qtopia::Emails) );
359 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 362 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
diff --git a/libopie/pim/opimaccesstemplate.h b/libopie/pim/opimaccesstemplate.h
index a0d8f63..3e1f393 100644
--- a/libopie/pim/opimaccesstemplate.h
+++ b/libopie/pim/opimaccesstemplate.h
@@ -1,167 +1,161 @@
1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H 1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
2#define OPIE_PIM_ACCESS_TEMPLATE_H 2#define OPIE_PIM_ACCESS_TEMPLATE_H
3 3
4#include <qarray.h> 4#include <qarray.h>
5 5
6#include <opie/opimrecord.h> 6#include <opie/opimrecord.h>
7#include <opie/opimaccessbackend.h> 7#include <opie/opimaccessbackend.h>
8#include <opie/orecordlist.h> 8#include <opie/orecordlist.h>
9 9
10#include "opimcache.h" 10#include "opimcache.h"
11#include "otemplatebase.h" 11#include "otemplatebase.h"
12 12
13/** 13/**
14 * Thats the frontend to our OPIE PIM 14 * Thats the frontend to our OPIE PIM
15 * Library. Either you want to use it's 15 * Library. Either you want to use it's
16 * interface or you want to implement 16 * interface or you want to implement
17 * your own Access lib 17 * your own Access lib
18 * Just create a OPimRecord and inherit from 18 * Just create a OPimRecord and inherit from
19 * the plugins 19 * the plugins
20 */ 20 */
21 21
22template <class T = OPimRecord > 22template <class T = OPimRecord >
23class OPimAccessTemplate : public OTemplateBase<T> { 23class OPimAccessTemplate : public OTemplateBase<T> {
24public: 24public:
25 typedef ORecordList<T> List; 25 typedef ORecordList<T> List;
26 typedef OPimAccessBackend<T> BackEnd; 26 typedef OPimAccessBackend<T> BackEnd;
27 typedef OPimCache<T> Cache; 27 typedef OPimCache<T> Cache;
28 28
29 /** 29 /**
30 * our sort order
31 * should be safe explaining
32 */
33 enum SortOrder { WildCards = 0, IgnoreCase = 1,
34 RegExp = 2, ExactMatch = 4 };
35
36 /**
37 * c'tor BackEnd 30 * c'tor BackEnd
38 */ 31 */
39 OPimAccessTemplate( BackEnd* end); 32 OPimAccessTemplate( BackEnd* end);
40 virtual ~OPimAccessTemplate(); 33 virtual ~OPimAccessTemplate();
41 34
42 /** 35 /**
43 * load from the backend 36 * load from the backend
44 */ 37 */
45 virtual bool load(); 38 virtual bool load();
46 39
47 /** 40 /**
48 * reload from the backend 41 * reload from the backend
49 */ 42 */
50 virtual bool reload(); 43 virtual bool reload();
51 44
52 /** 45 /**
53 * save to the backend 46 * save to the backend
54 */ 47 */
55 virtual bool save(); 48 virtual bool save();
56 49
57 /** 50 /**
58 * if the resource was changed externally 51 * if the resource was changed externally
59 */ 52 */
60 bool wasChangedExternally()const; 53 bool wasChangedExternally()const;
61 54
62 /** 55 /**
63 * return a List of records 56 * return a List of records
64 * you can iterate over them 57 * you can iterate over them
65 */ 58 */
66 virtual List allRecords()const; 59 virtual List allRecords()const;
67 60
68 /** 61 /**
69 * queryByExample 62 * queryByExample)
63 * @see otodoaccess, ocontactaccess
70 */ 64 */
71 virtual List queryByExample( const T& t, int sortOrder ); 65 virtual List queryByExample( const T& t, int querySettings );
72 66
73 /** 67 /**
74 * find the OPimRecord uid 68 * find the OPimRecord uid
75 */ 69 */
76 virtual T find( int uid )const; 70 virtual T find( int uid )const;
77 71
78 /** 72 /**
79 * read ahead cache find method ;) 73 * read ahead cache find method ;)
80 */ 74 */
81 virtual T find( int uid, const QArray<int>&, 75 virtual T find( int uid, const QArray<int>&,
82 uint current, CacheDirection dir = Forward )const; 76 uint current, CacheDirection dir = Forward )const;
83 77
84 /* invalidate cache here */ 78 /* invalidate cache here */
85 /** 79 /**
86 * clears the backend and invalidates the backend 80 * clears the backend and invalidates the backend
87 */ 81 */
88 virtual void clear() ; 82 virtual void clear() ;
89 83
90 /** 84 /**
91 * add T to the backend 85 * add T to the backend
92 */ 86 */
93 virtual bool add( const T& t ) ; 87 virtual bool add( const T& t ) ;
94 88
95 /* only the uid matters */ 89 /* only the uid matters */
96 /** 90 /**
97 * remove T from the backend 91 * remove T from the backend
98 */ 92 */
99 virtual bool remove( const T& t ); 93 virtual bool remove( const T& t );
100 94
101 /** 95 /**
102 * remove the OPimRecord with uid 96 * remove the OPimRecord with uid
103 */ 97 */
104 virtual bool remove( int uid ); 98 virtual bool remove( int uid );
105 99
106 /** 100 /**
107 * replace T from backend 101 * replace T from backend
108 */ 102 */
109 virtual bool replace( const T& t) ; 103 virtual bool replace( const T& t) ;
110 104
111 /** 105 /**
112 * @internal 106 * @internal
113 */ 107 */
114 void cache( const T& )const; 108 void cache( const T& )const;
115 void setSaneCacheSize( int ); 109 void setSaneCacheSize( int );
116protected: 110protected:
117 /** 111 /**
118 * invalidate the cache 112 * invalidate the cache
119 */ 113 */
120 void invalidateCache(); 114 void invalidateCache();
121 115
122 void setBackEnd( BackEnd* end ); 116 void setBackEnd( BackEnd* end );
123 /** 117 /**
124 * returns the backend 118 * returns the backend
125 */ 119 */
126 BackEnd* backEnd(); 120 BackEnd* backEnd();
127 BackEnd* m_backEnd; 121 BackEnd* m_backEnd;
128 Cache m_cache; 122 Cache m_cache;
129 123
130}; 124};
131 125
132template <class T> 126template <class T>
133OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) 127OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
134 : OTemplateBase<T>(), m_backEnd( end ) 128 : OTemplateBase<T>(), m_backEnd( end )
135{ 129{
136 if (end ) 130 if (end )
137 end->setFrontend( this ); 131 end->setFrontend( this );
138} 132}
139template <class T> 133template <class T>
140OPimAccessTemplate<T>::~OPimAccessTemplate() { 134OPimAccessTemplate<T>::~OPimAccessTemplate() {
141 qWarning("~OPimAccessTemplate<T>"); 135 qWarning("~OPimAccessTemplate<T>");
142 delete m_backEnd; 136 delete m_backEnd;
143} 137}
144template <class T> 138template <class T>
145bool OPimAccessTemplate<T>::load() { 139bool OPimAccessTemplate<T>::load() {
146 invalidateCache(); 140 invalidateCache();
147 return m_backEnd->load(); 141 return m_backEnd->load();
148} 142}
149template <class T> 143template <class T>
150bool OPimAccessTemplate<T>::reload() { 144bool OPimAccessTemplate<T>::reload() {
151 return m_backEnd->reload(); 145 return m_backEnd->reload();
152} 146}
153template <class T> 147template <class T>
154bool OPimAccessTemplate<T>::save() { 148bool OPimAccessTemplate<T>::save() {
155 return m_backEnd->save(); 149 return m_backEnd->save();
156} 150}
157template <class T> 151template <class T>
158OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { 152OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
159 QArray<int> ints = m_backEnd->allRecords(); 153 QArray<int> ints = m_backEnd->allRecords();
160 List lis(ints, this ); 154 List lis(ints, this );
161 return lis; 155 return lis;
162} 156}
163template <class T> 157template <class T>
164OPimAccessTemplate<T>::List 158OPimAccessTemplate<T>::List
165OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) { 159OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) {
166 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder ); 160 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder );
167 161
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index f3b0783..3b4cab2 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -94,193 +94,193 @@ bool OTodoAccessXML::load() {
94 ++j; 94 ++j;
95 } 95 }
96 if ( i == j ) { 96 if ( i == j ) {
97 // empty value 97 // empty value
98 i = j + 1; 98 i = j + 1;
99 continue; 99 continue;
100 } 100 }
101 101
102 QCString value( dt+i, j-i+1 ); 102 QCString value( dt+i, j-i+1 );
103 i = j + 1; 103 i = j + 1;
104 104
105 QString str = (haveUtf ? QString::fromUtf8( value ) 105 QString str = (haveUtf ? QString::fromUtf8( value )
106 : QString::fromLatin1( value ) ); 106 : QString::fromLatin1( value ) );
107 if ( haveEnt ) 107 if ( haveEnt )
108 str = Qtopia::plainString( str ); 108 str = Qtopia::plainString( str );
109 109
110 /* 110 /*
111 * add key + value 111 * add key + value
112 */ 112 */
113 todo( &dict, ev, attr, str ); 113 todo( &dict, ev, attr, str );
114 114
115 } 115 }
116 /* 116 /*
117 * now add it 117 * now add it
118 */ 118 */
119 m_events.insert(ev.uid(), ev ); 119 m_events.insert(ev.uid(), ev );
120 } 120 }
121 121
122 qWarning("counts %d", m_events.count() ); 122 qWarning("counts %d", m_events.count() );
123 return true; 123 return true;
124} 124}
125bool OTodoAccessXML::reload() { 125bool OTodoAccessXML::reload() {
126 return load(); 126 return load();
127} 127}
128bool OTodoAccessXML::save() { 128bool OTodoAccessXML::save() {
129// qWarning("saving"); 129// qWarning("saving");
130 if (!m_opened || !m_changed ) { 130 if (!m_opened || !m_changed ) {
131// qWarning("not saving"); 131// qWarning("not saving");
132 return true; 132 return true;
133 } 133 }
134 QString strNewFile = m_file + ".new"; 134 QString strNewFile = m_file + ".new";
135 QFile f( strNewFile ); 135 QFile f( strNewFile );
136 if (!f.open( IO_WriteOnly|IO_Raw ) ) 136 if (!f.open( IO_WriteOnly|IO_Raw ) )
137 return false; 137 return false;
138 138
139 int written; 139 int written;
140 QString out; 140 QString out;
141 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 141 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
142 142
143 // for all todos 143 // for all todos
144 QMap<int, OTodo>::Iterator it; 144 QMap<int, OTodo>::Iterator it;
145 for (it = m_events.begin(); it != m_events.end(); ++it ) { 145 for (it = m_events.begin(); it != m_events.end(); ++it ) {
146 out+= "<Task " + toString( (*it) ) + " />\n"; 146 out+= "<Task " + toString( (*it) ) + " />\n";
147 QCString cstr = out.utf8(); 147 QCString cstr = out.utf8();
148 written = f.writeBlock( cstr.data(), cstr.length() ); 148 written = f.writeBlock( cstr.data(), cstr.length() );
149 149
150 /* less written then we wanted */ 150 /* less written then we wanted */
151 if ( written != (int)cstr.length() ) { 151 if ( written != (int)cstr.length() ) {
152 f.close(); 152 f.close();
153 QFile::remove( strNewFile ); 153 QFile::remove( strNewFile );
154 return false; 154 return false;
155 } 155 }
156 out = QString::null; 156 out = QString::null;
157 } 157 }
158 158
159 out += "</Tasks>"; 159 out += "</Tasks>";
160 QCString cstr = out.utf8(); 160 QCString cstr = out.utf8();
161 written = f.writeBlock( cstr.data(), cstr.length() ); 161 written = f.writeBlock( cstr.data(), cstr.length() );
162 162
163 if ( written != (int)cstr.length() ) { 163 if ( written != (int)cstr.length() ) {
164 f.close(); 164 f.close();
165 QFile::remove( strNewFile ); 165 QFile::remove( strNewFile );
166 return false; 166 return false;
167 } 167 }
168 /* flush before renaming */ 168 /* flush before renaming */
169 f.close(); 169 f.close();
170 170
171 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 171 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
172// qWarning("error renaming"); 172// qWarning("error renaming");
173 QFile::remove( strNewFile ); 173 QFile::remove( strNewFile );
174 } 174 }
175 175
176 m_changed = false; 176 m_changed = false;
177 return true; 177 return true;
178} 178}
179QArray<int> OTodoAccessXML::allRecords()const { 179QArray<int> OTodoAccessXML::allRecords()const {
180 QArray<int> ids( m_events.count() ); 180 QArray<int> ids( m_events.count() );
181 QMap<int, OTodo>::ConstIterator it; 181 QMap<int, OTodo>::ConstIterator it;
182 int i = 0; 182 int i = 0;
183 183
184 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 184 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
185 ids[i] = it.key(); 185 ids[i] = it.key();
186 i++; 186 i++;
187 } 187 }
188 return ids; 188 return ids;
189} 189}
190QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int sort ) { 190QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) {
191 QArray<int> ids(0); 191 QArray<int> ids(0);
192 return ids; 192 return ids;
193} 193}
194OTodo OTodoAccessXML::find( int uid )const { 194OTodo OTodoAccessXML::find( int uid )const {
195 OTodo todo; 195 OTodo todo;
196 todo.setUid( 0 ); // isEmpty() 196 todo.setUid( 0 ); // isEmpty()
197 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 197 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
198 if ( it != m_events.end() ) 198 if ( it != m_events.end() )
199 todo = it.data(); 199 todo = it.data();
200 200
201 return todo; 201 return todo;
202} 202}
203void OTodoAccessXML::clear() { 203void OTodoAccessXML::clear() {
204 if (m_opened ) 204 if (m_opened )
205 m_changed = true; 205 m_changed = true;
206 206
207 m_events.clear(); 207 m_events.clear();
208} 208}
209bool OTodoAccessXML::add( const OTodo& todo ) { 209bool OTodoAccessXML::add( const OTodo& todo ) {
210// qWarning("add"); 210// qWarning("add");
211 m_changed = true; 211 m_changed = true;
212 m_events.insert( todo.uid(), todo ); 212 m_events.insert( todo.uid(), todo );
213 213
214 return true; 214 return true;
215} 215}
216bool OTodoAccessXML::remove( int uid ) { 216bool OTodoAccessXML::remove( int uid ) {
217 m_changed = true; 217 m_changed = true;
218 m_events.remove( uid ); 218 m_events.remove( uid );
219 219
220 return true; 220 return true;
221} 221}
222bool OTodoAccessXML::replace( const OTodo& todo) { 222bool OTodoAccessXML::replace( const OTodo& todo) {
223 m_changed = true; 223 m_changed = true;
224 m_events.replace( todo.uid(), todo ); 224 m_events.replace( todo.uid(), todo );
225 225
226 return true; 226 return true;
227} 227}
228QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 228QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
229 const QDate& end, 229 const QDate& end,
230 bool includeNoDates ) { 230 bool includeNoDates ) {
231 QArray<int> ids( m_events.count() ); 231 QArray<int> ids( m_events.count() );
232 QMap<int, OTodo>::Iterator it; 232 QMap<int, OTodo>::Iterator it;
233 233
234 int i = 0; 234 int i = 0;
235 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 235 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
236 if ( !it.data().hasDueDate() ) { 236 if ( !it.data().hasDueDate() ) {
237 if ( includeNoDates ) { 237 if ( includeNoDates ) {
238 ids[i] = it.key(); 238 ids[i] = it.key();
239 i++; 239 i++;
240 } 240 }
241 }else if ( it.data().dueDate() >= start && 241 }else if ( it.data().dueDate() >= start &&
242 it.data().dueDate() <= end ) { 242 it.data().dueDate() <= end ) {
243 ids[i] = it.key(); 243 ids[i] = it.key();
244 i++; 244 i++;
245 } 245 }
246 } 246 }
247 ids.resize( i ); 247 ids.resize( i );
248 return ids; 248 return ids;
249} 249}
250QArray<int> OTodoAccessXML::overDue() { 250QArray<int> OTodoAccessXML::overDue() {
251 QArray<int> ids( m_events.count() ); 251 QArray<int> ids( m_events.count() );
252 int i = 0; 252 int i = 0;
253 253
254 QMap<int, OTodo>::Iterator it; 254 QMap<int, OTodo>::Iterator it;
255 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 255 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
256 if ( it.data().isOverdue() ) { 256 if ( it.data().isOverdue() ) {
257 ids[i] = it.key(); 257 ids[i] = it.key();
258 i++; 258 i++;
259 } 259 }
260 } 260 }
261 ids.resize( i ); 261 ids.resize( i );
262 return ids; 262 return ids;
263} 263}
264 264
265 265
266/* private */ 266/* private */
267void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, 267void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
268 const QCString& attr, const QString& val) { 268 const QCString& attr, const QString& val) {
269// qWarning("parse to do from XMLElement" ); 269// qWarning("parse to do from XMLElement" );
270 270
271 int *find=0; 271 int *find=0;
272 272
273 find = (*dict)[ attr.data() ]; 273 find = (*dict)[ attr.data() ];
274 if (!find ) { 274 if (!find ) {
275// qWarning("Unknown option" + it.key() ); 275// qWarning("Unknown option" + it.key() );
276 ev.setCustomField( attr, val ); 276 ev.setCustomField( attr, val );
277 return; 277 return;
278 } 278 }
279 279
280 switch( *find ) { 280 switch( *find ) {
281 case OTodo::Uid: 281 case OTodo::Uid:
282 ev.setUid( val.toInt() ); 282 ev.setUid( val.toInt() );
283 break; 283 break;
284 case OTodo::Category: 284 case OTodo::Category:
285 ev.setCategories( ev.idsFromString( val ) ); 285 ev.setCategories( ev.idsFromString( val ) );
286 break; 286 break;
diff --git a/libopie/pim/otodoaccessxml.h b/libopie/pim/otodoaccessxml.h
index 1e7e371..dc41c32 100644
--- a/libopie/pim/otodoaccessxml.h
+++ b/libopie/pim/otodoaccessxml.h
@@ -1,56 +1,56 @@
1#ifndef OPIE_TODO_ACCESS_XML_H 1#ifndef OPIE_TODO_ACCESS_XML_H
2#define OPIE_TODO_ACCESS_XML_H 2#define OPIE_TODO_ACCESS_XML_H
3 3
4#include <qasciidict.h> 4#include <qasciidict.h>
5#include <qmap.h> 5#include <qmap.h>
6 6
7#include "otodoaccessbackend.h" 7#include "otodoaccessbackend.h"
8 8
9namespace Opie { 9namespace Opie {
10 class XMLElement; 10 class XMLElement;
11}; 11};
12 12
13class OTodoAccessXML : public OTodoAccessBackend { 13class OTodoAccessXML : public OTodoAccessBackend {
14public: 14public:
15 /** 15 /**
16 * fileName if Empty we will use the default path 16 * fileName if Empty we will use the default path
17 */ 17 */
18 OTodoAccessXML( const QString& appName, 18 OTodoAccessXML( const QString& appName,
19 const QString& fileName = QString::null ); 19 const QString& fileName = QString::null );
20 ~OTodoAccessXML(); 20 ~OTodoAccessXML();
21 21
22 bool load(); 22 bool load();
23 bool reload(); 23 bool reload();
24 bool save(); 24 bool save();
25 25
26 QArray<int> allRecords()const; 26 QArray<int> allRecords()const;
27 QArray<int> queryByExample( const OTodo&, int sort ); 27 QArray<int> queryByExample( const OTodo&, int querysettings );
28 OTodo find( int uid )const; 28 OTodo find( int uid )const;
29 void clear(); 29 void clear();
30 bool add( const OTodo& ); 30 bool add( const OTodo& );
31 bool remove( int uid ); 31 bool remove( int uid );
32 bool replace( const OTodo& ); 32 bool replace( const OTodo& );
33 33
34 /* our functions */ 34 /* our functions */
35 QArray<int> effectiveToDos( const QDate& start, 35 QArray<int> effectiveToDos( const QDate& start,
36 const QDate& end, 36 const QDate& end,
37 bool includeNoDates ); 37 bool includeNoDates );
38 QArray<int> overDue(); 38 QArray<int> overDue();
39 QArray<int> sorted( bool asc, int sortOrder, 39 QArray<int> sorted( bool asc, int sortOrder,
40 int sortFilter, int cat ); 40 int sortFilter, int cat );
41private: 41private:
42 void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& ); 42 void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& );
43 QString toString( const OTodo& )const; 43 QString toString( const OTodo& )const;
44 QString toString( const QArray<int>& ints ) const; 44 QString toString( const QArray<int>& ints ) const;
45 QMap<int, OTodo> m_events; 45 QMap<int, OTodo> m_events;
46 QString m_file; 46 QString m_file;
47 QString m_app; 47 QString m_app;
48 bool m_opened : 1; 48 bool m_opened : 1;
49 bool m_changed : 1; 49 bool m_changed : 1;
50 class OTodoAccessXMLPrivate; 50 class OTodoAccessXMLPrivate;
51 OTodoAccessXMLPrivate* d; 51 OTodoAccessXMLPrivate* d;
52 int m_year, m_month, m_day; 52 int m_year, m_month, m_day;
53 53
54}; 54};
55 55
56#endif 56#endif
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
index 97ef40f..50ea329 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
@@ -1,359 +1,362 @@
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.3 2002/10/14 16:21:54 eilers
21 * Some minor interface updates
22 *
20 * Revision 1.2 2002/10/07 17:34:24 eilers 23 * Revision 1.2 2002/10/07 17:34:24 eilers
21 * added OBackendFactory for advanced backend access 24 * added OBackendFactory for advanced backend access
22 * 25 *
23 * Revision 1.1 2002/09/27 17:11:44 eilers 26 * Revision 1.1 2002/09/27 17:11:44 eilers
24 * Added API for accessing the Contact-Database ! It is compiling, but 27 * Added API for accessing the Contact-Database ! It is compiling, but
25 * please do not expect that anything is working ! 28 * please do not expect that anything is working !
26 * I will debug that stuff in the next time .. 29 * I will debug that stuff in the next time ..
27 * Please read README_COMPILE for compiling ! 30 * Please read README_COMPILE for compiling !
28 * 31 *
29 * 32 *
30 */ 33 */
31 34
32#ifndef _OContactAccessBackend_XML_ 35#ifndef _OContactAccessBackend_XML_
33#define _OContactAccessBackend_XML_ 36#define _OContactAccessBackend_XML_
34 37
35#include <qasciidict.h> 38#include <qasciidict.h>
36#include <qdatetime.h> 39#include <qdatetime.h>
37#include <qfile.h> 40#include <qfile.h>
38#include <qfileinfo.h> 41#include <qfileinfo.h>
39#include <qregexp.h> 42#include <qregexp.h>
40#include <qarray.h> 43#include <qarray.h>
41 44
42#include <qpe/global.h> 45#include <qpe/global.h>
43 46
44#include <opie/xmltree.h> 47#include <opie/xmltree.h>
45#include "ocontactaccessbackend.h" 48#include "ocontactaccessbackend.h"
46#include "ocontactaccess.h" 49#include "ocontactaccess.h"
47 50
48#include <stdlib.h> 51#include <stdlib.h>
49#include <errno.h> 52#include <errno.h>
50 53
51using namespace Opie; 54using namespace Opie;
52 55
53/* the default xml implementation */ 56/* the default xml implementation */
54class OContactAccessBackend_XML : public OContactAccessBackend { 57class OContactAccessBackend_XML : public OContactAccessBackend {
55 public: 58 public:
56 OContactAccessBackend_XML ( QString appname, QString filename = 0l ) 59 OContactAccessBackend_XML ( QString appname, QString filename = 0l )
57 { 60 {
58 m_appName = appname; 61 m_appName = appname;
59 62
60 /* Set journalfile name ... */ 63 /* Set journalfile name ... */
61 m_journalName = getenv("HOME"); 64 m_journalName = getenv("HOME");
62 m_journalName +="/.abjournal" + appname; 65 m_journalName +="/.abjournal" + appname;
63 66
64 /* Expecting to access the default filename if nothing else is set */ 67 /* Expecting to access the default filename if nothing else is set */
65 if ( filename.isEmpty() ){ 68 if ( filename.isEmpty() ){
66 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); 69 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
67 } else 70 } else
68 m_fileName = filename; 71 m_fileName = filename;
69 72
70 /* Load Database now */ 73 /* Load Database now */
71 load (); 74 load ();
72 } 75 }
73 76
74 bool save() { 77 bool save() {
75 QString strNewFile = m_fileName + ".new"; 78 QString strNewFile = m_fileName + ".new";
76 QFile f( strNewFile ); 79 QFile f( strNewFile );
77 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 80 if ( !f.open( IO_WriteOnly|IO_Raw ) )
78 return false; 81 return false;
79 82
80 int total_written; 83 int total_written;
81 QString out; 84 QString out;
82 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 85 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
83 " <Groups>\n" 86 " <Groups>\n"
84 " </Groups>\n" 87 " </Groups>\n"
85 " <Contacts>\n"; 88 " <Contacts>\n";
86 //QValueList<Contact>::iterator it; 89 //QValueList<Contact>::iterator it;
87 QValueListConstIterator<OContact> it; 90 QValueListConstIterator<OContact> it;
88 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) { 91 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
89 out += "<Contact "; 92 out += "<Contact ";
90 (*it).save( out ); 93 (*it).save( out );
91 out += "/>\n"; 94 out += "/>\n";
92 QCString cstr = out.utf8(); 95 QCString cstr = out.utf8();
93 total_written = f.writeBlock( cstr.data(), cstr.length() ); 96 total_written = f.writeBlock( cstr.data(), cstr.length() );
94 if ( total_written != int(cstr.length()) ) { 97 if ( total_written != int(cstr.length()) ) {
95 f.close(); 98 f.close();
96 QFile::remove( strNewFile ); 99 QFile::remove( strNewFile );
97 return false; 100 return false;
98 } 101 }
99 out = ""; 102 out = "";
100 } 103 }
101 out += " </Contacts>\n</AddressBook>\n"; 104 out += " </Contacts>\n</AddressBook>\n";
102 105
103 QCString cstr = out.utf8(); 106 QCString cstr = out.utf8();
104 total_written = f.writeBlock( cstr.data(), cstr.length() ); 107 total_written = f.writeBlock( cstr.data(), cstr.length() );
105 if ( total_written != int( cstr.length() ) ) { 108 if ( total_written != int( cstr.length() ) ) {
106 f.close(); 109 f.close();
107 QFile::remove( strNewFile ); 110 QFile::remove( strNewFile );
108 return false; 111 return false;
109 } 112 }
110 f.close(); 113 f.close();
111 114
112 // move the file over, I'm just going to use the system call 115 // move the file over, I'm just going to use the system call
113 // because, I don't feel like using QDir. 116 // because, I don't feel like using QDir.
114 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 117 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
115 qWarning( "problem renaming file %s to %s, errno: %d", 118 qWarning( "problem renaming file %s to %s, errno: %d",
116 strNewFile.latin1(), m_journalName.latin1(), errno ); 119 strNewFile.latin1(), m_journalName.latin1(), errno );
117 // remove the tmp file... 120 // remove the tmp file...
118 QFile::remove( strNewFile ); 121 QFile::remove( strNewFile );
119 } 122 }
120 123
121 /* The journalfile should be removed now... */ 124 /* The journalfile should be removed now... */
122 removeJournal(); 125 removeJournal();
123 return true; 126 return true;
124 } 127 }
125 128
126 bool load () { 129 bool load () {
127 m_contactList.clear(); 130 m_contactList.clear();
128 131
129 /* Load XML-File and journal if it exists */ 132 /* Load XML-File and journal if it exists */
130 if ( !load ( m_fileName, false ) ) 133 if ( !load ( m_fileName, false ) )
131 return false; 134 return false;
132 /* The returncode of the journalfile is ignored due to the 135 /* The returncode of the journalfile is ignored due to the
133 * fact that it does not exist when this class is instantiated ! 136 * fact that it does not exist when this class is instantiated !
134 * But there may such a file exist, if the application crashed. 137 * But there may such a file exist, if the application crashed.
135 * Therefore we try to load it to get the changes before the # 138 * Therefore we try to load it to get the changes before the #
136 * crash happened... 139 * crash happened...
137 */ 140 */
138 load (m_journalName, true); 141 load (m_journalName, true);
139 142
140 return true; 143 return true;
141 } 144 }
142 145
143 void clear () { 146 void clear () {
144 m_contactList.clear(); 147 m_contactList.clear();
145 148
146 } 149 }
147 150
148 bool wasChangedExternally() 151 bool wasChangedExternally()
149 { 152 {
150 QFileInfo fi( m_fileName ); 153 QFileInfo fi( m_fileName );
151 154
152 QDateTime lastmod = fi.lastModified (); 155 QDateTime lastmod = fi.lastModified ();
153 156
154 return (lastmod != m_readtime); 157 return (lastmod != m_readtime);
155 } 158 }
156 159
157 QArray<int> allRecords() const { 160 QArray<int> allRecords() const {
158 QArray<int> uid_list( m_contactList.count() ); 161 QArray<int> uid_list( m_contactList.count() );
159 162
160 uint counter = 0; 163 uint counter = 0;
161 QValueListConstIterator<OContact> it; 164 QValueListConstIterator<OContact> it;
162 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 165 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
163 uid_list[counter++] = (*it).uid(); 166 uid_list[counter++] = (*it).uid();
164 } 167 }
165 168
166 return ( uid_list ); 169 return ( uid_list );
167 } 170 }
168 171
169 OContact find ( int uid ) const 172 OContact find ( int uid ) const
170 { 173 {
171 bool found = false; 174 bool found = false;
172 OContact foundContact; //Create empty contact 175 OContact foundContact; //Create empty contact
173 176
174 QValueListConstIterator<OContact> it; 177 QValueListConstIterator<OContact> it;
175 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 178 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
176 if ((*it).uid() == uid){ 179 if ((*it).uid() == uid){
177 found = true; 180 found = true;
178 break; 181 break;
179 } 182 }
180 } 183 }
181 if ( found ){ 184 if ( found ){
182 foundContact = *it; 185 foundContact = *it;
183 } 186 }
184 187
185 return ( foundContact ); 188 return ( foundContact );
186 } 189 }
187 190
188 QArray<int> queryByExample ( const OContact &query, int settings ){ 191 QArray<int> queryByExample ( const OContact &query, int settings ){
189 192
190 QArray<int> m_currentQuery( m_contactList.count() ); 193 QArray<int> m_currentQuery( m_contactList.count() );
191 QValueListConstIterator<OContact> it; 194 QValueListConstIterator<OContact> it;
192 uint arraycounter = 0; 195 uint arraycounter = 0;
193 196
194 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 197 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
195 /* Search all fields and compare them with query object. Store them into list 198 /* Search all fields and compare them with query object. Store them into list
196 * if all fields matches. 199 * if all fields matches.
197 */ 200 */
198 bool allcorrect = true; 201 bool allcorrect = true;
199 for ( int i = 0; i < Qtopia::rid; i++ ) { 202 for ( int i = 0; i < Qtopia::rid; i++ ) {
200 /* Just compare fields which are not empty in the query object */ 203 /* Just compare fields which are not empty in the query object */
201 if ( !query.field(i).isEmpty() ){ 204 if ( !query.field(i).isEmpty() ){
202 switch ( settings & ~OContactAccess::query_IgnoreCase ){ 205 switch ( settings & ~OContactAccess::IgnoreCase ){
203 case OContactAccess::query_RegExp:{ 206 case OContactAccess::RegExp:{
204 QRegExp expr ( query.field(i), 207 QRegExp expr ( query.field(i),
205 !(settings & OContactAccess::query_IgnoreCase), 208 !(settings & OContactAccess::IgnoreCase),
206 false ); 209 false );
207 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 210 if ( expr.find ( (*it).field(i), 0 ) == -1 )
208 allcorrect = false; 211 allcorrect = false;
209 } 212 }
210 break; 213 break;
211 case OContactAccess::query_WildCards:{ 214 case OContactAccess::WildCards:{
212 QRegExp expr ( query.field(i), 215 QRegExp expr ( query.field(i),
213 !(settings & OContactAccess::query_IgnoreCase), 216 !(settings & OContactAccess::IgnoreCase),
214 true ); 217 true );
215 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 218 if ( expr.find ( (*it).field(i), 0 ) == -1 )
216 allcorrect = false; 219 allcorrect = false;
217 } 220 }
218 break; 221 break;
219 case OContactAccess::query_ExactMatch:{ 222 case OContactAccess::ExactMatch:{
220 if (settings & OContactAccess::query_IgnoreCase){ 223 if (settings & OContactAccess::IgnoreCase){
221 if ( query.field(i).upper() != 224 if ( query.field(i).upper() !=
222 (*it).field(i).upper() ) 225 (*it).field(i).upper() )
223 allcorrect = false; 226 allcorrect = false;
224 }else{ 227 }else{
225 if ( query.field(i) != (*it).field(i) ) 228 if ( query.field(i) != (*it).field(i) )
226 allcorrect = false; 229 allcorrect = false;
227 } 230 }
228 } 231 }
229 break; 232 break;
230 } 233 }
231 } 234 }
232 } 235 }
233 if ( allcorrect ){ 236 if ( allcorrect ){
234 m_currentQuery[arraycounter++] = (*it).uid(); 237 m_currentQuery[arraycounter++] = (*it).uid();
235 } 238 }
236 } 239 }
237 240
238 // Shrink to fit.. 241 // Shrink to fit..
239 m_currentQuery.resize(arraycounter); 242 m_currentQuery.resize(arraycounter);
240 243
241 return m_currentQuery; 244 return m_currentQuery;
242 } 245 }
243 246
244 const uint querySettings() 247 const uint querySettings()
245 { 248 {
246 return ( OContactAccess::query_WildCards 249 return ( OContactAccess::WildCards
247 & OContactAccess::query_IgnoreCase 250 & OContactAccess::IgnoreCase
248 & OContactAccess::query_RegExp 251 & OContactAccess::RegExp
249 & OContactAccess::query_ExactMatch ); 252 & OContactAccess::ExactMatch );
250 } 253 }
251 254
252 bool hasQuerySettings (uint querySettings) const 255 bool hasQuerySettings (uint querySettings) const
253 { 256 {
254 /* OContactAccess::query_IgnoreCase may be added with one 257 /* OContactAccess::IgnoreCase may be added with one
255 * of the other settings, but never used alone. 258 * of the other settings, but never used alone.
256 * The other settings are just valid alone... 259 * The other settings are just valid alone...
257 */ 260 */
258 switch ( querySettings & ~OContactAccess::query_IgnoreCase ){ 261 switch ( querySettings & ~OContactAccess::IgnoreCase ){
259 case OContactAccess::query_RegExp: 262 case OContactAccess::RegExp:
260 return ( true ); 263 return ( true );
261 case OContactAccess::query_WildCards: 264 case OContactAccess::WildCards:
262 return ( true ); 265 return ( true );
263 case OContactAccess::query_ExactMatch: 266 case OContactAccess::ExactMatch:
264 return ( true ); 267 return ( true );
265 default: 268 default:
266 return ( false ); 269 return ( false );
267 } 270 }
268 } 271 }
269 272
270 bool add ( const OContact &newcontact ) 273 bool add ( const OContact &newcontact )
271 { 274 {
272 //qWarning("odefaultbackend: ACTION::ADD"); 275 //qWarning("odefaultbackend: ACTION::ADD");
273 updateJournal (newcontact, OContact::ACTION_ADD); 276 updateJournal (newcontact, OContact::ACTION_ADD);
274 addContact_p( newcontact ); 277 addContact_p( newcontact );
275 return true; 278 return true;
276 } 279 }
277 280
278 bool replace ( const OContact &contact ) 281 bool replace ( const OContact &contact )
279 { 282 {
280 bool found = false; 283 bool found = false;
281 284
282 QValueListIterator<OContact> it; 285 QValueListIterator<OContact> it;
283 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 286 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
284 if ( (*it).uid() == contact.uid() ){ 287 if ( (*it).uid() == contact.uid() ){
285 found = true; 288 found = true;
286 break; 289 break;
287 } 290 }
288 } 291 }
289 if (found) { 292 if (found) {
290 updateJournal (contact, OContact::ACTION_REPLACE); 293 updateJournal (contact, OContact::ACTION_REPLACE);
291 m_contactList.remove (it); 294 m_contactList.remove (it);
292 m_contactList.append (contact); 295 m_contactList.append (contact);
293 return true; 296 return true;
294 } else 297 } else
295 return false; 298 return false;
296 } 299 }
297 300
298 bool remove ( int uid ) 301 bool remove ( int uid )
299 { 302 {
300 bool found = false; 303 bool found = false;
301 QValueListIterator<OContact> it; 304 QValueListIterator<OContact> it;
302 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 305 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
303 if ((*it).uid() == uid){ 306 if ((*it).uid() == uid){
304 found = true; 307 found = true;
305 break; 308 break;
306 } 309 }
307 } 310 }
308 if (found) { 311 if (found) {
309 updateJournal ( *it, OContact::ACTION_REMOVE); 312 updateJournal ( *it, OContact::ACTION_REMOVE);
310 m_contactList.remove (it); 313 m_contactList.remove (it);
311 return true; 314 return true;
312 } else 315 } else
313 return false; 316 return false;
314 } 317 }
315 318
316 bool reload(){ 319 bool reload(){
317 /* Reload is the same as load in this implementation */ 320 /* Reload is the same as load in this implementation */
318 return ( load() ); 321 return ( load() );
319 } 322 }
320 323
321 private: 324 private:
322 void addContact_p( const OContact &newcontact ){ 325 void addContact_p( const OContact &newcontact ){
323 m_contactList.append (newcontact); 326 m_contactList.append (newcontact);
324 } 327 }
325 328
326 /* This function loads the xml-database and the journalfile */ 329 /* This function loads the xml-database and the journalfile */
327 bool load( const QString filename, bool isJournal ) { 330 bool load( const QString filename, bool isJournal ) {
328 331
329 /* We use the time of the last read to check if the file was 332 /* We use the time of the last read to check if the file was
330 * changed externally. 333 * changed externally.
331 */ 334 */
332 if ( !isJournal ){ 335 if ( !isJournal ){
333 QFileInfo fi( filename ); 336 QFileInfo fi( filename );
334 m_readtime = fi.lastModified (); 337 m_readtime = fi.lastModified ();
335 } 338 }
336 339
337 const int JOURNALACTION = Qtopia::Notes + 1; 340 const int JOURNALACTION = Qtopia::Notes + 1;
338 const int JOURNALROW = JOURNALACTION + 1; 341 const int JOURNALROW = JOURNALACTION + 1;
339 342
340 bool foundAction = false; 343 bool foundAction = false;
341 OContact::journal_action action = OContact::ACTION_ADD; 344 OContact::journal_action action = OContact::ACTION_ADD;
342 int journalKey = 0; 345 int journalKey = 0;
343 QMap<int, QString> contactMap; 346 QMap<int, QString> contactMap;
344 QMap<QString, QString> customMap; 347 QMap<QString, QString> customMap;
345 QMap<QString, QString>::Iterator customIt; 348 QMap<QString, QString>::Iterator customIt;
346 QAsciiDict<int> dict( 47 ); 349 QAsciiDict<int> dict( 47 );
347 350
348 dict.setAutoDelete( TRUE ); 351 dict.setAutoDelete( TRUE );
349 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 352 dict.insert( "Uid", new int(Qtopia::AddressUid) );
350 dict.insert( "Title", new int(Qtopia::Title) ); 353 dict.insert( "Title", new int(Qtopia::Title) );
351 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 354 dict.insert( "FirstName", new int(Qtopia::FirstName) );
352 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 355 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
353 dict.insert( "LastName", new int(Qtopia::LastName) ); 356 dict.insert( "LastName", new int(Qtopia::LastName) );
354 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 357 dict.insert( "Suffix", new int(Qtopia::Suffix) );
355 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 358 dict.insert( "FileAs", new int(Qtopia::FileAs) );
356 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 359 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
357 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 360 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
358 dict.insert( "Emails", new int(Qtopia::Emails) ); 361 dict.insert( "Emails", new int(Qtopia::Emails) );
359 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 362 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp
index f3b0783..3b4cab2 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.cpp
+++ b/libopie2/opiepim/backend/otodoaccessxml.cpp
@@ -94,193 +94,193 @@ bool OTodoAccessXML::load() {
94 ++j; 94 ++j;
95 } 95 }
96 if ( i == j ) { 96 if ( i == j ) {
97 // empty value 97 // empty value
98 i = j + 1; 98 i = j + 1;
99 continue; 99 continue;
100 } 100 }
101 101
102 QCString value( dt+i, j-i+1 ); 102 QCString value( dt+i, j-i+1 );
103 i = j + 1; 103 i = j + 1;
104 104
105 QString str = (haveUtf ? QString::fromUtf8( value ) 105 QString str = (haveUtf ? QString::fromUtf8( value )
106 : QString::fromLatin1( value ) ); 106 : QString::fromLatin1( value ) );
107 if ( haveEnt ) 107 if ( haveEnt )
108 str = Qtopia::plainString( str ); 108 str = Qtopia::plainString( str );
109 109
110 /* 110 /*
111 * add key + value 111 * add key + value
112 */ 112 */
113 todo( &dict, ev, attr, str ); 113 todo( &dict, ev, attr, str );
114 114
115 } 115 }
116 /* 116 /*
117 * now add it 117 * now add it
118 */ 118 */
119 m_events.insert(ev.uid(), ev ); 119 m_events.insert(ev.uid(), ev );
120 } 120 }
121 121
122 qWarning("counts %d", m_events.count() ); 122 qWarning("counts %d", m_events.count() );
123 return true; 123 return true;
124} 124}
125bool OTodoAccessXML::reload() { 125bool OTodoAccessXML::reload() {
126 return load(); 126 return load();
127} 127}
128bool OTodoAccessXML::save() { 128bool OTodoAccessXML::save() {
129// qWarning("saving"); 129// qWarning("saving");
130 if (!m_opened || !m_changed ) { 130 if (!m_opened || !m_changed ) {
131// qWarning("not saving"); 131// qWarning("not saving");
132 return true; 132 return true;
133 } 133 }
134 QString strNewFile = m_file + ".new"; 134 QString strNewFile = m_file + ".new";
135 QFile f( strNewFile ); 135 QFile f( strNewFile );
136 if (!f.open( IO_WriteOnly|IO_Raw ) ) 136 if (!f.open( IO_WriteOnly|IO_Raw ) )
137 return false; 137 return false;
138 138
139 int written; 139 int written;
140 QString out; 140 QString out;
141 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 141 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
142 142
143 // for all todos 143 // for all todos
144 QMap<int, OTodo>::Iterator it; 144 QMap<int, OTodo>::Iterator it;
145 for (it = m_events.begin(); it != m_events.end(); ++it ) { 145 for (it = m_events.begin(); it != m_events.end(); ++it ) {
146 out+= "<Task " + toString( (*it) ) + " />\n"; 146 out+= "<Task " + toString( (*it) ) + " />\n";
147 QCString cstr = out.utf8(); 147 QCString cstr = out.utf8();
148 written = f.writeBlock( cstr.data(), cstr.length() ); 148 written = f.writeBlock( cstr.data(), cstr.length() );
149 149
150 /* less written then we wanted */ 150 /* less written then we wanted */
151 if ( written != (int)cstr.length() ) { 151 if ( written != (int)cstr.length() ) {
152 f.close(); 152 f.close();
153 QFile::remove( strNewFile ); 153 QFile::remove( strNewFile );
154 return false; 154 return false;
155 } 155 }
156 out = QString::null; 156 out = QString::null;
157 } 157 }
158 158
159 out += "</Tasks>"; 159 out += "</Tasks>";
160 QCString cstr = out.utf8(); 160 QCString cstr = out.utf8();
161 written = f.writeBlock( cstr.data(), cstr.length() ); 161 written = f.writeBlock( cstr.data(), cstr.length() );
162 162
163 if ( written != (int)cstr.length() ) { 163 if ( written != (int)cstr.length() ) {
164 f.close(); 164 f.close();
165 QFile::remove( strNewFile ); 165 QFile::remove( strNewFile );
166 return false; 166 return false;
167 } 167 }
168 /* flush before renaming */ 168 /* flush before renaming */
169 f.close(); 169 f.close();
170 170
171 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 171 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
172// qWarning("error renaming"); 172// qWarning("error renaming");
173 QFile::remove( strNewFile ); 173 QFile::remove( strNewFile );
174 } 174 }
175 175
176 m_changed = false; 176 m_changed = false;
177 return true; 177 return true;
178} 178}
179QArray<int> OTodoAccessXML::allRecords()const { 179QArray<int> OTodoAccessXML::allRecords()const {
180 QArray<int> ids( m_events.count() ); 180 QArray<int> ids( m_events.count() );
181 QMap<int, OTodo>::ConstIterator it; 181 QMap<int, OTodo>::ConstIterator it;
182 int i = 0; 182 int i = 0;
183 183
184 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 184 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
185 ids[i] = it.key(); 185 ids[i] = it.key();
186 i++; 186 i++;
187 } 187 }
188 return ids; 188 return ids;
189} 189}
190QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int sort ) { 190QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) {
191 QArray<int> ids(0); 191 QArray<int> ids(0);
192 return ids; 192 return ids;
193} 193}
194OTodo OTodoAccessXML::find( int uid )const { 194OTodo OTodoAccessXML::find( int uid )const {
195 OTodo todo; 195 OTodo todo;
196 todo.setUid( 0 ); // isEmpty() 196 todo.setUid( 0 ); // isEmpty()
197 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 197 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
198 if ( it != m_events.end() ) 198 if ( it != m_events.end() )
199 todo = it.data(); 199 todo = it.data();
200 200
201 return todo; 201 return todo;
202} 202}
203void OTodoAccessXML::clear() { 203void OTodoAccessXML::clear() {
204 if (m_opened ) 204 if (m_opened )
205 m_changed = true; 205 m_changed = true;
206 206
207 m_events.clear(); 207 m_events.clear();
208} 208}
209bool OTodoAccessXML::add( const OTodo& todo ) { 209bool OTodoAccessXML::add( const OTodo& todo ) {
210// qWarning("add"); 210// qWarning("add");
211 m_changed = true; 211 m_changed = true;
212 m_events.insert( todo.uid(), todo ); 212 m_events.insert( todo.uid(), todo );
213 213
214 return true; 214 return true;
215} 215}
216bool OTodoAccessXML::remove( int uid ) { 216bool OTodoAccessXML::remove( int uid ) {
217 m_changed = true; 217 m_changed = true;
218 m_events.remove( uid ); 218 m_events.remove( uid );
219 219
220 return true; 220 return true;
221} 221}
222bool OTodoAccessXML::replace( const OTodo& todo) { 222bool OTodoAccessXML::replace( const OTodo& todo) {
223 m_changed = true; 223 m_changed = true;
224 m_events.replace( todo.uid(), todo ); 224 m_events.replace( todo.uid(), todo );
225 225
226 return true; 226 return true;
227} 227}
228QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 228QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
229 const QDate& end, 229 const QDate& end,
230 bool includeNoDates ) { 230 bool includeNoDates ) {
231 QArray<int> ids( m_events.count() ); 231 QArray<int> ids( m_events.count() );
232 QMap<int, OTodo>::Iterator it; 232 QMap<int, OTodo>::Iterator it;
233 233
234 int i = 0; 234 int i = 0;
235 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 235 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
236 if ( !it.data().hasDueDate() ) { 236 if ( !it.data().hasDueDate() ) {
237 if ( includeNoDates ) { 237 if ( includeNoDates ) {
238 ids[i] = it.key(); 238 ids[i] = it.key();
239 i++; 239 i++;
240 } 240 }
241 }else if ( it.data().dueDate() >= start && 241 }else if ( it.data().dueDate() >= start &&
242 it.data().dueDate() <= end ) { 242 it.data().dueDate() <= end ) {
243 ids[i] = it.key(); 243 ids[i] = it.key();
244 i++; 244 i++;
245 } 245 }
246 } 246 }
247 ids.resize( i ); 247 ids.resize( i );
248 return ids; 248 return ids;
249} 249}
250QArray<int> OTodoAccessXML::overDue() { 250QArray<int> OTodoAccessXML::overDue() {
251 QArray<int> ids( m_events.count() ); 251 QArray<int> ids( m_events.count() );
252 int i = 0; 252 int i = 0;
253 253
254 QMap<int, OTodo>::Iterator it; 254 QMap<int, OTodo>::Iterator it;
255 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 255 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
256 if ( it.data().isOverdue() ) { 256 if ( it.data().isOverdue() ) {
257 ids[i] = it.key(); 257 ids[i] = it.key();
258 i++; 258 i++;
259 } 259 }
260 } 260 }
261 ids.resize( i ); 261 ids.resize( i );
262 return ids; 262 return ids;
263} 263}
264 264
265 265
266/* private */ 266/* private */
267void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, 267void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
268 const QCString& attr, const QString& val) { 268 const QCString& attr, const QString& val) {
269// qWarning("parse to do from XMLElement" ); 269// qWarning("parse to do from XMLElement" );
270 270
271 int *find=0; 271 int *find=0;
272 272
273 find = (*dict)[ attr.data() ]; 273 find = (*dict)[ attr.data() ];
274 if (!find ) { 274 if (!find ) {
275// qWarning("Unknown option" + it.key() ); 275// qWarning("Unknown option" + it.key() );
276 ev.setCustomField( attr, val ); 276 ev.setCustomField( attr, val );
277 return; 277 return;
278 } 278 }
279 279
280 switch( *find ) { 280 switch( *find ) {
281 case OTodo::Uid: 281 case OTodo::Uid:
282 ev.setUid( val.toInt() ); 282 ev.setUid( val.toInt() );
283 break; 283 break;
284 case OTodo::Category: 284 case OTodo::Category:
285 ev.setCategories( ev.idsFromString( val ) ); 285 ev.setCategories( ev.idsFromString( val ) );
286 break; 286 break;
diff --git a/libopie2/opiepim/backend/otodoaccessxml.h b/libopie2/opiepim/backend/otodoaccessxml.h
index 1e7e371..dc41c32 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.h
+++ b/libopie2/opiepim/backend/otodoaccessxml.h
@@ -1,56 +1,56 @@
1#ifndef OPIE_TODO_ACCESS_XML_H 1#ifndef OPIE_TODO_ACCESS_XML_H
2#define OPIE_TODO_ACCESS_XML_H 2#define OPIE_TODO_ACCESS_XML_H
3 3
4#include <qasciidict.h> 4#include <qasciidict.h>
5#include <qmap.h> 5#include <qmap.h>
6 6
7#include "otodoaccessbackend.h" 7#include "otodoaccessbackend.h"
8 8
9namespace Opie { 9namespace Opie {
10 class XMLElement; 10 class XMLElement;
11}; 11};
12 12
13class OTodoAccessXML : public OTodoAccessBackend { 13class OTodoAccessXML : public OTodoAccessBackend {
14public: 14public:
15 /** 15 /**
16 * fileName if Empty we will use the default path 16 * fileName if Empty we will use the default path
17 */ 17 */
18 OTodoAccessXML( const QString& appName, 18 OTodoAccessXML( const QString& appName,
19 const QString& fileName = QString::null ); 19 const QString& fileName = QString::null );
20 ~OTodoAccessXML(); 20 ~OTodoAccessXML();
21 21
22 bool load(); 22 bool load();
23 bool reload(); 23 bool reload();
24 bool save(); 24 bool save();
25 25
26 QArray<int> allRecords()const; 26 QArray<int> allRecords()const;
27 QArray<int> queryByExample( const OTodo&, int sort ); 27 QArray<int> queryByExample( const OTodo&, int querysettings );
28 OTodo find( int uid )const; 28 OTodo find( int uid )const;
29 void clear(); 29 void clear();
30 bool add( const OTodo& ); 30 bool add( const OTodo& );
31 bool remove( int uid ); 31 bool remove( int uid );
32 bool replace( const OTodo& ); 32 bool replace( const OTodo& );
33 33
34 /* our functions */ 34 /* our functions */
35 QArray<int> effectiveToDos( const QDate& start, 35 QArray<int> effectiveToDos( const QDate& start,
36 const QDate& end, 36 const QDate& end,
37 bool includeNoDates ); 37 bool includeNoDates );
38 QArray<int> overDue(); 38 QArray<int> overDue();
39 QArray<int> sorted( bool asc, int sortOrder, 39 QArray<int> sorted( bool asc, int sortOrder,
40 int sortFilter, int cat ); 40 int sortFilter, int cat );
41private: 41private:
42 void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& ); 42 void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& );
43 QString toString( const OTodo& )const; 43 QString toString( const OTodo& )const;
44 QString toString( const QArray<int>& ints ) const; 44 QString toString( const QArray<int>& ints ) const;
45 QMap<int, OTodo> m_events; 45 QMap<int, OTodo> m_events;
46 QString m_file; 46 QString m_file;
47 QString m_app; 47 QString m_app;
48 bool m_opened : 1; 48 bool m_opened : 1;
49 bool m_changed : 1; 49 bool m_changed : 1;
50 class OTodoAccessXMLPrivate; 50 class OTodoAccessXMLPrivate;
51 OTodoAccessXMLPrivate* d; 51 OTodoAccessXMLPrivate* d;
52 int m_year, m_month, m_day; 52 int m_year, m_month, m_day;
53 53
54}; 54};
55 55
56#endif 56#endif
diff --git a/libopie2/opiepim/core/ocontactaccess.cpp b/libopie2/opiepim/core/ocontactaccess.cpp
index b5f358b..e8c0a45 100644
--- a/libopie2/opiepim/core/ocontactaccess.cpp
+++ b/libopie2/opiepim/core/ocontactaccess.cpp
@@ -1,165 +1,167 @@
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.4 2002/10/14 16:21:54 eilers
25 * Some minor interface updates
26 *
24 * Revision 1.3 2002/10/07 17:34:24 eilers 27 * Revision 1.3 2002/10/07 17:34:24 eilers
25 * added OBackendFactory for advanced backend access 28 * added OBackendFactory for advanced backend access
26 * 29 *
27 * Revision 1.2 2002/10/02 16:18:11 eilers 30 * Revision 1.2 2002/10/02 16:18:11 eilers
28 * debugged and seems to work almost perfectly .. 31 * debugged and seems to work almost perfectly ..
29 * 32 *
30 * Revision 1.1 2002/09/27 17:11:44 eilers 33 * Revision 1.1 2002/09/27 17:11:44 eilers
31 * Added API for accessing the Contact-Database ! It is compiling, but 34 * Added API for accessing the Contact-Database ! It is compiling, but
32 * please do not expect that anything is working ! 35 * please do not expect that anything is working !
33 * I will debug that stuff in the next time .. 36 * I will debug that stuff in the next time ..
34 * Please read README_COMPILE for compiling ! 37 * Please read README_COMPILE for compiling !
35 * 38 *
36 * 39 *
37 */ 40 */
38 41
39#include "ocontactaccess.h" 42#include "ocontactaccess.h"
40#include "obackendfactory.h" 43#include "obackendfactory.h"
41 44
42#include <qasciidict.h> 45#include <qasciidict.h>
43#include <qdatetime.h> 46#include <qdatetime.h>
44#include <qfile.h> 47#include <qfile.h>
45#include <qregexp.h> 48#include <qregexp.h>
46#include <qlist.h> 49#include <qlist.h>
47#include <qcopchannel_qws.h> 50#include <qcopchannel_qws.h>
48 51
49//#include <qpe/qcopenvelope_qws.h> 52//#include <qpe/qcopenvelope_qws.h>
50#include <qpe/global.h> 53#include <qpe/global.h>
51 54
52#include <errno.h> 55#include <errno.h>
53#include <fcntl.h> 56#include <fcntl.h>
54#include <unistd.h> 57#include <unistd.h>
55#include <stdlib.h> 58#include <stdlib.h>
56 59
57#include "ocontactaccessbackend_xml.h" 60#include "ocontactaccessbackend_xml.h"
58 61
59 62
60OContactAccess::OContactAccess ( const QString appname, const QString , 63OContactAccess::OContactAccess ( const QString appname, const QString ,
61 OContactAccessBackend* end, bool autosync ): 64 OContactAccessBackend* end, bool autosync ):
62 OPimAccessTemplate<OContact>( end ), 65 OPimAccessTemplate<OContact>( end ),
63 m_changed ( false ) 66 m_changed ( false )
64{ 67{
65 /* take care of the backend. If there is no one defined, we 68 /* take care of the backend. If there is no one defined, we
66 * will use the XML-Backend as default (until we have a cute SQL-Backend..). 69 * will use the XML-Backend as default (until we have a cute SQL-Backend..).
67 */ 70 */
68 if( end == 0 ) { 71 if( end == 0 ) {
69 // __asm__("int3");
70 qWarning ("Using BackendFactory !"); 72 qWarning ("Using BackendFactory !");
71 end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname ); 73 end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname );
72 } 74 }
73 // Set backend locally and in template 75 // Set backend locally and in template
74 m_backEnd = end; 76 m_backEnd = end;
75 OPimAccessTemplate<OContact>::setBackEnd (end); 77 OPimAccessTemplate<OContact>::setBackEnd (end);
76 78
77 79
78 /* Connect signal of external db change to function */ 80 /* Connect signal of external db change to function */
79 QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this ); 81 QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this );
80 connect( dbchannel, SIGNAL(received(const QCString &, const QByteArray &)), 82 connect( dbchannel, SIGNAL(received(const QCString &, const QByteArray &)),
81 this, SLOT(copMessage( const QCString &, const QByteArray &)) ); 83 this, SLOT(copMessage( const QCString &, const QByteArray &)) );
82 if ( autosync ){ 84 if ( autosync ){
83 QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this ); 85 QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this );
84 connect( syncchannel, SIGNAL(received(const QCString &, const QByteArray &)), 86 connect( syncchannel, SIGNAL(received(const QCString &, const QByteArray &)),
85 this, SLOT(copMessage( const QCString &, const QByteArray &)) ); 87 this, SLOT(copMessage( const QCString &, const QByteArray &)) );
86 } 88 }
87 89
88 90
89} 91}
90OContactAccess::~OContactAccess () 92OContactAccess::~OContactAccess ()
91{ 93{
92 /* The user may forget to save the changed database, therefore try to 94 /* The user may forget to save the changed database, therefore try to
93 * do it for him.. 95 * do it for him..
94 */ 96 */
95 if ( m_changed ) 97 if ( m_changed )
96 save(); 98 save();
97 // delete m_backEnd; is done by template.. 99 // delete m_backEnd; is done by template..
98} 100}
99 101
100bool OContactAccess::load() 102bool OContactAccess::load()
101{ 103{
102 return ( m_backEnd->load() ); 104 return ( m_backEnd->load() );
103} 105}
104 106
105bool OContactAccess::save () 107bool OContactAccess::save ()
106{ 108{
107 /* If the database was changed externally, we could not save the 109 /* If the database was changed externally, we could not save the
108 * Data. This will remove added items which is unacceptable ! 110 * Data. This will remove added items which is unacceptable !
109 * Therefore: Reload database and merge the data... 111 * Therefore: Reload database and merge the data...
110 */ 112 */
111 if ( m_backEnd->wasChangedExternally() ) 113 if ( m_backEnd->wasChangedExternally() )
112 reload(); 114 reload();
113 115
114 if ( m_changed ){ 116 if ( m_changed ){
115 bool status = m_backEnd->save(); 117 bool status = m_backEnd->save();
116 if ( !status ) return false; 118 if ( !status ) return false;
117 119
118 m_changed = false; 120 m_changed = false;
119 /* Now tell everyone that new data is available. 121 /* Now tell everyone that new data is available.
120 */ 122 */
121 QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" ); 123 QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
122 124
123 } 125 }
124 126
125 return true; 127 return true;
126} 128}
127 129
128const uint OContactAccess::querySettings() 130const uint OContactAccess::querySettings()
129{ 131{
130 return ( m_backEnd->querySettings() ); 132 return ( m_backEnd->querySettings() );
131} 133}
132 134
133bool OContactAccess::hasQuerySettings ( int querySettings ) const 135bool OContactAccess::hasQuerySettings ( int querySettings ) const
134{ 136{
135 return ( m_backEnd->hasQuerySettings ( querySettings ) ); 137 return ( m_backEnd->hasQuerySettings ( querySettings ) );
136} 138}
137 139
138bool OContactAccess::add ( const OContact& newcontact ) 140bool OContactAccess::add ( const OContact& newcontact )
139{ 141{
140 m_changed = true; 142 m_changed = true;
141 return ( m_backEnd->add ( newcontact ) ); 143 return ( m_backEnd->add ( newcontact ) );
142} 144}
143 145
144bool OContactAccess::replace ( const OContact& contact ) 146bool OContactAccess::replace ( const OContact& contact )
145{ 147{
146 m_changed = true; 148 m_changed = true;
147 return ( m_backEnd->replace ( contact ) ); 149 return ( m_backEnd->replace ( contact ) );
148} 150}
149 151
150bool OContactAccess::remove ( const OContact& t ) 152bool OContactAccess::remove ( const OContact& t )
151{ 153{
152 m_changed = true; 154 m_changed = true;
153 return ( m_backEnd->remove ( t.uid() ) ); 155 return ( m_backEnd->remove ( t.uid() ) );
154} 156}
155 157
156bool OContactAccess::remove ( int uid ) 158bool OContactAccess::remove ( int uid )
157{ 159{
158 m_changed = true; 160 m_changed = true;
159 return ( m_backEnd->remove ( uid ) ); 161 return ( m_backEnd->remove ( uid ) );
160} 162}
161 163
162bool OContactAccess::wasChangedExternally()const 164bool OContactAccess::wasChangedExternally()const
163{ 165{
164 return ( m_backEnd->wasChangedExternally() ); 166 return ( m_backEnd->wasChangedExternally() );
165} 167}
diff --git a/libopie2/opiepim/core/ocontactaccess.h b/libopie2/opiepim/core/ocontactaccess.h
index 54f7f07..adc66cf 100644
--- a/libopie2/opiepim/core/ocontactaccess.h
+++ b/libopie2/opiepim/core/ocontactaccess.h
@@ -1,197 +1,168 @@
1/* 1/*
2 * Class to manage the Contacts. 2 * Class to manage the Contacts.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org) 5 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
6 * 6 *
7 * ===================================================================== 7 * =====================================================================
8 *This program is free software; you can redistribute it and/or 8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public 9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; 10 * License as published by the Free Software Foundation;
11 * either version 2 of the License, or (at your option) any later 11 * either version 2 of the License, or (at your option) any later
12 * version. 12 * version.
13 * ===================================================================== 13 * =====================================================================
14 * ToDo: Define enum for query settings 14 * ToDo: Define enum for query settings
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.2 2002/10/14 16:21:54 eilers
21 * Some minor interface updates
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#ifndef _OCONTACTACCESS_H 31#ifndef _OCONTACTACCESS_H
29#define _OCONTACTACCESS_H 32#define _OCONTACTACCESS_H
30 33
31#include <qobject.h> 34#include <qobject.h>
32 35
33#include <qpe/qcopenvelope_qws.h> 36#include <qpe/qcopenvelope_qws.h>
34 37
35#include <qvaluelist.h> 38#include <qvaluelist.h>
36#include <qfileinfo.h> 39#include <qfileinfo.h>
37 40
38#include "ocontact.h" 41#include "ocontact.h"
39#include "ocontactaccessbackend.h" 42#include "ocontactaccessbackend.h"
40#include "opimaccesstemplate.h" 43#include "opimaccesstemplate.h"
41 44
42/** Class to access the contacts database. 45/** Class to access the contacts database.
43 * This is just a frontend for the real database handling which is 46 * This is just a frontend for the real database handling which is
44 * done by the backend. 47 * done by the backend.
45 */ 48 */
46class OContactAccess: public QObject, public OPimAccessTemplate<OContact> 49class OContactAccess: public QObject, public OPimAccessTemplate<OContact>
47{ 50{
48 Q_OBJECT 51 Q_OBJECT
49 52
50
51 /* class Iterator{
52 friend OContactAccess;
53 public:
54 Iterator();
55 Iterator ( const Iterator& copy );
56
57 bool operator== ( const Iterator& it );
58 bool operator!= ( const Iterator& it );
59 Iterator& operator= ( const Iterator& it );
60 Iterator& operator++ (); // prefix
61 Iterator operator++ ( int ); // postfix
62 Iterator& operator-- (); // prefix
63 Iterator operator-- ( int ); // postfix
64 Contact operator*() const;
65 Contact operator->() const;
66
67 Iterator begin();
68 Iterator end();
69
70 uint count() const;
71
72 private:
73 QValueList<int> m_uids;
74 int m_cur_position;
75 bool m_end_reached;
76 OContactAccess *m_db;
77
78 };
79
80 */
81
82 public: 53 public:
83 /** Create Database with contacts (addressbook). 54 /** Create Database with contacts (addressbook).
84 * @param appname Name of application which wants access to the database 55 * @param appname Name of application which wants access to the database
85 * (i.e. "todolist") 56 * (i.e. "todolist")
86 * @param filename The name of the database file. If not set, the default one 57 * @param filename The name of the database file. If not set, the default one
87 * is used. 58 * is used.
88 * @param backend Pointer to an alternative Backend. If not set, we will use 59 * @param backend Pointer to an alternative Backend. If not set, we will use
89 * the default backend. 60 * the default backend.
90 * @param handlesync If <b>true</b> the database stores the current state 61 * @param handlesync If <b>true</b> the database stores the current state
91 * automatically if it receives the signals <i>flush()</i> and <i>reload()</i> 62 * automatically if it receives the signals <i>flush()</i> and <i>reload()</i>
92 * which are used before and after synchronisation. If the application wants 63 * which are used before and after synchronisation. If the application wants
93 * to react itself, it should be disabled by setting it to <b>false</b> 64 * to react itself, it should be disabled by setting it to <b>false</b>
94 * @see OContactBackend 65 * @see OContactAccessBackend
95 */ 66 */
96 OContactAccess (const QString appname, const QString filename = 0l, 67 OContactAccess (const QString appname, const QString filename = 0l,
97 OContactAccessBackend* backend = 0l, bool handlesync = true); 68 OContactAccessBackend* backend = 0l, bool handlesync = true);
98 ~OContactAccess (); 69 ~OContactAccess ();
99 70
100 /** Constants for query. 71 /** Constants for query.
101 * Use this constants to set the query parameters. 72 * Use this constants to set the query parameters.
102 * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes ! 73 * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes !
103 * @see queryByExample() 74 * @see queryByExample()
104 * - why not enum - zecke?
105 * -> Had some implementation problems .. Will use enum soon ! .. (se)
106 */ 75 */
107 static const int query_WildCards = 0x0001; 76 enum QuerySettings {
108 static const int query_IgnoreCase = 0x0002; 77 WildCards = 0x0001,
109 static const int query_RegExp = 0x0004; 78 IgnoreCase = 0x0002,
110 static const int query_ExactMatch = 0x0008; 79 RegExp = 0x0004,
80 ExactMatch = 0x0008,
81 };
111 82
112 /** Return all possible settings. 83 /** Return all possible settings.
113 * @return All settings provided by the current backend 84 * @return All settings provided by the current backend
114 * (i.e.: query_WildCards & query_IgnoreCase) 85 * (i.e.: query_WildCards & query_IgnoreCase)
115 */ 86 */
116 const uint querySettings(); 87 const uint querySettings();
117 88
118 /** Check whether settings are correct. 89 /** Check whether settings are correct.
119 * @return <i>true</i> if the given settings are correct and possible. 90 * @return <i>true</i> if the given settings are correct and possible.
120 */ 91 */
121 bool hasQuerySettings ( int querySettings ) const; 92 bool hasQuerySettings ( int querySettings ) const;
122 93
123 /** Add Contact to database. 94 /** Add Contact to database.
124 * @param newcontact The contact to add. 95 * @param newcontact The contact to add.
125 * @return <i>true</i> if added successfully. 96 * @return <i>true</i> if added successfully.
126 */ 97 */
127 bool add (const OContact& newcontact); 98 bool add (const OContact& newcontact);
128 99
129 /** Replace contact. 100 /** Replace contact.
130 * Replaces given contact with contact with the user id <i>uid</i>. 101 * Replaces given contact with contact with the user id <i>uid</i>.
131 * @param uid The user ID 102 * @param uid The user ID
132 * @param contact The new contact 103 * @param contact The new contact
133 * @return <i>true</i> if successful. 104 * @return <i>true</i> if successful.
134 */ 105 */
135 bool replace ( const OContact& contact ); 106 bool replace ( const OContact& contact );
136 107
137 /** Remove contact. 108 /** Remove contact.
138 * Removes contact with the user id <i>uid</i>. 109 * Removes contact with the user id <i>uid</i>.
139 * @param The contact to remove 110 * @param The contact to remove
140 * @return <i>true</i> if successful. 111 * @return <i>true</i> if successful.
141 */ 112 */
142 bool remove ( const OContact& t ); 113 bool remove ( const OContact& t );
143 114
144 /** Remove contact. 115 /** Remove contact.
145 * Removes contact with the user id <i>uid</i>. 116 * Removes contact with the user id <i>uid</i>.
146 * @param The user id of the contact to remove 117 * @param The user id of the contact to remove
147 * @return <i>true</i> if successful. 118 * @return <i>true</i> if successful.
148 */ 119 */
149 bool remove ( int uid ); 120 bool remove ( int uid );
150 121
151 /** Load Database * 122 /** Load Database *
152 */ 123 */
153 bool load(); 124 bool load();
154 125
155 /** 126 /**
156 * if the resource was changed externally. 127 * if the resource was changed externally.
157 * You should use the signal instead of polling possible changes ! 128 * You should use the signal instead of polling possible changes !
158 */ 129 */
159 bool wasChangedExternally()const; 130 bool wasChangedExternally()const;
160 131
161 /** Reload database. 132 /** Reload database.
162 * You should execute this function if the external database 133 * You should execute this function if the external database
163 * was changed. 134 * was changed.
164 * This function will load the external database and afterwards 135 * This function will load the external database and afterwards
165 * rejoin the local changes. Therefore the local database will be set consistent. 136 * rejoin the local changes. Therefore the local database will be set consistent.
166 */ 137 */
167 bool reload(); 138 bool reload();
168 139
169 /** Save contacts database. 140 /** Save contacts database.
170 * Save is more a "commit". After calling this function, all changes are public available. 141 * Save is more a "commit". After calling this function, all changes are public available.
171 * @return true if successful 142 * @return true if successful
172 */ 143 */
173 bool save(); 144 bool save();
174 145
175 signals: 146 signals:
176 /* Signal is emitted if the database was changed. Therefore 147 /* Signal is emitted if the database was changed. Therefore
177 * we may need to reload to stay consistent. 148 * we may need to reload to stay consistent.
178 * @param which Pointer to the database who created this event. This pointer 149 * @param which Pointer to the database who created this event. This pointer
179 * is useful if an application has to handle multiple databases at the same time. 150 * is useful if an application has to handle multiple databases at the same time.
180 * @see reload() 151 * @see reload()
181 */ 152 */
182 void signalChanged ( const OContactAccess *which ); 153 void signalChanged ( const OContactAccess *which );
183 154
184 155
185 private: 156 private:
186 // class OContactAccessPrivate; 157 // class OContactAccessPrivate;
187 // OContactAccessPrivate* d; 158 // OContactAccessPrivate* d;
188 OContactAccessBackend *m_backEnd; 159 OContactAccessBackend *m_backEnd;
189 bool m_loading:1; 160 bool m_loading:1;
190 bool m_changed; 161 bool m_changed;
191 162
192 private slots: 163 private slots:
193 void copMessage( const QCString &msg, const QByteArray &data ); 164 void copMessage( const QCString &msg, const QByteArray &data );
194 165
195 166
196}; 167};
197#endif 168#endif
diff --git a/libopie2/opiepim/core/opimaccesstemplate.h b/libopie2/opiepim/core/opimaccesstemplate.h
index a0d8f63..3e1f393 100644
--- a/libopie2/opiepim/core/opimaccesstemplate.h
+++ b/libopie2/opiepim/core/opimaccesstemplate.h
@@ -1,167 +1,161 @@
1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H 1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
2#define OPIE_PIM_ACCESS_TEMPLATE_H 2#define OPIE_PIM_ACCESS_TEMPLATE_H
3 3
4#include <qarray.h> 4#include <qarray.h>
5 5
6#include <opie/opimrecord.h> 6#include <opie/opimrecord.h>
7#include <opie/opimaccessbackend.h> 7#include <opie/opimaccessbackend.h>
8#include <opie/orecordlist.h> 8#include <opie/orecordlist.h>
9 9
10#include "opimcache.h" 10#include "opimcache.h"
11#include "otemplatebase.h" 11#include "otemplatebase.h"
12 12
13/** 13/**
14 * Thats the frontend to our OPIE PIM 14 * Thats the frontend to our OPIE PIM
15 * Library. Either you want to use it's 15 * Library. Either you want to use it's
16 * interface or you want to implement 16 * interface or you want to implement
17 * your own Access lib 17 * your own Access lib
18 * Just create a OPimRecord and inherit from 18 * Just create a OPimRecord and inherit from
19 * the plugins 19 * the plugins
20 */ 20 */
21 21
22template <class T = OPimRecord > 22template <class T = OPimRecord >
23class OPimAccessTemplate : public OTemplateBase<T> { 23class OPimAccessTemplate : public OTemplateBase<T> {
24public: 24public:
25 typedef ORecordList<T> List; 25 typedef ORecordList<T> List;
26 typedef OPimAccessBackend<T> BackEnd; 26 typedef OPimAccessBackend<T> BackEnd;
27 typedef OPimCache<T> Cache; 27 typedef OPimCache<T> Cache;
28 28
29 /** 29 /**
30 * our sort order
31 * should be safe explaining
32 */
33 enum SortOrder { WildCards = 0, IgnoreCase = 1,
34 RegExp = 2, ExactMatch = 4 };
35
36 /**
37 * c'tor BackEnd 30 * c'tor BackEnd
38 */ 31 */
39 OPimAccessTemplate( BackEnd* end); 32 OPimAccessTemplate( BackEnd* end);
40 virtual ~OPimAccessTemplate(); 33 virtual ~OPimAccessTemplate();
41 34
42 /** 35 /**
43 * load from the backend 36 * load from the backend
44 */ 37 */
45 virtual bool load(); 38 virtual bool load();
46 39
47 /** 40 /**
48 * reload from the backend 41 * reload from the backend
49 */ 42 */
50 virtual bool reload(); 43 virtual bool reload();
51 44
52 /** 45 /**
53 * save to the backend 46 * save to the backend
54 */ 47 */
55 virtual bool save(); 48 virtual bool save();
56 49
57 /** 50 /**
58 * if the resource was changed externally 51 * if the resource was changed externally
59 */ 52 */
60 bool wasChangedExternally()const; 53 bool wasChangedExternally()const;
61 54
62 /** 55 /**
63 * return a List of records 56 * return a List of records
64 * you can iterate over them 57 * you can iterate over them
65 */ 58 */
66 virtual List allRecords()const; 59 virtual List allRecords()const;
67 60
68 /** 61 /**
69 * queryByExample 62 * queryByExample)
63 * @see otodoaccess, ocontactaccess
70 */ 64 */
71 virtual List queryByExample( const T& t, int sortOrder ); 65 virtual List queryByExample( const T& t, int querySettings );
72 66
73 /** 67 /**
74 * find the OPimRecord uid 68 * find the OPimRecord uid
75 */ 69 */
76 virtual T find( int uid )const; 70 virtual T find( int uid )const;
77 71
78 /** 72 /**
79 * read ahead cache find method ;) 73 * read ahead cache find method ;)
80 */ 74 */
81 virtual T find( int uid, const QArray<int>&, 75 virtual T find( int uid, const QArray<int>&,
82 uint current, CacheDirection dir = Forward )const; 76 uint current, CacheDirection dir = Forward )const;
83 77
84 /* invalidate cache here */ 78 /* invalidate cache here */
85 /** 79 /**
86 * clears the backend and invalidates the backend 80 * clears the backend and invalidates the backend
87 */ 81 */
88 virtual void clear() ; 82 virtual void clear() ;
89 83
90 /** 84 /**
91 * add T to the backend 85 * add T to the backend
92 */ 86 */
93 virtual bool add( const T& t ) ; 87 virtual bool add( const T& t ) ;
94 88
95 /* only the uid matters */ 89 /* only the uid matters */
96 /** 90 /**
97 * remove T from the backend 91 * remove T from the backend
98 */ 92 */
99 virtual bool remove( const T& t ); 93 virtual bool remove( const T& t );
100 94
101 /** 95 /**
102 * remove the OPimRecord with uid 96 * remove the OPimRecord with uid
103 */ 97 */
104 virtual bool remove( int uid ); 98 virtual bool remove( int uid );
105 99
106 /** 100 /**
107 * replace T from backend 101 * replace T from backend
108 */ 102 */
109 virtual bool replace( const T& t) ; 103 virtual bool replace( const T& t) ;
110 104
111 /** 105 /**
112 * @internal 106 * @internal
113 */ 107 */
114 void cache( const T& )const; 108 void cache( const T& )const;
115 void setSaneCacheSize( int ); 109 void setSaneCacheSize( int );
116protected: 110protected:
117 /** 111 /**
118 * invalidate the cache 112 * invalidate the cache
119 */ 113 */
120 void invalidateCache(); 114 void invalidateCache();
121 115
122 void setBackEnd( BackEnd* end ); 116 void setBackEnd( BackEnd* end );
123 /** 117 /**
124 * returns the backend 118 * returns the backend
125 */ 119 */
126 BackEnd* backEnd(); 120 BackEnd* backEnd();
127 BackEnd* m_backEnd; 121 BackEnd* m_backEnd;
128 Cache m_cache; 122 Cache m_cache;
129 123
130}; 124};
131 125
132template <class T> 126template <class T>
133OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) 127OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
134 : OTemplateBase<T>(), m_backEnd( end ) 128 : OTemplateBase<T>(), m_backEnd( end )
135{ 129{
136 if (end ) 130 if (end )
137 end->setFrontend( this ); 131 end->setFrontend( this );
138} 132}
139template <class T> 133template <class T>
140OPimAccessTemplate<T>::~OPimAccessTemplate() { 134OPimAccessTemplate<T>::~OPimAccessTemplate() {
141 qWarning("~OPimAccessTemplate<T>"); 135 qWarning("~OPimAccessTemplate<T>");
142 delete m_backEnd; 136 delete m_backEnd;
143} 137}
144template <class T> 138template <class T>
145bool OPimAccessTemplate<T>::load() { 139bool OPimAccessTemplate<T>::load() {
146 invalidateCache(); 140 invalidateCache();
147 return m_backEnd->load(); 141 return m_backEnd->load();
148} 142}
149template <class T> 143template <class T>
150bool OPimAccessTemplate<T>::reload() { 144bool OPimAccessTemplate<T>::reload() {
151 return m_backEnd->reload(); 145 return m_backEnd->reload();
152} 146}
153template <class T> 147template <class T>
154bool OPimAccessTemplate<T>::save() { 148bool OPimAccessTemplate<T>::save() {
155 return m_backEnd->save(); 149 return m_backEnd->save();
156} 150}
157template <class T> 151template <class T>
158OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { 152OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
159 QArray<int> ints = m_backEnd->allRecords(); 153 QArray<int> ints = m_backEnd->allRecords();
160 List lis(ints, this ); 154 List lis(ints, this );
161 return lis; 155 return lis;
162} 156}
163template <class T> 157template <class T>
164OPimAccessTemplate<T>::List 158OPimAccessTemplate<T>::List
165OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) { 159OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) {
166 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder ); 160 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder );
167 161