summaryrefslogtreecommitdiff
path: root/libopie/pim
Unidiff
Diffstat (limited to 'libopie/pim') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/obackendfactory.h16
-rw-r--r--libopie/pim/ocontact.h13
-rw-r--r--libopie/pim/ocontactaccessbackend_sql.cpp664
-rw-r--r--libopie/pim/ocontactaccessbackend_sql.h96
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.cpp7
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h6
-rw-r--r--libopie/pim/ocontactfields.cpp456
-rw-r--r--libopie/pim/ocontactfields.h60
-rw-r--r--libopie/pim/otodoaccesssql.cpp73
-rw-r--r--libopie/pim/otodoaccesssql.h6
-rw-r--r--libopie/pim/test/converter.cpp64
-rw-r--r--libopie/pim/test/converter.pro12
-rw-r--r--libopie/pim/test/converter_base.ui43
13 files changed, 1492 insertions, 24 deletions
diff --git a/libopie/pim/obackendfactory.h b/libopie/pim/obackendfactory.h
index f3c339d..3567687 100644
--- a/libopie/pim/obackendfactory.h
+++ b/libopie/pim/obackendfactory.h
@@ -1,166 +1,176 @@
1/* 1/*
2 * Class to manage Backends. 2 * Class to manage Backends.
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; 9 * License as published by the Free Software Foundation;
10 * either version 2 of the License, or (at your option) any later 10 * either version 2 of the License, or (at your option) any later
11 * version. 11 * version.
12 * ===================================================================== 12 * =====================================================================
13 * ToDo: Use plugins 13 * ToDo: Use plugins
14 * ===================================================================== 14 * =====================================================================
15 * Version: $Id$ 15 * Version: $Id$
16 * ===================================================================== 16 * =====================================================================
17 * History: 17 * History:
18 * $Log$ 18 * $Log$
19 * Revision 1.8 2003/09/22 14:31:16 eilers
20 * Added first experimental incarnation of sql-backend for addressbook.
21 * Some modifications to be able to compile the todo sql-backend.
22 * A lot of changes fill follow...
23 *
19 * Revision 1.7 2003/08/01 12:30:16 eilers 24 * Revision 1.7 2003/08/01 12:30:16 eilers
20 * Merging changes from BRANCH_1_0 to HEAD 25 * Merging changes from BRANCH_1_0 to HEAD
21 * 26 *
22 * Revision 1.6.4.1 2003/06/30 14:34:19 eilers 27 * Revision 1.6.4.1 2003/06/30 14:34:19 eilers
23 * Patches from Zecke: 28 * Patches from Zecke:
24 * Fixing and cleaning up extraMap handling 29 * Fixing and cleaning up extraMap handling
25 * Adding d_ptr for binary compatibility in the future 30 * Adding d_ptr for binary compatibility in the future
26 * 31 *
27 * Revision 1.6 2003/04/13 18:07:10 zecke 32 * Revision 1.6 2003/04/13 18:07:10 zecke
28 * More API doc 33 * More API doc
29 * QString -> const QString& 34 * QString -> const QString&
30 * QString = 0l -> QString::null 35 * QString = 0l -> QString::null
31 * 36 *
32 * Revision 1.5 2003/02/21 23:31:52 zecke 37 * Revision 1.5 2003/02/21 23:31:52 zecke
33 * Add XML datebookresource 38 * Add XML datebookresource
34 * -clean up todoaccessxml header 39 * -clean up todoaccessxml header
35 * -implement some more stuff in the oeven tester 40 * -implement some more stuff in the oeven tester
36 * -extend DefaultFactory to not crash and to use datebook 41 * -extend DefaultFactory to not crash and to use datebook
37 * 42 *
38 * -reading of OEvents is working nicely.. saving will be added 43 * -reading of OEvents is working nicely.. saving will be added
39 * tomorrow 44 * tomorrow
40 * -fix spelling in ODateBookAcces 45 * -fix spelling in ODateBookAcces
41 * 46 *
42 * Revision 1.4 2002/10/14 15:55:18 eilers 47 * Revision 1.4 2002/10/14 15:55:18 eilers
43 * Redeactivate SQL.. ;) 48 * Redeactivate SQL.. ;)
44 * 49 *
45 * Revision 1.3 2002/10/10 17:08:58 zecke 50 * Revision 1.3 2002/10/10 17:08:58 zecke
46 * The Cache is finally in place 51 * The Cache is finally in place
47 * I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;) 52 * I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;)
48 * The read ahead functionality does not make sense for XMLs backends because most of the stuff is already in memory. While using readahead on SQL makes things a lot faster.... 53 * The read ahead functionality does not make sense for XMLs backends because most of the stuff is already in memory. While using readahead on SQL makes things a lot faster....
49 * I still have to fully implement read ahead 54 * I still have to fully implement read ahead
50 * This change is bic but sc 55 * This change is bic but sc
51 * 56 *
52 * Revision 1.2 2002/10/08 09:27:36 eilers 57 * Revision 1.2 2002/10/08 09:27:36 eilers
53 * Fixed libopie.pro to include the new pim-API. 58 * Fixed libopie.pro to include the new pim-API.
54 * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to 59 * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to
55 * compile itself would need to install libsqlite, libopiesql... 60 * compile itself would need to install libsqlite, libopiesql...
56 * Therefore, the backend currently uses XML only.. 61 * Therefore, the backend currently uses XML only..
57 * 62 *
58 * Revision 1.1 2002/10/07 17:35:01 eilers 63 * Revision 1.1 2002/10/07 17:35:01 eilers
59 * added OBackendFactory for advanced backend access 64 * added OBackendFactory for advanced backend access
60 * 65 *
61 * 66 *
62 * ===================================================================== 67 * =====================================================================
63 */ 68 */
64#ifndef OPIE_BACKENDFACTORY_H_ 69#ifndef OPIE_BACKENDFACTORY_H_
65#define OPIE_BACKENDFACTORY_H_ 70#define OPIE_BACKENDFACTORY_H_
66 71
67#include <qstring.h> 72#include <qstring.h>
68#include <qasciidict.h> 73#include <qasciidict.h>
69#include <qpe/config.h> 74#include <qpe/config.h>
70 75
71#include "otodoaccessxml.h" 76#include "otodoaccessxml.h"
72#include "ocontactaccessbackend_xml.h" 77#include "ocontactaccessbackend_xml.h"
73#include "odatebookaccessbackend_xml.h" 78#include "odatebookaccessbackend_xml.h"
74 79
75#ifdef __USE_SQL 80#ifdef __USE_SQL
76#include "otodoaccesssql.h" 81#include "otodoaccesssql.h"
82#include "ocontactaccessbackend_sql.h"
77#endif 83#endif
78 84
79class OBackendPrivate; 85class OBackendPrivate;
80 86
81/** 87/**
82 * This class is our factory. It will give us the default implementations 88 * This class is our factory. It will give us the default implementations
83 * of at least Todolist, Contacts and Datebook. In the future this class will 89 * of at least Todolist, Contacts and Datebook. In the future this class will
84 * allow users to switch the backend with ( XML->SQLite ) without the need 90 * allow users to switch the backend with ( XML->SQLite ) without the need
85 * to recompile.# 91 * to recompile.#
86 * This class as the whole PIM Api is making use of templates 92 * This class as the whole PIM Api is making use of templates
87 * 93 *
88 * <pre> 94 * <pre>
89 * OTodoAccessBackend* backend = OBackEndFactory<OTodoAccessBackend>::Default("todo", QString::null ); 95 * OTodoAccessBackend* backend = OBackEndFactory<OTodoAccessBackend>::Default("todo", QString::null );
90 * backend->load(); 96 * backend->load();
91 * </pre> 97 * </pre>
92 * 98 *
93 * @author Stefan Eilers 99 * @author Stefan Eilers
94 * @version 0.1 100 * @version 0.1
95 */ 101 */
96template<class T> 102template<class T>
97class OBackendFactory 103class OBackendFactory
98{ 104{
99 public: 105 public:
100 OBackendFactory() {}; 106 OBackendFactory() {};
101 107
102 enum BACKENDS { 108 enum BACKENDS {
103 TODO, 109 TODO,
104 CONTACT, 110 CONTACT,
105 DATE 111 DATE
106 }; 112 };
107 113
108 /** 114 /**
109 * Returns a backend implementation for backendName 115 * Returns a backend implementation for backendName
110 * @param backendName the type of the backend 116 * @param backendName the type of the backend
111 * @param appName will be passed on to the backend 117 * @param appName will be passed on to the backend
112 */ 118 */
113 static T* Default( const QString backendName, const QString& appName ){ 119 static T* Default( const QString backendName, const QString& appName ){
114 120
115 // __asm__("int3"); 121 // __asm__("int3");
116 122
117 Config config( "pimaccess" ); 123 Config config( "pimaccess" );
118 config.setGroup ( backendName ); 124 config.setGroup ( backendName );
119 QString backend = config.readEntry( "usebackend" ); 125 QString backend = config.readEntry( "usebackend" );
120 126
127 qWarning("Selected backend for %s is: %s", backendName.latin1(), backend.latin1() );
128
121 QAsciiDict<int> dict ( 3 ); 129 QAsciiDict<int> dict ( 3 );
122 dict.setAutoDelete ( TRUE ); 130 dict.setAutoDelete ( TRUE );
123 131
124 dict.insert( "todo", new int (TODO) ); 132 dict.insert( "todo", new int (TODO) );
125 dict.insert( "contact", new int (CONTACT) ); 133 dict.insert( "contact", new int (CONTACT) );
126 dict.insert( "datebook", new int(DATE) ); 134 dict.insert( "datebook", new int(DATE) );
127 135
128 qWarning ("TODO is: %d", TODO);
129 qWarning ("CONTACT is: %d", CONTACT);
130
131 int *find = dict[ backendName ]; 136 int *find = dict[ backendName ];
132 if (!find ) return 0; 137 if (!find ) return 0;
133 138
134 switch ( *find ){ 139 switch ( *find ){
135 case TODO: 140 case TODO:
136#ifdef __USE_SQL 141#ifdef __USE_SQL
137 if ( backend == "sql" ) 142 if ( backend == "sql" )
138 return (T*) new OTodoAccessBackendSQL(""); 143 return (T*) new OTodoAccessBackendSQL("");
139#else 144#else
140 if ( backend == "sql" ) 145 if ( backend == "sql" )
141 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); 146 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!");
142#endif 147#endif
143 148
144 return (T*) new OTodoAccessXML( appName ); 149 return (T*) new OTodoAccessXML( appName );
145 case CONTACT: 150 case CONTACT:
151#ifdef __USE_SQL
152 if ( backend == "sql" )
153 return (T*) new OContactAccessBackend_SQL("");
154#else
146 if ( backend == "sql" ) 155 if ( backend == "sql" )
147 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); 156 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!");
157#endif
148 158
149 return (T*) new OContactAccessBackend_XML( appName ); 159 return (T*) new OContactAccessBackend_XML( appName );
150 case DATE: 160 case DATE:
151 if ( backend == "sql" ) 161 if ( backend == "sql" )
152 qWarning("OBackendFactory:: sql Backend not implemented! Using XML instead!"); 162 qWarning("OBackendFactory:: sql Backend not implemented! Using XML instead!");
153 163
154 return (T*) new ODateBookAccessBackend_XML( appName ); 164 return (T*) new ODateBookAccessBackend_XML( appName );
155 default: 165 default:
156 return NULL; 166 return NULL;
157 } 167 }
158 168
159 169
160 } 170 }
161 private: 171 private:
162 OBackendPrivate* d; 172 OBackendPrivate* d;
163}; 173};
164 174
165 175
166#endif 176#endif
diff --git a/libopie/pim/ocontact.h b/libopie/pim/ocontact.h
index 9a1a8dc..1d46b81 100644
--- a/libopie/pim/ocontact.h
+++ b/libopie/pim/ocontact.h
@@ -1,245 +1,240 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de) 3** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
4** 4**
5** This file may be distributed and/or modified under the terms of the 5** This file may be distributed and/or modified under the terms of the
6** GNU General Public License version 2 as published by the Free Software 6** GNU General Public License version 2 as published by the Free Software
7** Foundation and appearing in the file LICENSE.GPL included in the 7** Foundation and appearing in the file LICENSE.GPL included in the
8** packaging of this file. 8** packaging of this file.
9** 9**
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 11** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12** 12**
13** See http://www.trolltech.com/gpl/ for GPL licensing information. 13** See http://www.trolltech.com/gpl/ for GPL licensing information.
14** 14**
15** Contact info@trolltech.com if any conditions of this licensing are 15** Contact info@trolltech.com if any conditions of this licensing are
16** not clear to you. 16** not clear to you.
17** 17**
18**********************************************************************/ 18**********************************************************************/
19 19
20#ifndef __OCONTACT_H__ 20#ifndef __OCONTACT_H__
21#define __OCONTACT_H__ 21#define __OCONTACT_H__
22 22
23#include <opie/opimrecord.h> 23#include <opie/opimrecord.h>
24#include <qpe/recordfields.h> 24#include <qpe/recordfields.h>
25 25
26#include <qdatetime.h> 26#include <qdatetime.h>
27#include <qstringlist.h> 27#include <qstringlist.h>
28 28
29#if defined(QPC_TEMPLATEDLL) 29#if defined(QPC_TEMPLATEDLL)
30// MOC_SKIP_BEGIN 30// MOC_SKIP_BEGIN
31QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>; 31QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>;
32// MOC_SKIP_END 32// MOC_SKIP_END
33#endif 33#endif
34 34
35class OContactPrivate; 35class OContactPrivate;
36 36
37/** 37/**
38 * OContact class represents a specialised PIM Record for contacts. 38 * OContact class represents a specialised PIM Record for contacts.
39 * It does store all kind of persopn related information. 39 * It does store all kind of persopn related information.
40 * 40 *
41 * @short Contact Container 41 * @short Contact Container
42 * @author TT, Stefan Eiler, Holger Freyther 42 * @author TT, Stefan Eiler, Holger Freyther
43 */ 43 */
44class QPC_EXPORT OContact : public OPimRecord 44class QPC_EXPORT OContact : public OPimRecord
45{ 45{
46 friend class DataSet; 46 friend class DataSet;
47public: 47public:
48 OContact(); 48 OContact();
49 OContact( const QMap<int, QString> &fromMap ); 49 OContact( const QMap<int, QString> &fromMap );
50 virtual ~OContact(); 50 virtual ~OContact();
51 51
52 enum DateFormat{ 52 enum DateFormat{
53 Zip_City_State = 0, 53 Zip_City_State = 0,
54 City_State_Zip 54 City_State_Zip
55 }; 55 };
56 56
57 /* 57 /*
58 * do we need to inline them 58 * do we need to inline them
59 * if yes do we need to inline them this way? 59 * if yes do we need to inline them this way?
60 * -zecke 60 * -zecke
61 */ 61 */
62 void setTitle( const QString &v ) { replace( Qtopia::Title, v ); } 62 void setTitle( const QString &v ) { replace( Qtopia::Title, v ); }
63 void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); } 63 void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); }
64 void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); } 64 void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); }
65 void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); } 65 void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); }
66 void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); } 66 void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); }
67 void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); } 67 void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); }
68 void setFileAs(); 68 void setFileAs();
69 69
70 // default email address 70 // default email address
71 void setDefaultEmail( const QString &v ); 71 void setDefaultEmail( const QString &v );
72 // inserts email to list and ensure's doesn't already exist 72 // inserts email to list and ensure's doesn't already exist
73 void insertEmail( const QString &v ); 73 void insertEmail( const QString &v );
74 void removeEmail( const QString &v ); 74 void removeEmail( const QString &v );
75 void clearEmails(); 75 void clearEmails();
76 void insertEmails( const QStringList &v ); 76 void insertEmails( const QStringList &v );
77 77
78 // home 78 // home
79 void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); } 79 void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); }
80 void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); } 80 void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); }
81 void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); } 81 void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); }
82 void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); } 82 void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); }
83 void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); } 83 void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); }
84 void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); } 84 void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); }
85 void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); } 85 void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); }
86 void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); } 86 void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); }
87 void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); } 87 void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); }
88 88
89 // business 89 // business
90 void setCompany( const QString &v ) { replace( Qtopia::Company, v ); } 90 void setCompany( const QString &v ) { replace( Qtopia::Company, v ); }
91 void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); } 91 void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); }
92 void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); } 92 void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); }
93 void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); } 93 void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); }
94 void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); } 94 void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); }
95 void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); } 95 void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); }
96 void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); } 96 void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); }
97 void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); } 97 void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); }
98 void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); } 98 void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); }
99 void setOffice( const QString &v ) { replace( Qtopia::Office, v ); } 99 void setOffice( const QString &v ) { replace( Qtopia::Office, v ); }
100 void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); } 100 void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); }
101 void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); } 101 void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); }
102 void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); } 102 void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); }
103 void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); } 103 void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); }
104 void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); } 104 void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); }
105 void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); } 105 void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); }
106 void setManager( const QString &v ) { replace( Qtopia::Manager, v ); } 106 void setManager( const QString &v ) { replace( Qtopia::Manager, v ); }
107 107
108 // personal 108 // personal
109 void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); } 109 void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); }
110 void setGender( const QString &v ) { replace( Qtopia::Gender, v ); } 110 void setGender( const QString &v ) { replace( Qtopia::Gender, v ); }
111 void setBirthday( const QDate &v ); 111 void setBirthday( const QDate &v );
112 void setAnniversary( const QDate &v ); 112 void setAnniversary( const QDate &v );
113 void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); } 113 void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); }
114 void setChildren( const QString &v ); 114 void setChildren( const QString &v );
115 115
116 // other 116 // other
117 void setNotes( const QString &v ) { replace( Qtopia::Notes, v); } 117 void setNotes( const QString &v ) { replace( Qtopia::Notes, v); }
118 118
119 virtual bool match( const QRegExp &regexp ) const; 119 virtual bool match( const QRegExp &regexp ) const;
120 120
121// // custom 121// // custom
122// void setCustomField( const QString &key, const QString &v ) 122// void setCustomField( const QString &key, const QString &v )
123// { replace(Custom- + key, v ); } 123// { replace(Custom- + key, v ); }
124 124
125 // name 125 // name
126 QString fullName() const; 126 QString fullName() const;
127 QString title() const { return find( Qtopia::Title ); } 127 QString title() const { return find( Qtopia::Title ); }
128 QString firstName() const { return find( Qtopia::FirstName ); } 128 QString firstName() const { return find( Qtopia::FirstName ); }
129 QString middleName() const { return find( Qtopia::MiddleName ); } 129 QString middleName() const { return find( Qtopia::MiddleName ); }
130 QString lastName() const { return find( Qtopia::LastName ); } 130 QString lastName() const { return find( Qtopia::LastName ); }
131 QString suffix() const { return find( Qtopia::Suffix ); } 131 QString suffix() const { return find( Qtopia::Suffix ); }
132 QString fileAs() const { return find( Qtopia::FileAs ); } 132 QString fileAs() const { return find( Qtopia::FileAs ); }
133 133
134 // email 134 // email
135 QString defaultEmail() const { return find( Qtopia::DefaultEmail ); } 135 QString defaultEmail() const { return find( Qtopia::DefaultEmail ); }
136 QStringList emailList() const; 136 QStringList emailList() const;
137 137
138 // home 138 // home
139 /* 139 /*
140 * OPimAddress address(enum Location)const; 140 * OPimAddress address(enum Location)const;
141 * would be some how nicer... 141 * would be some how nicer...
142 * -zecke 142 * -zecke
143 */ 143 */
144 QString homeStreet() const { return find( Qtopia::HomeStreet ); } 144 QString homeStreet() const { return find( Qtopia::HomeStreet ); }
145 QString homeCity() const { return find( Qtopia::HomeCity ); } 145 QString homeCity() const { return find( Qtopia::HomeCity ); }
146 QString homeState() const { return find( Qtopia::HomeState ); } 146 QString homeState() const { return find( Qtopia::HomeState ); }
147 QString homeZip() const { return find( Qtopia::HomeZip ); } 147 QString homeZip() const { return find( Qtopia::HomeZip ); }
148 QString homeCountry() const { return find( Qtopia::HomeCountry ); } 148 QString homeCountry() const { return find( Qtopia::HomeCountry ); }
149 QString homePhone() const { return find( Qtopia::HomePhone ); } 149 QString homePhone() const { return find( Qtopia::HomePhone ); }
150 QString homeFax() const { return find( Qtopia::HomeFax ); } 150 QString homeFax() const { return find( Qtopia::HomeFax ); }
151 QString homeMobile() const { return find( Qtopia::HomeMobile ); } 151 QString homeMobile() const { return find( Qtopia::HomeMobile ); }
152 QString homeWebpage() const { return find( Qtopia::HomeWebPage ); } 152 QString homeWebpage() const { return find( Qtopia::HomeWebPage ); }
153 /** Multi line string containing all non-empty address info in the form 153 /** Multi line string containing all non-empty address info in the form
154 * Street 154 * Street
155 * City, State Zip 155 * City, State Zip
156 * Country 156 * Country
157 */ 157 */
158 QString displayHomeAddress() const; 158 QString displayHomeAddress() const;
159 159
160 // business 160 // business
161 QString company() const { return find( Qtopia::Company ); } 161 QString company() const { return find( Qtopia::Company ); }
162 QString businessStreet() const { return find( Qtopia::BusinessStreet ); } 162 QString businessStreet() const { return find( Qtopia::BusinessStreet ); }
163 QString businessCity() const { return find( Qtopia::BusinessCity ); } 163 QString businessCity() const { return find( Qtopia::BusinessCity ); }
164 QString businessState() const { return find( Qtopia::BusinessState ); } 164 QString businessState() const { return find( Qtopia::BusinessState ); }
165 QString businessZip() const { return find( Qtopia::BusinessZip ); } 165 QString businessZip() const { return find( Qtopia::BusinessZip ); }
166 QString businessCountry() const { return find( Qtopia::BusinessCountry ); } 166 QString businessCountry() const { return find( Qtopia::BusinessCountry ); }
167 QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); } 167 QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); }
168 QString jobTitle() const { return find( Qtopia::JobTitle ); } 168 QString jobTitle() const { return find( Qtopia::JobTitle ); }
169 QString department() const { return find( Qtopia::Department ); } 169 QString department() const { return find( Qtopia::Department ); }
170 QString office() const { return find( Qtopia::Office ); } 170 QString office() const { return find( Qtopia::Office ); }
171 QString businessPhone() const { return find( Qtopia::BusinessPhone ); } 171 QString businessPhone() const { return find( Qtopia::BusinessPhone ); }
172 QString businessFax() const { return find( Qtopia::BusinessFax ); } 172 QString businessFax() const { return find( Qtopia::BusinessFax ); }
173 QString businessMobile() const { return find( Qtopia::BusinessMobile ); } 173 QString businessMobile() const { return find( Qtopia::BusinessMobile ); }
174 QString businessPager() const { return find( Qtopia::BusinessPager ); } 174 QString businessPager() const { return find( Qtopia::BusinessPager ); }
175 QString profession() const { return find( Qtopia::Profession ); } 175 QString profession() const { return find( Qtopia::Profession ); }
176 QString assistant() const { return find( Qtopia::Assistant ); } 176 QString assistant() const { return find( Qtopia::Assistant ); }
177 QString manager() const { return find( Qtopia::Manager ); } 177 QString manager() const { return find( Qtopia::Manager ); }
178 /** Multi line string containing all non-empty address info in the form 178 /** Multi line string containing all non-empty address info in the form
179 * Street 179 * Street
180 * City, State Zip 180 * City, State Zip
181 * Country 181 * Country
182 */ 182 */
183 QString displayBusinessAddress() const; 183 QString displayBusinessAddress() const;
184 184
185 //personal 185 //personal
186 QString spouse() const { return find( Qtopia::Spouse ); } 186 QString spouse() const { return find( Qtopia::Spouse ); }
187 QString gender() const { return find( Qtopia::Gender ); } 187 QString gender() const { return find( Qtopia::Gender ); }
188 QDate birthday() const; 188 QDate birthday() const;
189 QDate anniversary() const; 189 QDate anniversary() const;
190 QString nickname() const { return find( Qtopia::Nickname ); } 190 QString nickname() const { return find( Qtopia::Nickname ); }
191 QString children() const { return find( Qtopia::Children ); } 191 QString children() const { return find( Qtopia::Children ); }
192 QStringList childrenList() const; 192 QStringList childrenList() const;
193 193
194 // other 194 // other
195 QString notes() const { return find( Qtopia::Notes ); } 195 QString notes() const { return find( Qtopia::Notes ); }
196 QString groups() const { return find( Qtopia::Groups ); } 196 QString groups() const { return find( Qtopia::Groups ); }
197 QStringList groupList() const; 197 QStringList groupList() const;
198 198
199// // custom
200// const QString &customField( const QString &key )
201// { return find( Custom- + key ); }
202
203
204 QString toRichText() const; 199 QString toRichText() const;
205 QMap<int, QString> toMap() const; 200 QMap<int, QString> toMap() const;
206 QString field( int key ) const { return find( key ); } 201 QString field( int key ) const { return find( key ); }
207 202
208 203
209 void setUid( int i ); 204 void setUid( int i );
210 205
211 QString toShortText()const; 206 QString toShortText()const;
212 QString OContact::type()const; 207 QString type()const;
213 QMap<QString,QString> OContact::toExtraMap() const; 208 class QString recordField(int) const;
214 class QString OContact::recordField(int) const;
215 209
216 // Why private ? (eilers,se) 210 // Why private ? (eilers,se)
217 QString emailSeparator() const { return " "; } 211 QString emailSeparator() const { return " "; }
212
218 // the emails should be seperated by a comma 213 // the emails should be seperated by a comma
219 void setEmails( const QString &v ); 214 void setEmails( const QString &v );
220 QString emails() const { return find( Qtopia::Emails ); } 215 QString emails() const { return find( Qtopia::Emails ); }
221 static int rtti(); 216 static int rtti();
222 217
223private: 218private:
224 // The XML-Backend needs some access to the private functions 219 // The XML Backend needs some access to the private functions
225 friend class OContactAccessBackend_XML; 220 friend class OContactAccessBackend_XML;
226 221
227 void insert( int key, const QString &value ); 222 void insert( int key, const QString &value );
228 void replace( int key, const QString &value ); 223 void replace( int key, const QString &value );
229 QString find( int key ) const; 224 QString find( int key ) const;
230 static QStringList fields(); 225 static QStringList fields();
231 226
232 void save( QString &buf ) const; 227 void save( QString &buf ) const;
233 228
234 QString displayAddress( const QString &street, 229 QString displayAddress( const QString &street,
235 const QString &city, 230 const QString &city,
236 const QString &state, 231 const QString &state,
237 const QString &zip, 232 const QString &zip,
238 const QString &country ) const; 233 const QString &country ) const;
239 234
240 QMap<int, QString> mMap; 235 QMap<int, QString> mMap;
241 OContactPrivate *d; 236 OContactPrivate *d;
242}; 237};
243 238
244 239
245#endif 240#endif
diff --git a/libopie/pim/ocontactaccessbackend_sql.cpp b/libopie/pim/ocontactaccessbackend_sql.cpp
new file mode 100644
index 0000000..4afa5f3
--- a/dev/null
+++ b/libopie/pim/ocontactaccessbackend_sql.cpp
@@ -0,0 +1,664 @@
1/*
2 * SQL Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * =====================================================================
13 * Version: $Id$
14 * =====================================================================
15 * History:
16 * $Log$
17 * Revision 1.1 2003/09/22 14:31:16 eilers
18 * Added first experimental incarnation of sql-backend for addressbook.
19 * Some modifications to be able to compile the todo sql-backend.
20 * A lot of changes fill follow...
21 *
22 */
23
24#include "ocontactaccessbackend_sql.h"
25
26#include <qarray.h>
27#include <qdatetime.h>
28#include <qstringlist.h>
29
30#include <qpe/global.h>
31#include <qpe/recordfields.h>
32
33#include <opie/ocontactfields.h>
34#include <opie/oconversion.h>
35#include <opie2/osqldriver.h>
36#include <opie2/osqlresult.h>
37#include <opie2/osqlmanager.h>
38#include <opie2/osqlquery.h>
39
40/*
41 * Implementation of used query types
42 * CREATE query
43 * LOAD query
44 * INSERT
45 * REMOVE
46 * CLEAR
47 */
48namespace {
49 /**
50 * CreateQuery for the Todolist Table
51 */
52 class CreateQuery : public OSQLQuery {
53 public:
54 CreateQuery();
55 ~CreateQuery();
56 QString query()const;
57 };
58
59 /**
60 * Clears (delete) a Table
61 */
62 class ClearQuery : public OSQLQuery {
63 public:
64 ClearQuery();
65 ~ClearQuery();
66 QString query()const;
67
68 };
69
70
71 /**
72 * LoadQuery
73 * this one queries for all uids
74 */
75 class LoadQuery : public OSQLQuery {
76 public:
77 LoadQuery();
78 ~LoadQuery();
79 QString query()const;
80 };
81
82 /**
83 * inserts/adds a OContact to the table
84 */
85 class InsertQuery : public OSQLQuery {
86 public:
87 InsertQuery(const OContact& );
88 ~InsertQuery();
89 QString query()const;
90 private:
91 OContact m_contact;
92 };
93
94
95 /**
96 * removes one from the table
97 */
98 class RemoveQuery : public OSQLQuery {
99 public:
100 RemoveQuery(int uid );
101 ~RemoveQuery();
102 QString query()const;
103 private:
104 int m_uid;
105 };
106
107 /**
108 * a find query for noncustom elements
109 */
110 class FindQuery : public OSQLQuery {
111 public:
112 FindQuery(int uid);
113 FindQuery(const QArray<int>& );
114 ~FindQuery();
115 QString query()const;
116 private:
117 QString single()const;
118 QString multi()const;
119 QArray<int> m_uids;
120 int m_uid;
121 };
122
123 /**
124 * a find query for custom elements
125 */
126 class FindCustomQuery : public OSQLQuery {
127 public:
128 FindCustomQuery(int uid);
129 FindCustomQuery(const QArray<int>& );
130 ~FindCustomQuery();
131 QString query()const;
132 private:
133 QString single()const;
134 QString multi()const;
135 QArray<int> m_uids;
136 int m_uid;
137 };
138
139
140
141 // We using three tables to store the information:
142 // 1. addressbook : It contains General information about the contact (non custom)
143 // 2. dates : Stuff like birthdays, anniversaries, etc.
144 // 3. custom_data : Not official supported entries
145 // All tables are connected by the uid of the contact.
146 // Maybe I should add a table for meta-information ?
147 CreateQuery::CreateQuery() : OSQLQuery() {}
148 CreateQuery::~CreateQuery() {}
149 QString CreateQuery::query()const {
150 QString qu;
151 qu += "create table addressbook( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id));";
152 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
153 // qu += "create table dates( uid PRIMARY KEY, type, day, month, year, hour, minute, second );";
154 return qu;
155 }
156
157 ClearQuery::ClearQuery()
158 : OSQLQuery() {}
159 ClearQuery::~ClearQuery() {}
160 QString ClearQuery::query()const {
161 QString qu = "drop table addressbook;";
162 qu += "drop table custom_data;";
163 qu += "drop table dates;";
164 return qu;
165 }
166
167// Distinct loading is not very fast. If I expect that every person has just
168// one (and always one) 'Last Name', I can request all uid's for existing lastnames,
169// which is faster..
170// But this may not be true for all entries, like company contacts..
171// The current AddressBook application handles this problem, but other may not.. (eilers)
172#define __USE_SUPERFAST_LOADQUERY
173
174 LoadQuery::LoadQuery() : OSQLQuery() {}
175 LoadQuery::~LoadQuery() {}
176 QString LoadQuery::query()const {
177 QString qu;
178#ifndef __USE_SUPERFAST_LOADQUERY
179 qu += "select distinct uid from addressbook";
180#else
181 qu += "select uid from addressbook where type = 'Last Name'";
182#endif
183
184 return qu;
185 }
186
187
188 InsertQuery::InsertQuery( const OContact& contact )
189 : OSQLQuery(), m_contact( contact ) {
190 }
191
192 InsertQuery::~InsertQuery() {
193 }
194
195 /*
196 * converts from a OContact to a query
197 */
198 QString InsertQuery::query()const{
199
200 // Get all information out of the contact-class
201 // Remember: The category is stored in contactMap, too !
202 QMap<int, QString> contactMap = m_contact.toMap();
203 QMap<QString, QString> customMap = m_contact.toExtraMap();
204
205 QMap<QString, QString> addressbook_db;
206
207 // Get the translation from the ID to the String
208 QMap<int, QString> transMap = OContactFields::idToUntrFields();
209
210 for( QMap<int, QString>::Iterator it = contactMap.begin();
211 it != contactMap.end(); ++it ){
212 switch ( it.key() ){
213 case Qtopia::Birthday:{
214 // These entries should stored in a special format
215 // year-month-day
216 QDate day = m_contact.birthday();
217 addressbook_db.insert( transMap[it.key()],
218 QString("%1-%2-%3")
219 .arg( day.year() )
220 .arg( day.month() )
221 .arg( day.day() ) );
222 }
223 break;
224 case Qtopia::Anniversary:{
225 // These entries should stored in a special format
226 // year-month-day
227 QDate day = m_contact.anniversary();
228 addressbook_db.insert( transMap[it.key()],
229 QString("%1-%2-%3")
230 .arg( day.year() )
231 .arg( day.month() )
232 .arg( day.day() ) );
233 }
234 break;
235 case Qtopia::AddressUid: // Ignore UID
236 break;
237 default: // Translate id to String
238 addressbook_db.insert( transMap[it.key()], it.data() );
239 break;
240 }
241
242 }
243
244 // Now convert this whole stuff into a SQL String, beginning with
245 // the addressbook table..
246 QString qu;
247 // qu += "begin transaction;";
248 int id = 0;
249 for( QMap<QString, QString>::Iterator it = addressbook_db.begin();
250 it != addressbook_db.end(); ++it ){
251 qu += "insert into addressbook VALUES("
252 + QString::number( m_contact.uid() )
253 + ","
254 + QString::number( id++ )
255 + ",'"
256 + it.key() //.latin1()
257 + "',"
258 + "0" // Priority for future enhancements
259 + ",'"
260 + it.data() //.latin1()
261 + "');";
262 }
263
264 // Now add custom data..
265 id = 0;
266 for( QMap<QString, QString>::Iterator it = customMap.begin();
267 it != customMap.end(); ++it ){
268 qu += "insert into custom_data VALUES("
269 + QString::number( m_contact.uid() )
270 + ","
271 + QString::number( id++ )
272 + ",'"
273 + it.key() //.latin1()
274 + "',"
275 + "0" // Priority for future enhancements
276 + ",'"
277 + it.data() //.latin1()
278 + "');";
279 }
280
281 // qu += "commit;";
282 qWarning("add %s", qu.latin1() );
283 return qu;
284 }
285
286
287 RemoveQuery::RemoveQuery(int uid )
288 : OSQLQuery(), m_uid( uid ) {}
289 RemoveQuery::~RemoveQuery() {}
290 QString RemoveQuery::query()const {
291 QString qu = "DELETE from addressbook where uid = "
292 + QString::number(m_uid) + ";";
293 qu += "DELETE from dates where uid = "
294 + QString::number(m_uid) + ";";
295 qu += "DELETE from custom_data where uid = "
296 + QString::number(m_uid) + ";";
297 return qu;
298 }
299
300
301
302
303 FindQuery::FindQuery(int uid)
304 : OSQLQuery(), m_uid( uid ) {
305 }
306 FindQuery::FindQuery(const QArray<int>& ints)
307 : OSQLQuery(), m_uids( ints ){
308 }
309 FindQuery::~FindQuery() {
310 }
311 QString FindQuery::query()const{
312 // if ( m_uids.count() == 0 )
313 return single();
314 }
315 /*
316 else
317 return multi();
318 }
319 QString FindQuery::multi()const {
320 QString qu = "select uid, type, value from addressbook where";
321 for (uint i = 0; i < m_uids.count(); i++ ) {
322 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
323 }
324 qu.remove( qu.length()-2, 2 ); // Hmmmm..
325 return qu;
326 }
327 */
328 QString FindQuery::single()const{
329 QString qu = "select uid, type, value from addressbook where uid = ";
330 qu += QString::number(m_uid);
331 return qu;
332 }
333
334
335 FindCustomQuery::FindCustomQuery(int uid)
336 : OSQLQuery(), m_uid( uid ) {
337 }
338 FindCustomQuery::FindCustomQuery(const QArray<int>& ints)
339 : OSQLQuery(), m_uids( ints ){
340 }
341 FindCustomQuery::~FindCustomQuery() {
342 }
343 QString FindCustomQuery::query()const{
344 // if ( m_uids.count() == 0 )
345 return single();
346 }
347 QString FindCustomQuery::single()const{
348 QString qu = "select uid, type, value from custom_data where uid = ";
349 qu += QString::number(m_uid);
350 return qu;
351 }
352
353};
354
355
356/* --------------------------------------------------------------------------- */
357
358OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */,
359 const QString& filename ): m_changed(false)
360{
361 qWarning("C'tor OContactAccessBackend_SQL starts");
362 QTime t;
363 t.start();
364
365 /* Expecting to access the default filename if nothing else is set */
366 if ( filename.isEmpty() ){
367 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
368 } else
369 m_fileName = filename;
370
371 // Get the standart sql-driver from the OSQLManager..
372 OSQLManager man;
373 m_driver = man.standard();
374 m_driver->setUrl( m_fileName );
375
376 load();
377
378 qWarning("C'tor OContactAccessBackend_SQL ends: %d", t.elapsed() );
379}
380
381
382bool OContactAccessBackend_SQL::load ()
383{
384 if (!m_driver->open() )
385 return false;
386
387 // Don't expect that the database exists.
388 // It is save here to create the table, even if it
389 // do exist. ( Is that correct for all databases ?? )
390 CreateQuery creat;
391 OSQLResult res = m_driver->query( &creat );
392
393 update();
394
395 return true;
396
397}
398
399bool OContactAccessBackend_SQL::reload()
400{
401 return load();
402}
403
404bool OContactAccessBackend_SQL::save()
405{
406 return m_driver->close();
407}
408
409
410void OContactAccessBackend_SQL::clear ()
411{
412 ClearQuery cle;
413 OSQLResult res = m_driver->query( &cle );
414 CreateQuery qu;
415 res = m_driver->query(&qu);
416}
417
418bool OContactAccessBackend_SQL::wasChangedExternally()
419{
420 return false;
421}
422
423QArray<int> OContactAccessBackend_SQL::allRecords() const
424{
425
426 // FIXME: Think about cute handling of changed tables..
427 // Thus, we don't have to call update here...
428 if ( m_changed )
429 ((OContactAccessBackend_SQL*)this)->update();
430
431 return m_uids;
432}
433
434bool OContactAccessBackend_SQL::add ( const OContact &newcontact )
435{
436 InsertQuery ins( newcontact );
437 OSQLResult res = m_driver->query( &ins );
438
439 if ( res.state() == OSQLResult::Failure )
440 return false;
441
442 int c = m_uids.count();
443 m_uids.resize( c+1 );
444 m_uids[c] = newcontact.uid();
445
446 return true;
447}
448
449
450bool OContactAccessBackend_SQL::remove ( int uid )
451{
452 RemoveQuery rem( uid );
453 OSQLResult res = m_driver->query(&rem );
454
455 if ( res.state() == OSQLResult::Failure )
456 return false;
457
458 m_changed = true;
459
460 return true;
461}
462
463bool OContactAccessBackend_SQL::replace ( const OContact &contact )
464{
465 if ( !remove( contact.uid() ) )
466 return false;
467
468 return add( contact );
469}
470
471
472OContact OContactAccessBackend_SQL::find ( int uid ) const
473{
474 qWarning("OContactAccessBackend_SQL::find()");
475 QTime t;
476 t.start();
477
478 OContact retContact( requestNonCustom( uid ) );
479 retContact.setExtraMap( requestCustom( uid ) );
480
481 qWarning("OContactAccessBackend_SQL::find() needed: %d", t.elapsed() );
482 return retContact;
483}
484
485
486
487QArray<int> OContactAccessBackend_SQL::queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() )
488{
489 QArray<int> nix(0);
490 return nix;
491}
492
493QArray<int> OContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
494{
495 QArray<int> nix(0);
496 return nix;
497}
498
499const uint OContactAccessBackend_SQL::querySettings()
500{
501 return 0;
502}
503
504bool OContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const
505{
506 return false;
507}
508
509QArray<int> OContactAccessBackend_SQL::sorted( bool asc, int , int , int )
510{
511 QTime t;
512 t.start();
513
514 // Not implemented..
515 QString query = "SELECT uid FROM addressbook WHERE type = 'Last Name' ";
516
517 query += "ORDER BY value ";
518 if ( !asc )
519 query += "DESC";
520
521 qWarning("sorted query is: %s", query.latin1() );
522
523 OSQLRawQuery raw( query );
524 OSQLResult res = m_driver->query( &raw );
525 if ( res.state() != OSQLResult::Success ){
526 QArray<int> empty;
527 return empty;
528 }
529
530 QArray<int> list = extractUids( res );
531
532 qWarning("sorted needed %d ms!", t.elapsed() );
533 return list;
534}
535
536
537void OContactAccessBackend_SQL::update()
538{
539 qWarning("Update starts");
540 QTime t;
541 t.start();
542
543 // Now load the database set and extract the uid's
544 // which will be held locally
545
546 LoadQuery lo;
547 OSQLResult res = m_driver->query(&lo);
548 if ( res.state() != OSQLResult::Success )
549 return;
550
551 m_uids = extractUids( res );
552
553 m_changed = false;
554
555 qWarning("Update ends %d", t.elapsed() );
556}
557
558QArray<int> OContactAccessBackend_SQL::extractUids( OSQLResult& res ) const
559{
560 qWarning("extractUids");
561 QTime t;
562 t.start();
563 OSQLResultItem::ValueList list = res.results();
564 OSQLResultItem::ValueList::Iterator it;
565 QArray<int> ints(list.count() );
566 qWarning(" count = %d", list.count() );
567
568 int i = 0;
569 for (it = list.begin(); it != list.end(); ++it ) {
570 ints[i] = (*it).data("uid").toInt();
571 i++;
572 }
573 qWarning("extractUids ready: count2 = %d needs %d ms", i, t.elapsed() );
574
575 return ints;
576
577}
578
579QMap<int, QString> OContactAccessBackend_SQL::requestNonCustom( int uid ) const
580{
581 QTime t;
582 t.start();
583
584 QMap<int, QString> nonCustomMap;
585
586 int t2needed = 0;
587 QTime t2;
588 t2.start();
589 FindQuery query( uid );
590 OSQLResult res_noncustom = m_driver->query( &query );
591 t2needed = t2.elapsed();
592
593 if ( res_noncustom.state() == OSQLResult::Failure ) {
594 qWarning("OSQLResult::Failure in find query !!");
595 QMap<int, QString> empty;
596 return empty;
597 }
598
599 int t3needed = 0;
600 QTime t3;
601 t3.start();
602 QMap<QString, int> translateMap = OContactFields::untrFieldsToId();
603
604 OSQLResultItem::ValueList list = res_noncustom.results();
605 OSQLResultItem::ValueList::Iterator it = list.begin();
606 for ( ; it != list.end(); ++it ) {
607 if ( (*it).data("type") != "" ){
608 int typeId = translateMap[(*it).data( "type" )];
609 switch( typeId ){
610 case Qtopia::Birthday:
611 case Qtopia::Anniversary:{
612 // Birthday and Anniversary are encoded special ( yyyy-mm-dd )
613 QStringList list = QStringList::split( '-', (*it).data( "value" ) );
614 QStringList::Iterator lit = list.begin();
615 int year = (*lit).toInt();
616 qWarning("1. %s", (*lit).latin1());
617 int month = (*(++lit)).toInt();
618 qWarning("2. %s", (*lit).latin1());
619 int day = (*(++lit)).toInt();
620 qWarning("3. %s", (*lit).latin1());
621 qWarning( "RequestNonCustom->Converting:%s to Year: %d, Month: %d, Day: %d ", (*it).data( "value" ).latin1(), year, month, day );
622 QDate date( year, month, day );
623 nonCustomMap.insert( typeId, OConversion::dateToString( date ) );
624 }
625 break;
626 default:
627 nonCustomMap.insert( typeId,
628 (*it).data( "value" ) );
629 }
630 }
631 }
632 // Add UID to Map..
633 nonCustomMap.insert( Qtopia::AddressUid, QString::number( uid ) );
634 t3needed = t3.elapsed();
635
636 qWarning("RequestNonCustom needed: ins:%d, query: %d, mapping: %d", t.elapsed(), t2needed, t3needed );
637 return nonCustomMap;
638}
639
640QMap<QString, QString> OContactAccessBackend_SQL::requestCustom( int uid ) const
641{
642 QTime t;
643 t.start();
644
645 QMap<QString, QString> customMap;
646
647 FindCustomQuery query( uid );
648 OSQLResult res_custom = m_driver->query( &query );
649
650 if ( res_custom.state() == OSQLResult::Failure ) {
651 qWarning("OSQLResult::Failure in find query !!");
652 QMap<QString, QString> empty;
653 return empty;
654 }
655
656 OSQLResultItem::ValueList list = res_custom.results();
657 OSQLResultItem::ValueList::Iterator it = list.begin();
658 for ( ; it != list.end(); ++it ) {
659 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) );
660 }
661
662 qWarning("RequestCustom needed: %d", t.elapsed() );
663 return customMap;
664}
diff --git a/libopie/pim/ocontactaccessbackend_sql.h b/libopie/pim/ocontactaccessbackend_sql.h
new file mode 100644
index 0000000..bb22551
--- a/dev/null
+++ b/libopie/pim/ocontactaccessbackend_sql.h
@@ -0,0 +1,96 @@
1/*
2 * SQL Backend for the OPIE-Contact Database.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 *
13 *
14 * =====================================================================
15 * Version: $Id$
16 * =====================================================================
17 * History:
18 * $Log$
19 * Revision 1.1 2003/09/22 14:31:16 eilers
20 * Added first experimental incarnation of sql-backend for addressbook.
21 * Some modifications to be able to compile the todo sql-backend.
22 * A lot of changes fill follow...
23 *
24 *
25 */
26
27#ifndef _OContactAccessBackend_SQL_
28#define _OContactAccessBackend_SQL_
29
30#include "ocontactaccessbackend.h"
31#include "ocontactaccess.h"
32
33#include <qlist.h>
34#include <qdict.h>
35
36class OSQLDriver;
37class OSQLResult;
38class OSQLResultItem;
39
40/* the default xml implementation */
41/**
42 * This class is the SQL implementation of a Contact backend
43 * it does implement everything available for OContact.
44 * @see OPimAccessBackend for more information of available methods
45 */
46class OContactAccessBackend_SQL : public OContactAccessBackend {
47 public:
48 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null );
49
50 bool save();
51
52 bool load ();
53
54 void clear ();
55
56 bool wasChangedExternally();
57
58 QArray<int> allRecords() const;
59
60 OContact find ( int uid ) const;
61 // FIXME: Add lookahead-cache support !
62 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
63
64 QArray<int> queryByExample ( const OContact &query, int settings,
65 const QDateTime& d );
66
67 QArray<int> matchRegexp( const QRegExp &r ) const;
68
69 const uint querySettings();
70
71 bool hasQuerySettings (uint querySettings) const;
72
73 // Currently only asc implemented..
74 QArray<int> sorted( bool asc, int , int , int );
75 bool add ( const OContact &newcontact );
76
77 bool replace ( const OContact &contact );
78
79 bool remove ( int uid );
80 bool reload();
81
82 private:
83 QArray<int> extractUids( OSQLResult& res ) const;
84 QMap<int, QString> requestNonCustom( int uid ) const;
85 QMap<QString, QString> requestCustom( int uid ) const;
86 void update();
87
88 protected:
89 bool m_changed;
90 QString m_fileName;
91 QArray<int> m_uids;
92
93 OSQLDriver* m_driver;
94};
95
96#endif
diff --git a/libopie/pim/ocontactaccessbackend_xml.cpp b/libopie/pim/ocontactaccessbackend_xml.cpp
index 1b5af2f..aae7fca 100644
--- a/libopie/pim/ocontactaccessbackend_xml.cpp
+++ b/libopie/pim/ocontactaccessbackend_xml.cpp
@@ -1,817 +1,820 @@
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...
13 *
14 * 12 *
15 * ===================================================================== 13 * =====================================================================
16 * Version: $Id$ 14 * Version: $Id$
17 * ===================================================================== 15 * =====================================================================
18 * History: 16 * History:
19 * $Log$ 17 * $Log$
18 * Revision 1.9 2003/09/22 14:31:16 eilers
19 * Added first experimental incarnation of sql-backend for addressbook.
20 * Some modifications to be able to compile the todo sql-backend.
21 * A lot of changes fill follow...
22 *
20 * Revision 1.8 2003/08/30 15:28:26 eilers 23 * Revision 1.8 2003/08/30 15:28:26 eilers
21 * Removed some unimportant debug output which causes slow down.. 24 * Removed some unimportant debug output which causes slow down..
22 * 25 *
23 * Revision 1.7 2003/08/01 12:30:16 eilers 26 * Revision 1.7 2003/08/01 12:30:16 eilers
24 * Merging changes from BRANCH_1_0 to HEAD 27 * Merging changes from BRANCH_1_0 to HEAD
25 * 28 *
26 * Revision 1.6 2003/07/07 16:19:47 eilers 29 * Revision 1.6 2003/07/07 16:19:47 eilers
27 * Fixing serious bug in hasQuerySettings() 30 * Fixing serious bug in hasQuerySettings()
28 * 31 *
29 * Revision 1.5 2003/04/13 18:07:10 zecke 32 * Revision 1.5 2003/04/13 18:07:10 zecke
30 * More API doc 33 * More API doc
31 * QString -> const QString& 34 * QString -> const QString&
32 * QString = 0l -> QString::null 35 * QString = 0l -> QString::null
33 * 36 *
34 * Revision 1.4 2003/03/21 14:32:54 mickeyl 37 * Revision 1.4 2003/03/21 14:32:54 mickeyl
35 * g++ compliance fix: default arguments belong into the declaration, but not the definition 38 * g++ compliance fix: default arguments belong into the declaration, but not the definition
36 * 39 *
37 * Revision 1.3 2003/03/21 12:26:28 eilers 40 * Revision 1.3 2003/03/21 12:26:28 eilers
38 * Fixing small bug: If we search a birthday from today to today, it returned 41 * Fixing small bug: If we search a birthday from today to today, it returned
39 * every contact .. 42 * every contact ..
40 * 43 *
41 * Revision 1.2 2003/03/21 10:33:09 eilers 44 * Revision 1.2 2003/03/21 10:33:09 eilers
42 * Merged speed optimized xml backend for contacts to main. 45 * Merged speed optimized xml backend for contacts to main.
43 * Added QDateTime to querybyexample. For instance, it is now possible to get 46 * Added QDateTime to querybyexample. For instance, it is now possible to get
44 * all Birthdays/Anniversaries between two dates. This should be used 47 * all Birthdays/Anniversaries between two dates. This should be used
45 * to show all birthdays in the datebook.. 48 * to show all birthdays in the datebook..
46 * This change is sourcecode backward compatible but you have to upgrade 49 * This change is sourcecode backward compatible but you have to upgrade
47 * the binaries for today-addressbook. 50 * the binaries for today-addressbook.
48 * 51 *
49 * Revision 1.1.2.2 2003/02/11 12:17:28 eilers 52 * Revision 1.1.2.2 2003/02/11 12:17:28 eilers
50 * Speed optimization. Removed the sequential search loops. 53 * Speed optimization. Removed the sequential search loops.
51 * 54 *
52 * Revision 1.1.2.1 2003/02/10 15:31:38 eilers 55 * Revision 1.1.2.1 2003/02/10 15:31:38 eilers
53 * Writing offsets to debug output.. 56 * Writing offsets to debug output..
54 * 57 *
55 * Revision 1.1 2003/02/09 15:05:01 eilers 58 * Revision 1.1 2003/02/09 15:05:01 eilers
56 * Nothing happened.. Just some cleanup before I will start.. 59 * Nothing happened.. Just some cleanup before I will start..
57 * 60 *
58 * Revision 1.12 2003/01/03 16:58:03 eilers 61 * Revision 1.12 2003/01/03 16:58:03 eilers
59 * Reenable debug output 62 * Reenable debug output
60 * 63 *
61 * Revision 1.11 2003/01/03 12:31:28 eilers 64 * Revision 1.11 2003/01/03 12:31:28 eilers
62 * Bugfix for calculating data diffs.. 65 * Bugfix for calculating data diffs..
63 * 66 *
64 * Revision 1.10 2003/01/02 14:27:12 eilers 67 * Revision 1.10 2003/01/02 14:27:12 eilers
65 * Improved query by example: Search by date is possible.. First step 68 * Improved query by example: Search by date is possible.. First step
66 * for a today plugin for birthdays.. 69 * for a today plugin for birthdays..
67 * 70 *
68 * Revision 1.9 2002/12/08 12:48:57 eilers 71 * Revision 1.9 2002/12/08 12:48:57 eilers
69 * Moved journal-enum from ocontact into i the xml-backend.. 72 * Moved journal-enum from ocontact into i the xml-backend..
70 * 73 *
71 * Revision 1.8 2002/11/14 17:04:24 eilers 74 * Revision 1.8 2002/11/14 17:04:24 eilers
72 * Sorting will now work if fullname is identical on some entries 75 * Sorting will now work if fullname is identical on some entries
73 * 76 *
74 * Revision 1.7 2002/11/13 15:02:46 eilers 77 * Revision 1.7 2002/11/13 15:02:46 eilers
75 * Small Bug in sorted fixed 78 * Small Bug in sorted fixed
76 * 79 *
77 * Revision 1.6 2002/11/13 14:14:51 eilers 80 * Revision 1.6 2002/11/13 14:14:51 eilers
78 * Added sorted for Contacts.. 81 * Added sorted for Contacts..
79 * 82 *
80 * Revision 1.5 2002/11/01 15:10:42 eilers 83 * Revision 1.5 2002/11/01 15:10:42 eilers
81 * Added regExp-search in database for all fields in a contact. 84 * Added regExp-search in database for all fields in a contact.
82 * 85 *
83 * Revision 1.4 2002/10/16 10:52:40 eilers 86 * Revision 1.4 2002/10/16 10:52:40 eilers
84 * Added some docu to the interface and now using the cache infrastucture by zecke.. :) 87 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
85 * 88 *
86 * Revision 1.3 2002/10/14 16:21:54 eilers 89 * Revision 1.3 2002/10/14 16:21:54 eilers
87 * Some minor interface updates 90 * Some minor interface updates
88 * 91 *
89 * Revision 1.2 2002/10/07 17:34:24 eilers 92 * Revision 1.2 2002/10/07 17:34:24 eilers
90 * added OBackendFactory for advanced backend access 93 * added OBackendFactory for advanced backend access
91 * 94 *
92 * Revision 1.1 2002/09/27 17:11:44 eilers 95 * Revision 1.1 2002/09/27 17:11:44 eilers
93 * Added API for accessing the Contact-Database ! It is compiling, but 96 * Added API for accessing the Contact-Database ! It is compiling, but
94 * please do not expect that anything is working ! 97 * please do not expect that anything is working !
95 * I will debug that stuff in the next time .. 98 * I will debug that stuff in the next time ..
96 * Please read README_COMPILE for compiling ! 99 * Please read README_COMPILE for compiling !
97 * 100 *
98 * 101 *
99 */ 102 */
100 103
101#include "ocontactaccessbackend_xml.h" 104#include "ocontactaccessbackend_xml.h"
102 105
103#include <qasciidict.h> 106#include <qasciidict.h>
104#include <qdatetime.h> 107#include <qdatetime.h>
105#include <qfile.h> 108#include <qfile.h>
106#include <qfileinfo.h> 109#include <qfileinfo.h>
107#include <qregexp.h> 110#include <qregexp.h>
108#include <qarray.h> 111#include <qarray.h>
109#include <qmap.h> 112#include <qmap.h>
110#include <qdatetime.h> 113#include <qdatetime.h>
111 114
112#include <qpe/global.h> 115#include <qpe/global.h>
113 116
114#include <opie/xmltree.h> 117#include <opie/xmltree.h>
115#include "ocontactaccessbackend.h" 118#include "ocontactaccessbackend.h"
116#include "ocontactaccess.h" 119#include "ocontactaccess.h"
117 120
118#include <stdlib.h> 121#include <stdlib.h>
119#include <errno.h> 122#include <errno.h>
120 123
121using namespace Opie; 124using namespace Opie;
122 125
123 126
124OContactAccessBackend_XML::OContactAccessBackend_XML ( const QString& appname, const QString& filename ): 127OContactAccessBackend_XML::OContactAccessBackend_XML ( const QString& appname, const QString& filename ):
125 m_changed( false ) 128 m_changed( false )
126{ 129{
127 // Just m_contactlist should call delete if an entry 130 // Just m_contactlist should call delete if an entry
128 // is removed. 131 // is removed.
129 m_contactList.setAutoDelete( true ); 132 m_contactList.setAutoDelete( true );
130 m_uidToContact.setAutoDelete( false ); 133 m_uidToContact.setAutoDelete( false );
131 134
132 m_appName = appname; 135 m_appName = appname;
133 136
134 /* Set journalfile name ... */ 137 /* Set journalfile name ... */
135 m_journalName = getenv("HOME"); 138 m_journalName = getenv("HOME");
136 m_journalName +="/.abjournal" + appname; 139 m_journalName +="/.abjournal" + appname;
137 140
138 /* Expecting to access the default filename if nothing else is set */ 141 /* Expecting to access the default filename if nothing else is set */
139 if ( filename.isEmpty() ){ 142 if ( filename.isEmpty() ){
140 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); 143 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
141 } else 144 } else
142 m_fileName = filename; 145 m_fileName = filename;
143 146
144 /* Load Database now */ 147 /* Load Database now */
145 load (); 148 load ();
146} 149}
147 150
148bool OContactAccessBackend_XML::save() 151bool OContactAccessBackend_XML::save()
149{ 152{
150 153
151 if ( !m_changed ) 154 if ( !m_changed )
152 return true; 155 return true;
153 156
154 QString strNewFile = m_fileName + ".new"; 157 QString strNewFile = m_fileName + ".new";
155 QFile f( strNewFile ); 158 QFile f( strNewFile );
156 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 159 if ( !f.open( IO_WriteOnly|IO_Raw ) )
157 return false; 160 return false;
158 161
159 int total_written; 162 int total_written;
160 int idx_offset = 0; 163 int idx_offset = 0;
161 QString out; 164 QString out;
162 165
163 // Write Header 166 // Write Header
164 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 167 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
165 " <Groups>\n" 168 " <Groups>\n"
166 " </Groups>\n" 169 " </Groups>\n"
167 " <Contacts>\n"; 170 " <Contacts>\n";
168 QCString cstr = out.utf8(); 171 QCString cstr = out.utf8();
169 f.writeBlock( cstr.data(), cstr.length() ); 172 f.writeBlock( cstr.data(), cstr.length() );
170 idx_offset += cstr.length(); 173 idx_offset += cstr.length();
171 out = ""; 174 out = "";
172 175
173 // Write all contacts 176 // Write all contacts
174 QListIterator<OContact> it( m_contactList ); 177 QListIterator<OContact> it( m_contactList );
175 for ( ; it.current(); ++it ) { 178 for ( ; it.current(); ++it ) {
176 // qWarning(" Uid %d at Offset: %x", (*it)->uid(), idx_offset ); 179 // qWarning(" Uid %d at Offset: %x", (*it)->uid(), idx_offset );
177 out += "<Contact "; 180 out += "<Contact ";
178 (*it)->save( out ); 181 (*it)->save( out );
179 out += "/>\n"; 182 out += "/>\n";
180 cstr = out.utf8(); 183 cstr = out.utf8();
181 total_written = f.writeBlock( cstr.data(), cstr.length() ); 184 total_written = f.writeBlock( cstr.data(), cstr.length() );
182 idx_offset += cstr.length(); 185 idx_offset += cstr.length();
183 if ( total_written != int(cstr.length()) ) { 186 if ( total_written != int(cstr.length()) ) {
184 f.close(); 187 f.close();
185 QFile::remove( strNewFile ); 188 QFile::remove( strNewFile );
186 return false; 189 return false;
187 } 190 }
188 out = ""; 191 out = "";
189 } 192 }
190 out += " </Contacts>\n</AddressBook>\n"; 193 out += " </Contacts>\n</AddressBook>\n";
191 194
192 // Write Footer 195 // Write Footer
193 cstr = out.utf8(); 196 cstr = out.utf8();
194 total_written = f.writeBlock( cstr.data(), cstr.length() ); 197 total_written = f.writeBlock( cstr.data(), cstr.length() );
195 if ( total_written != int( cstr.length() ) ) { 198 if ( total_written != int( cstr.length() ) ) {
196 f.close(); 199 f.close();
197 QFile::remove( strNewFile ); 200 QFile::remove( strNewFile );
198 return false; 201 return false;
199 } 202 }
200 f.close(); 203 f.close();
201 204
202 // move the file over, I'm just going to use the system call 205 // move the file over, I'm just going to use the system call
203 // because, I don't feel like using QDir. 206 // because, I don't feel like using QDir.
204 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 207 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
205 qWarning( "problem renaming file %s to %s, errno: %d", 208 qWarning( "problem renaming file %s to %s, errno: %d",
206 strNewFile.latin1(), m_journalName.latin1(), errno ); 209 strNewFile.latin1(), m_journalName.latin1(), errno );
207 // remove the tmp file... 210 // remove the tmp file...
208 QFile::remove( strNewFile ); 211 QFile::remove( strNewFile );
209 } 212 }
210 213
211 /* The journalfile should be removed now... */ 214 /* The journalfile should be removed now... */
212 removeJournal(); 215 removeJournal();
213 216
214 m_changed = false; 217 m_changed = false;
215 return true; 218 return true;
216} 219}
217 220
218bool OContactAccessBackend_XML::load () 221bool OContactAccessBackend_XML::load ()
219{ 222{
220 m_contactList.clear(); 223 m_contactList.clear();
221 m_uidToContact.clear(); 224 m_uidToContact.clear();
222 225
223 /* Load XML-File and journal if it exists */ 226 /* Load XML-File and journal if it exists */
224 if ( !load ( m_fileName, false ) ) 227 if ( !load ( m_fileName, false ) )
225 return false; 228 return false;
226 /* The returncode of the journalfile is ignored due to the 229 /* The returncode of the journalfile is ignored due to the
227 * fact that it does not exist when this class is instantiated ! 230 * fact that it does not exist when this class is instantiated !
228 * But there may such a file exist, if the application crashed. 231 * But there may such a file exist, if the application crashed.
229 * Therefore we try to load it to get the changes before the # 232 * Therefore we try to load it to get the changes before the #
230 * crash happened... 233 * crash happened...
231 */ 234 */
232 load (m_journalName, true); 235 load (m_journalName, true);
233 236
234 return true; 237 return true;
235} 238}
236 239
237void OContactAccessBackend_XML::clear () 240void OContactAccessBackend_XML::clear ()
238{ 241{
239 m_contactList.clear(); 242 m_contactList.clear();
240 m_uidToContact.clear(); 243 m_uidToContact.clear();
241 244
242 m_changed = false; 245 m_changed = false;
243} 246}
244 247
245bool OContactAccessBackend_XML::wasChangedExternally() 248bool OContactAccessBackend_XML::wasChangedExternally()
246{ 249{
247 QFileInfo fi( m_fileName ); 250 QFileInfo fi( m_fileName );
248 251
249 QDateTime lastmod = fi.lastModified (); 252 QDateTime lastmod = fi.lastModified ();
250 253
251 return (lastmod != m_readtime); 254 return (lastmod != m_readtime);
252} 255}
253 256
254QArray<int> OContactAccessBackend_XML::allRecords() const 257QArray<int> OContactAccessBackend_XML::allRecords() const
255{ 258{
256 QArray<int> uid_list( m_contactList.count() ); 259 QArray<int> uid_list( m_contactList.count() );
257 260
258 uint counter = 0; 261 uint counter = 0;
259 QListIterator<OContact> it( m_contactList ); 262 QListIterator<OContact> it( m_contactList );
260 for( ; it.current(); ++it ){ 263 for( ; it.current(); ++it ){
261 uid_list[counter++] = (*it)->uid(); 264 uid_list[counter++] = (*it)->uid();
262 } 265 }
263 266
264 return ( uid_list ); 267 return ( uid_list );
265} 268}
266 269
267OContact OContactAccessBackend_XML::find ( int uid ) const 270OContact OContactAccessBackend_XML::find ( int uid ) const
268{ 271{
269 OContact foundContact; //Create empty contact 272 OContact foundContact; //Create empty contact
270 273
271 OContact* found = m_uidToContact.find( QString().setNum( uid ) ); 274 OContact* found = m_uidToContact.find( QString().setNum( uid ) );
272 275
273 if ( found ){ 276 if ( found ){
274 foundContact = *found; 277 foundContact = *found;
275 } 278 }
276 279
277 return ( foundContact ); 280 return ( foundContact );
278} 281}
279 282
280QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings, 283QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings,
281 const QDateTime& d ) 284 const QDateTime& d )
282{ 285{
283 286
284 QArray<int> m_currentQuery( m_contactList.count() ); 287 QArray<int> m_currentQuery( m_contactList.count() );
285 QListIterator<OContact> it( m_contactList ); 288 QListIterator<OContact> it( m_contactList );
286 uint arraycounter = 0; 289 uint arraycounter = 0;
287 290
288 for( ; it.current(); ++it ){ 291 for( ; it.current(); ++it ){
289 /* Search all fields and compare them with query object. Store them into list 292 /* Search all fields and compare them with query object. Store them into list
290 * if all fields matches. 293 * if all fields matches.
291 */ 294 */
292 QDate* queryDate = 0l; 295 QDate* queryDate = 0l;
293 QDate* checkDate = 0l; 296 QDate* checkDate = 0l;
294 bool allcorrect = true; 297 bool allcorrect = true;
295 for ( int i = 0; i < Qtopia::Groups; i++ ) { 298 for ( int i = 0; i < Qtopia::Groups; i++ ) {
296 // Birthday and anniversary are special nonstring fields and should 299 // Birthday and anniversary are special nonstring fields and should
297 // be handled specially 300 // be handled specially
298 switch ( i ){ 301 switch ( i ){
299 case Qtopia::Birthday: 302 case Qtopia::Birthday:
300 queryDate = new QDate( query.birthday() ); 303 queryDate = new QDate( query.birthday() );
301 checkDate = new QDate( (*it)->birthday() ); 304 checkDate = new QDate( (*it)->birthday() );
302 case Qtopia::Anniversary: 305 case Qtopia::Anniversary:
303 if ( queryDate == 0l ){ 306 if ( queryDate == 0l ){
304 queryDate = new QDate( query.anniversary() ); 307 queryDate = new QDate( query.anniversary() );
305 checkDate = new QDate( (*it)->anniversary() ); 308 checkDate = new QDate( (*it)->anniversary() );
306 } 309 }
307 310
308 if ( queryDate->isValid() ){ 311 if ( queryDate->isValid() ){
309 if( checkDate->isValid() ){ 312 if( checkDate->isValid() ){
310 if ( settings & OContactAccess::DateYear ){ 313 if ( settings & OContactAccess::DateYear ){
311 if ( queryDate->year() != checkDate->year() ) 314 if ( queryDate->year() != checkDate->year() )
312 allcorrect = false; 315 allcorrect = false;
313 } 316 }
314 if ( settings & OContactAccess::DateMonth ){ 317 if ( settings & OContactAccess::DateMonth ){
315 if ( queryDate->month() != checkDate->month() ) 318 if ( queryDate->month() != checkDate->month() )
316 allcorrect = false; 319 allcorrect = false;
317 } 320 }
318 if ( settings & OContactAccess::DateDay ){ 321 if ( settings & OContactAccess::DateDay ){
319 if ( queryDate->day() != checkDate->day() ) 322 if ( queryDate->day() != checkDate->day() )
320 allcorrect = false; 323 allcorrect = false;
321 } 324 }
322 if ( settings & OContactAccess::DateDiff ) { 325 if ( settings & OContactAccess::DateDiff ) {
323 QDate current; 326 QDate current;
324 // If we get an additional date, we 327 // If we get an additional date, we
325 // will take this date instead of 328 // will take this date instead of
326 // the current one.. 329 // the current one..
327 if ( !d.date().isValid() ) 330 if ( !d.date().isValid() )
328 current = QDate::currentDate(); 331 current = QDate::currentDate();
329 else 332 else
330 current = d.date(); 333 current = d.date();
331 334
332 // We have to equalize the year, otherwise 335 // We have to equalize the year, otherwise
333 // the search will fail.. 336 // the search will fail..
334 checkDate->setYMD( current.year(), 337 checkDate->setYMD( current.year(),
335 checkDate->month(), 338 checkDate->month(),
336 checkDate->day() ); 339 checkDate->day() );
337 if ( *checkDate < current ) 340 if ( *checkDate < current )
338 checkDate->setYMD( current.year()+1, 341 checkDate->setYMD( current.year()+1,
339 checkDate->month(), 342 checkDate->month(),
340 checkDate->day() ); 343 checkDate->day() );
341 344
342 // Check whether the birthday/anniversary date is between 345 // Check whether the birthday/anniversary date is between
343 // the current/given date and the maximum date 346 // the current/given date and the maximum date
344 // ( maximum time range ) ! 347 // ( maximum time range ) !
345 qWarning("Checking if %s is between %s and %s ! ", 348 qWarning("Checking if %s is between %s and %s ! ",
346 checkDate->toString().latin1(), 349 checkDate->toString().latin1(),
347 current.toString().latin1(), 350 current.toString().latin1(),
348 queryDate->toString().latin1() ); 351 queryDate->toString().latin1() );
349 if ( current.daysTo( *queryDate ) >= 0 ){ 352 if ( current.daysTo( *queryDate ) >= 0 ){
350 if ( !( ( *checkDate >= current ) && 353 if ( !( ( *checkDate >= current ) &&
351 ( *checkDate <= *queryDate ) ) ){ 354 ( *checkDate <= *queryDate ) ) ){
352 allcorrect = false; 355 allcorrect = false;
353 qWarning (" Nope!.."); 356 qWarning (" Nope!..");
354 } 357 }
355 } 358 }
356 } 359 }
357 } else{ 360 } else{
358 // checkDate is invalid. Therefore this entry is always rejected 361 // checkDate is invalid. Therefore this entry is always rejected
359 allcorrect = false; 362 allcorrect = false;
360 } 363 }
361 } 364 }
362 365
363 delete queryDate; 366 delete queryDate;
364 queryDate = 0l; 367 queryDate = 0l;
365 delete checkDate; 368 delete checkDate;
366 checkDate = 0l; 369 checkDate = 0l;
367 break; 370 break;
368 default: 371 default:
369 /* Just compare fields which are not empty in the query object */ 372 /* Just compare fields which are not empty in the query object */
370 if ( !query.field(i).isEmpty() ){ 373 if ( !query.field(i).isEmpty() ){
371 switch ( settings & ~( OContactAccess::IgnoreCase 374 switch ( settings & ~( OContactAccess::IgnoreCase
372 | OContactAccess::DateDiff 375 | OContactAccess::DateDiff
373 | OContactAccess::DateYear 376 | OContactAccess::DateYear
374 | OContactAccess::DateMonth 377 | OContactAccess::DateMonth
375 | OContactAccess::DateDay 378 | OContactAccess::DateDay
376 | OContactAccess::MatchOne 379 | OContactAccess::MatchOne
377 ) ){ 380 ) ){
378 381
379 case OContactAccess::RegExp:{ 382 case OContactAccess::RegExp:{
380 QRegExp expr ( query.field(i), 383 QRegExp expr ( query.field(i),
381 !(settings & OContactAccess::IgnoreCase), 384 !(settings & OContactAccess::IgnoreCase),
382 false ); 385 false );
383 if ( expr.find ( (*it)->field(i), 0 ) == -1 ) 386 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
384 allcorrect = false; 387 allcorrect = false;
385 } 388 }
386 break; 389 break;
387 case OContactAccess::WildCards:{ 390 case OContactAccess::WildCards:{
388 QRegExp expr ( query.field(i), 391 QRegExp expr ( query.field(i),
389 !(settings & OContactAccess::IgnoreCase), 392 !(settings & OContactAccess::IgnoreCase),
390 true ); 393 true );
391 if ( expr.find ( (*it)->field(i), 0 ) == -1 ) 394 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
392 allcorrect = false; 395 allcorrect = false;
393 } 396 }
394 break; 397 break;
395 case OContactAccess::ExactMatch:{ 398 case OContactAccess::ExactMatch:{
396 if (settings & OContactAccess::IgnoreCase){ 399 if (settings & OContactAccess::IgnoreCase){
397 if ( query.field(i).upper() != 400 if ( query.field(i).upper() !=
398 (*it)->field(i).upper() ) 401 (*it)->field(i).upper() )
399 allcorrect = false; 402 allcorrect = false;
400 }else{ 403 }else{
401 if ( query.field(i) != (*it)->field(i) ) 404 if ( query.field(i) != (*it)->field(i) )
402 allcorrect = false; 405 allcorrect = false;
403 } 406 }
404 } 407 }
405 break; 408 break;
406 } 409 }
407 } 410 }
408 } 411 }
409 } 412 }
410 if ( allcorrect ){ 413 if ( allcorrect ){
411 m_currentQuery[arraycounter++] = (*it)->uid(); 414 m_currentQuery[arraycounter++] = (*it)->uid();
412 } 415 }
413 } 416 }
414 417
415 // Shrink to fit.. 418 // Shrink to fit..
416 m_currentQuery.resize(arraycounter); 419 m_currentQuery.resize(arraycounter);
417 420
418 return m_currentQuery; 421 return m_currentQuery;
419} 422}
420 423
421QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const 424QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
422{ 425{
423 QArray<int> m_currentQuery( m_contactList.count() ); 426 QArray<int> m_currentQuery( m_contactList.count() );
424 QListIterator<OContact> it( m_contactList ); 427 QListIterator<OContact> it( m_contactList );
425 uint arraycounter = 0; 428 uint arraycounter = 0;
426 429
427 for( ; it.current(); ++it ){ 430 for( ; it.current(); ++it ){
428 if ( (*it)->match( r ) ){ 431 if ( (*it)->match( r ) ){
429 m_currentQuery[arraycounter++] = (*it)->uid(); 432 m_currentQuery[arraycounter++] = (*it)->uid();
430 } 433 }
431 434
432 } 435 }
433 // Shrink to fit.. 436 // Shrink to fit..
434 m_currentQuery.resize(arraycounter); 437 m_currentQuery.resize(arraycounter);
435 438
436 return m_currentQuery; 439 return m_currentQuery;
437} 440}
438 441
439const uint OContactAccessBackend_XML::querySettings() 442const uint OContactAccessBackend_XML::querySettings()
440{ 443{
441 return ( OContactAccess::WildCards 444 return ( OContactAccess::WildCards
442 | OContactAccess::IgnoreCase 445 | OContactAccess::IgnoreCase
443 | OContactAccess::RegExp 446 | OContactAccess::RegExp
444 | OContactAccess::ExactMatch 447 | OContactAccess::ExactMatch
445 | OContactAccess::DateDiff 448 | OContactAccess::DateDiff
446 | OContactAccess::DateYear 449 | OContactAccess::DateYear
447 | OContactAccess::DateMonth 450 | OContactAccess::DateMonth
448 | OContactAccess::DateDay 451 | OContactAccess::DateDay
449 ); 452 );
450} 453}
451 454
452bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const 455bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
453{ 456{
454 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay 457 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
455 * may be added with any of the other settings. IgnoreCase should never used alone. 458 * may be added with any of the other settings. IgnoreCase should never used alone.
456 * Wildcards, RegExp, ExactMatch should never used at the same time... 459 * Wildcards, RegExp, ExactMatch should never used at the same time...
457 */ 460 */
458 461
459 // Step 1: Check whether the given settings are supported by this backend 462 // Step 1: Check whether the given settings are supported by this backend
460 if ( ( querySettings & ( 463 if ( ( querySettings & (
461 OContactAccess::IgnoreCase 464 OContactAccess::IgnoreCase
462 | OContactAccess::WildCards 465 | OContactAccess::WildCards
463 | OContactAccess::DateDiff 466 | OContactAccess::DateDiff
464 | OContactAccess::DateYear 467 | OContactAccess::DateYear
465 | OContactAccess::DateMonth 468 | OContactAccess::DateMonth
466 | OContactAccess::DateDay 469 | OContactAccess::DateDay
467 | OContactAccess::RegExp 470 | OContactAccess::RegExp
468 | OContactAccess::ExactMatch 471 | OContactAccess::ExactMatch
469 ) ) != querySettings ) 472 ) ) != querySettings )
470 return false; 473 return false;
471 474
472 // Step 2: Check whether the given combinations are ok.. 475 // Step 2: Check whether the given combinations are ok..
473 476
474 // IngoreCase alone is invalid 477 // IngoreCase alone is invalid
475 if ( querySettings == OContactAccess::IgnoreCase ) 478 if ( querySettings == OContactAccess::IgnoreCase )
476 return false; 479 return false;
477 480
478 // WildCards, RegExp and ExactMatch should never used at the same time 481 // WildCards, RegExp and ExactMatch should never used at the same time
479 switch ( querySettings & ~( OContactAccess::IgnoreCase 482 switch ( querySettings & ~( OContactAccess::IgnoreCase
480 | OContactAccess::DateDiff 483 | OContactAccess::DateDiff
481 | OContactAccess::DateYear 484 | OContactAccess::DateYear
482 | OContactAccess::DateMonth 485 | OContactAccess::DateMonth
483 | OContactAccess::DateDay 486 | OContactAccess::DateDay
484 ) 487 )
485 ){ 488 ){
486 case OContactAccess::RegExp: 489 case OContactAccess::RegExp:
487 return ( true ); 490 return ( true );
488 case OContactAccess::WildCards: 491 case OContactAccess::WildCards:
489 return ( true ); 492 return ( true );
490 case OContactAccess::ExactMatch: 493 case OContactAccess::ExactMatch:
491 return ( true ); 494 return ( true );
492 case 0: // one of the upper removed bits were set.. 495 case 0: // one of the upper removed bits were set..
493 return ( true ); 496 return ( true );
494 default: 497 default:
495 return ( false ); 498 return ( false );
496 } 499 }
497} 500}
498 501
499// Currently only asc implemented.. 502// Currently only asc implemented..
500QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int ) 503QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int )
501{ 504{
502 QMap<QString, int> nameToUid; 505 QMap<QString, int> nameToUid;
503 QStringList names; 506 QStringList names;
504 QArray<int> m_currentQuery( m_contactList.count() ); 507 QArray<int> m_currentQuery( m_contactList.count() );
505 508
506 // First fill map and StringList with all Names 509 // First fill map and StringList with all Names
507 // Afterwards sort namelist and use map to fill array to return.. 510 // Afterwards sort namelist and use map to fill array to return..
508 QListIterator<OContact> it( m_contactList ); 511 QListIterator<OContact> it( m_contactList );
509 for( ; it.current(); ++it ){ 512 for( ; it.current(); ++it ){
510 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) ); 513 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
511 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() ); 514 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
512 } 515 }
513 names.sort(); 516 names.sort();
514 517
515 int i = 0; 518 int i = 0;
516 if ( asc ){ 519 if ( asc ){
517 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it ) 520 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
518 m_currentQuery[i++] = nameToUid[ (*it) ]; 521 m_currentQuery[i++] = nameToUid[ (*it) ];
519 }else{ 522 }else{
520 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it ) 523 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
521 m_currentQuery[i++] = nameToUid[ (*it) ]; 524 m_currentQuery[i++] = nameToUid[ (*it) ];
522 } 525 }
523 526
524 return m_currentQuery; 527 return m_currentQuery;
525 528
526} 529}
527 530
528bool OContactAccessBackend_XML::add ( const OContact &newcontact ) 531bool OContactAccessBackend_XML::add ( const OContact &newcontact )
529{ 532{
530 //qWarning("odefaultbackend: ACTION::ADD"); 533 //qWarning("odefaultbackend: ACTION::ADD");
531 updateJournal (newcontact, ACTION_ADD); 534 updateJournal (newcontact, ACTION_ADD);
532 addContact_p( newcontact ); 535 addContact_p( newcontact );
533 536
534 m_changed = true; 537 m_changed = true;
535 538
536 return true; 539 return true;
537} 540}
538 541
539bool OContactAccessBackend_XML::replace ( const OContact &contact ) 542bool OContactAccessBackend_XML::replace ( const OContact &contact )
540{ 543{
541 m_changed = true; 544 m_changed = true;
542 545
543 OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) ); 546 OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
544 547
545 if ( found ) { 548 if ( found ) {
546 OContact* newCont = new OContact( contact ); 549 OContact* newCont = new OContact( contact );
547 550
548 updateJournal ( *newCont, ACTION_REPLACE); 551 updateJournal ( *newCont, ACTION_REPLACE);
549 m_contactList.removeRef ( found ); 552 m_contactList.removeRef ( found );
550 m_contactList.append ( newCont ); 553 m_contactList.append ( newCont );
551 m_uidToContact.remove( QString().setNum( contact.uid() ) ); 554 m_uidToContact.remove( QString().setNum( contact.uid() ) );
552 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont ); 555 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
553 556
554 qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid()); 557 qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid());
555 558
556 return true; 559 return true;
557 } else 560 } else
558 return false; 561 return false;
559} 562}
560 563
561bool OContactAccessBackend_XML::remove ( int uid ) 564bool OContactAccessBackend_XML::remove ( int uid )
562{ 565{
563 m_changed = true; 566 m_changed = true;
564 567
565 OContact* found = m_uidToContact.find ( QString().setNum( uid ) ); 568 OContact* found = m_uidToContact.find ( QString().setNum( uid ) );
566 569
567 if ( found ) { 570 if ( found ) {
568 updateJournal ( *found, ACTION_REMOVE); 571 updateJournal ( *found, ACTION_REMOVE);
569 m_contactList.removeRef ( found ); 572 m_contactList.removeRef ( found );
570 m_uidToContact.remove( QString().setNum( uid ) ); 573 m_uidToContact.remove( QString().setNum( uid ) );
571 574
572 return true; 575 return true;
573 } else 576 } else
574 return false; 577 return false;
575} 578}
576 579
577bool OContactAccessBackend_XML::reload(){ 580bool OContactAccessBackend_XML::reload(){
578 /* Reload is the same as load in this implementation */ 581 /* Reload is the same as load in this implementation */
579 return ( load() ); 582 return ( load() );
580} 583}
581 584
582void OContactAccessBackend_XML::addContact_p( const OContact &newcontact ) 585void OContactAccessBackend_XML::addContact_p( const OContact &newcontact )
583{ 586{
584 OContact* contRef = new OContact( newcontact ); 587 OContact* contRef = new OContact( newcontact );
585 588
586 m_contactList.append ( contRef ); 589 m_contactList.append ( contRef );
587 m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef ); 590 m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef );
588} 591}
589 592
590/* This function loads the xml-database and the journalfile */ 593/* This function loads the xml-database and the journalfile */
591bool OContactAccessBackend_XML::load( const QString filename, bool isJournal ) 594bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
592{ 595{
593 596
594 /* We use the time of the last read to check if the file was 597 /* We use the time of the last read to check if the file was
595 * changed externally. 598 * changed externally.
596 */ 599 */
597 if ( !isJournal ){ 600 if ( !isJournal ){
598 QFileInfo fi( filename ); 601 QFileInfo fi( filename );
599 m_readtime = fi.lastModified (); 602 m_readtime = fi.lastModified ();
600 } 603 }
601 604
602 const int JOURNALACTION = Qtopia::Notes + 1; 605 const int JOURNALACTION = Qtopia::Notes + 1;
603 const int JOURNALROW = JOURNALACTION + 1; 606 const int JOURNALROW = JOURNALACTION + 1;
604 607
605 bool foundAction = false; 608 bool foundAction = false;
606 journal_action action = ACTION_ADD; 609 journal_action action = ACTION_ADD;
607 int journalKey = 0; 610 int journalKey = 0;
608 QMap<int, QString> contactMap; 611 QMap<int, QString> contactMap;
609 QMap<QString, QString> customMap; 612 QMap<QString, QString> customMap;
610 QMap<QString, QString>::Iterator customIt; 613 QMap<QString, QString>::Iterator customIt;
611 QAsciiDict<int> dict( 47 ); 614 QAsciiDict<int> dict( 47 );
612 615
613 dict.setAutoDelete( TRUE ); 616 dict.setAutoDelete( TRUE );
614 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 617 dict.insert( "Uid", new int(Qtopia::AddressUid) );
615 dict.insert( "Title", new int(Qtopia::Title) ); 618 dict.insert( "Title", new int(Qtopia::Title) );
616 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 619 dict.insert( "FirstName", new int(Qtopia::FirstName) );
617 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 620 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
618 dict.insert( "LastName", new int(Qtopia::LastName) ); 621 dict.insert( "LastName", new int(Qtopia::LastName) );
619 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 622 dict.insert( "Suffix", new int(Qtopia::Suffix) );
620 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 623 dict.insert( "FileAs", new int(Qtopia::FileAs) );
621 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 624 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
622 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 625 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
623 dict.insert( "Emails", new int(Qtopia::Emails) ); 626 dict.insert( "Emails", new int(Qtopia::Emails) );
624 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 627 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
625 dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); 628 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
626 dict.insert( "HomeState", new int(Qtopia::HomeState) ); 629 dict.insert( "HomeState", new int(Qtopia::HomeState) );
627 dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); 630 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
628 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); 631 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
629 dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); 632 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
630 dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); 633 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
631 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); 634 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
632 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); 635 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
633 dict.insert( "Company", new int(Qtopia::Company) ); 636 dict.insert( "Company", new int(Qtopia::Company) );
634 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); 637 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
635 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); 638 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
636 dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); 639 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
637 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); 640 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
638 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); 641 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
639 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); 642 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
640 dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); 643 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
641 dict.insert( "Department", new int(Qtopia::Department) ); 644 dict.insert( "Department", new int(Qtopia::Department) );
642 dict.insert( "Office", new int(Qtopia::Office) ); 645 dict.insert( "Office", new int(Qtopia::Office) );
643 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); 646 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
644 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); 647 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
645 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); 648 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
646 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); 649 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
647 dict.insert( "Profession", new int(Qtopia::Profession) ); 650 dict.insert( "Profession", new int(Qtopia::Profession) );
648 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 651 dict.insert( "Assistant", new int(Qtopia::Assistant) );
649 dict.insert( "Manager", new int(Qtopia::Manager) ); 652 dict.insert( "Manager", new int(Qtopia::Manager) );
650 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 653 dict.insert( "Spouse", new int(Qtopia::Spouse) );
651 dict.insert( "Children", new int(Qtopia::Children) ); 654 dict.insert( "Children", new int(Qtopia::Children) );
652 dict.insert( "Gender", new int(Qtopia::Gender) ); 655 dict.insert( "Gender", new int(Qtopia::Gender) );
653 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 656 dict.insert( "Birthday", new int(Qtopia::Birthday) );
654 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 657 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
655 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 658 dict.insert( "Nickname", new int(Qtopia::Nickname) );
656 dict.insert( "Notes", new int(Qtopia::Notes) ); 659 dict.insert( "Notes", new int(Qtopia::Notes) );
657 dict.insert( "action", new int(JOURNALACTION) ); 660 dict.insert( "action", new int(JOURNALACTION) );
658 dict.insert( "actionrow", new int(JOURNALROW) ); 661 dict.insert( "actionrow", new int(JOURNALROW) );
659 662
660 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); 663 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
661 664
662 XMLElement *root = XMLElement::load( filename ); 665 XMLElement *root = XMLElement::load( filename );
663 if(root != 0l ){ // start parsing 666 if(root != 0l ){ // start parsing
664 /* Parse all XML-Elements and put the data into the 667 /* Parse all XML-Elements and put the data into the
665 * Contact-Class 668 * Contact-Class
666 */ 669 */
667 XMLElement *element = root->firstChild(); 670 XMLElement *element = root->firstChild();
668 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() ); 671 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
669 element = element->firstChild(); 672 element = element->firstChild();
670 673
671 /* Search Tag "Contacts" which is the parent of all Contacts */ 674 /* Search Tag "Contacts" which is the parent of all Contacts */
672 while( element && !isJournal ){ 675 while( element && !isJournal ){
673 if( element->tagName() != QString::fromLatin1("Contacts") ){ 676 if( element->tagName() != QString::fromLatin1("Contacts") ){
674 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s", 677 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
675 // element->tagName().latin1()); 678 // element->tagName().latin1());
676 element = element->nextChild(); 679 element = element->nextChild();
677 } else { 680 } else {
678 element = element->firstChild(); 681 element = element->firstChild();
679 break; 682 break;
680 } 683 }
681 } 684 }
682 /* Parse all Contacts and ignore unknown tags */ 685 /* Parse all Contacts and ignore unknown tags */
683 while( element ){ 686 while( element ){
684 if( element->tagName() != QString::fromLatin1("Contact") ){ 687 if( element->tagName() != QString::fromLatin1("Contact") ){
685 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s", 688 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
686 // element->tagName().latin1()); 689 // element->tagName().latin1());
687 element = element->nextChild(); 690 element = element->nextChild();
688 continue; 691 continue;
689 } 692 }
690 /* Found alement with tagname "contact", now parse and store all 693 /* Found alement with tagname "contact", now parse and store all
691 * attributes contained 694 * attributes contained
692 */ 695 */
693 //qWarning("OContactDefBack::load element tagName() : %s", 696 //qWarning("OContactDefBack::load element tagName() : %s",
694 // element->tagName().latin1() ); 697 // element->tagName().latin1() );
695 QString dummy; 698 QString dummy;
696 foundAction = false; 699 foundAction = false;
697 700
698 XMLElement::AttributeMap aMap = element->attributes(); 701 XMLElement::AttributeMap aMap = element->attributes();
699 XMLElement::AttributeMap::Iterator it; 702 XMLElement::AttributeMap::Iterator it;
700 contactMap.clear(); 703 contactMap.clear();
701 customMap.clear(); 704 customMap.clear();
702 for( it = aMap.begin(); it != aMap.end(); ++it ){ 705 for( it = aMap.begin(); it != aMap.end(); ++it ){
703 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1()); 706 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
704 707
705 int *find = dict[ it.key() ]; 708 int *find = dict[ it.key() ];
706 /* Unknown attributes will be stored as "Custom" elements */ 709 /* Unknown attributes will be stored as "Custom" elements */
707 if ( !find ) { 710 if ( !find ) {
708 // qWarning("Attribute %s not known.", it.key().latin1()); 711 // qWarning("Attribute %s not known.", it.key().latin1());
709 //contact.setCustomField(it.key(), it.data()); 712 //contact.setCustomField(it.key(), it.data());
710 customMap.insert( it.key(), it.data() ); 713 customMap.insert( it.key(), it.data() );
711 continue; 714 continue;
712 } 715 }
713 716
714 /* Check if special conversion is needed and add attribute 717 /* Check if special conversion is needed and add attribute
715 * into Contact class 718 * into Contact class
716 */ 719 */
717 switch( *find ) { 720 switch( *find ) {
718 /* 721 /*
719 case Qtopia::AddressUid: 722 case Qtopia::AddressUid:
720 contact.setUid( it.data().toInt() ); 723 contact.setUid( it.data().toInt() );
721 break; 724 break;
722 case Qtopia::AddressCategory: 725 case Qtopia::AddressCategory:
723 contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); 726 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
724 break; 727 break;
725 */ 728 */
726 case JOURNALACTION: 729 case JOURNALACTION:
727 action = journal_action(it.data().toInt()); 730 action = journal_action(it.data().toInt());
728 foundAction = true; 731 foundAction = true;
729 qWarning ("ODefBack(journal)::ACTION found: %d", action); 732 qWarning ("ODefBack(journal)::ACTION found: %d", action);
730 break; 733 break;
731 case JOURNALROW: 734 case JOURNALROW:
732 journalKey = it.data().toInt(); 735 journalKey = it.data().toInt();
733 break; 736 break;
734 default: // no conversion needed add them to the map 737 default: // no conversion needed add them to the map
735 contactMap.insert( *find, it.data() ); 738 contactMap.insert( *find, it.data() );
736 break; 739 break;
737 } 740 }
738 } 741 }
739 /* now generate the Contact contact */ 742 /* now generate the Contact contact */
740 OContact contact( contactMap ); 743 OContact contact( contactMap );
741 744
742 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { 745 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
743 contact.setCustomField( customIt.key(), customIt.data() ); 746 contact.setCustomField( customIt.key(), customIt.data() );
744 } 747 }
745 748
746 if (foundAction){ 749 if (foundAction){
747 foundAction = false; 750 foundAction = false;
748 switch ( action ) { 751 switch ( action ) {
749 case ACTION_ADD: 752 case ACTION_ADD:
750 addContact_p (contact); 753 addContact_p (contact);
751 break; 754 break;
752 case ACTION_REMOVE: 755 case ACTION_REMOVE:
753 if ( !remove (contact.uid()) ) 756 if ( !remove (contact.uid()) )
754 qWarning ("ODefBack(journal)::Unable to remove uid: %d", 757 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
755 contact.uid() ); 758 contact.uid() );
756 break; 759 break;
757 case ACTION_REPLACE: 760 case ACTION_REPLACE:
758 if ( !replace ( contact ) ) 761 if ( !replace ( contact ) )
759 qWarning ("ODefBack(journal)::Unable to replace uid: %d", 762 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
760 contact.uid() ); 763 contact.uid() );
761 break; 764 break;
762 default: 765 default:
763 qWarning ("Unknown action: ignored !"); 766 qWarning ("Unknown action: ignored !");
764 break; 767 break;
765 } 768 }
766 }else{ 769 }else{
767 /* Add contact to list */ 770 /* Add contact to list */
768 addContact_p (contact); 771 addContact_p (contact);
769 } 772 }
770 773
771 /* Move to next element */ 774 /* Move to next element */
772 element = element->nextChild(); 775 element = element->nextChild();
773 } 776 }
774 }else { 777 }else {
775 qWarning("ODefBack::could not load"); 778 qWarning("ODefBack::could not load");
776 } 779 }
777 delete root; 780 delete root;
778 qWarning("returning from loading" ); 781 qWarning("returning from loading" );
779 return true; 782 return true;
780} 783}
781 784
782 785
783void OContactAccessBackend_XML::updateJournal( const OContact& cnt, 786void OContactAccessBackend_XML::updateJournal( const OContact& cnt,
784 journal_action action ) 787 journal_action action )
785{ 788{
786 QFile f( m_journalName ); 789 QFile f( m_journalName );
787 bool created = !f.exists(); 790 bool created = !f.exists();
788 if ( !f.open(IO_WriteOnly|IO_Append) ) 791 if ( !f.open(IO_WriteOnly|IO_Append) )
789 return; 792 return;
790 793
791 QString buf; 794 QString buf;
792 QCString str; 795 QCString str;
793 796
794 // if the file was created, we have to set the Tag "<CONTACTS>" to 797 // if the file was created, we have to set the Tag "<CONTACTS>" to
795 // get a XML-File which is readable by our parser. 798 // get a XML-File which is readable by our parser.
796 // This is just a cheat, but better than rewrite the parser. 799 // This is just a cheat, but better than rewrite the parser.
797 if ( created ){ 800 if ( created ){
798 buf = "<Contacts>"; 801 buf = "<Contacts>";
799 QCString cstr = buf.utf8(); 802 QCString cstr = buf.utf8();
800 f.writeBlock( cstr.data(), cstr.length() ); 803 f.writeBlock( cstr.data(), cstr.length() );
801 } 804 }
802 805
803 buf = "<Contact "; 806 buf = "<Contact ";
804 cnt.save( buf ); 807 cnt.save( buf );
805 buf += " action=\"" + QString::number( (int)action ) + "\" "; 808 buf += " action=\"" + QString::number( (int)action ) + "\" ";
806 buf += "/>\n"; 809 buf += "/>\n";
807 QCString cstr = buf.utf8(); 810 QCString cstr = buf.utf8();
808 f.writeBlock( cstr.data(), cstr.length() ); 811 f.writeBlock( cstr.data(), cstr.length() );
809} 812}
810 813
811void OContactAccessBackend_XML::removeJournal() 814void OContactAccessBackend_XML::removeJournal()
812{ 815{
813 QFile f ( m_journalName ); 816 QFile f ( m_journalName );
814 if ( f.exists() ) 817 if ( f.exists() )
815 f.remove(); 818 f.remove();
816} 819}
817 820
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
index 7b5365b..a0cae4d 100644
--- a/libopie/pim/ocontactaccessbackend_xml.h
+++ b/libopie/pim/ocontactaccessbackend_xml.h
@@ -1,154 +1,160 @@
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 * File Locking to protect against concurrent access
13 * 14 *
14 * 15 *
15 * ===================================================================== 16 * =====================================================================
16 * Version: $Id$ 17 * Version: $Id$
17 * ===================================================================== 18 * =====================================================================
18 * History: 19 * History:
19 * $Log$ 20 * $Log$
21 * Revision 1.15 2003/09/22 14:31:16 eilers
22 * Added first experimental incarnation of sql-backend for addressbook.
23 * Some modifications to be able to compile the todo sql-backend.
24 * A lot of changes fill follow...
25 *
20 * Revision 1.14 2003/04/13 18:07:10 zecke 26 * Revision 1.14 2003/04/13 18:07:10 zecke
21 * More API doc 27 * More API doc
22 * QString -> const QString& 28 * QString -> const QString&
23 * QString = 0l -> QString::null 29 * QString = 0l -> QString::null
24 * 30 *
25 * Revision 1.13 2003/03/21 10:33:09 eilers 31 * Revision 1.13 2003/03/21 10:33:09 eilers
26 * Merged speed optimized xml backend for contacts to main. 32 * Merged speed optimized xml backend for contacts to main.
27 * Added QDateTime to querybyexample. For instance, it is now possible to get 33 * Added QDateTime to querybyexample. For instance, it is now possible to get
28 * all Birthdays/Anniversaries between two dates. This should be used 34 * all Birthdays/Anniversaries between two dates. This should be used
29 * to show all birthdays in the datebook.. 35 * to show all birthdays in the datebook..
30 * This change is sourcecode backward compatible but you have to upgrade 36 * This change is sourcecode backward compatible but you have to upgrade
31 * the binaries for today-addressbook. 37 * the binaries for today-addressbook.
32 * 38 *
33 * Revision 1.12.2.2 2003/02/11 12:17:28 eilers 39 * Revision 1.12.2.2 2003/02/11 12:17:28 eilers
34 * Speed optimization. Removed the sequential search loops. 40 * Speed optimization. Removed the sequential search loops.
35 * 41 *
36 * Revision 1.12.2.1 2003/02/09 15:05:01 eilers 42 * Revision 1.12.2.1 2003/02/09 15:05:01 eilers
37 * Nothing happened.. Just some cleanup before I will start.. 43 * Nothing happened.. Just some cleanup before I will start..
38 * 44 *
39 * Revision 1.12 2003/01/03 16:58:03 eilers 45 * Revision 1.12 2003/01/03 16:58:03 eilers
40 * Reenable debug output 46 * Reenable debug output
41 * 47 *
42 * Revision 1.11 2003/01/03 12:31:28 eilers 48 * Revision 1.11 2003/01/03 12:31:28 eilers
43 * Bugfix for calculating data diffs.. 49 * Bugfix for calculating data diffs..
44 * 50 *
45 * Revision 1.10 2003/01/02 14:27:12 eilers 51 * Revision 1.10 2003/01/02 14:27:12 eilers
46 * Improved query by example: Search by date is possible.. First step 52 * Improved query by example: Search by date is possible.. First step
47 * for a today plugin for birthdays.. 53 * for a today plugin for birthdays..
48 * 54 *
49 * Revision 1.9 2002/12/08 12:48:57 eilers 55 * Revision 1.9 2002/12/08 12:48:57 eilers
50 * Moved journal-enum from ocontact into i the xml-backend.. 56 * Moved journal-enum from ocontact into i the xml-backend..
51 * 57 *
52 * Revision 1.8 2002/11/14 17:04:24 eilers 58 * Revision 1.8 2002/11/14 17:04:24 eilers
53 * Sorting will now work if fullname is identical on some entries 59 * Sorting will now work if fullname is identical on some entries
54 * 60 *
55 * Revision 1.7 2002/11/13 15:02:46 eilers 61 * Revision 1.7 2002/11/13 15:02:46 eilers
56 * Small Bug in sorted fixed 62 * Small Bug in sorted fixed
57 * 63 *
58 * Revision 1.6 2002/11/13 14:14:51 eilers 64 * Revision 1.6 2002/11/13 14:14:51 eilers
59 * Added sorted for Contacts.. 65 * Added sorted for Contacts..
60 * 66 *
61 * Revision 1.5 2002/11/01 15:10:42 eilers 67 * Revision 1.5 2002/11/01 15:10:42 eilers
62 * Added regExp-search in database for all fields in a contact. 68 * Added regExp-search in database for all fields in a contact.
63 * 69 *
64 * Revision 1.4 2002/10/16 10:52:40 eilers 70 * Revision 1.4 2002/10/16 10:52:40 eilers
65 * Added some docu to the interface and now using the cache infrastucture by zecke.. :) 71 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
66 * 72 *
67 * Revision 1.3 2002/10/14 16:21:54 eilers 73 * Revision 1.3 2002/10/14 16:21:54 eilers
68 * Some minor interface updates 74 * Some minor interface updates
69 * 75 *
70 * Revision 1.2 2002/10/07 17:34:24 eilers 76 * Revision 1.2 2002/10/07 17:34:24 eilers
71 * added OBackendFactory for advanced backend access 77 * added OBackendFactory for advanced backend access
72 * 78 *
73 * Revision 1.1 2002/09/27 17:11:44 eilers 79 * Revision 1.1 2002/09/27 17:11:44 eilers
74 * Added API for accessing the Contact-Database ! It is compiling, but 80 * Added API for accessing the Contact-Database ! It is compiling, but
75 * please do not expect that anything is working ! 81 * please do not expect that anything is working !
76 * I will debug that stuff in the next time .. 82 * I will debug that stuff in the next time ..
77 * Please read README_COMPILE for compiling ! 83 * Please read README_COMPILE for compiling !
78 * 84 *
79 * 85 *
80 */ 86 */
81 87
82#ifndef _OContactAccessBackend_XML_ 88#ifndef _OContactAccessBackend_XML_
83#define _OContactAccessBackend_XML_ 89#define _OContactAccessBackend_XML_
84 90
85#include "ocontactaccessbackend.h" 91#include "ocontactaccessbackend.h"
86#include "ocontactaccess.h" 92#include "ocontactaccess.h"
87 93
88#include <qlist.h> 94#include <qlist.h>
89#include <qdict.h> 95#include <qdict.h>
90 96
91/* the default xml implementation */ 97/* the default xml implementation */
92/** 98/**
93 * This class is the XML implementation of a Contact backend 99 * This class is the XML implementation of a Contact backend
94 * it does implement everything available for OContact. 100 * it does implement everything available for OContact.
95 * @see OPimAccessBackend for more information of available methods 101 * @see OPimAccessBackend for more information of available methods
96 */ 102 */
97class OContactAccessBackend_XML : public OContactAccessBackend { 103class OContactAccessBackend_XML : public OContactAccessBackend {
98 public: 104 public:
99 OContactAccessBackend_XML ( const QString& appname, const QString& filename = QString::null ); 105 OContactAccessBackend_XML ( const QString& appname, const QString& filename = QString::null );
100 106
101 bool save(); 107 bool save();
102 108
103 bool load (); 109 bool load ();
104 110
105 void clear (); 111 void clear ();
106 112
107 bool wasChangedExternally(); 113 bool wasChangedExternally();
108 114
109 QArray<int> allRecords() const; 115 QArray<int> allRecords() const;
110 116
111 OContact find ( int uid ) const; 117 OContact find ( int uid ) const;
112 118
113 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() ); 119 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
114 120
115 QArray<int> matchRegexp( const QRegExp &r ) const; 121 QArray<int> matchRegexp( const QRegExp &r ) const;
116 122
117 const uint querySettings(); 123 const uint querySettings();
118 124
119 bool hasQuerySettings (uint querySettings) const; 125 bool hasQuerySettings (uint querySettings) const;
120 126
121 // Currently only asc implemented.. 127 // Currently only asc implemented..
122 QArray<int> sorted( bool asc, int , int , int ); 128 QArray<int> sorted( bool asc, int , int , int );
123 bool add ( const OContact &newcontact ); 129 bool add ( const OContact &newcontact );
124 130
125 bool replace ( const OContact &contact ); 131 bool replace ( const OContact &contact );
126 132
127 bool remove ( int uid ); 133 bool remove ( int uid );
128 bool reload(); 134 bool reload();
129 135
130 private: 136 private:
131 137
132 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; 138 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
133 139
134 void addContact_p( const OContact &newcontact ); 140 void addContact_p( const OContact &newcontact );
135 141
136 /* This function loads the xml-database and the journalfile */ 142 /* This function loads the xml-database and the journalfile */
137 bool load( const QString filename, bool isJournal ); 143 bool load( const QString filename, bool isJournal );
138 144
139 145
140 void updateJournal( const OContact& cnt, journal_action action ); 146 void updateJournal( const OContact& cnt, journal_action action );
141 void removeJournal(); 147 void removeJournal();
142 148
143 protected: 149 protected:
144 bool m_changed; 150 bool m_changed;
145 QString m_journalName; 151 QString m_journalName;
146 QString m_fileName; 152 QString m_fileName;
147 QString m_appName; 153 QString m_appName;
148 QList<OContact> m_contactList; 154 QList<OContact> m_contactList;
149 QDateTime m_readtime; 155 QDateTime m_readtime;
150 156
151 QDict<OContact> m_uidToContact; 157 QDict<OContact> m_uidToContact;
152}; 158};
153 159
154#endif 160#endif
diff --git a/libopie/pim/ocontactfields.cpp b/libopie/pim/ocontactfields.cpp
new file mode 100644
index 0000000..831a596
--- a/dev/null
+++ b/libopie/pim/ocontactfields.cpp
@@ -0,0 +1,456 @@
1
2#include "ocontactfields.h"
3
4#include <qstringlist.h>
5#include <qobject.h>
6
7// We should use our own enum in the future ..
8#include <qpe/recordfields.h>
9#include <qpe/config.h>
10#include <opie/ocontact.h>
11
12/*!
13 \internal
14 Returns a list of details field names for a contact.
15*/
16QStringList OContactFields::untrdetailsfields( bool sorted )
17{
18 QStringList list;
19 QMap<int, QString> mapIdToStr = idToUntrFields();
20
21 list.append( mapIdToStr[ Qtopia::Office ] );
22 list.append( mapIdToStr[ Qtopia::Profession ] );
23 list.append( mapIdToStr[ Qtopia::Assistant ] );
24 list.append( mapIdToStr[ Qtopia::Manager ] );
25
26 list.append( mapIdToStr[ Qtopia::Spouse ] );
27 list.append( mapIdToStr[ Qtopia::Gender ] );
28 list.append( mapIdToStr[ Qtopia::Birthday ] );
29 list.append( mapIdToStr[ Qtopia::Anniversary ] );
30 list.append( mapIdToStr[ Qtopia::Nickname ] );
31 list.append( mapIdToStr[ Qtopia::Children ] );
32
33 if (sorted) list.sort();
34 return list;
35}
36
37/*!
38 \internal
39 Returns a translated list of details field names for a contact.
40*/
41QStringList OContactFields::trdetailsfields( bool sorted )
42{
43 QStringList list;
44 QMap<int, QString> mapIdToStr = idToTrFields();
45
46 list.append( mapIdToStr[Qtopia::Office] );
47 list.append( mapIdToStr[Qtopia::Profession] );
48 list.append( mapIdToStr[Qtopia::Assistant] );
49 list.append( mapIdToStr[Qtopia::Manager] );
50
51 list.append( mapIdToStr[Qtopia::Spouse] );
52 list.append( mapIdToStr[Qtopia::Gender] );
53 list.append( mapIdToStr[Qtopia::Birthday] );
54 list.append( mapIdToStr[Qtopia::Anniversary] );
55 list.append( mapIdToStr[Qtopia::Nickname] );
56 list.append( mapIdToStr[Qtopia::Children] );
57
58 if (sorted) list.sort();
59 return list;
60}
61
62
63/*!
64 \internal
65 Returns a translated list of phone field names for a contact.
66*/
67QStringList OContactFields::trphonefields( bool sorted )
68{
69 QStringList list;
70 QMap<int, QString> mapIdToStr = idToTrFields();
71
72 list.append( mapIdToStr[Qtopia::BusinessPhone] );
73 list.append( mapIdToStr[Qtopia::BusinessFax] );
74 list.append( mapIdToStr[Qtopia::BusinessMobile] );
75 list.append( mapIdToStr[Qtopia::BusinessPager] );
76 list.append( mapIdToStr[Qtopia::BusinessWebPage] );
77
78 list.append( mapIdToStr[Qtopia::DefaultEmail] );
79 list.append( mapIdToStr[Qtopia::Emails] );
80
81 list.append( mapIdToStr[Qtopia::HomePhone] );
82 list.append( mapIdToStr[Qtopia::HomeFax] );
83 list.append( mapIdToStr[Qtopia::HomeMobile] );
84 // list.append( mapIdToStr[Qtopia::HomePager] );
85 list.append( mapIdToStr[Qtopia::HomeWebPage] );
86
87 if (sorted) list.sort();
88
89 return list;
90}
91
92
93/*!
94 \internal
95 Returns a list of phone field names for a contact.
96*/
97QStringList OContactFields::untrphonefields( bool sorted )
98{
99 QStringList list;
100 QMap<int, QString> mapIdToStr = idToUntrFields();
101
102 list.append( mapIdToStr[ Qtopia::BusinessPhone ] );
103 list.append( mapIdToStr[ Qtopia::BusinessFax ] );
104 list.append( mapIdToStr[ Qtopia::BusinessMobile ] );
105 list.append( mapIdToStr[ Qtopia::BusinessPager ] );
106 list.append( mapIdToStr[ Qtopia::BusinessWebPage ] );
107
108 list.append( mapIdToStr[ Qtopia::DefaultEmail ] );
109 list.append( mapIdToStr[ Qtopia::Emails ] );
110
111 list.append( mapIdToStr[ Qtopia::HomePhone ] );
112 list.append( mapIdToStr[ Qtopia::HomeFax ] );
113 list.append( mapIdToStr[ Qtopia::HomeMobile ] );
114 //list.append( mapIdToStr[Qtopia::HomePager] );
115 list.append( mapIdToStr[Qtopia::HomeWebPage] );
116
117 if (sorted) list.sort();
118
119 return list;
120}
121
122
123/*!
124 \internal
125 Returns a translated list of field names for a contact.
126*/
127QStringList OContactFields::trfields( bool sorted )
128{
129 QStringList list;
130 QMap<int, QString> mapIdToStr = idToTrFields();
131
132 list.append( mapIdToStr[Qtopia::Title]);
133 list.append( mapIdToStr[Qtopia::FirstName] );
134 list.append( mapIdToStr[Qtopia::MiddleName] );
135 list.append( mapIdToStr[Qtopia::LastName] );
136 list.append( mapIdToStr[Qtopia::Suffix] );
137 list.append( mapIdToStr[Qtopia::FileAs] );
138
139 list.append( mapIdToStr[Qtopia::JobTitle] );
140 list.append( mapIdToStr[Qtopia::Department] );
141 list.append( mapIdToStr[Qtopia::Company] );
142
143 list += trphonefields( sorted );
144
145 list.append( mapIdToStr[Qtopia::BusinessStreet] );
146 list.append( mapIdToStr[Qtopia::BusinessCity] );
147 list.append( mapIdToStr[Qtopia::BusinessState] );
148 list.append( mapIdToStr[Qtopia::BusinessZip] );
149 list.append( mapIdToStr[Qtopia::BusinessCountry] );
150
151 list.append( mapIdToStr[Qtopia::HomeStreet] );
152 list.append( mapIdToStr[Qtopia::HomeCity] );
153 list.append( mapIdToStr[Qtopia::HomeState] );
154 list.append( mapIdToStr[Qtopia::HomeZip] );
155 list.append( mapIdToStr[Qtopia::HomeCountry] );
156
157 list += trdetailsfields( sorted );
158
159 list.append( mapIdToStr[Qtopia::Notes] );
160 list.append( mapIdToStr[Qtopia::Groups] );
161
162 if (sorted) list.sort();
163
164 return list;
165}
166
167/*!
168 \internal
169 Returns an untranslated list of field names for a contact.
170*/
171QStringList OContactFields::untrfields( bool sorted )
172{
173 QStringList list;
174 QMap<int, QString> mapIdToStr = idToUntrFields();
175
176 list.append( mapIdToStr[ Qtopia::Title ] );
177 list.append( mapIdToStr[ Qtopia::FirstName ] );
178 list.append( mapIdToStr[ Qtopia::MiddleName ] );
179 list.append( mapIdToStr[ Qtopia::LastName ] );
180 list.append( mapIdToStr[ Qtopia::Suffix ] );
181 list.append( mapIdToStr[ Qtopia::FileAs ] );
182
183 list.append( mapIdToStr[ Qtopia::JobTitle ] );
184 list.append( mapIdToStr[ Qtopia::Department ] );
185 list.append( mapIdToStr[ Qtopia::Company ] );
186
187 list += untrphonefields( sorted );
188
189 list.append( mapIdToStr[ Qtopia::BusinessStreet ] );
190 list.append( mapIdToStr[ Qtopia::BusinessCity ] );
191 list.append( mapIdToStr[ Qtopia::BusinessState ] );
192 list.append( mapIdToStr[ Qtopia::BusinessZip ] );
193 list.append( mapIdToStr[ Qtopia::BusinessCountry ] );
194
195 list.append( mapIdToStr[ Qtopia::HomeStreet ] );
196 list.append( mapIdToStr[ Qtopia::HomeCity ] );
197 list.append( mapIdToStr[ Qtopia::HomeState ] );
198 list.append( mapIdToStr[ Qtopia::HomeZip ] );
199 list.append( mapIdToStr[ Qtopia::HomeCountry ] );
200
201 list += untrdetailsfields( sorted );
202
203 list.append( mapIdToStr[ Qtopia::Notes ] );
204 list.append( mapIdToStr[ Qtopia::Groups ] );
205
206 if (sorted) list.sort();
207
208 return list;
209}
210QMap<int, QString> OContactFields::idToTrFields()
211{
212 QMap<int, QString> ret_map;
213
214 ret_map.insert( Qtopia::Title, QObject::tr( "Name Title") );
215 ret_map.insert( Qtopia::FirstName, QObject::tr( "First Name" ) );
216 ret_map.insert( Qtopia::MiddleName, QObject::tr( "Middle Name" ) );
217 ret_map.insert( Qtopia::LastName, QObject::tr( "Last Name" ) );
218 ret_map.insert( Qtopia::Suffix, QObject::tr( "Suffix" ));
219 ret_map.insert( Qtopia::FileAs, QObject::tr( "File As" ) );
220
221 ret_map.insert( Qtopia::JobTitle, QObject::tr( "Job Title" ) );
222 ret_map.insert( Qtopia::Department, QObject::tr( "Department" ) );
223 ret_map.insert( Qtopia::Company, QObject::tr( "Company" ) );
224 ret_map.insert( Qtopia::BusinessPhone, QObject::tr( "Business Phone" ) );
225 ret_map.insert( Qtopia::BusinessFax, QObject::tr( "Business Fax" ) );
226 ret_map.insert( Qtopia::BusinessMobile, QObject::tr( "Business Mobile" ));
227
228 // email
229 ret_map.insert( Qtopia::DefaultEmail, QObject::tr( "Default Email" ) );
230 ret_map.insert( Qtopia::Emails, QObject::tr( "Emails" ) );
231
232 ret_map.insert( Qtopia::HomePhone, QObject::tr( "Home Phone" ) );
233 ret_map.insert( Qtopia::HomeFax, QObject::tr( "Home Fax" ) );
234 ret_map.insert( Qtopia::HomeMobile, QObject::tr( "Home Mobile" ) );
235
236 // business
237 ret_map.insert( Qtopia::BusinessStreet, QObject::tr( "Business Street" ) );
238 ret_map.insert( Qtopia::BusinessCity, QObject::tr( "Business City" ) );
239 ret_map.insert( Qtopia::BusinessState, QObject::tr( "Business State" ) );
240 ret_map.insert( Qtopia::BusinessZip, QObject::tr( "Business Zip" ) );
241 ret_map.insert( Qtopia::BusinessCountry, QObject::tr( "Business Country" ) );
242 ret_map.insert( Qtopia::BusinessPager, QObject::tr( "Business Pager" ) );
243 ret_map.insert( Qtopia::BusinessWebPage, QObject::tr( "Business WebPage" ) );
244
245 ret_map.insert( Qtopia::Office, QObject::tr( "Office" ) );
246 ret_map.insert( Qtopia::Profession, QObject::tr( "Profession" ) );
247 ret_map.insert( Qtopia::Assistant, QObject::tr( "Assistant" ) );
248 ret_map.insert( Qtopia::Manager, QObject::tr( "Manager" ) );
249
250 // home
251 ret_map.insert( Qtopia::HomeStreet, QObject::tr( "Home Street" ) );
252 ret_map.insert( Qtopia::HomeCity, QObject::tr( "Home City" ) );
253 ret_map.insert( Qtopia::HomeState, QObject::tr( "Home State" ) );
254 ret_map.insert( Qtopia::HomeZip, QObject::tr( "Home Zip" ) );
255 ret_map.insert( Qtopia::HomeCountry, QObject::tr( "Home Country" ) );
256 ret_map.insert( Qtopia::HomeWebPage, QObject::tr( "Home Web Page" ) );
257
258 //personal
259 ret_map.insert( Qtopia::Spouse, QObject::tr( "Spouse" ) );
260 ret_map.insert( Qtopia::Gender, QObject::tr( "Gender" ) );
261 ret_map.insert( Qtopia::Birthday, QObject::tr( "Birthday" ) );
262 ret_map.insert( Qtopia::Anniversary, QObject::tr( "Anniversary" ) );
263 ret_map.insert( Qtopia::Nickname, QObject::tr( "Nickname" ) );
264 ret_map.insert( Qtopia::Children, QObject::tr( "Children" ) );
265
266 // other
267 ret_map.insert( Qtopia::Notes, QObject::tr( "Notes" ) );
268
269
270 return ret_map;
271}
272
273QMap<int, QString> OContactFields::idToUntrFields()
274{
275 QMap<int, QString> ret_map;
276
277 ret_map.insert( Qtopia::Title, "Name Title" );
278 ret_map.insert( Qtopia::FirstName, "First Name" );
279 ret_map.insert( Qtopia::MiddleName, "Middle Name" );
280 ret_map.insert( Qtopia::LastName, "Last Name" );
281 ret_map.insert( Qtopia::Suffix, "Suffix" );
282 ret_map.insert( Qtopia::FileAs, "File As" );
283
284 ret_map.insert( Qtopia::JobTitle, "Job Title" );
285 ret_map.insert( Qtopia::Department, "Department" );
286 ret_map.insert( Qtopia::Company, "Company" );
287 ret_map.insert( Qtopia::BusinessPhone, "Business Phone" );
288 ret_map.insert( Qtopia::BusinessFax, "Business Fax" );
289 ret_map.insert( Qtopia::BusinessMobile, "Business Mobile" );
290
291 // email
292 ret_map.insert( Qtopia::DefaultEmail, "Default Email" );
293 ret_map.insert( Qtopia::Emails, "Emails" );
294
295 ret_map.insert( Qtopia::HomePhone, "Home Phone" );
296 ret_map.insert( Qtopia::HomeFax, "Home Fax" );
297 ret_map.insert( Qtopia::HomeMobile, "Home Mobile" );
298
299 // business
300 ret_map.insert( Qtopia::BusinessStreet, "Business Street" );
301 ret_map.insert( Qtopia::BusinessCity, "Business City" );
302 ret_map.insert( Qtopia::BusinessState, "Business State" );
303 ret_map.insert( Qtopia::BusinessZip, "Business Zip" );
304 ret_map.insert( Qtopia::BusinessCountry, "Business Country" );
305 ret_map.insert( Qtopia::BusinessPager, "Business Pager" );
306 ret_map.insert( Qtopia::BusinessWebPage, "Business WebPage" );
307
308 ret_map.insert( Qtopia::Office, "Office" );
309 ret_map.insert( Qtopia::Profession, "Profession" );
310 ret_map.insert( Qtopia::Assistant, "Assistant" );
311 ret_map.insert( Qtopia::Manager, "Manager" );
312
313 // home
314 ret_map.insert( Qtopia::HomeStreet, "Home Street" );
315 ret_map.insert( Qtopia::HomeCity, "Home City" );
316 ret_map.insert( Qtopia::HomeState, "Home State" );
317 ret_map.insert( Qtopia::HomeZip, "Home Zip" );
318 ret_map.insert( Qtopia::HomeCountry, "Home Country" );
319 ret_map.insert( Qtopia::HomeWebPage, "Home Web Page" );
320
321 //personal
322 ret_map.insert( Qtopia::Spouse, "Spouse" );
323 ret_map.insert( Qtopia::Gender, "Gender" );
324 ret_map.insert( Qtopia::Birthday, "Birthday" );
325 ret_map.insert( Qtopia::Anniversary, "Anniversary" );
326 ret_map.insert( Qtopia::Nickname, "Nickname" );
327 ret_map.insert( Qtopia::Children, "Children" );
328
329 // other
330 ret_map.insert( Qtopia::Notes, "Notes" );
331
332
333 return ret_map;
334}
335
336QMap<QString, int> OContactFields::trFieldsToId()
337{
338 QMap<int, QString> idtostr = idToTrFields();
339 QMap<QString, int> ret_map;
340
341
342 QMap<int, QString>::Iterator it;
343 for( it = idtostr.begin(); it != idtostr.end(); ++it )
344 ret_map.insert( *it, it.key() );
345
346
347 return ret_map;
348}
349
350QMap<QString, int> OContactFields::untrFieldsToId()
351{
352 QMap<int, QString> idtostr = idToUntrFields();
353 QMap<QString, int> ret_map;
354
355
356 QMap<int, QString>::Iterator it;
357 for( it = idtostr.begin(); it != idtostr.end(); ++it )
358 ret_map.insert( *it, it.key() );
359
360
361 return ret_map;
362}
363
364
365OContactFields::OContactFields():
366 fieldOrder( DEFAULT_FIELD_ORDER ),
367 changedFieldOrder( false )
368{
369 // Get the global field order from the config file and
370 // use it as a start pattern
371 Config cfg ( "AddressBook" );
372 cfg.setGroup( "ContactFieldOrder" );
373 globalFieldOrder = cfg.readEntry( "General", DEFAULT_FIELD_ORDER );
374}
375
376OContactFields::~OContactFields(){
377
378 // We will store the fieldorder into the config file
379 // to reuse it for the future..
380 if ( changedFieldOrder ){
381 Config cfg ( "AddressBook" );
382 cfg.setGroup( "ContactFieldOrder" );
383 cfg.writeEntry( "General", globalFieldOrder );
384 }
385}
386
387
388
389void OContactFields::saveToRecord( OContact &cnt ){
390
391 qDebug("ocontactfields saveToRecord: >%s<",fieldOrder.latin1());
392
393 // Store fieldorder into this contact.
394 cnt.setCustomField( CONTACT_FIELD_ORDER_NAME, fieldOrder );
395
396 globalFieldOrder = fieldOrder;
397 changedFieldOrder = true;
398
399}
400
401void OContactFields::loadFromRecord( const OContact &cnt ){
402 qDebug("ocontactfields loadFromRecord");
403 qDebug("loading >%s<",cnt.fullName().latin1());
404
405 // Get fieldorder for this contact. If none is defined,
406 // we will use the global one from the config file..
407
408 fieldOrder = cnt.customField( CONTACT_FIELD_ORDER_NAME );
409
410 qDebug("fieldOrder from contact>%s<",fieldOrder.latin1());
411
412 if (fieldOrder.isEmpty()){
413 fieldOrder = globalFieldOrder;
414 }
415
416
417 qDebug("effective fieldOrder in loadFromRecord >%s<",fieldOrder.latin1());
418}
419
420void OContactFields::setFieldOrder( int num, int index ){
421 qDebug("qcontactfields setfieldorder pos %i -> %i",num,index);
422
423 fieldOrder[num] = QString::number( index, 16 )[0];
424
425 // We will store this new fieldorder globally to
426 // remember it for contacts which have none
427 globalFieldOrder = fieldOrder;
428 changedFieldOrder = true;
429
430 qDebug("fieldOrder >%s<",fieldOrder.latin1());
431}
432
433int OContactFields::getFieldOrder( int num, int defIndex ){
434 qDebug("ocontactfields getFieldOrder");
435 qDebug("fieldOrder >%s<",fieldOrder.latin1());
436
437 // Get index of combo as char..
438 QChar poschar = fieldOrder[num];
439
440 bool ok;
441 int ret = 0;
442 // Convert char to number..
443 if ( !( poschar == QChar::null ) )
444 ret = QString( poschar ).toInt(&ok, 16);
445 else
446 ok = false;
447
448 // Return default value if index for
449 // num was not set or if anything else happened..
450 if ( !ok ) ret = defIndex;
451
452 qDebug("returning >%i<",ret);
453
454 return ret;
455
456}
diff --git a/libopie/pim/ocontactfields.h b/libopie/pim/ocontactfields.h
new file mode 100644
index 0000000..9f6171b
--- a/dev/null
+++ b/libopie/pim/ocontactfields.h
@@ -0,0 +1,60 @@
1#ifndef OPIE_CONTACTS_FIELDS
2#define OPIE_CONTACTS_FIELDS
3
4class QStringList;
5
6#include <qmap.h>
7#include <qstring.h>
8#include <opie/ocontact.h>
9
10#define CONTACT_FIELD_ORDER_NAME "opie-contactfield-order"
11#define DEFAULT_FIELD_ORDER "__________"
12
13class OContactFields{
14
15 public:
16 OContactFields();
17 ~OContactFields();
18 /** Set the index for combo boxes.
19 * Sets the <b>index</b> of combo <b>num</b>.
20 * @param num selects the number of the combo
21 * @param index sets the index in the combo
22 */
23 void setFieldOrder( int num, int index );
24
25 /** Get the index for combo boxes.
26 * Returns the index of combo <b>num</b> or defindex
27 * if none was defined..
28 * @param num Selects the number of the combo
29 * @param defIndex will be returned if none was defined (either
30 * globally in the config file, nor by the contact which was used
31 * by loadFromRecord() )
32 */
33 int getFieldOrder( int num, int defIndex);
34
35 /** Store fieldorder to contact. */
36 void saveToRecord( OContact& );
37 /** Get Fieldorder from contact. */
38 void loadFromRecord( const OContact& );
39
40 private:
41 QString fieldOrder;
42 QString globalFieldOrder;
43 bool changedFieldOrder;
44
45 public:
46 static QStringList trphonefields( bool sorted = true );
47 static QStringList untrphonefields( bool sorted = true );
48 static QStringList trdetailsfields( bool sorted = true );
49 static QStringList untrdetailsfields( bool sorted = true );
50 static QStringList trfields( bool sorted = true );
51 static QStringList untrfields( bool sorted = true );
52
53 static QMap<int, QString> idToTrFields();
54 static QMap<QString, int> trFieldsToId();
55 static QMap<int, QString> idToUntrFields();
56 static QMap<QString, int> untrFieldsToId();
57
58};
59
60#endif
diff --git a/libopie/pim/otodoaccesssql.cpp b/libopie/pim/otodoaccesssql.cpp
index ec9c14c..23e0c3e 100644
--- a/libopie/pim/otodoaccesssql.cpp
+++ b/libopie/pim/otodoaccesssql.cpp
@@ -1,540 +1,593 @@
1 1
2#include <qdatetime.h> 2#include <qdatetime.h>
3 3
4#include <qpe/global.h> 4#include <qpe/global.h>
5 5
6#include <opie/osqldriver.h> 6#include <opie2/osqldriver.h>
7#include <opie/osqlresult.h> 7#include <opie2/osqlresult.h>
8#include <opie/osqlmanager.h> 8#include <opie2/osqlmanager.h>
9#include <opie/osqlquery.h> 9#include <opie2/osqlquery.h>
10 10
11#include "otodoaccesssql.h" 11#include "otodoaccesssql.h"
12 12
13/* 13/*
14 * first some query 14 * first some query
15 * CREATE query 15 * CREATE query
16 * LOAD query 16 * LOAD query
17 * INSERT 17 * INSERT
18 * REMOVE 18 * REMOVE
19 * CLEAR 19 * CLEAR
20 */ 20 */
21namespace { 21namespace {
22 /** 22 /**
23 * CreateQuery for the Todolist Table 23 * CreateQuery for the Todolist Table
24 */ 24 */
25 class CreateQuery : public OSQLQuery { 25 class CreateQuery : public OSQLQuery {
26 public: 26 public:
27 CreateQuery(); 27 CreateQuery();
28 ~CreateQuery(); 28 ~CreateQuery();
29 QString query()const; 29 QString query()const;
30 }; 30 };
31 31
32 /** 32 /**
33 * LoadQuery 33 * LoadQuery
34 * this one queries for all uids 34 * this one queries for all uids
35 */ 35 */
36 class LoadQuery : public OSQLQuery { 36 class LoadQuery : public OSQLQuery {
37 public: 37 public:
38 LoadQuery(); 38 LoadQuery();
39 ~LoadQuery(); 39 ~LoadQuery();
40 QString query()const; 40 QString query()const;
41 }; 41 };
42 42
43 /** 43 /**
44 * inserts/adds a OTodo to the table 44 * inserts/adds a OTodo to the table
45 */ 45 */
46 class InsertQuery : public OSQLQuery { 46 class InsertQuery : public OSQLQuery {
47 public: 47 public:
48 InsertQuery(const OTodo& ); 48 InsertQuery(const OTodo& );
49 ~InsertQuery(); 49 ~InsertQuery();
50 QString query()const; 50 QString query()const;
51 private: 51 private:
52 OTodo m_todo; 52 OTodo m_todo;
53 }; 53 };
54 54
55 /** 55 /**
56 * removes one from the table 56 * removes one from the table
57 */ 57 */
58 class RemoveQuery : public OSQLQuery { 58 class RemoveQuery : public OSQLQuery {
59 public: 59 public:
60 RemoveQuery(int uid ); 60 RemoveQuery(int uid );
61 ~RemoveQuery(); 61 ~RemoveQuery();
62 QString query()const; 62 QString query()const;
63 private: 63 private:
64 int m_uid; 64 int m_uid;
65 }; 65 };
66 66
67 /** 67 /**
68 * Clears (delete) a Table 68 * Clears (delete) a Table
69 */ 69 */
70 class ClearQuery : public OSQLQuery { 70 class ClearQuery : public OSQLQuery {
71 public: 71 public:
72 ClearQuery(); 72 ClearQuery();
73 ~ClearQuery(); 73 ~ClearQuery();
74 QString query()const; 74 QString query()const;
75 75
76 }; 76 };
77 77
78 /** 78 /**
79 * a find query 79 * a find query
80 */ 80 */
81 class FindQuery : public OSQLQuery { 81 class FindQuery : public OSQLQuery {
82 public: 82 public:
83 FindQuery(int uid); 83 FindQuery(int uid);
84 FindQuery(const QArray<int>& ); 84 FindQuery(const QArray<int>& );
85 ~FindQuery(); 85 ~FindQuery();
86 QString query()const; 86 QString query()const;
87 private: 87 private:
88 QString single()const; 88 QString single()const;
89 QString multi()const; 89 QString multi()const;
90 QArray<int> m_uids; 90 QArray<int> m_uids;
91 int m_uid; 91 int m_uid;
92 }; 92 };
93 93
94 /** 94 /**
95 * overdue query 95 * overdue query
96 */ 96 */
97 class OverDueQuery : public OSQLQuery { 97 class OverDueQuery : public OSQLQuery {
98 public: 98 public:
99 OverDueQuery(); 99 OverDueQuery();
100 ~OverDueQuery(); 100 ~OverDueQuery();
101 QString query()const; 101 QString query()const;
102 }; 102 };
103 class EffQuery : public OSQLQuery { 103 class EffQuery : public OSQLQuery {
104 public: 104 public:
105 EffQuery( const QDate&, const QDate&, bool inc ); 105 EffQuery( const QDate&, const QDate&, bool inc );
106 ~EffQuery(); 106 ~EffQuery();
107 QString query()const; 107 QString query()const;
108 private: 108 private:
109 QString with()const; 109 QString with()const;
110 QString out()const; 110 QString out()const;
111 QDate m_start; 111 QDate m_start;
112 QDate m_end; 112 QDate m_end;
113 bool m_inc :1; 113 bool m_inc :1;
114 }; 114 };
115 115
116 116
117 CreateQuery::CreateQuery() : OSQLQuery() {} 117 CreateQuery::CreateQuery() : OSQLQuery() {}
118 CreateQuery::~CreateQuery() {} 118 CreateQuery::~CreateQuery() {}
119 QString CreateQuery::query()const { 119 QString CreateQuery::query()const {
120 QString qu; 120 QString qu;
121 qu += "create table todolist( uid, categories, completed, progress, "; 121 qu += "create table todolist( uid, categories, completed, progress, ";
122 qu += "summary, DueDate, priority, description )"; 122 qu += "summary, DueDate, priority, description )";
123 return qu; 123 return qu;
124 } 124 }
125 125
126 LoadQuery::LoadQuery() : OSQLQuery() {} 126 LoadQuery::LoadQuery() : OSQLQuery() {}
127 LoadQuery::~LoadQuery() {} 127 LoadQuery::~LoadQuery() {}
128 QString LoadQuery::query()const { 128 QString LoadQuery::query()const {
129 QString qu; 129 QString qu;
130 qu += "select distinct uid from todolist"; 130 qu += "select distinct uid from todolist";
131 131
132 return qu; 132 return qu;
133 } 133 }
134 134
135 InsertQuery::InsertQuery( const OTodo& todo ) 135 InsertQuery::InsertQuery( const OTodo& todo )
136 : OSQLQuery(), m_todo( todo ) { 136 : OSQLQuery(), m_todo( todo ) {
137 } 137 }
138 InsertQuery::~InsertQuery() { 138 InsertQuery::~InsertQuery() {
139 } 139 }
140 /* 140 /*
141 * converts from a OTodo to a query 141 * converts from a OTodo to a query
142 * we leave out X-Ref + Alarms 142 * we leave out X-Ref + Alarms
143 */ 143 */
144 QString InsertQuery::query()const{ 144 QString InsertQuery::query()const{
145 145
146 int year, month, day; 146 int year, month, day;
147 year = month = day = 0; 147 year = month = day = 0;
148 if (m_todo.hasDueDate() ) { 148 if (m_todo.hasDueDate() ) {
149 QDate date = m_todo.dueDate(); 149 QDate date = m_todo.dueDate();
150 year = date.year(); 150 year = date.year();
151 month = date.month(); 151 month = date.month();
152 day = date.day(); 152 day = date.day();
153 } 153 }
154 QString qu; 154 QString qu;
155 qu = "insert into todolist VALUES(" + QString::number( m_todo.uid() ) + ",'" + m_todo.idsToString( m_todo.categories() ) + "',"; 155 qu = "insert into todolist VALUES(" + QString::number( m_todo.uid() ) + ",'" + m_todo.idsToString( m_todo.categories() ) + "',";
156 qu += QString::number( m_todo.isCompleted() ) + "," + QString::number( m_todo.progress() ) + ","; 156 qu += QString::number( m_todo.isCompleted() ) + "," + QString::number( m_todo.progress() ) + ",";
157 qu += "'"+m_todo.summary()+"','"+QString::number(year)+"-"+QString::number(month)+"-"+QString::number(day)+"',"; 157 qu += "'"+m_todo.summary()+"','"+QString::number(year)+"-"+QString::number(month)+"-"+QString::number(day)+"',";
158 qu += QString::number(m_todo.priority() ) +",'" + m_todo.description() + "')"; 158 qu += QString::number(m_todo.priority() ) +",'" + m_todo.description() + "')";
159 159
160 qWarning("add %s", qu.latin1() ); 160 qWarning("add %s", qu.latin1() );
161 return qu; 161 return qu;
162 } 162 }
163 163
164 RemoveQuery::RemoveQuery(int uid ) 164 RemoveQuery::RemoveQuery(int uid )
165 : OSQLQuery(), m_uid( uid ) {} 165 : OSQLQuery(), m_uid( uid ) {}
166 RemoveQuery::~RemoveQuery() {} 166 RemoveQuery::~RemoveQuery() {}
167 QString RemoveQuery::query()const { 167 QString RemoveQuery::query()const {
168 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid); 168 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
169 return qu; 169 return qu;
170 } 170 }
171 171
172 172
173 ClearQuery::ClearQuery() 173 ClearQuery::ClearQuery()
174 : OSQLQuery() {} 174 : OSQLQuery() {}
175 ClearQuery::~ClearQuery() {} 175 ClearQuery::~ClearQuery() {}
176 QString ClearQuery::query()const { 176 QString ClearQuery::query()const {
177 QString qu = "drop table todolist"; 177 QString qu = "drop table todolist";
178 return qu; 178 return qu;
179 } 179 }
180 FindQuery::FindQuery(int uid) 180 FindQuery::FindQuery(int uid)
181 : OSQLQuery(), m_uid(uid ) { 181 : OSQLQuery(), m_uid(uid ) {
182 } 182 }
183 FindQuery::FindQuery(const QArray<int>& ints) 183 FindQuery::FindQuery(const QArray<int>& ints)
184 : OSQLQuery(), m_uids(ints){ 184 : OSQLQuery(), m_uids(ints){
185 } 185 }
186 FindQuery::~FindQuery() { 186 FindQuery::~FindQuery() {
187 } 187 }
188 QString FindQuery::query()const{ 188 QString FindQuery::query()const{
189 if (m_uids.count() == 0 ) 189 if (m_uids.count() == 0 )
190 return single(); 190 return single();
191 else 191 else
192 return multi(); 192 return multi();
193 } 193 }
194 QString FindQuery::single()const{ 194 QString FindQuery::single()const{
195 QString qu = "select uid, categories, completed, progress, summary, "; 195 QString qu = "select uid, categories, completed, progress, summary, ";
196 qu += "DueDate, priority, description from todolist where uid = " + QString::number(m_uid); 196 qu += "DueDate, priority, description from todolist where uid = " + QString::number(m_uid);
197 return qu; 197 return qu;
198 } 198 }
199 QString FindQuery::multi()const { 199 QString FindQuery::multi()const {
200 QString qu = "select uid, categories, completed, progress, summary, "; 200 QString qu = "select uid, categories, completed, progress, summary, ";
201 qu += "DueDate, priority, description from todolist where "; 201 qu += "DueDate, priority, description from todolist where ";
202 for (uint i = 0; i < m_uids.count(); i++ ) { 202 for (uint i = 0; i < m_uids.count(); i++ ) {
203 qu += " UID = " + QString::number( m_uids[i] ) + " OR"; 203 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
204 } 204 }
205 qu.remove( qu.length()-2, 2 ); 205 qu.remove( qu.length()-2, 2 );
206 return qu; 206 return qu;
207 } 207 }
208 208
209 OverDueQuery::OverDueQuery(): OSQLQuery() {} 209 OverDueQuery::OverDueQuery(): OSQLQuery() {}
210 OverDueQuery::~OverDueQuery() {} 210 OverDueQuery::~OverDueQuery() {}
211 QString OverDueQuery::query()const { 211 QString OverDueQuery::query()const {
212 QDate date = QDate::currentDate(); 212 QDate date = QDate::currentDate();
213 QString str; 213 QString str;
214 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() ); 214 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
215 215
216 return str; 216 return str;
217 } 217 }
218 218
219 219
220 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc ) 220 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
221 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {} 221 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
222 EffQuery::~EffQuery() {} 222 EffQuery::~EffQuery() {}
223 QString EffQuery::query()const { 223 QString EffQuery::query()const {
224 return m_inc ? with() : out(); 224 return m_inc ? with() : out();
225 } 225 }
226 QString EffQuery::with()const { 226 QString EffQuery::with()const {
227 QString str; 227 QString str;
228 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ") 228 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
229 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() ) 229 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
230 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() ); 230 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
231 return str; 231 return str;
232 } 232 }
233 QString EffQuery::out()const { 233 QString EffQuery::out()const {
234 QString str; 234 QString str;
235 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'") 235 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
236 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() ) 236 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
237 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() ); 237 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
238 238
239 return str; 239 return str;
240 } 240 }
241}; 241};
242 242
243OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file ) 243OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
244 : OTodoAccessBackend(), m_dict(15), m_dirty(true) 244 : OTodoAccessBackend(), m_dict(15), m_dirty(true)
245{ 245{
246 QString fi = file; 246 QString fi = file;
247 if ( fi.isEmpty() ) 247 if ( fi.isEmpty() )
248 fi = Global::applicationFileName( "todolist", "todolist.db" ); 248 fi = Global::applicationFileName( "todolist", "todolist.db" );
249 OSQLManager man; 249 OSQLManager man;
250 m_driver = man.standard(); 250 m_driver = man.standard();
251 m_driver->setUrl(fi); 251 m_driver->setUrl(fi);
252 fillDict(); 252 // fillDict();
253} 253}
254 254
255OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){ 255OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
256} 256}
257bool OTodoAccessBackendSQL::load(){ 257bool OTodoAccessBackendSQL::load(){
258 if (!m_driver->open() ) 258 if (!m_driver->open() )
259 return false; 259 return false;
260 260
261 CreateQuery creat; 261 CreateQuery creat;
262 OSQLResult res = m_driver->query(&creat ); 262 OSQLResult res = m_driver->query(&creat );
263 263
264 m_dirty = true; 264 m_dirty = true;
265 return true; 265 return true;
266} 266}
267bool OTodoAccessBackendSQL::reload(){ 267bool OTodoAccessBackendSQL::reload(){
268 return load(); 268 return load();
269} 269}
270 270
271bool OTodoAccessBackendSQL::save(){ 271bool OTodoAccessBackendSQL::save(){
272 return m_driver->close(); 272 return m_driver->close();
273} 273}
274QArray<int> OTodoAccessBackendSQL::allRecords()const { 274QArray<int> OTodoAccessBackendSQL::allRecords()const {
275 if (m_dirty ) 275 if (m_dirty )
276 update(); 276 update();
277 277
278 return m_uids; 278 return m_uids;
279} 279}
280QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){ 280QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
281 QArray<int> ints(0); 281 QArray<int> ints(0);
282 return ints; 282 return ints;
283} 283}
284OTodo OTodoAccessBackendSQL::find(int uid ) const{ 284OTodo OTodoAccessBackendSQL::find(int uid ) const{
285 FindQuery query( uid ); 285 FindQuery query( uid );
286 return todo( m_driver->query(&query) ); 286 return todo( m_driver->query(&query) );
287 287
288} 288}
289OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints, 289OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
290 uint cur, Frontend::CacheDirection dir ) const{ 290 uint cur, Frontend::CacheDirection dir ) const{
291 int CACHE = readAhead(); 291 int CACHE = readAhead();
292 qWarning("searching for %d", uid ); 292 qWarning("searching for %d", uid );
293 QArray<int> search( CACHE ); 293 QArray<int> search( CACHE );
294 uint size =0; 294 uint size =0;
295 OTodo to; 295 OTodo to;
296 296
297 // we try to cache CACHE items 297 // we try to cache CACHE items
298 switch( dir ) { 298 switch( dir ) {
299 /* forward */ 299 /* forward */
300 case 0: 300 case 0: // FIXME: Not a good style to use magic numbers here (eilers)
301 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) { 301 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
302 qWarning("size %d %d", size, ints[i] ); 302 qWarning("size %d %d", size, ints[i] );
303 search[size] = ints[i]; 303 search[size] = ints[i];
304 size++; 304 size++;
305 } 305 }
306 break; 306 break;
307 /* reverse */ 307 /* reverse */
308 case 1: 308 case 1: // FIXME: Not a good style to use magic numbers here (eilers)
309 for (uint i = cur; i != 0 && size < CACHE; i-- ) { 309 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
310 search[size] = ints[i]; 310 search[size] = ints[i];
311 size++; 311 size++;
312 } 312 }
313 break; 313 break;
314 } 314 }
315 search.resize( size ); 315 search.resize( size );
316 FindQuery query( search ); 316 FindQuery query( search );
317 OSQLResult res = m_driver->query( &query ); 317 OSQLResult res = m_driver->query( &query );
318 if ( res.state() != OSQLResult::Success ) 318 if ( res.state() != OSQLResult::Success )
319 return to; 319 return to;
320 320
321 return todo( res ); 321 return todo( res );
322} 322}
323void OTodoAccessBackendSQL::clear() { 323void OTodoAccessBackendSQL::clear() {
324 ClearQuery cle; 324 ClearQuery cle;
325 OSQLResult res = m_driver->query( &cle ); 325 OSQLResult res = m_driver->query( &cle );
326 CreateQuery qu; 326 CreateQuery qu;
327 res = m_driver->query(&qu); 327 res = m_driver->query(&qu);
328} 328}
329bool OTodoAccessBackendSQL::add( const OTodo& t) { 329bool OTodoAccessBackendSQL::add( const OTodo& t) {
330 InsertQuery ins( t ); 330 InsertQuery ins( t );
331 OSQLResult res = m_driver->query( &ins ); 331 OSQLResult res = m_driver->query( &ins );
332 332
333 if ( res.state() == OSQLResult::Failure ) 333 if ( res.state() == OSQLResult::Failure )
334 return false; 334 return false;
335 int c = m_uids.count(); 335 int c = m_uids.count();
336 m_uids.resize( c+1 ); 336 m_uids.resize( c+1 );
337 m_uids[c] = t.uid(); 337 m_uids[c] = t.uid();
338 338
339 return true; 339 return true;
340} 340}
341bool OTodoAccessBackendSQL::remove( int uid ) { 341bool OTodoAccessBackendSQL::remove( int uid ) {
342 RemoveQuery rem( uid ); 342 RemoveQuery rem( uid );
343 OSQLResult res = m_driver->query(&rem ); 343 OSQLResult res = m_driver->query(&rem );
344 344
345 if ( res.state() == OSQLResult::Failure ) 345 if ( res.state() == OSQLResult::Failure )
346 return false; 346 return false;
347 347
348 m_dirty = true; 348 m_dirty = true;
349 return true; 349 return true;
350} 350}
351/* 351/*
352 * FIXME better set query 352 * FIXME better set query
353 * but we need the cache for that 353 * but we need the cache for that
354 * now we remove 354 * now we remove
355 */ 355 */
356bool OTodoAccessBackendSQL::replace( const OTodo& t) { 356bool OTodoAccessBackendSQL::replace( const OTodo& t) {
357 remove( t.uid() ); 357 remove( t.uid() );
358 bool b= add(t); 358 bool b= add(t);
359 m_dirty = false; // we changed some stuff but the UID stayed the same 359 m_dirty = false; // we changed some stuff but the UID stayed the same
360 return b; 360 return b;
361} 361}
362QArray<int> OTodoAccessBackendSQL::overDue() { 362QArray<int> OTodoAccessBackendSQL::overDue() {
363 OverDueQuery qu; 363 OverDueQuery qu;
364 return uids( m_driver->query(&qu ) ); 364 return uids( m_driver->query(&qu ) );
365} 365}
366QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s, 366QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s,
367 const QDate& t, 367 const QDate& t,
368 bool u) { 368 bool u) {
369 EffQuery ef(s, t, u ); 369 EffQuery ef(s, t, u );
370 return uids (m_driver->query(&ef) ); 370 return uids (m_driver->query(&ef) );
371} 371}
372/* 372/*
373 * 373 *
374 */ 374 */
375QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder, 375QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
376 int sortFilter, int cat ) { 376 int sortFilter, int cat ) {
377 qWarning("sorted %d, %d", asc, sortOrder ); 377 qWarning("sorted %d, %d", asc, sortOrder );
378 QString query; 378 QString query;
379 query = "select uid from todolist WHERE "; 379 query = "select uid from todolist WHERE ";
380 380
381 /* 381 /*
382 * Sort Filter stuff 382 * Sort Filter stuff
383 * not that straight forward 383 * not that straight forward
384 * FIXME: Replace magic numbers
384 * 385 *
385 */ 386 */
386 /* Category */ 387 /* Category */
387 if ( sortFilter & 1 ) { 388 if ( sortFilter & 1 ) {
388 QString str; 389 QString str;
389 if (cat != 0 ) str = QString::number( cat ); 390 if (cat != 0 ) str = QString::number( cat );
390 query += " categories like '%" +str+"%' AND"; 391 query += " categories like '%" +str+"%' AND";
391 } 392 }
392 /* Show only overdue */ 393 /* Show only overdue */
393 if ( sortFilter & 2 ) { 394 if ( sortFilter & 2 ) {
394 QDate date = QDate::currentDate(); 395 QDate date = QDate::currentDate();
395 QString due; 396 QString due;
396 QString base; 397 QString base;
397 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() ); 398 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() );
398 query += " " + base + " AND"; 399 query += " " + base + " AND";
399 } 400 }
400 /* not show completed */ 401 /* not show completed */
401 if ( sortFilter & 4 ) { 402 if ( sortFilter & 4 ) {
402 query += " completed = 0 AND"; 403 query += " completed = 0 AND";
403 }else{ 404 }else{
404 query += " ( completed = 1 OR completed = 0) AND"; 405 query += " ( completed = 1 OR completed = 0) AND";
405 } 406 }
406 /* srtip the end */ 407 /* srtip the end */
407 query = query.remove( query.length()-3, 3 ); 408 query = query.remove( query.length()-3, 3 );
408 409
409 410
410 /* 411 /*
411 * sort order stuff 412 * sort order stuff
412 * quite straight forward 413 * quite straight forward
413 */ 414 */
414 query += "ORDER BY "; 415 query += "ORDER BY ";
415 switch( sortOrder ) { 416 switch( sortOrder ) {
416 /* completed */ 417 /* completed */
417 case 0: 418 case 0:
418 query += "completed"; 419 query += "completed";
419 break; 420 break;
420 case 1: 421 case 1:
421 query += "priority"; 422 query += "priority";
422 break; 423 break;
423 case 2: 424 case 2:
424 query += "summary"; 425 query += "summary";
425 break; 426 break;
426 case 3: 427 case 3:
427 query += "DueDate"; 428 query += "DueDate";
428 break; 429 break;
429 } 430 }
430 431
431 if ( !asc ) { 432 if ( !asc ) {
432 qWarning("not ascending!"); 433 qWarning("not ascending!");
433 query += " DESC"; 434 query += " DESC";
434 } 435 }
435 436
436 qWarning( query ); 437 qWarning( query );
437 OSQLRawQuery raw(query ); 438 OSQLRawQuery raw(query );
438 return uids( m_driver->query(&raw) ); 439 return uids( m_driver->query(&raw) );
439} 440}
440bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{ 441bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
441 if ( str == "0-0-0" ) 442 if ( str == "0-0-0" )
442 return false; 443 return false;
443 else{ 444 else{
444 int day, year, month; 445 int day, year, month;
445 QStringList list = QStringList::split("-", str ); 446 QStringList list = QStringList::split("-", str );
446 year = list[0].toInt(); 447 year = list[0].toInt();
447 month = list[1].toInt(); 448 month = list[1].toInt();
448 day = list[2].toInt(); 449 day = list[2].toInt();
449 da.setYMD( year, month, day ); 450 da.setYMD( year, month, day );
450 return true; 451 return true;
451 } 452 }
452} 453}
453OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{ 454OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{
454 if ( res.state() == OSQLResult::Failure ) { 455 if ( res.state() == OSQLResult::Failure ) {
455 OTodo to; 456 OTodo to;
456 return to; 457 return to;
457 } 458 }
458 459
459 OSQLResultItem::ValueList list = res.results(); 460 OSQLResultItem::ValueList list = res.results();
460 OSQLResultItem::ValueList::Iterator it = list.begin(); 461 OSQLResultItem::ValueList::Iterator it = list.begin();
461 qWarning("todo1"); 462 qWarning("todo1");
462 OTodo to = todo( (*it) ); 463 OTodo to = todo( (*it) );
463 cache( to ); 464 cache( to );
464 ++it; 465 ++it;
465 466
466 for ( ; it != list.end(); ++it ) { 467 for ( ; it != list.end(); ++it ) {
467 qWarning("caching"); 468 qWarning("caching");
468 cache( todo( (*it) ) ); 469 cache( todo( (*it) ) );
469 } 470 }
470 return to; 471 return to;
471} 472}
472OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const { 473OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
473 qWarning("todo"); 474 qWarning("todo");
474 bool has = false; QDate da = QDate::currentDate(); 475 bool has = false; QDate da = QDate::currentDate();
475 has = date( da, item.data("DueDate") ); 476 has = date( da, item.data("DueDate") );
476 QStringList cats = QStringList::split(";", item.data("categories") ); 477 QStringList cats = QStringList::split(";", item.data("categories") );
477 478
478 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(), 479 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(),
479 cats, item.data("summary"), item.data("description"), 480 cats, item.data("summary"), item.data("description"),
480 item.data("progress").toUShort(), has, da, 481 item.data("progress").toUShort(), has, da,
481 item.data("uid").toInt() ); 482 item.data("uid").toInt() );
482 return to; 483 return to;
483} 484}
484OTodo OTodoAccessBackendSQL::todo( int uid )const { 485OTodo OTodoAccessBackendSQL::todo( int uid )const {
485 FindQuery find( uid ); 486 FindQuery find( uid );
486 return todo( m_driver->query(&find) ); 487 return todo( m_driver->query(&find) );
487} 488}
488/* 489/*
489 * update the dict 490 * update the dict
490 */ 491 */
491void OTodoAccessBackendSQL::fillDict() { 492void OTodoAccessBackendSQL::fillDict() {
492 /* initialize dict */ 493 /* initialize dict */
493 /* 494 /*
494 * UPDATE dict if you change anything!!! 495 * UPDATE dict if you change anything!!!
496 * FIXME: Isn't this dict obsolete ? (eilers)
495 */ 497 */
496 m_dict.setAutoDelete( TRUE ); 498 m_dict.setAutoDelete( TRUE );
497 m_dict.insert("Categories" , new int(OTodo::Category) ); 499 m_dict.insert("Categories" , new int(OTodo::Category) );
498 m_dict.insert("Uid" , new int(OTodo::Uid) ); 500 m_dict.insert("Uid" , new int(OTodo::Uid) );
499 m_dict.insert("HasDate" , new int(OTodo::HasDate) ); 501 m_dict.insert("HasDate" , new int(OTodo::HasDate) );
500 m_dict.insert("Completed" , new int(OTodo::Completed) ); 502 m_dict.insert("Completed" , new int(OTodo::Completed) );
501 m_dict.insert("Description" , new int(OTodo::Description) ); 503 m_dict.insert("Description" , new int(OTodo::Description) );
502 m_dict.insert("Summary" , new int(OTodo::Summary) ); 504 m_dict.insert("Summary" , new int(OTodo::Summary) );
503 m_dict.insert("Priority" , new int(OTodo::Priority) ); 505 m_dict.insert("Priority" , new int(OTodo::Priority) );
504 m_dict.insert("DateDay" , new int(OTodo::DateDay) ); 506 m_dict.insert("DateDay" , new int(OTodo::DateDay) );
505 m_dict.insert("DateMonth" , new int(OTodo::DateMonth) ); 507 m_dict.insert("DateMonth" , new int(OTodo::DateMonth) );
506 m_dict.insert("DateYear" , new int(OTodo::DateYear) ); 508 m_dict.insert("DateYear" , new int(OTodo::DateYear) );
507 m_dict.insert("Progress" , new int(OTodo::Progress) ); 509 m_dict.insert("Progress" , new int(OTodo::Progress) );
508 m_dict.insert("Completed", new int(OTodo::Completed) ); 510 m_dict.insert("Completed", new int(OTodo::Completed) ); // Why twice ? (eilers)
509 m_dict.insert("CrossReference", new int(OTodo::CrossReference) ); 511 m_dict.insert("CrossReference", new int(OTodo::CrossReference) );
510 m_dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); 512// m_dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); // old stuff (eilers)
511 m_dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); 513// m_dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); // old stuff (eilers)
512} 514}
513/* 515/*
514 * need to be const so let's fool the 516 * need to be const so let's fool the
515 * compiler :( 517 * compiler :(
516 */ 518 */
517void OTodoAccessBackendSQL::update()const { 519void OTodoAccessBackendSQL::update()const {
518 ((OTodoAccessBackendSQL*)this)->m_dirty = false; 520 ((OTodoAccessBackendSQL*)this)->m_dirty = false;
519 LoadQuery lo; 521 LoadQuery lo;
520 OSQLResult res = m_driver->query(&lo); 522 OSQLResult res = m_driver->query(&lo);
521 if ( res.state() != OSQLResult::Success ) 523 if ( res.state() != OSQLResult::Success )
522 return; 524 return;
523 525
524 ((OTodoAccessBackendSQL*)this)->m_uids = uids( res ); 526 ((OTodoAccessBackendSQL*)this)->m_uids = uids( res );
525} 527}
526QArray<int> OTodoAccessBackendSQL::uids( const OSQLResult& res) const{ 528QArray<int> OTodoAccessBackendSQL::uids( const OSQLResult& res) const{
527 529
528 OSQLResultItem::ValueList list = res.results(); 530 OSQLResultItem::ValueList list = res.results();
529 OSQLResultItem::ValueList::Iterator it; 531 OSQLResultItem::ValueList::Iterator it;
530 QArray<int> ints(list.count() ); 532 QArray<int> ints(list.count() );
531 qWarning(" count = %d", list.count() ); 533 qWarning(" count = %d", list.count() );
532 534
533 int i = 0; 535 int i = 0;
534 for (it = list.begin(); it != list.end(); ++it ) { 536 for (it = list.begin(); it != list.end(); ++it ) {
535 ints[i] = (*it).data("uid").toInt(); 537 ints[i] = (*it).data("uid").toInt();
536 i++; 538 i++;
537 } 539 }
538 return ints; 540 return ints;
539} 541}
540 542
543QArray<int> OTodoAccessBackendSQL::matchRegexp( const QRegExp &r ) const
544{
545
546#warning OTodoAccessBackendSQL::matchRegexp() not implemented !!
547
548#if 0
549
550 Copied from xml-backend by not adapted to sql (eilers)
551
552 QArray<int> m_currentQuery( m_events.count() );
553 uint arraycounter = 0;
554
555
556
557 QMap<int, OTodo>::ConstIterator it;
558 for (it = m_events.begin(); it != m_events.end(); ++it ) {
559 if ( it.data().match( r ) )
560 m_currentQuery[arraycounter++] = it.data().uid();
561
562 }
563 // Shrink to fit..
564 m_currentQuery.resize(arraycounter);
565
566 return m_currentQuery;
567#endif
568 QArray<int> empty;
569 return empty;
570}
571QBitArray OTodoAccessBackendSQL::supports()const {
572
573 static QBitArray ar = sup();
574 return ar;
575}
576
577QBitArray OTodoAccessBackendSQL::sup() {
578
579 QBitArray ar( OTodo::CompletedDate + 1 );
580 ar.fill( true );
581 ar[OTodo::CrossReference] = false;
582 ar[OTodo::State ] = false;
583 ar[OTodo::Reminders] = false;
584 ar[OTodo::Notifiers] = false;
585 ar[OTodo::Maintainer] = false;
586
587 return ar;
588}
589
590void OTodoAccessBackendSQL::removeAllCompleted(){
591#warning OTodoAccessBackendSQL::removeAllCompleted() not implemented !!
592
593}
diff --git a/libopie/pim/otodoaccesssql.h b/libopie/pim/otodoaccesssql.h
index 6a4257c..77d8b77 100644
--- a/libopie/pim/otodoaccesssql.h
+++ b/libopie/pim/otodoaccesssql.h
@@ -1,50 +1,56 @@
1#ifndef OPIE_PIM_ACCESS_SQL_H 1#ifndef OPIE_PIM_ACCESS_SQL_H
2#define OPIE_PIM_ACCESS_SQL_H 2#define OPIE_PIM_ACCESS_SQL_H
3 3
4#include <qasciidict.h> 4#include <qasciidict.h>
5 5
6#include "otodoaccessbackend.h" 6#include "otodoaccessbackend.h"
7 7
8class OSQLDriver; 8class OSQLDriver;
9class OSQLResult; 9class OSQLResult;
10class OSQLResultItem; 10class OSQLResultItem;
11class OTodoAccessBackendSQL : public OTodoAccessBackend { 11class OTodoAccessBackendSQL : public OTodoAccessBackend {
12public: 12public:
13 OTodoAccessBackendSQL( const QString& file ); 13 OTodoAccessBackendSQL( const QString& file );
14 ~OTodoAccessBackendSQL(); 14 ~OTodoAccessBackendSQL();
15 15
16 bool load(); 16 bool load();
17 bool reload(); 17 bool reload();
18 bool save(); 18 bool save();
19 QArray<int> allRecords()const; 19 QArray<int> allRecords()const;
20 20
21 QArray<int> queryByExample( const OTodo& t, int settings, const QDateTime& d = QDateTime() ); 21 QArray<int> queryByExample( const OTodo& t, int settings, const QDateTime& d = QDateTime() );
22 OTodo find(int uid)const; 22 OTodo find(int uid)const;
23 OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const; 23 OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
24 void clear(); 24 void clear();
25 bool add( const OTodo& t ); 25 bool add( const OTodo& t );
26 bool remove( int uid ); 26 bool remove( int uid );
27 bool replace( const OTodo& t ); 27 bool replace( const OTodo& t );
28 28
29 QArray<int> overDue(); 29 QArray<int> overDue();
30 QArray<int> effectiveToDos( const QDate& start, 30 QArray<int> effectiveToDos( const QDate& start,
31 const QDate& end, bool includeNoDates ); 31 const QDate& end, bool includeNoDates );
32 QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat ); 32 QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat );
33 33
34 QBitArray supports()const;
35 QArray<int> matchRegexp( const QRegExp &r ) const;
36 void removeAllCompleted();
37
38
34private: 39private:
35 void update()const; 40 void update()const;
36 void fillDict(); 41 void fillDict();
37 inline bool date( QDate& date, const QString& )const; 42 inline bool date( QDate& date, const QString& )const;
38 inline OTodo todo( const OSQLResult& )const; 43 inline OTodo todo( const OSQLResult& )const;
39 inline OTodo todo( OSQLResultItem& )const; 44 inline OTodo todo( OSQLResultItem& )const;
40 inline QArray<int> uids( const OSQLResult& )const; 45 inline QArray<int> uids( const OSQLResult& )const;
41 OTodo todo( int uid )const; 46 OTodo todo( int uid )const;
47 QBitArray sup();
42 48
43 QAsciiDict<int> m_dict; 49 QAsciiDict<int> m_dict;
44 OSQLDriver* m_driver; 50 OSQLDriver* m_driver;
45 QArray<int> m_uids; 51 QArray<int> m_uids;
46 bool m_dirty : 1; 52 bool m_dirty : 1;
47}; 53};
48 54
49 55
50#endif 56#endif
diff --git a/libopie/pim/test/converter.cpp b/libopie/pim/test/converter.cpp
new file mode 100644
index 0000000..0a488f2
--- a/dev/null
+++ b/libopie/pim/test/converter.cpp
@@ -0,0 +1,64 @@
1#include <qpe/qpeapplication.h>
2
3#include <opie/ocontactaccess.h>
4#include <opie/ocontactaccessbackend_xml.h>
5#include <opie/ocontactaccessbackend_sql.h>
6
7#include "converter_base.h"
8
9class ConvertXMLToSQL: public converter_base {
10public:
11 ConvertXMLToSQL()
12 {
13 convertContact();
14 }
15private:
16 void convertContact();
17
18};
19
20
21void ConvertXMLToSQL::convertContact(){
22 qWarning("Converting Contacts from XML to SQL..");
23
24 // Creating backends to the requested databases..
25 OContactAccessBackend* xmlBackend = new OContactAccessBackend_XML( "Converter",
26 QString::null );
27
28 OContactAccessBackend* sqlBackend = new OContactAccessBackend_SQL( QString::null,
29 QString::null );
30 // Put the created backends into frontends to access them
31 OContactAccess* xmlAccess = new OContactAccess ( "addressbook_xml",
32 QString::null , xmlBackend, true );
33
34 OContactAccess* sqlAccess = new OContactAccess ( "addressbook_sql",
35 QString::null , sqlBackend, true );
36
37 // Clean the sql-database..
38 sqlAccess->clear();
39
40 // Now trasmit every contact from the xml database to the sql-database
41 OContactAccess::List contactList = xmlAccess->allRecords();
42 if ( sqlAccess && xmlAccess ){
43 OContactAccess::List::Iterator it;
44 for ( it = contactList.begin(); it != contactList.end(); ++it )
45 sqlAccess->add( *it );
46 }
47
48 // Delete the frontends. Backends will be deleted automatically, too !
49 delete sqlAccess;
50 delete xmlAccess;
51}
52
53int main( int argc, char** argv ) {
54
55 QPEApplication a( argc, argv );
56
57 ConvertXMLToSQL dlg;
58
59 a.showMainWidget( &dlg );
60 // dlg. showMaximized ( );
61
62 return a.exec();
63
64}
diff --git a/libopie/pim/test/converter.pro b/libopie/pim/test/converter.pro
new file mode 100644
index 0000000..aa74bff
--- a/dev/null
+++ b/libopie/pim/test/converter.pro
@@ -0,0 +1,12 @@
1 TEMPLATE= app
2 CONFIG = qt warn_on debug
3 # CONFIG = qt warn_on release
4 #HEADERS =
5 SOURCES = converter.cpp
6INTERFACES = converter_base.ui
7 INCLUDEPATH+= $(OPIEDIR)/include
8 DEPENDPATH+= $(OPIEDIR)/include
9LIBS += -lqpe -lopie
10 TARGET = converter
11
12include ( $(OPIEDIR)/include.pro )
diff --git a/libopie/pim/test/converter_base.ui b/libopie/pim/test/converter_base.ui
new file mode 100644
index 0000000..f680550
--- a/dev/null
+++ b/libopie/pim/test/converter_base.ui
@@ -0,0 +1,43 @@
1<!DOCTYPE UI><UI>
2<class>converter_base</class>
3<widget>
4 <class>QDialog</class>
5 <property stdset="1">
6 <name>name</name>
7 <cstring>converter_base</cstring>
8 </property>
9 <property stdset="1">
10 <name>geometry</name>
11 <rect>
12 <x>0</x>
13 <y>0</y>
14 <width>579</width>
15 <height>211</height>
16 </rect>
17 </property>
18 <property stdset="1">
19 <name>caption</name>
20 <string>Form2</string>
21 </property>
22 <widget>
23 <class>QLabel</class>
24 <property stdset="1">
25 <name>name</name>
26 <cstring>TextLabel1</cstring>
27 </property>
28 <property stdset="1">
29 <name>geometry</name>
30 <rect>
31 <x>340</x>
32 <y>40</y>
33 <width>210</width>
34 <height>20</height>
35 </rect>
36 </property>
37 <property stdset="1">
38 <name>text</name>
39 <string>Converter from XML-&gt;SQL</string>
40 </property>
41 </widget>
42</widget>
43</UI>