summaryrefslogtreecommitdiff
path: root/libopie/pim
authoreilers <eilers>2002-10-14 16:21:54 (UTC)
committer eilers <eilers>2002-10-14 16:21:54 (UTC)
commitf48ddfb53e49550f9fe8e9502f2a44aeb8b359cc (patch) (unidiff)
tree7972f3fc9a1d61e22fe57ff0fa96fd9a0badb55d /libopie/pim
parentda3868438e739310862bf65b0d0c8ffa864392e8 (diff)
downloadopie-f48ddfb53e49550f9fe8e9502f2a44aeb8b359cc.zip
opie-f48ddfb53e49550f9fe8e9502f2a44aeb8b359cc.tar.gz
opie-f48ddfb53e49550f9fe8e9502f2a44aeb8b359cc.tar.bz2
Some minor interface updates
Diffstat (limited to 'libopie/pim') (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
7 files changed, 37 insertions, 73 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,186 +1,188 @@
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}
166 168
167 169
168bool OContactAccess::reload() 170bool OContactAccess::reload()
169{ 171{
170 return ( m_backEnd->reload() ); 172 return ( m_backEnd->reload() );
171} 173}
172 174
173void OContactAccess::copMessage( const QCString &msg, const QByteArray & ) 175void OContactAccess::copMessage( const QCString &msg, const QByteArray & )
174{ 176{
175 if ( msg == "addressbookUpdated()" ){ 177 if ( msg == "addressbookUpdated()" ){
176 qWarning ("OContactAccess: Received addressbokUpdated()"); 178 qWarning ("OContactAccess: Received addressbokUpdated()");
177 emit signalChanged ( this ); 179 emit signalChanged ( this );
178 } else if ( msg == "flush()" ) { 180 } else if ( msg == "flush()" ) {
179 qWarning ("OContactAccess: Received flush()"); 181 qWarning ("OContactAccess: Received flush()");
180 save (); 182 save ();
181 } else if ( msg == "reload()" ) { 183 } else if ( msg == "reload()" ) {
182 qWarning ("OContactAccess: Received reload()"); 184 qWarning ("OContactAccess: Received reload()");
183 reload (); 185 reload ();
184 emit signalChanged ( this ); 186 emit signalChanged ( this );
185 } 187 }
186} 188}
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,560 +1,563 @@
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) );
360 dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); 363 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
361 dict.insert( "HomeState", new int(Qtopia::HomeState) ); 364 dict.insert( "HomeState", new int(Qtopia::HomeState) );
362 dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); 365 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
363 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); 366 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
364 dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); 367 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
365 dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); 368 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
366 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); 369 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
367 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); 370 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
368 dict.insert( "Company", new int(Qtopia::Company) ); 371 dict.insert( "Company", new int(Qtopia::Company) );
369 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); 372 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
370 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); 373 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
371 dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); 374 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
372 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); 375 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
373 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); 376 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
374 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); 377 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
375 dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); 378 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
376 dict.insert( "Department", new int(Qtopia::Department) ); 379 dict.insert( "Department", new int(Qtopia::Department) );
377 dict.insert( "Office", new int(Qtopia::Office) ); 380 dict.insert( "Office", new int(Qtopia::Office) );
378 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); 381 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
379 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); 382 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
380 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); 383 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
381 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); 384 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
382 dict.insert( "Profession", new int(Qtopia::Profession) ); 385 dict.insert( "Profession", new int(Qtopia::Profession) );
383 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 386 dict.insert( "Assistant", new int(Qtopia::Assistant) );
384 dict.insert( "Manager", new int(Qtopia::Manager) ); 387 dict.insert( "Manager", new int(Qtopia::Manager) );
385 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 388 dict.insert( "Spouse", new int(Qtopia::Spouse) );
386 dict.insert( "Children", new int(Qtopia::Children) ); 389 dict.insert( "Children", new int(Qtopia::Children) );
387 dict.insert( "Gender", new int(Qtopia::Gender) ); 390 dict.insert( "Gender", new int(Qtopia::Gender) );
388 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 391 dict.insert( "Birthday", new int(Qtopia::Birthday) );
389 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 392 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
390 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 393 dict.insert( "Nickname", new int(Qtopia::Nickname) );
391 dict.insert( "Notes", new int(Qtopia::Notes) ); 394 dict.insert( "Notes", new int(Qtopia::Notes) );
392 dict.insert( "action", new int(JOURNALACTION) ); 395 dict.insert( "action", new int(JOURNALACTION) );
393 dict.insert( "actionrow", new int(JOURNALROW) ); 396 dict.insert( "actionrow", new int(JOURNALROW) );
394 397
395 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); 398 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
396 399
397 XMLElement *root = XMLElement::load( filename ); 400 XMLElement *root = XMLElement::load( filename );
398 if(root != 0l ){ // start parsing 401 if(root != 0l ){ // start parsing
399 /* Parse all XML-Elements and put the data into the 402 /* Parse all XML-Elements and put the data into the
400 * Contact-Class 403 * Contact-Class
401 */ 404 */
402 XMLElement *element = root->firstChild(); 405 XMLElement *element = root->firstChild();
403 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() ); 406 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
404 element = element->firstChild(); 407 element = element->firstChild();
405 408
406 /* Search Tag "Contacts" which is the parent of all Contacts */ 409 /* Search Tag "Contacts" which is the parent of all Contacts */
407 while( element && !isJournal ){ 410 while( element && !isJournal ){
408 if( element->tagName() != QString::fromLatin1("Contacts") ){ 411 if( element->tagName() != QString::fromLatin1("Contacts") ){
409 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s", 412 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
410 // element->tagName().latin1()); 413 // element->tagName().latin1());
411 element = element->nextChild(); 414 element = element->nextChild();
412 } else { 415 } else {
413 element = element->firstChild(); 416 element = element->firstChild();
414 break; 417 break;
415 } 418 }
416 } 419 }
417 /* Parse all Contacts and ignore unknown tags */ 420 /* Parse all Contacts and ignore unknown tags */
418 while( element ){ 421 while( element ){
419 if( element->tagName() != QString::fromLatin1("Contact") ){ 422 if( element->tagName() != QString::fromLatin1("Contact") ){
420 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s", 423 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
421 // element->tagName().latin1()); 424 // element->tagName().latin1());
422 element = element->nextChild(); 425 element = element->nextChild();
423 continue; 426 continue;
424 } 427 }
425 /* Found alement with tagname "contact", now parse and store all 428 /* Found alement with tagname "contact", now parse and store all
426 * attributes contained 429 * attributes contained
427 */ 430 */
428 //qWarning("OContactDefBack::load element tagName() : %s", 431 //qWarning("OContactDefBack::load element tagName() : %s",
429 // element->tagName().latin1() ); 432 // element->tagName().latin1() );
430 QString dummy; 433 QString dummy;
431 foundAction = false; 434 foundAction = false;
432 435
433 XMLElement::AttributeMap aMap = element->attributes(); 436 XMLElement::AttributeMap aMap = element->attributes();
434 XMLElement::AttributeMap::Iterator it; 437 XMLElement::AttributeMap::Iterator it;
435 contactMap.clear(); 438 contactMap.clear();
436 customMap.clear(); 439 customMap.clear();
437 for( it = aMap.begin(); it != aMap.end(); ++it ){ 440 for( it = aMap.begin(); it != aMap.end(); ++it ){
438 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1()); 441 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
439 442
440 int *find = dict[ it.key() ]; 443 int *find = dict[ it.key() ];
441 /* Unknown attributes will be stored as "Custom" elements */ 444 /* Unknown attributes will be stored as "Custom" elements */
442 if ( !find ) { 445 if ( !find ) {
443 qWarning("Attribute %s not known.", it.key().latin1()); 446 qWarning("Attribute %s not known.", it.key().latin1());
444 //contact.setCustomField(it.key(), it.data()); 447 //contact.setCustomField(it.key(), it.data());
445 customMap.insert( it.key(), it.data() ); 448 customMap.insert( it.key(), it.data() );
446 continue; 449 continue;
447 } 450 }
448 451
449 /* Check if special conversion is needed and add attribute 452 /* Check if special conversion is needed and add attribute
450 * into Contact class 453 * into Contact class
451 */ 454 */
452 switch( *find ) { 455 switch( *find ) {
453 /* 456 /*
454 case Qtopia::AddressUid: 457 case Qtopia::AddressUid:
455 contact.setUid( it.data().toInt() ); 458 contact.setUid( it.data().toInt() );
456 break; 459 break;
457 case Qtopia::AddressCategory: 460 case Qtopia::AddressCategory:
458 contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); 461 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
459 break; 462 break;
460 */ 463 */
461 case JOURNALACTION: 464 case JOURNALACTION:
462 action = OContact::journal_action(it.data().toInt()); 465 action = OContact::journal_action(it.data().toInt());
463 foundAction = true; 466 foundAction = true;
464 qWarning ("ODefBack(journal)::ACTION found: %d", action); 467 qWarning ("ODefBack(journal)::ACTION found: %d", action);
465 break; 468 break;
466 case JOURNALROW: 469 case JOURNALROW:
467 journalKey = it.data().toInt(); 470 journalKey = it.data().toInt();
468 break; 471 break;
469 default: // no conversion needed add them to the map 472 default: // no conversion needed add them to the map
470 contactMap.insert( *find, it.data() ); 473 contactMap.insert( *find, it.data() );
471 break; 474 break;
472 } 475 }
473 } 476 }
474 /* now generate the Contact contact */ 477 /* now generate the Contact contact */
475 OContact contact( contactMap ); 478 OContact contact( contactMap );
476 479
477 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { 480 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
478 contact.setCustomField( customIt.key(), customIt.data() ); 481 contact.setCustomField( customIt.key(), customIt.data() );
479 } 482 }
480 483
481 if (foundAction){ 484 if (foundAction){
482 foundAction = false; 485 foundAction = false;
483 switch ( action ) { 486 switch ( action ) {
484 case OContact::ACTION_ADD: 487 case OContact::ACTION_ADD:
485 addContact_p (contact); 488 addContact_p (contact);
486 break; 489 break;
487 case OContact::ACTION_REMOVE: 490 case OContact::ACTION_REMOVE:
488 if ( !remove (contact.uid()) ) 491 if ( !remove (contact.uid()) )
489 qWarning ("ODefBack(journal)::Unable to remove uid: %d", 492 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
490 contact.uid() ); 493 contact.uid() );
491 break; 494 break;
492 case OContact::ACTION_REPLACE: 495 case OContact::ACTION_REPLACE:
493 if ( !replace ( contact ) ) 496 if ( !replace ( contact ) )
494 qWarning ("ODefBack(journal)::Unable to replace uid: %d", 497 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
495 contact.uid() ); 498 contact.uid() );
496 break; 499 break;
497 default: 500 default:
498 qWarning ("Unknown action: ignored !"); 501 qWarning ("Unknown action: ignored !");
499 break; 502 break;
500 } 503 }
501 }else{ 504 }else{
502 /* Add contact to list */ 505 /* Add contact to list */
503 addContact_p (contact); 506 addContact_p (contact);
504 } 507 }
505 508
506 /* Move to next element */ 509 /* Move to next element */
507 element = element->nextChild(); 510 element = element->nextChild();
508 } 511 }
509 }else { 512 }else {
510 qWarning("ODefBack::could not load"); 513 qWarning("ODefBack::could not load");
511 } 514 }
512 delete root; 515 delete root;
513 qWarning("returning from loading" ); 516 qWarning("returning from loading" );
514 return true; 517 return true;
515 } 518 }
516 519
517 520
518 void updateJournal( const OContact& cnt, 521 void updateJournal( const OContact& cnt,
519 OContact::journal_action action ) { 522 OContact::journal_action action ) {
520 QFile f( m_journalName ); 523 QFile f( m_journalName );
521 bool created = !f.exists(); 524 bool created = !f.exists();
522 if ( !f.open(IO_WriteOnly|IO_Append) ) 525 if ( !f.open(IO_WriteOnly|IO_Append) )
523 return; 526 return;
524 527
525 QString buf; 528 QString buf;
526 QCString str; 529 QCString str;
527 530
528 // if the file was created, we have to set the Tag "<CONTACTS>" to 531 // if the file was created, we have to set the Tag "<CONTACTS>" to
529 // get a XML-File which is readable by our parser. 532 // get a XML-File which is readable by our parser.
530 // This is just a cheat, but better than rewrite the parser. 533 // This is just a cheat, but better than rewrite the parser.
531 if ( created ){ 534 if ( created ){
532 buf = "<Contacts>"; 535 buf = "<Contacts>";
533 QCString cstr = buf.utf8(); 536 QCString cstr = buf.utf8();
534 f.writeBlock( cstr.data(), cstr.length() ); 537 f.writeBlock( cstr.data(), cstr.length() );
535 } 538 }
536 539
537 buf = "<Contact "; 540 buf = "<Contact ";
538 cnt.save( buf ); 541 cnt.save( buf );
539 buf += " action=\"" + QString::number( (int)action ) + "\" "; 542 buf += " action=\"" + QString::number( (int)action ) + "\" ";
540 buf += "/>\n"; 543 buf += "/>\n";
541 QCString cstr = buf.utf8(); 544 QCString cstr = buf.utf8();
542 f.writeBlock( cstr.data(), cstr.length() ); 545 f.writeBlock( cstr.data(), cstr.length() );
543 } 546 }
544 547
545 void removeJournal() 548 void removeJournal()
546 { 549 {
547 QFile f ( m_journalName ); 550 QFile f ( m_journalName );
548 if ( f.exists() ) 551 if ( f.exists() )
549 f.remove(); 552 f.remove();
550 } 553 }
551 554
552 protected: 555 protected:
553 QString m_journalName; 556 QString m_journalName;
554 QString m_fileName; 557 QString m_fileName;
555 QString m_appName; 558 QString m_appName;
556 QValueList<OContact> m_contactList; 559 QValueList<OContact> m_contactList;
557 QDateTime m_readtime; 560 QDateTime m_readtime;
558}; 561};
559 562
560#endif 563#endif
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,245 +1,239 @@
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
168 List lis(ints, this ); 162 List lis(ints, this );
169 return lis; 163 return lis;
170} 164}
171template <class T> 165template <class T>
172T OPimAccessTemplate<T>::find( int uid ) const{ 166T OPimAccessTemplate<T>::find( int uid ) const{
173 T t = m_backEnd->find( uid ); 167 T t = m_backEnd->find( uid );
174 cache( t ); 168 cache( t );
175 return t; 169 return t;
176} 170}
177template <class T> 171template <class T>
178T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar, 172T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
179 uint current, CacheDirection dir )const { 173 uint current, CacheDirection dir )const {
180 /* 174 /*
181 * better do T.isEmpty() 175 * better do T.isEmpty()
182 * after a find this way we would 176 * after a find this way we would
183 * avoid two finds in QCache... 177 * avoid two finds in QCache...
184 */ 178 */
185 // qWarning("find it now %d", uid ); 179 // qWarning("find it now %d", uid );
186 if (m_cache.contains( uid ) ) { 180 if (m_cache.contains( uid ) ) {
187 return m_cache.find( uid ); 181 return m_cache.find( uid );
188 } 182 }
189 183
190 T t = m_backEnd->find( uid, ar, current, dir ); 184 T t = m_backEnd->find( uid, ar, current, dir );
191 cache( t ); 185 cache( t );
192 return t; 186 return t;
193} 187}
194template <class T> 188template <class T>
195void OPimAccessTemplate<T>::clear() { 189void OPimAccessTemplate<T>::clear() {
196 invalidateCache(); 190 invalidateCache();
197 m_backEnd->clear(); 191 m_backEnd->clear();
198} 192}
199template <class T> 193template <class T>
200bool OPimAccessTemplate<T>::add( const T& t ) { 194bool OPimAccessTemplate<T>::add( const T& t ) {
201 cache( t ); 195 cache( t );
202 return m_backEnd->add( t ); 196 return m_backEnd->add( t );
203} 197}
204template <class T> 198template <class T>
205bool OPimAccessTemplate<T>::remove( const T& t ) { 199bool OPimAccessTemplate<T>::remove( const T& t ) {
206 return remove( t.uid() ); 200 return remove( t.uid() );
207} 201}
208template <class T> 202template <class T>
209bool OPimAccessTemplate<T>::remove( int uid ) { 203bool OPimAccessTemplate<T>::remove( int uid ) {
210 m_cache.remove( uid ); 204 m_cache.remove( uid );
211 return m_backEnd->remove( uid ); 205 return m_backEnd->remove( uid );
212} 206}
213template <class T> 207template <class T>
214bool OPimAccessTemplate<T>::replace( const T& t ) { 208bool OPimAccessTemplate<T>::replace( const T& t ) {
215 m_cache.replace( t ); 209 m_cache.replace( t );
216 return m_backEnd->replace( t ); 210 return m_backEnd->replace( t );
217} 211}
218template <class T> 212template <class T>
219void OPimAccessTemplate<T>::invalidateCache() { 213void OPimAccessTemplate<T>::invalidateCache() {
220 m_cache.invalidate(); 214 m_cache.invalidate();
221} 215}
222template <class T> 216template <class T>
223OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() { 217OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() {
224 return m_backEnd; 218 return m_backEnd;
225} 219}
226template <class T> 220template <class T>
227bool OPimAccessTemplate<T>::wasChangedExternally()const { 221bool OPimAccessTemplate<T>::wasChangedExternally()const {
228 return false; 222 return false;
229} 223}
230template <class T> 224template <class T>
231void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) { 225void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) {
232 m_backEnd = end; 226 m_backEnd = end;
233 if (m_backEnd ) 227 if (m_backEnd )
234 m_backEnd->setFrontend( this ); 228 m_backEnd->setFrontend( this );
235} 229}
236template <class T> 230template <class T>
237void OPimAccessTemplate<T>::cache( const T& t ) const{ 231void OPimAccessTemplate<T>::cache( const T& t ) const{
238 /* hacky we need to work around the const*/ 232 /* hacky we need to work around the const*/
239 ((OPimAccessTemplate<T>*)this)->m_cache.add( t ); 233 ((OPimAccessTemplate<T>*)this)->m_cache.add( t );
240} 234}
241template <class T> 235template <class T>
242void OPimAccessTemplate<T>::setSaneCacheSize( int size ) { 236void OPimAccessTemplate<T>::setSaneCacheSize( int size ) {
243 m_cache.setSize( size ); 237 m_cache.setSize( size );
244} 238}
245#endif 239#endif
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
@@ -1,549 +1,549 @@
1#include <qfile.h> 1#include <qfile.h>
2#include <qvector.h> 2#include <qvector.h>
3 3
4#include <qpe/global.h> 4#include <qpe/global.h>
5#include <qpe/stringutil.h> 5#include <qpe/stringutil.h>
6#include <qpe/timeconversion.h> 6#include <qpe/timeconversion.h>
7 7
8#include <opie/xmltree.h> 8#include <opie/xmltree.h>
9 9
10#include "otodoaccessxml.h" 10#include "otodoaccessxml.h"
11 11
12OTodoAccessXML::OTodoAccessXML( const QString& appName, 12OTodoAccessXML::OTodoAccessXML( const QString& appName,
13 const QString& fileName ) 13 const QString& fileName )
14 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) 14 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
15{ 15{
16 if (!fileName.isEmpty() ) 16 if (!fileName.isEmpty() )
17 m_file = fileName; 17 m_file = fileName;
18 else 18 else
19 m_file = Global::applicationFileName( "todolist", "todolist.xml" ); 19 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
20} 20}
21OTodoAccessXML::~OTodoAccessXML() { 21OTodoAccessXML::~OTodoAccessXML() {
22 22
23} 23}
24bool OTodoAccessXML::load() { 24bool OTodoAccessXML::load() {
25 m_opened = true; 25 m_opened = true;
26 m_changed = false; 26 m_changed = false;
27 /* initialize dict */ 27 /* initialize dict */
28 /* 28 /*
29 * UPDATE dict if you change anything!!! 29 * UPDATE dict if you change anything!!!
30 */ 30 */
31 QAsciiDict<int> dict(15); 31 QAsciiDict<int> dict(15);
32 dict.setAutoDelete( TRUE ); 32 dict.setAutoDelete( TRUE );
33 dict.insert("Categories" , new int(OTodo::Category) ); 33 dict.insert("Categories" , new int(OTodo::Category) );
34 dict.insert("Uid" , new int(OTodo::Uid) ); 34 dict.insert("Uid" , new int(OTodo::Uid) );
35 dict.insert("HasDate" , new int(OTodo::HasDate) ); 35 dict.insert("HasDate" , new int(OTodo::HasDate) );
36 dict.insert("Completed" , new int(OTodo::Completed) ); 36 dict.insert("Completed" , new int(OTodo::Completed) );
37 dict.insert("Description" , new int(OTodo::Description) ); 37 dict.insert("Description" , new int(OTodo::Description) );
38 dict.insert("Summary" , new int(OTodo::Summary) ); 38 dict.insert("Summary" , new int(OTodo::Summary) );
39 dict.insert("Priority" , new int(OTodo::Priority) ); 39 dict.insert("Priority" , new int(OTodo::Priority) );
40 dict.insert("DateDay" , new int(OTodo::DateDay) ); 40 dict.insert("DateDay" , new int(OTodo::DateDay) );
41 dict.insert("DateMonth" , new int(OTodo::DateMonth) ); 41 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
42 dict.insert("DateYear" , new int(OTodo::DateYear) ); 42 dict.insert("DateYear" , new int(OTodo::DateYear) );
43 dict.insert("Progress" , new int(OTodo::Progress) ); 43 dict.insert("Progress" , new int(OTodo::Progress) );
44 dict.insert("Completed", new int(OTodo::Completed) ); 44 dict.insert("Completed", new int(OTodo::Completed) );
45 dict.insert("CrossReference", new int(OTodo::CrossReference) ); 45 dict.insert("CrossReference", new int(OTodo::CrossReference) );
46 dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); 46 dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) );
47 dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); 47 dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) );
48 48
49 // here the custom XML parser from TT it's GPL 49 // here the custom XML parser from TT it's GPL
50 // but we want to push that to TT..... 50 // but we want to push that to TT.....
51 QFile f(m_file ); 51 QFile f(m_file );
52 if (!f.open(IO_ReadOnly) ) 52 if (!f.open(IO_ReadOnly) )
53 return false; 53 return false;
54 54
55 QByteArray ba = f.readAll(); 55 QByteArray ba = f.readAll();
56 f.close(); 56 f.close();
57 char* dt = ba.data(); 57 char* dt = ba.data();
58 int len = ba.size(); 58 int len = ba.size();
59 int i = 0; 59 int i = 0;
60 char *point; 60 char *point;
61 const char* collectionString = "<Task "; 61 const char* collectionString = "<Task ";
62 while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { 62 while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) {
63 i = point -dt; 63 i = point -dt;
64 i+= strlen(collectionString); 64 i+= strlen(collectionString);
65 OTodo ev; 65 OTodo ev;
66 m_year = m_month = m_day = 0; 66 m_year = m_month = m_day = 0;
67 67
68 while ( TRUE ) { 68 while ( TRUE ) {
69 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 69 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
70 ++i; 70 ++i;
71 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 71 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
72 break; 72 break;
73 73
74 // we have another attribute, read it. 74 // we have another attribute, read it.
75 int j = i; 75 int j = i;
76 while ( j < len && dt[j] != '=' ) 76 while ( j < len && dt[j] != '=' )
77 ++j; 77 ++j;
78 QCString attr( dt+i, j-i+1); 78 QCString attr( dt+i, j-i+1);
79 79
80 i = ++j; // skip = 80 i = ++j; // skip =
81 81
82 // find the start of quotes 82 // find the start of quotes
83 while ( i < len && dt[i] != '"' ) 83 while ( i < len && dt[i] != '"' )
84 ++i; 84 ++i;
85 j = ++i; 85 j = ++i;
86 86
87 bool haveUtf = FALSE; 87 bool haveUtf = FALSE;
88 bool haveEnt = FALSE; 88 bool haveEnt = FALSE;
89 while ( j < len && dt[j] != '"' ) { 89 while ( j < len && dt[j] != '"' ) {
90 if ( ((unsigned char)dt[j]) > 0x7f ) 90 if ( ((unsigned char)dt[j]) > 0x7f )
91 haveUtf = TRUE; 91 haveUtf = TRUE;
92 if ( dt[j] == '&' ) 92 if ( dt[j] == '&' )
93 haveEnt = TRUE; 93 haveEnt = TRUE;
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;
287 case OTodo::HasDate: 287 case OTodo::HasDate:
288 ev.setHasDueDate( val.toInt() ); 288 ev.setHasDueDate( val.toInt() );
289 break; 289 break;
290 case OTodo::Completed: 290 case OTodo::Completed:
291 ev.setCompleted( val.toInt() ); 291 ev.setCompleted( val.toInt() );
292 break; 292 break;
293 case OTodo::Description: 293 case OTodo::Description:
294 ev.setDescription( val ); 294 ev.setDescription( val );
295 break; 295 break;
296 case OTodo::Summary: 296 case OTodo::Summary:
297 ev.setSummary( val ); 297 ev.setSummary( val );
298 break; 298 break;
299 case OTodo::Priority: 299 case OTodo::Priority:
300 ev.setPriority( val.toInt() ); 300 ev.setPriority( val.toInt() );
301 break; 301 break;
302 case OTodo::DateDay: 302 case OTodo::DateDay:
303 m_day = val.toInt(); 303 m_day = val.toInt();
304 break; 304 break;
305 case OTodo::DateMonth: 305 case OTodo::DateMonth:
306 m_month = val.toInt(); 306 m_month = val.toInt();
307 break; 307 break;
308 case OTodo::DateYear: 308 case OTodo::DateYear:
309 m_year = val.toInt(); 309 m_year = val.toInt();
310 break; 310 break;
311 case OTodo::Progress: 311 case OTodo::Progress:
312 ev.setProgress( val.toInt() ); 312 ev.setProgress( val.toInt() );
313 break; 313 break;
314 case OTodo::CrossReference: 314 case OTodo::CrossReference:
315 { 315 {
316 /* 316 /*
317 * A cross refernce looks like 317 * A cross refernce looks like
318 * appname,id;appname,id 318 * appname,id;appname,id
319 * we need to split it up 319 * we need to split it up
320 */ 320 */
321 QStringList refs = QStringList::split(';', val ); 321 QStringList refs = QStringList::split(';', val );
322 QStringList::Iterator strIt; 322 QStringList::Iterator strIt;
323 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { 323 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
324 int pos = (*strIt).find(','); 324 int pos = (*strIt).find(',');
325 if ( pos > -1 ) 325 if ( pos > -1 )
326 ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); 326 ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
327 327
328 } 328 }
329 break; 329 break;
330 } 330 }
331 case OTodo::HasAlarmDateTime: 331 case OTodo::HasAlarmDateTime:
332 ev.setHasAlarmDateTime( val.toInt() ); 332 ev.setHasAlarmDateTime( val.toInt() );
333 break; 333 break;
334 case OTodo::AlarmDateTime: { 334 case OTodo::AlarmDateTime: {
335 /* this sounds better ;) zecke */ 335 /* this sounds better ;) zecke */
336 ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) ); 336 ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) );
337 break; 337 break;
338 } 338 }
339 default: 339 default:
340 break; 340 break;
341 } 341 }
342 342
343 if ( ev.hasDueDate() ) { 343 if ( ev.hasDueDate() ) {
344 QDate date( m_year, m_month, m_day ); 344 QDate date( m_year, m_month, m_day );
345 ev.setDueDate( date ); 345 ev.setDueDate( date );
346 } 346 }
347} 347}
348QString OTodoAccessXML::toString( const OTodo& ev )const { 348QString OTodoAccessXML::toString( const OTodo& ev )const {
349 QString str; 349 QString str;
350 350
351 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; 351 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
352 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; 352 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
353 str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; 353 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
354 str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; 354 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
355 355
356 str += "Categories=\"" + toString( ev.categories() ) + "\" "; 356 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
357 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; 357 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
358 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; 358 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
359 359
360 if ( ev.hasDueDate() ) { 360 if ( ev.hasDueDate() ) {
361 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; 361 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
362 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; 362 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
363 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; 363 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
364 } 364 }
365// qWarning( "Uid %d", ev.uid() ); 365// qWarning( "Uid %d", ev.uid() );
366 str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; 366 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
367 367
368// append the extra options 368// append the extra options
369 /* FIXME Qtopia::Record this is currently not 369 /* FIXME Qtopia::Record this is currently not
370 * possible you can set custom fields 370 * possible you can set custom fields
371 * but don' iterate over the list 371 * but don' iterate over the list
372 * I may do #define private protected 372 * I may do #define private protected
373 * for this case - cough --zecke 373 * for this case - cough --zecke
374 */ 374 */
375 /* 375 /*
376 QMap<QString, QString> extras = ev.extras(); 376 QMap<QString, QString> extras = ev.extras();
377 QMap<QString, QString>::Iterator extIt; 377 QMap<QString, QString>::Iterator extIt;
378 for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) 378 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
379 str += extIt.key() + "=\"" + extIt.data() + "\" "; 379 str += extIt.key() + "=\"" + extIt.data() + "\" ";
380 */ 380 */
381 // cross refernce 381 // cross refernce
382 QStringList list = ev.relatedApps(); 382 QStringList list = ev.relatedApps();
383 QStringList::Iterator listIt; 383 QStringList::Iterator listIt;
384 QString refs; 384 QString refs;
385 str += "CrossReference=\""; 385 str += "CrossReference=\"";
386 bool added = false; 386 bool added = false;
387 for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { 387 for ( listIt = list.begin(); listIt != list.end(); ++listIt ) {
388 added = true; 388 added = true;
389 QArray<int> ints = ev.relations( (*listIt) ); 389 QArray<int> ints = ev.relations( (*listIt) );
390 for ( uint i = 0; i< ints.count(); i++ ) { 390 for ( uint i = 0; i< ints.count(); i++ ) {
391 str += (*listIt) + "," + QString::number( i ) + ";"; 391 str += (*listIt) + "," + QString::number( i ) + ";";
392 } 392 }
393 } 393 }
394 if ( added ) 394 if ( added )
395 str = str.remove( str.length()-1, 1 ); 395 str = str.remove( str.length()-1, 1 );
396 396
397 str += "\" "; 397 str += "\" ";
398 398
399 str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; 399 str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" ";
400 400
401 return str; 401 return str;
402} 402}
403QString OTodoAccessXML::toString( const QArray<int>& ints ) const { 403QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
404 return Qtopia::Record::idsToString( ints ); 404 return Qtopia::Record::idsToString( ints );
405} 405}
406 406
407/* internal class for sorting */ 407/* internal class for sorting */
408 408
409struct OTodoXMLContainer { 409struct OTodoXMLContainer {
410 OTodo todo; 410 OTodo todo;
411}; 411};
412 /* 412 /*
413 * Returns: 413 * Returns:
414 * 0 if item1 == item2 414 * 0 if item1 == item2
415 * 415 *
416 * non-zero if item1 != item2 416 * non-zero if item1 != item2
417 * 417 *
418 * This function returns int rather than bool so that reimplementations 418 * This function returns int rather than bool so that reimplementations
419 * can return one of three values and use it to sort by: 419 * can return one of three values and use it to sort by:
420 * 420 *
421 * 0 if item1 == item2 421 * 0 if item1 == item2
422 * 422 *
423 * > 0 (positive integer) if item1 > item2 423 * > 0 (positive integer) if item1 > item2
424 * 424 *
425 * < 0 (negative integer) if item1 < item2 425 * < 0 (negative integer) if item1 < item2
426 * 426 *
427 */ 427 */
428class OTodoXMLVector : public QVector<OTodoXMLContainer> { 428class OTodoXMLVector : public QVector<OTodoXMLContainer> {
429public: 429public:
430 OTodoXMLVector(int size, bool asc, int sort) 430 OTodoXMLVector(int size, bool asc, int sort)
431 : QVector<OTodoXMLContainer>( size ) 431 : QVector<OTodoXMLContainer>( size )
432 { 432 {
433 setAutoDelete( true ); 433 setAutoDelete( true );
434 m_asc = asc; 434 m_asc = asc;
435 m_sort = sort; 435 m_sort = sort;
436 } 436 }
437 /* return the summary/description */ 437 /* return the summary/description */
438 QString string( const OTodo& todo) { 438 QString string( const OTodo& todo) {
439 return todo.summary().isEmpty() ? 439 return todo.summary().isEmpty() ?
440 todo.description().left(20 ) : 440 todo.description().left(20 ) :
441 todo.summary(); 441 todo.summary();
442 } 442 }
443 /** 443 /**
444 * we take the sortorder( switch on it ) 444 * we take the sortorder( switch on it )
445 * 445 *
446 */ 446 */
447 int compareItems( Item d1, Item d2 ) { 447 int compareItems( Item d1, Item d2 ) {
448 int ret =0; 448 int ret =0;
449 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; 449 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
450 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; 450 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
451 451
452 /* same item */ 452 /* same item */
453 if ( con1->todo.uid() == con2->todo.uid() ) 453 if ( con1->todo.uid() == con2->todo.uid() )
454 return 0; 454 return 0;
455 455
456 switch ( m_sort ) { 456 switch ( m_sort ) {
457 /* completed */ 457 /* completed */
458 case 0: { 458 case 0: {
459 ret = 0; 459 ret = 0;
460 if ( con1->todo.isCompleted() ) ret++; 460 if ( con1->todo.isCompleted() ) ret++;
461 if ( con2->todo.isCompleted() ) ret--; 461 if ( con2->todo.isCompleted() ) ret--;
462 break; 462 break;
463 } 463 }
464 /* priority */ 464 /* priority */
465 case 1: { 465 case 1: {
466 ret = con1->todo.priority() - con2->todo.priority(); 466 ret = con1->todo.priority() - con2->todo.priority();
467 qWarning(" priority %d %d %d", ret, 467 qWarning(" priority %d %d %d", ret,
468 con1->todo.priority(), 468 con1->todo.priority(),
469 con2->todo.priority() 469 con2->todo.priority()
470 ); 470 );
471 break; 471 break;
472 } 472 }
473 /* description */ 473 /* description */
474 case 2: { 474 case 2: {
475 QString str1 = string( con1->todo ); 475 QString str1 = string( con1->todo );
476 QString str2 = string( con2->todo ); 476 QString str2 = string( con2->todo );
477 ret = QString::compare( str1, str2 ); 477 ret = QString::compare( str1, str2 );
478 break; 478 break;
479 } 479 }
480 /* deadline */ 480 /* deadline */
481 case 3: { 481 case 3: {
482 /* either bot got a dueDate 482 /* either bot got a dueDate
483 * or one of them got one 483 * or one of them got one
484 */ 484 */
485 if ( con1->todo.hasDueDate() && 485 if ( con1->todo.hasDueDate() &&
486 con2->todo.hasDueDate() ) 486 con2->todo.hasDueDate() )
487 ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() ); 487 ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() );
488 488
489 489
490 else if ( con1->todo.hasDueDate() ) 490 else if ( con1->todo.hasDueDate() )
491 ret = -1; 491 ret = -1;
492 else if ( con2->todo.hasDueDate() ) 492 else if ( con2->todo.hasDueDate() )
493 ret = 0; 493 ret = 0;
494 break; 494 break;
495 } 495 }
496 default: 496 default:
497 ret = 0; 497 ret = 0;
498 break; 498 break;
499 }; 499 };
500 500
501 /* twist it we're not ascending*/ 501 /* twist it we're not ascending*/
502 if (!m_asc) 502 if (!m_asc)
503 ret = ret * -1; 503 ret = ret * -1;
504 return ret; 504 return ret;
505 } 505 }
506 private: 506 private:
507 bool m_asc; 507 bool m_asc;
508 int m_sort; 508 int m_sort;
509 509
510}; 510};
511 511
512QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, 512QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
513 int sortFilter, int cat ) { 513 int sortFilter, int cat ) {
514 qWarning("sorted! %d cat", cat); 514 qWarning("sorted! %d cat", cat);
515 OTodoXMLVector vector(m_events.count(), asc,sortOrder ); 515 OTodoXMLVector vector(m_events.count(), asc,sortOrder );
516 QMap<int, OTodo>::Iterator it; 516 QMap<int, OTodo>::Iterator it;
517 int item = 0; 517 int item = 0;
518 518
519 bool bCat = sortFilter & 1 ? true : false; 519 bool bCat = sortFilter & 1 ? true : false;
520 bool bOnly = sortFilter & 2 ? true : false; 520 bool bOnly = sortFilter & 2 ? true : false;
521 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 521 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
522 522
523 /* show category */ 523 /* show category */
524 if ( bCat && cat != 0) 524 if ( bCat && cat != 0)
525 if (!(*it).categories().contains( cat ) ) 525 if (!(*it).categories().contains( cat ) )
526 continue; 526 continue;
527 /* isOverdue but we should not show overdue */ 527 /* isOverdue but we should not show overdue */
528 if ( (*it).isOverdue() && !bOnly ) 528 if ( (*it).isOverdue() && !bOnly )
529 continue; 529 continue;
530 if ( !(*it).isOverdue() && bOnly ) 530 if ( !(*it).isOverdue() && bOnly )
531 continue; 531 continue;
532 532
533 533
534 OTodoXMLContainer* con = new OTodoXMLContainer(); 534 OTodoXMLContainer* con = new OTodoXMLContainer();
535 con->todo = (*it); 535 con->todo = (*it);
536 vector.insert(item, con ); 536 vector.insert(item, con );
537 item++; 537 item++;
538 } 538 }
539 vector.resize( item ); 539 vector.resize( item );
540 /* sort it now */ 540 /* sort it now */
541 vector.sort(); 541 vector.sort();
542 /* now get the uids */ 542 /* now get the uids */
543 QArray<int> array( vector.count() ); 543 QArray<int> array( vector.count() );
544 for (uint i= 0; i < vector.count(); i++ ) { 544 for (uint i= 0; i < vector.count(); i++ ) {
545 array[i] = ( vector.at(i) )->todo.uid(); 545 array[i] = ( vector.at(i) )->todo.uid();
546 } 546 }
547 qWarning("array count = %d %d", array.count(), vector.count() ); 547 qWarning("array count = %d %d", array.count(), vector.count() );
548 return array; 548 return array;
549}; 549};
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