summaryrefslogtreecommitdiff
path: root/libopie/pim
authormickeyl <mickeyl>2004-11-16 19:14:18 (UTC)
committer mickeyl <mickeyl>2004-11-16 19:14:18 (UTC)
commitea3945a9bd8f9830f70b1efa133f9df13b19362f (patch) (unidiff)
treef2ea22cc50e9aa8aa73ee7dea148f41c563c9666 /libopie/pim
parent1c6f490e8541626f68422e0a3a7c7281d7f5b7d3 (diff)
downloadopie-ea3945a9bd8f9830f70b1efa133f9df13b19362f.zip
opie-ea3945a9bd8f9830f70b1efa133f9df13b19362f.tar.gz
opie-ea3945a9bd8f9830f70b1efa133f9df13b19362f.tar.bz2
libopie1 goes into unsupported
Diffstat (limited to 'libopie/pim') (more/less context) (show whitespace changes)
-rw-r--r--libopie/pim/.cvsignore2
-rw-r--r--libopie/pim/ABSTRACT18
-rw-r--r--libopie/pim/DESIGN56
-rw-r--r--libopie/pim/TODO34
-rw-r--r--libopie/pim/libopie.pro64
-rw-r--r--libopie/pim/obackendfactory.h194
-rw-r--r--libopie/pim/ocontact.cpp1207
-rw-r--r--libopie/pim/ocontact.h240
-rw-r--r--libopie/pim/ocontactaccess.cpp173
-rw-r--r--libopie/pim/ocontactaccess.h193
-rw-r--r--libopie/pim/ocontactaccessbackend.h128
-rw-r--r--libopie/pim/ocontactaccessbackend_sql.cpp945
-rw-r--r--libopie/pim/ocontactaccessbackend_sql.h107
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.cpp646
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.h96
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.cpp821
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h160
-rw-r--r--libopie/pim/ocontactfields.cpp477
-rw-r--r--libopie/pim/ocontactfields.h67
-rw-r--r--libopie/pim/oconversion.cpp113
-rw-r--r--libopie/pim/oconversion.h48
-rw-r--r--libopie/pim/odatebookaccess.cpp81
-rw-r--r--libopie/pim/odatebookaccess.h44
-rw-r--r--libopie/pim/odatebookaccessbackend.cpp182
-rw-r--r--libopie/pim/odatebookaccessbackend.h90
-rw-r--r--libopie/pim/odatebookaccessbackend_sql.cpp371
-rw-r--r--libopie/pim/odatebookaccessbackend_sql.h65
-rw-r--r--libopie/pim/odatebookaccessbackend_xml.cpp612
-rw-r--r--libopie/pim/odatebookaccessbackend_xml.h55
-rw-r--r--libopie/pim/oevent.cpp717
-rw-r--r--libopie/pim/oevent.h236
-rw-r--r--libopie/pim/opimaccessbackend.h160
-rw-r--r--libopie/pim/opimaccesstemplate.h302
-rw-r--r--libopie/pim/opimcache.h131
-rw-r--r--libopie/pim/opimmaintainer.cpp37
-rw-r--r--libopie/pim/opimmaintainer.h40
-rw-r--r--libopie/pim/opimmainwindow.cpp150
-rw-r--r--libopie/pim/opimmainwindow.h99
-rw-r--r--libopie/pim/opimnotify.cpp227
-rw-r--r--libopie/pim/opimnotify.h144
-rw-r--r--libopie/pim/opimnotifymanager.cpp162
-rw-r--r--libopie/pim/opimnotifymanager.h91
-rw-r--r--libopie/pim/opimrecord.cpp182
-rw-r--r--libopie/pim/opimrecord.h158
-rw-r--r--libopie/pim/opimresolver.cpp198
-rw-r--r--libopie/pim/opimresolver.h90
-rw-r--r--libopie/pim/opimstate.cpp64
-rw-r--r--libopie/pim/opimstate.h46
-rw-r--r--libopie/pim/opimxref.cpp47
-rw-r--r--libopie/pim/opimxref.h39
-rw-r--r--libopie/pim/opimxrefmanager.cpp71
-rw-r--r--libopie/pim/opimxrefmanager.h43
-rw-r--r--libopie/pim/opimxrefpartner.cpp43
-rw-r--r--libopie/pim/opimxrefpartner.h40
-rw-r--r--libopie/pim/orecordlist.h306
-rw-r--r--libopie/pim/orecur.cpp593
-rw-r--r--libopie/pim/orecur.h107
-rw-r--r--libopie/pim/otemplatebase.h98
-rw-r--r--libopie/pim/otimezone.cpp113
-rw-r--r--libopie/pim/otimezone.h71
-rw-r--r--libopie/pim/otodo.cpp519
-rw-r--r--libopie/pim/otodo.h285
-rw-r--r--libopie/pim/otodoaccess.cpp62
-rw-r--r--libopie/pim/otodoaccess.h105
-rw-r--r--libopie/pim/otodoaccessbackend.cpp10
-rw-r--r--libopie/pim/otodoaccessbackend.h28
-rw-r--r--libopie/pim/otodoaccesssql.cpp694
-rw-r--r--libopie/pim/otodoaccesssql.h61
-rw-r--r--libopie/pim/otodoaccessvcal.cpp249
-rw-r--r--libopie/pim/otodoaccessvcal.h40
-rw-r--r--libopie/pim/otodoaccessxml.cpp876
-rw-r--r--libopie/pim/otodoaccessxml.h60
-rw-r--r--libopie/pim/test/converter.cpp107
-rwxr-xr-xlibopie/pim/test/converter.h18
-rw-r--r--libopie/pim/test/converter.pro12
-rw-r--r--libopie/pim/test/converter_base.ui238
-rw-r--r--libopie/pim/test/oevent_test.cpp35
-rw-r--r--libopie/pim/test/oevent_test.pro11
-rw-r--r--libopie/pim/test/test_todo.cpp36
-rw-r--r--libopie/pim/test/todo_test.pro11
80 files changed, 0 insertions, 15551 deletions
diff --git a/libopie/pim/.cvsignore b/libopie/pim/.cvsignore
deleted file mode 100644
index aef62c4..0000000
--- a/libopie/pim/.cvsignore
+++ b/dev/null
@@ -1,2 +0,0 @@
1config.in
2moc*
diff --git a/libopie/pim/ABSTRACT b/libopie/pim/ABSTRACT
deleted file mode 100644
index 5538d19..0000000
--- a/libopie/pim/ABSTRACT
+++ b/dev/null
@@ -1,18 +0,0 @@
1What is Opie PIM? Why is it special?
2Why do we need Opie PIM?
3
4The goal of OpiePIM is to be first of all
5extendable, light weight, scalable and fast.
6For the programmer we try to add a nice but
7powerful API to all classes.
8
9Memory is a costy resource on small and embedded
10devices. So we try to keep the memory usage as
11low as possible. Never the less we won't use structs
12and Pointers in the public API.
13The whole pim framework is value based. Internally we try
14to use implicit sharing as found in other Qt classes as well.
15This makes it possible to give 3rd party devels a nice
16API while keeping the memory usage as low as possible.
17
18We use C++ Templates
diff --git a/libopie/pim/DESIGN b/libopie/pim/DESIGN
deleted file mode 100644
index bd92b1b..0000000
--- a/libopie/pim/DESIGN
+++ b/dev/null
@@ -1,56 +0,0 @@
1Hija to the DESIGN of our OPIE PIM stuff
2
3This design was firstly discussed in the train
4from Frankfurt to Hannover between me (zecke ) and eilers.
5
6We had a look at our pim implementation and the one from
7trolltech and we looked what was missing.
8
9GOALS:
10 - clean implementation
11 - share code
12 - ObjectOriented Design
13 - Scalable
14 - Integration into common solutions like STL and Qt
15 - Addition
16 - Ease of Use
17
18GENERAL:
19 - use templates
20 - have a common base class for all Records OPimRecord
21 - use references instead of pointers
22 - make use of QShared internally memory consumption
23
24We've a 'public' and 'private' part in our lib
25OPimAccessTemplate is the public part. This will be used
26by 3rd party developers to access the PIMs.
27OPimAccessBackend is the backend. You could also call it
28resource.
29
30Both things need to be implemented for different kind of records.
31By using templates we can make sure we share code and the reason
32not to use simple inheretance is that we can specialise quite easy.
33
34For example we have OTodoAccess : public OPimAccessTemplate<OTodo>;
35the we would do
36OTodoAccess::List list = otodoAccess.all();
37OTodoAccess::List::Iterator it;
38for( it = list.begin(); it != list.end(); ++it );
39
40
41as you can see from here it just behaves like you expect from Qt or STL.
42
43The kewlest thing is that List and List::Iterator is free to use if you
44want to implement your own OPimAccessTemplate.
45You just have to sub class it and voila you're done
46
47
48Hope you enjoy using OPIE PIM
49
50regards Holger 'zecke' Freyther
51
52
53
54
55
56
diff --git a/libopie/pim/TODO b/libopie/pim/TODO
deleted file mode 100644
index 9bd2789..0000000
--- a/libopie/pim/TODO
+++ b/dev/null
@@ -1,34 +0,0 @@
1-Add XML Index ( dropped )
2-Add ReadOnly Resources ( to be discussed )
3-Add Sorted/Random Access mode for faster access to the base ( to be discussed )
4
5Yeah Stefan you're right I need to stop the fragmentation but these are just ideas
6we not to talk about.
7
8New Ideas Widgets:
9 OCategoryPopup:
10 Like the function Menu in Xemacs. If there are too many
11 Categories sort them into sub popups. A-B,B-G,H-K....
12 Integrate SUbcategories
13
14
15New Ideas on Infrastructure:
16 -finally switch to sqlite
17 -rework Category Sub Categories
18 -X-Ref!!!!!
19 -signalling ( Peer to Peer/ Backend to Backend communication of changes on a file basis )
20 -Signal the User about updates. Use QSignal and make it generic push from backend
21 to the access.
22 -flocking, mmapping
23 -Generic Tablewidget, getting QString for a record and attribute ( generic ) like QProperty
24 -chooser widgets
25 -hierachies
26 -multiple backends
27 -public private sort public and private on backends. default backend for each if multiple
28 backends loaded. Move from backend to backend.. ( backend mover app? )
29 -importer/exporter
30 -check if cache also drops
31 -port to BigSize Api
32
33 ORedoManager ORedoItem both are templates to allow undoing and redoing to a level...
34 \ No newline at end of file
diff --git a/libopie/pim/libopie.pro b/libopie/pim/libopie.pro
deleted file mode 100644
index 62f235d..0000000
--- a/libopie/pim/libopie.pro
+++ b/dev/null
@@ -1,64 +0,0 @@
1TEMPLATE = lib
2CONFIG += qte warn_on release
3HEADERS = ofontmenu.h \
4 tododb.h \
5 todoevent.h todoresource.h \
6 todovcalresource.h xmltree.h \
7 colordialog.h colorpopupmenu.h \
8 oclickablelabel.h oprocctrl.h \
9 oprocess.h odevice.h \
10 otimepicker.h otabwidget.h \
11 otabbar.h otabinfo.h \
12 ofileselector/ofiledialog.h \
13 ofileselector/ofilelistview.h \
14 ofileselector/ofileselector.h \
15 ofileselector/ofileselectoritem.h \
16 ofileselector/ofileview.h \
17 ofileselector/olister.h \
18 ofileselector/olocallister.h \
19 ofileselector/ofileselectormain.h \
20 pim/opimrecord.h \
21 pim/otodo.h \
22 pim/orecordlist.h \
23 pim/opimaccesstemplate.h \
24 pim/opimaccessbackend.h \
25 pim/otodoaccess.h \
26 pim/otodacessbackend.h \
27 pim/ocontact.h \
28 pim/ocontactaccess.h \
29 pim/ocontactaccessbackend.h \
30 pim/ocontactaccessbackend_xml.h \
31 pim/orecord.h
32
33SOURCES = ofontmenu.cc \
34 xmltree.cc \
35 tododb.cpp todoevent.cpp \
36 todovcalresource.cpp colordialog.cpp \
37 colorpopupmenu.cpp oclickablelabel.cpp \
38 oprocctrl.cpp oprocess.cpp \
39 odevice.cpp otimepicker.cpp \
40 otabwidget.cpp otabbar.cpp \
41 ofileselector/ofiledialog.cpp \
42 ofileselector/ofilelistview.cpp \
43 ofileselector/ofileselector.cpp \
44 ofileselector/ofileselectoritem.cpp \
45 ofileselector/ofileview.cpp \
46 ofileselector/olister.cpp \
47 ofileselector/olocallister.cpp \
48 ofileselector/ofileselectormain.cpp \
49 pim/otodo.cpp \
50 pim/opimrecord.cpp \
51 pim/otodoaccess.cpp \
52 pim/otodoaccessbackend.cpp \
53 pim/ocontact.cpp \
54 pim/ocontactaccess.cpp \
55 pim/orecord.cpp
56
57TARGET = opie
58INCLUDEPATH += $(OPIEDIR)/include
59DESTDIR = $(OPIEDIR)/lib$(PROJMAK)
60#VERSION = 1.0.0
61
62INTERFACES = otimepickerbase.ui
63
64include ( $(OPIEDIR)/include.pro )
diff --git a/libopie/pim/obackendfactory.h b/libopie/pim/obackendfactory.h
deleted file mode 100644
index 761ab9a..0000000
--- a/libopie/pim/obackendfactory.h
+++ b/dev/null
@@ -1,194 +0,0 @@
1/*
2 * Class to manage Backends.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation;
10 * either version 2 of the License, or (at your option) any later
11 * version.
12 * =====================================================================
13 * ToDo: Use plugins
14 * =====================================================================
15 * Version: $Id$
16 * =====================================================================
17 * History:
18 * $Log$
19 * Revision 1.9 2003/12/22 10:19:26 eilers
20 * Finishing implementation of sql-backend for datebook. But I have to
21 * port the PIM datebook application to use it, before I could debug the
22 * whole stuff.
23 * Thus, PIM-Database backend is finished, but highly experimental. And some
24 * parts are still generic. For instance, the "queryByExample()" methods are
25 * not (or not fully) implemented. Todo: custom-entries not stored.
26 * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
27 * expression search in the database, which is not supported by sqlite !
28 * Therefore we need either an extended sqlite or a workaround which would
29 * be very slow and memory consuming..
30 *
31 * Revision 1.8 2003/09/22 14:31:16 eilers
32 * Added first experimental incarnation of sql-backend for addressbook.
33 * Some modifications to be able to compile the todo sql-backend.
34 * A lot of changes fill follow...
35 *
36 * Revision 1.7 2003/08/01 12:30:16 eilers
37 * Merging changes from BRANCH_1_0 to HEAD
38 *
39 * Revision 1.6.4.1 2003/06/30 14:34:19 eilers
40 * Patches from Zecke:
41 * Fixing and cleaning up extraMap handling
42 * Adding d_ptr for binary compatibility in the future
43 *
44 * Revision 1.6 2003/04/13 18:07:10 zecke
45 * More API doc
46 * QString -> const QString&
47 * QString = 0l -> QString::null
48 *
49 * Revision 1.5 2003/02/21 23:31:52 zecke
50 * Add XML datebookresource
51 * -clean up todoaccessxml header
52 * -implement some more stuff in the oeven tester
53 * -extend DefaultFactory to not crash and to use datebook
54 *
55 * -reading of OEvents is working nicely.. saving will be added
56 * tomorrow
57 * -fix spelling in ODateBookAcces
58 *
59 * Revision 1.4 2002/10/14 15:55:18 eilers
60 * Redeactivate SQL.. ;)
61 *
62 * Revision 1.3 2002/10/10 17:08:58 zecke
63 * The Cache is finally in place
64 * I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;)
65 * 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....
66 * I still have to fully implement read ahead
67 * This change is bic but sc
68 *
69 * Revision 1.2 2002/10/08 09:27:36 eilers
70 * Fixed libopie.pro to include the new pim-API.
71 * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to
72 * compile itself would need to install libsqlite, libopiesql...
73 * Therefore, the backend currently uses XML only..
74 *
75 * Revision 1.1 2002/10/07 17:35:01 eilers
76 * added OBackendFactory for advanced backend access
77 *
78 *
79 * =====================================================================
80 */
81#ifndef OPIE_BACKENDFACTORY_H_
82#define OPIE_BACKENDFACTORY_H_
83
84#include <qstring.h>
85#include <qasciidict.h>
86#include <qpe/config.h>
87
88#include "otodoaccessxml.h"
89#include "ocontactaccessbackend_xml.h"
90#include "odatebookaccessbackend_xml.h"
91
92#ifdef __USE_SQL
93#include "otodoaccesssql.h"
94#include "ocontactaccessbackend_sql.h"
95#include "odatebookaccessbackend_sql.h"
96#endif
97
98class OBackendPrivate;
99
100/**
101 * This class is our factory. It will give us the default implementations
102 * of at least Todolist, Contacts and Datebook. In the future this class will
103 * allow users to switch the backend with ( XML->SQLite ) without the need
104 * to recompile.#
105 * This class as the whole PIM Api is making use of templates
106 *
107 * <pre>
108 * OTodoAccessBackend* backend = OBackEndFactory<OTodoAccessBackend>::Default("todo", QString::null );
109 * backend->load();
110 * </pre>
111 *
112 * @author Stefan Eilers
113 * @version 0.1
114 */
115template<class T>
116class OBackendFactory
117{
118 public:
119 OBackendFactory() {};
120
121 enum BACKENDS {
122 TODO,
123 CONTACT,
124 DATE
125 };
126
127 /**
128 * Returns a backend implementation for backendName
129 * @param backendName the type of the backend
130 * @param appName will be passed on to the backend
131 */
132 static T* Default( const QString backendName, const QString& appName ){
133
134 // __asm__("int3");
135
136 Config config( "pimaccess" );
137 config.setGroup ( backendName );
138 QString backend = config.readEntry( "usebackend" );
139
140 qWarning("Selected backend for %s is: %s", backendName.latin1(), backend.latin1() );
141
142 QAsciiDict<int> dict ( 3 );
143 dict.setAutoDelete ( TRUE );
144
145 dict.insert( "todo", new int (TODO) );
146 dict.insert( "contact", new int (CONTACT) );
147 dict.insert( "datebook", new int(DATE) );
148
149 int *find = dict[ backendName ];
150 if (!find ) return 0;
151
152 switch ( *find ){
153 case TODO:
154#ifdef __USE_SQL
155 if ( backend == "sql" )
156 return (T*) new OTodoAccessBackendSQL("");
157#else
158 if ( backend == "sql" )
159 qWarning ("OBackendFactory:: sql Backend for TODO not implemented! Using XML instead!");
160#endif
161
162 return (T*) new OTodoAccessXML( appName );
163 case CONTACT:
164#ifdef __USE_SQL
165 if ( backend == "sql" )
166 return (T*) new OContactAccessBackend_SQL("");
167#else
168 if ( backend == "sql" )
169 qWarning ("OBackendFactory:: sql Backend for CONTACT not implemented! Using XML instead!");
170#endif
171
172 return (T*) new OContactAccessBackend_XML( appName );
173 case DATE:
174#ifdef __USE_SQL
175 if ( backend == "sql" )
176 return (T*) new ODateBookAccessBackend_SQL("");
177#else
178 if ( backend == "sql" )
179 qWarning("OBackendFactory:: sql Backend for DATEBOOK not implemented! Using XML instead!");
180#endif
181
182 return (T*) new ODateBookAccessBackend_XML( appName );
183 default:
184 return NULL;
185 }
186
187
188 }
189 private:
190 OBackendPrivate* d;
191};
192
193
194#endif
diff --git a/libopie/pim/ocontact.cpp b/libopie/pim/ocontact.cpp
deleted file mode 100644
index fcf3b26..0000000
--- a/libopie/pim/ocontact.cpp
+++ b/dev/null
@@ -1,1207 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
4**
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
7** Foundation and appearing in the file LICENSE.GPL included in the
8** packaging of this file.
9**
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.
12**
13** See http://www.trolltech.com/gpl/ for GPL licensing information.
14**
15** Contact info@trolltech.com if any conditions of this licensing are
16** not clear to you.
17**
18**********************************************************************/
19
20#define QTOPIA_INTERNAL_CONTACT_MRE
21
22#include "ocontact.h"
23#include "opimresolver.h"
24#include "oconversion.h"
25
26#include <qpe/stringutil.h>
27#include <qpe/timestring.h>
28#include <qpe/config.h>
29
30#include <qobject.h>
31#include <qregexp.h>
32#include <qstylesheet.h>
33#include <qfileinfo.h>
34#include <qmap.h>
35
36#include <stdio.h>
37
38/*!
39 \class Contact contact.h
40 \brief The Contact class holds the data of an address book entry.
41
42 This data includes information the name of the person, contact
43 information, and business information such as deparment and job title.
44
45 \ingroup qtopiaemb
46 \ingroup qtopiadesktop
47*/
48
49
50/*!
51 Creates a new, empty contact.
52*/
53OContact::OContact()
54 : OPimRecord(), mMap(), d( 0 )
55{
56}
57
58/*!
59 \internal
60 Creates a new contact. The properties of the contact are
61 set from \a fromMap.
62*/
63OContact::OContact( const QMap<int, QString> &fromMap ) :
64 OPimRecord(), mMap( fromMap ), d( 0 )
65{
66 QString cats = mMap[ Qtopia::AddressCategory ];
67 if ( !cats.isEmpty() )
68 setCategories( idsFromString( cats ) );
69
70 QString uidStr = find( Qtopia::AddressUid );
71
72 if ( uidStr.isEmpty() || (uidStr.toInt() == 0) ){
73 qWarning( "Invalid UID found. Generate new one.." );
74 setUid( uidGen().generate() );
75 }else
76 setUid( uidStr.toInt() );
77
78// if ( !uidStr.isEmpty() )
79 // setUid( uidStr.toInt() );
80}
81
82/*!
83 Destroys a contact.
84*/
85OContact::~OContact()
86{
87}
88
89/*! \fn void OContact::setTitle( const QString &str )
90 Sets the title of the contact to \a str.
91*/
92
93/*! \fn void OContact::setFirstName( const QString &str )
94 Sets the first name of the contact to \a str.
95*/
96
97/*! \fn void OContact::setMiddleName( const QString &str )
98 Sets the middle name of the contact to \a str.
99*/
100
101/*! \fn void OContact::setLastName( const QString &str )
102 Sets the last name of the contact to \a str.
103*/
104
105/*! \fn void OContact::setSuffix( const QString &str )
106 Sets the suffix of the contact to \a str.
107*/
108
109/*! \fn void OContact::setFileAs( const QString &str )
110 Sets the contact to filed as \a str.
111*/
112
113/*! \fn void OContact::setDefaultEmail( const QString &str )
114 Sets the default email of the contact to \a str.
115*/
116
117/*! \fn void OContact::setHomeStreet( const QString &str )
118 Sets the home street address of the contact to \a str.
119*/
120
121/*! \fn void OContact::setHomeCity( const QString &str )
122 Sets the home city of the contact to \a str.
123*/
124
125/*! \fn void OContact::setHomeState( const QString &str )
126 Sets the home state of the contact to \a str.
127*/
128
129/*! \fn void OContact::setHomeZip( const QString &str )
130 Sets the home zip code of the contact to \a str.
131*/
132
133/*! \fn void OContact::setHomeCountry( const QString &str )
134 Sets the home country of the contact to \a str.
135*/
136
137/*! \fn void OContact::setHomePhone( const QString &str )
138 Sets the home phone number of the contact to \a str.
139*/
140
141/*! \fn void OContact::setHomeFax( const QString &str )
142 Sets the home fax number of the contact to \a str.
143*/
144
145/*! \fn void OContact::setHomeMobile( const QString &str )
146 Sets the home mobile phone number of the contact to \a str.
147*/
148
149/*! \fn void OContact::setHomeWebpage( const QString &str )
150 Sets the home webpage of the contact to \a str.
151*/
152
153/*! \fn void OContact::setCompany( const QString &str )
154 Sets the company for contact to \a str.
155*/
156
157/*! \fn void OContact::setJobTitle( const QString &str )
158 Sets the job title of the contact to \a str.
159*/
160
161/*! \fn void OContact::setDepartment( const QString &str )
162 Sets the department for contact to \a str.
163*/
164
165/*! \fn void OContact::setOffice( const QString &str )
166 Sets the office for contact to \a str.
167*/
168
169/*! \fn void OContact::setBusinessStreet( const QString &str )
170 Sets the business street address of the contact to \a str.
171*/
172
173/*! \fn void OContact::setBusinessCity( const QString &str )
174 Sets the business city of the contact to \a str.
175*/
176
177/*! \fn void OContact::setBusinessState( const QString &str )
178 Sets the business state of the contact to \a str.
179*/
180
181/*! \fn void OContact::setBusinessZip( const QString &str )
182 Sets the business zip code of the contact to \a str.
183*/
184
185/*! \fn void OContact::setBusinessCountry( const QString &str )
186 Sets the business country of the contact to \a str.
187*/
188
189/*! \fn void OContact::setBusinessPhone( const QString &str )
190 Sets the business phone number of the contact to \a str.
191*/
192
193/*! \fn void OContact::setBusinessFax( const QString &str )
194 Sets the business fax number of the contact to \a str.
195*/
196
197/*! \fn void OContact::setBusinessMobile( const QString &str )
198 Sets the business mobile phone number of the contact to \a str.
199*/
200
201/*! \fn void OContact::setBusinessPager( const QString &str )
202 Sets the business pager number of the contact to \a str.
203*/
204
205/*! \fn void OContact::setBusinessWebpage( const QString &str )
206 Sets the business webpage of the contact to \a str.
207*/
208
209/*! \fn void OContact::setProfession( const QString &str )
210 Sets the profession of the contact to \a str.
211*/
212
213/*! \fn void OContact::setAssistant( const QString &str )
214 Sets the assistant of the contact to \a str.
215*/
216
217/*! \fn void OContact::setManager( const QString &str )
218 Sets the manager of the contact to \a str.
219*/
220
221/*! \fn void OContact::setSpouse( const QString &str )
222 Sets the spouse of the contact to \a str.
223*/
224
225/*! \fn void OContact::setGender( const QString &str )
226 Sets the gender of the contact to \a str.
227*/
228
229/*! \fn void OContact::setNickname( const QString &str )
230 Sets the nickname of the contact to \a str.
231*/
232
233/*! \fn void OContact::setNotes( const QString &str )
234 Sets the notes about the contact to \a str.
235*/
236
237/*! \fn QString OContact::title() const
238 Returns the title of the contact.
239*/
240
241/*! \fn QString OContact::firstName() const
242 Returns the first name of the contact.
243*/
244
245/*! \fn QString OContact::middleName() const
246 Returns the middle name of the contact.
247*/
248
249/*! \fn QString OContact::lastName() const
250 Returns the last name of the contact.
251*/
252
253/*! \fn QString OContact::suffix() const
254 Returns the suffix of the contact.
255*/
256
257/*! \fn QString OContact::fileAs() const
258 Returns the string the contact is filed as.
259*/
260
261/*! \fn QString OContact::defaultEmail() const
262 Returns the default email address of the contact.
263*/
264
265/*! \fn QString OContact::emails() const
266 Returns the list of email address for a contact separated by ';'s in a single
267 string.
268*/
269
270/*! \fn QString OContact::homeStreet() const
271 Returns the home street address of the contact.
272*/
273
274/*! \fn QString OContact::homeCity() const
275 Returns the home city of the contact.
276*/
277
278/*! \fn QString OContact::homeState() const
279 Returns the home state of the contact.
280*/
281
282/*! \fn QString OContact::homeZip() const
283 Returns the home zip of the contact.
284*/
285
286/*! \fn QString OContact::homeCountry() const
287 Returns the home country of the contact.
288*/
289
290/*! \fn QString OContact::homePhone() const
291 Returns the home phone number of the contact.
292*/
293
294/*! \fn QString OContact::homeFax() const
295 Returns the home fax number of the contact.
296*/
297
298/*! \fn QString OContact::homeMobile() const
299 Returns the home mobile number of the contact.
300*/
301
302/*! \fn QString OContact::homeWebpage() const
303 Returns the home webpage of the contact.
304*/
305
306/*! \fn QString OContact::company() const
307 Returns the company for the contact.
308*/
309
310/*! \fn QString OContact::department() const
311 Returns the department for the contact.
312*/
313
314/*! \fn QString OContact::office() const
315 Returns the office for the contact.
316*/
317
318/*! \fn QString OContact::jobTitle() const
319 Returns the job title of the contact.
320*/
321
322/*! \fn QString OContact::profession() const
323 Returns the profession of the contact.
324*/
325
326/*! \fn QString OContact::assistant() const
327 Returns the assistant of the contact.
328*/
329
330/*! \fn QString OContact::manager() const
331 Returns the manager of the contact.
332*/
333
334/*! \fn QString OContact::businessStreet() const
335 Returns the business street address of the contact.
336*/
337
338/*! \fn QString OContact::businessCity() const
339 Returns the business city of the contact.
340*/
341
342/*! \fn QString OContact::businessState() const
343 Returns the business state of the contact.
344*/
345
346/*! \fn QString OContact::businessZip() const
347 Returns the business zip of the contact.
348*/
349
350/*! \fn QString OContact::businessCountry() const
351 Returns the business country of the contact.
352*/
353
354/*! \fn QString OContact::businessPhone() const
355 Returns the business phone number of the contact.
356*/
357
358/*! \fn QString OContact::businessFax() const
359 Returns the business fax number of the contact.
360*/
361
362/*! \fn QString OContact::businessMobile() const
363 Returns the business mobile number of the contact.
364*/
365
366/*! \fn QString OContact::businessPager() const
367 Returns the business pager number of the contact.
368*/
369
370/*! \fn QString OContact::businessWebpage() const
371 Returns the business webpage of the contact.
372*/
373
374/*! \fn QString OContact::spouse() const
375 Returns the spouse of the contact.
376*/
377
378/*! \fn QString OContact::gender() const
379 Returns the gender of the contact.
380*/
381
382/*! \fn QString OContact::nickname() const
383 Returns the nickname of the contact.
384*/
385
386/*! \fn QString OContact::children() const
387 Returns the children of the contact.
388*/
389
390/*! \fn QString OContact::notes() const
391 Returns the notes relating to the the contact.
392*/
393
394/*! \fn QString OContact::groups() const
395 \internal
396 Returns the groups for the contact.
397*/
398
399/*! \fn QStringList OContact::groupList() const
400 \internal
401*/
402
403/*! \fn QString OContact::field(int) const
404 \internal
405*/
406
407/*! \fn void OContact::saveJournal( journal_action, const QString & = QString::null )
408 \internal
409*/
410
411/*! \fn void OContact::setUid( int id )
412 \internal
413 Sets the uid for this record to \a id.
414*/
415
416/*! \enum OContact::journal_action
417 \internal
418*/
419
420/*!
421 \internal
422*/
423QMap<int, QString> OContact::toMap() const
424{
425 QMap<int, QString> map = mMap;
426 QString cats = idsToString( categories() );
427 if ( !cats.isEmpty() )
428 map.insert( Qtopia::AddressCategory, cats );
429 return map;
430}
431
432/*!
433 Returns a rich text formatted QString representing the contents the contact.
434*/
435QString OContact::toRichText() const
436{
437 QString text;
438 QString value, comp, state;
439 QString str;
440 bool marker = false;
441
442 Config cfg("qpe");
443 cfg.setGroup("Appearance");
444 int addressformat = cfg.readNumEntry( "AddressFormat", Zip_City_State );
445
446 // name, jobtitle and company
447 if ( !(value = fullName()).isEmpty() )
448 text += "<b><h3><img src=\"addressbook/AddressBook\"> " + Qtopia::escapeString(value) + "</h3></b>";
449
450 if ( !(value = jobTitle()).isEmpty() )
451 text += Qtopia::escapeString(value) + " ";
452
453 comp = company();
454 if ( !(value = department()).isEmpty() ) {
455 text += Qtopia::escapeString(value);
456 if ( comp )
457 text += ", " + Qtopia::escapeString(comp);
458 }else if ( comp )
459 text += "<br>" + Qtopia::escapeString(comp);
460 text += "<br><hr>";
461
462 // defailt email
463 QString defEmail = defaultEmail();
464 if ( !defEmail.isEmpty() ){
465 text += "<b><img src=\"addressbook/email\"> " + QObject::tr("Default Email: ") + "</b>"
466 + Qtopia::escapeString(defEmail);
467 marker = true;
468 }
469
470 // business address
471 if ( !businessStreet().isEmpty() || !businessCity().isEmpty() ||
472 !businessZip().isEmpty() || !businessCountry().isEmpty() ) {
473 text += QObject::tr( "<br><b>Work Address:</b>" );
474 marker = true;
475 }
476
477 if ( !(value = businessStreet()).isEmpty() ){
478 text += "<br>" + Qtopia::escapeString(value);
479 marker = true;
480 }
481
482 switch( addressformat ){
483 case Zip_City_State:{ // Zip_Code City, State
484 state = businessState();
485 if ( !(value = businessZip()).isEmpty() ){
486 text += "<br>" + Qtopia::escapeString(value) + " ";
487 marker = true;
488
489 }
490 if ( !(value = businessCity()).isEmpty() ) {
491 marker = true;
492 if ( businessZip().isEmpty() && !businessStreet().isEmpty() )
493 text += "<br>";
494 text += Qtopia::escapeString(value);
495 if ( state )
496 text += ", " + Qtopia::escapeString(state);
497 } else if ( !state.isEmpty() ){
498 text += "<br>" + Qtopia::escapeString(state);
499 marker = true;
500 }
501 break;
502 }
503 case City_State_Zip:{ // City, State Zip_Code
504 state = businessState();
505 if ( !(value = businessCity()).isEmpty() ) {
506 marker = true;
507 text += "<br>" + Qtopia::escapeString(value);
508 if ( state )
509 text += ", " + Qtopia::escapeString(state);
510 } else if ( !state.isEmpty() ){
511 text += "<br>" + Qtopia::escapeString(state);
512 marker = true;
513 }
514 if ( !(value = businessZip()).isEmpty() ){
515 text += " " + Qtopia::escapeString(value);
516 marker = true;
517 }
518 break;
519 }
520 }
521
522 if ( !(value = businessCountry()).isEmpty() ){
523 text += "<br>" + Qtopia::escapeString(value);
524 marker = true;
525 }
526
527 // rest of Business data
528 str = office();
529 if ( !str.isEmpty() ){
530 text += "<br><b>" + QObject::tr("Office: ") + "</b>"
531 + Qtopia::escapeString(str);
532 marker = true;
533 }
534 str = businessWebpage();
535 if ( !str.isEmpty() ){
536 text += "<br><b><img src=\"addressbook/webpagework\"> " + QObject::tr("Business Web Page: ") + "</b>"
537 + Qtopia::escapeString(str);
538 marker = true;
539 }
540 str = businessPhone();
541 if ( !str.isEmpty() ){
542 text += "<br><b><img src=\"addressbook/phonework\"> " + QObject::tr("Business Phone: ") + "</b>"
543 + Qtopia::escapeString(str);
544 marker = true;
545 }
546 str = businessFax();
547 if ( !str.isEmpty() ){
548 text += "<br><b><img src=\"addressbook/faxwork\"> " + QObject::tr("Business Fax: ") + "</b>"
549 + Qtopia::escapeString(str);
550 marker = true;
551 }
552 str = businessMobile();
553 if ( !str.isEmpty() ){
554 text += "<br><b><img src=\"addressbook/mobilework\"> " + QObject::tr("Business Mobile: ") + "</b>"
555 + Qtopia::escapeString(str);
556 marker = true;
557 }
558 str = businessPager();
559 if ( !str.isEmpty() ){
560 text += "<br><b>" + QObject::tr("Business Pager: ") + "</b>"
561 + Qtopia::escapeString(str);
562 marker = true;
563 }
564
565 // text += "<br>";
566
567 // home address
568 if ( !homeStreet().isEmpty() || !homeCity().isEmpty() ||
569 !homeZip().isEmpty() || !homeCountry().isEmpty() ) {
570 text += QObject::tr( "<br><b>Home Address:</b>" );
571 marker = true;
572 }
573
574 if ( !(value = homeStreet()).isEmpty() ){
575 text += "<br>" + Qtopia::escapeString(value);
576 marker = true;
577 }
578
579 switch( addressformat ){
580 case Zip_City_State:{ // Zip_Code City, State
581 state = homeState();
582 if ( !(value = homeZip()).isEmpty() ){
583 text += "<br>" + Qtopia::escapeString(value) + " ";
584 marker = true;
585 }
586 if ( !(value = homeCity()).isEmpty() ) {
587 marker = true;
588 if ( homeZip().isEmpty() && !homeStreet().isEmpty() )
589 text += "<br>";
590 text += Qtopia::escapeString(value);
591 if ( !state.isEmpty() )
592 text += ", " + Qtopia::escapeString(state);
593 } else if (!state.isEmpty()) {
594 text += "<br>" + Qtopia::escapeString(state);
595 marker = true;
596 }
597 break;
598 }
599 case City_State_Zip:{ // City, State Zip_Code
600 state = homeState();
601 if ( !(value = homeCity()).isEmpty() ) {
602 marker = true;
603 text += "<br>" + Qtopia::escapeString(value);
604 if ( state )
605 text += ", " + Qtopia::escapeString(state);
606 } else if ( !state.isEmpty() ){
607 text += "<br>" + Qtopia::escapeString(state);
608 marker = true;
609 }
610 if ( !(value = homeZip()).isEmpty() ){
611 text += " " + Qtopia::escapeString(value);
612 marker = true;
613 }
614 break;
615 }
616 }
617
618 if ( !(value = homeCountry()).isEmpty() ){
619 text += "<br>" + Qtopia::escapeString(value);
620 marker = true;
621 }
622
623 // rest of Home data
624 str = homeWebpage();
625 if ( !str.isEmpty() ){
626 text += "<br><b><img src=\"addressbook/webpagehome\"> " + QObject::tr("Home Web Page: ") + "</b>"
627 + Qtopia::escapeString(str);
628 marker = true;
629 }
630 str = homePhone();
631 if ( !str.isEmpty() ){
632 text += "<br><b><img src=\"addressbook/phonehome\"> " + QObject::tr("Home Phone: ") + "</b>"
633 + Qtopia::escapeString(str);
634 marker = true;
635 }
636 str = homeFax();
637 if ( !str.isEmpty() ){
638 text += "<br><b><img src=\"addressbook/faxhome\"> " + QObject::tr("Home Fax: ") + "</b>"
639 + Qtopia::escapeString(str);
640 marker = true;
641 }
642 str = homeMobile();
643 if ( !str.isEmpty() ){
644 text += "<br><b><img src=\"addressbook/mobilehome\"> " + QObject::tr("Home Mobile: ") + "</b>"
645 + Qtopia::escapeString(str);
646 marker = true;
647 }
648
649 if ( marker )
650 text += "<br><hr>";
651
652 // the rest...
653 str = emails();
654 if ( !str.isEmpty() && ( str != defEmail ) )
655 text += "<br><b>" + QObject::tr("All Emails: ") + "</b>"
656 + Qtopia::escapeString(str);
657 str = profession();
658 if ( !str.isEmpty() )
659 text += "<br><b>" + QObject::tr("Profession: ") + "</b>"
660 + Qtopia::escapeString(str);
661 str = assistant();
662 if ( !str.isEmpty() )
663 text += "<br><b>" + QObject::tr("Assistant: ") + "</b>"
664 + Qtopia::escapeString(str);
665 str = manager();
666 if ( !str.isEmpty() )
667 text += "<br><b>" + QObject::tr("Manager: ") + "</b>"
668 + Qtopia::escapeString(str);
669 str = gender();
670 if ( !str.isEmpty() && str.toInt() != 0 ) {
671 text += "<br>";
672 if ( str.toInt() == 1 )
673 str = QObject::tr( "Male" );
674 else if ( str.toInt() == 2 )
675 str = QObject::tr( "Female" );
676 text += "<b>" + QObject::tr("Gender: ") + "</b>" + str;
677 }
678 str = spouse();
679 if ( !str.isEmpty() )
680 text += "<br><b>" + QObject::tr("Spouse: ") + "</b>"
681 + Qtopia::escapeString(str);
682 if ( birthday().isValid() ){
683 str = TimeString::numberDateString( birthday() );
684 text += "<br><b>" + QObject::tr("Birthday: ") + "</b>"
685 + Qtopia::escapeString(str);
686 }
687 if ( anniversary().isValid() ){
688 str = TimeString::numberDateString( anniversary() );
689 text += "<br><b>" + QObject::tr("Anniversary: ") + "</b>"
690 + Qtopia::escapeString(str);
691 }
692 str = children();
693 if ( !str.isEmpty() )
694 text += "<br><b>" + QObject::tr("Children: ") + "</b>"
695 + Qtopia::escapeString(str);
696
697 str = nickname();
698 if ( !str.isEmpty() )
699 text += "<br><b>" + QObject::tr("Nickname: ") + "</b>"
700 + Qtopia::escapeString(str);
701
702 // categories
703 if ( categoryNames("Contacts").count() ){
704 text += "<br><b>" + QObject::tr( "Category:") + "</b> ";
705 text += categoryNames("Contacts").join(", ");
706 }
707
708 // notes last
709 if ( !(value = notes()).isEmpty() ) {
710 text += "<br><hr><b>" + QObject::tr( "Notes:") + "</b> ";
711 QRegExp reg("\n");
712
713 //QString tmp = Qtopia::escapeString(value);
714 QString tmp = QStyleSheet::convertFromPlainText(value);
715 //tmp.replace( reg, "<br>" );
716 text += "<br>" + tmp + "<br>";
717 }
718 return text;
719}
720
721/*!
722 \internal
723*/
724void OContact::insert( int key, const QString &v )
725{
726 QString value = v.stripWhiteSpace();
727 if ( value.isEmpty() )
728 mMap.remove( key );
729 else
730 mMap.insert( key, value );
731}
732
733/*!
734 \internal
735*/
736void OContact::replace( int key, const QString & v )
737{
738 QString value = v.stripWhiteSpace();
739 if ( value.isEmpty() )
740 mMap.remove( key );
741 else
742 mMap.replace( key, value );
743}
744
745/*!
746 \internal
747*/
748QString OContact::find( int key ) const
749{
750 return mMap[key];
751}
752
753/*!
754 \internal
755*/
756QString OContact::displayAddress( const QString &street,
757 const QString &city,
758 const QString &state,
759 const QString &zip,
760 const QString &country ) const
761{
762 QString s = street;
763 if ( !street.isEmpty() )
764 s+= "\n";
765 s += city;
766 if ( !city.isEmpty() && !state.isEmpty() )
767 s += ", ";
768 s += state;
769 if ( !state.isEmpty() && !zip.isEmpty() )
770 s += " ";
771 s += zip;
772 if ( !country.isEmpty() && !s.isEmpty() )
773 s += "\n";
774 s += country;
775 return s;
776}
777
778/*!
779 \internal
780*/
781QString OContact::displayBusinessAddress() const
782{
783 return displayAddress( businessStreet(), businessCity(),
784 businessState(), businessZip(),
785 businessCountry() );
786}
787
788/*!
789 \internal
790*/
791QString OContact::displayHomeAddress() const
792{
793 return displayAddress( homeStreet(), homeCity(),
794 homeState(), homeZip(),
795 homeCountry() );
796}
797
798/*!
799 Returns the full name of the contact
800*/
801QString OContact::fullName() const
802{
803 QString title = find( Qtopia::Title );
804 QString firstName = find( Qtopia::FirstName );
805 QString middleName = find( Qtopia::MiddleName );
806 QString lastName = find( Qtopia::LastName );
807 QString suffix = find( Qtopia::Suffix );
808
809 QString name = title;
810 if ( !firstName.isEmpty() ) {
811 if ( !name.isEmpty() )
812 name += " ";
813 name += firstName;
814 }
815 if ( !middleName.isEmpty() ) {
816 if ( !name.isEmpty() )
817 name += " ";
818 name += middleName;
819 }
820 if ( !lastName.isEmpty() ) {
821 if ( !name.isEmpty() )
822 name += " ";
823 name += lastName;
824 }
825 if ( !suffix.isEmpty() ) {
826 if ( !name.isEmpty() )
827 name += " ";
828 name += suffix;
829 }
830 return name.simplifyWhiteSpace();
831}
832
833/*!
834 Returns a list of the names of the children of the contact.
835*/
836QStringList OContact::childrenList() const
837{
838 return QStringList::split( " ", find( Qtopia::Children ) );
839}
840
841/*! \fn void OContact::insertEmail( const QString &email )
842
843 Insert \a email into the email list. Ensures \a email can only be added
844 once. If there is no default email address set, it sets it to the \a email.
845*/
846
847/*! \fn void OContact::removeEmail( const QString &email )
848
849 Removes the \a email from the email list. If the default email was \a email,
850 then the default email address is assigned to the first email in the
851 email list
852*/
853
854/*! \fn void OContact::clearEmails()
855
856 Clears the email list.
857 */
858
859/*! \fn void OContact::insertEmails( const QStringList &emailList )
860
861 Appends the \a emailList to the exiting email list
862 */
863
864/*!
865 Returns a list of email addresses belonging to the contact, including
866 the default email address.
867*/
868QStringList OContact::emailList() const
869{
870 QString emailStr = emails();
871
872 QStringList r;
873 if ( !emailStr.isEmpty() ) {
874 qDebug(" emailstr ");
875 QStringList l = QStringList::split( emailSeparator(), emailStr );
876 for ( QStringList::ConstIterator it = l.begin();it != l.end();++it )
877 r += (*it).simplifyWhiteSpace();
878 }
879
880 return r;
881}
882
883/*!
884 \overload
885
886 Generates the string for the contact to be filed as from the first,
887 middle and last name of the contact.
888*/
889void OContact::setFileAs()
890{
891 QString lastName, firstName, middleName, fileas;
892
893 lastName = find( Qtopia::LastName );
894 firstName = find( Qtopia::FirstName );
895 middleName = find( Qtopia::MiddleName );
896 if ( !lastName.isEmpty() && !firstName.isEmpty()
897 && !middleName.isEmpty() )
898 fileas = lastName + ", " + firstName + " " + middleName;
899 else if ( !lastName.isEmpty() && !firstName.isEmpty() )
900 fileas = lastName + ", " + firstName;
901 else if ( !lastName.isEmpty() || !firstName.isEmpty() ||
902 !middleName.isEmpty() )
903 fileas = firstName + ( firstName.isEmpty() ? "" : " " )
904 + middleName + ( middleName.isEmpty() ? "" : " " )
905 + lastName;
906
907 replace( Qtopia::FileAs, fileas );
908}
909
910/*!
911 \internal
912 Appends the contact information to \a buf.
913*/
914void OContact::save( QString &buf ) const
915{
916 static const QStringList SLFIELDS = fields();
917 // I'm expecting "<Contact " in front of this...
918 for ( QMap<int, QString>::ConstIterator it = mMap.begin();
919 it != mMap.end(); ++it ) {
920 const QString &value = it.data();
921 int key = it.key();
922 if ( !value.isEmpty() ) {
923 if ( key == Qtopia::AddressCategory || key == Qtopia::AddressUid)
924 continue;
925
926 key -= Qtopia::AddressCategory+1;
927 buf += SLFIELDS[key];
928 buf += "=\"" + Qtopia::escapeString(value) + "\" ";
929 }
930 }
931 buf += customToXml();
932 if ( categories().count() > 0 )
933 buf += "Categories=\"" + idsToString( categories() ) + "\" ";
934 buf += "Uid=\"" + QString::number( uid() ) + "\" ";
935 // You need to close this yourself
936}
937
938
939/*!
940 \internal
941 Returns the list of fields belonging to a contact
942 Never change order of this list ! It has to be regarding
943 enum AddressBookFields !!
944*/
945QStringList OContact::fields()
946{
947 QStringList list;
948
949 list.append( "Title" ); // Not Used!
950 list.append( "FirstName" );
951 list.append( "MiddleName" );
952 list.append( "LastName" );
953 list.append( "Suffix" );
954 list.append( "FileAs" );
955
956 list.append( "JobTitle" );
957 list.append( "Department" );
958 list.append( "Company" );
959 list.append( "BusinessPhone" );
960 list.append( "BusinessFax" );
961 list.append( "BusinessMobile" );
962
963 list.append( "DefaultEmail" );
964 list.append( "Emails" );
965
966 list.append( "HomePhone" );
967 list.append( "HomeFax" );
968 list.append( "HomeMobile" );
969
970 list.append( "BusinessStreet" );
971 list.append( "BusinessCity" );
972 list.append( "BusinessState" );
973 list.append( "BusinessZip" );
974 list.append( "BusinessCountry" );
975 list.append( "BusinessPager" );
976 list.append( "BusinessWebPage" );
977
978 list.append( "Office" );
979 list.append( "Profession" );
980 list.append( "Assistant" );
981 list.append( "Manager" );
982
983 list.append( "HomeStreet" );
984 list.append( "HomeCity" );
985 list.append( "HomeState" );
986 list.append( "HomeZip" );
987 list.append( "HomeCountry" );
988 list.append( "HomeWebPage" );
989
990 list.append( "Spouse" );
991 list.append( "Gender" );
992 list.append( "Birthday" );
993 list.append( "Anniversary" );
994 list.append( "Nickname" );
995 list.append( "Children" );
996
997 list.append( "Notes" );
998 list.append( "Groups" );
999
1000 return list;
1001}
1002
1003
1004/*!
1005 Sets the list of email address for contact to those contained in \a str.
1006 Email address should be separated by ';'s.
1007*/
1008void OContact::setEmails( const QString &str )
1009{
1010 replace( Qtopia::Emails, str );
1011 if ( str.isEmpty() )
1012 setDefaultEmail( QString::null );
1013}
1014
1015/*!
1016 Sets the list of children for the contact to those contained in \a str.
1017*/
1018void OContact::setChildren( const QString &str )
1019{
1020 replace( Qtopia::Children, str );
1021}
1022
1023/*!
1024 \overload
1025 Returns TRUE if the contact matches the regular expression \a regexp.
1026 Otherwise returns FALSE.
1027*/
1028bool OContact::match( const QRegExp &r ) const
1029{
1030 setLastHitField( -1 );
1031 bool match;
1032 match = false;
1033 QMap<int, QString>::ConstIterator it;
1034 for ( it = mMap.begin(); it != mMap.end(); ++it ) {
1035 if ( (*it).find( r ) > -1 ) {
1036 setLastHitField( it.key() );
1037 match = true;
1038 break;
1039 }
1040 }
1041 return match;
1042}
1043
1044
1045QString OContact::toShortText() const
1046{
1047 return ( fullName() );
1048}
1049QString OContact::type() const
1050{
1051 return QString::fromLatin1( "OContact" );
1052}
1053
1054
1055
1056class QString OContact::recordField( int pos ) const
1057{
1058 QStringList SLFIELDS = fields(); // ?? why this ? (se)
1059 return SLFIELDS[pos];
1060}
1061
1062// In future releases, we should store birthday and anniversary
1063// internally as QDate instead of QString !
1064// QString is always too complicate to interprete (DD.MM.YY, DD/MM/YY, MM/DD/YY, etc..)(se)
1065
1066/*! \fn void OContact::setBirthday( const QDate& date )
1067 Sets the birthday for the contact to \a date. If date is null
1068 the current stored date will be removed.
1069*/
1070void OContact::setBirthday( const QDate &v )
1071{
1072 if ( v.isNull() ){
1073 qWarning( "Remove Birthday");
1074 replace( Qtopia::Birthday, QString::null );
1075 return;
1076 }
1077
1078 if ( v.isValid() )
1079 replace( Qtopia::Birthday, OConversion::dateToString( v ) );
1080
1081}
1082
1083
1084/*! \fn void OContact::setAnniversary( const QDate &date )
1085 Sets the anniversary of the contact to \a date. If date is
1086 null, the current stored date will be removed.
1087*/
1088void OContact::setAnniversary( const QDate &v )
1089{
1090 if ( v.isNull() ){
1091 qWarning( "Remove Anniversary");
1092 replace( Qtopia::Anniversary, QString::null );
1093 return;
1094 }
1095
1096 if ( v.isValid() )
1097 replace( Qtopia::Anniversary, OConversion::dateToString( v ) );
1098}
1099
1100/*! \fn QDate OContact::birthday() const
1101 Returns the birthday of the contact.
1102*/
1103QDate OContact::birthday() const
1104{
1105 QString str = find( Qtopia::Birthday );
1106 // qWarning ("Birthday %s", str.latin1() );
1107 if ( !str.isEmpty() )
1108 return OConversion::dateFromString ( str );
1109 else
1110 return QDate();
1111}
1112
1113
1114/*! \fn QDate OContact::anniversary() const
1115 Returns the anniversary of the contact.
1116*/
1117QDate OContact::anniversary() const
1118{
1119 QDate empty;
1120 QString str = find( Qtopia::Anniversary );
1121 // qWarning ("Anniversary %s", str.latin1() );
1122 if ( !str.isEmpty() )
1123 return OConversion::dateFromString ( str );
1124 else
1125 return empty;
1126}
1127
1128
1129void OContact::insertEmail( const QString &v )
1130{
1131 //qDebug("insertEmail %s", v.latin1());
1132 QString e = v.simplifyWhiteSpace();
1133 QString def = defaultEmail();
1134
1135 // if no default, set it as the default email and don't insert
1136 if ( def.isEmpty() ) {
1137 setDefaultEmail( e ); // will insert into the list for us
1138 return;
1139 }
1140
1141 // otherwise, insert assuming doesn't already exist
1142 QString emailsStr = find( Qtopia::Emails );
1143 if ( emailsStr.contains( e ))
1144 return;
1145 if ( !emailsStr.isEmpty() )
1146 emailsStr += emailSeparator();
1147 emailsStr += e;
1148 replace( Qtopia::Emails, emailsStr );
1149}
1150
1151void OContact::removeEmail( const QString &v )
1152{
1153 QString e = v.simplifyWhiteSpace();
1154 QString def = defaultEmail();
1155 QString emailsStr = find( Qtopia::Emails );
1156 QStringList emails = emailList();
1157
1158 // otherwise, must first contain it
1159 if ( !emailsStr.contains( e ) )
1160 return;
1161
1162 // remove it
1163 //qDebug(" removing email from list %s", e.latin1());
1164 emails.remove( e );
1165 // reset the string
1166 emailsStr = emails.join(emailSeparator()); // Sharp's brain dead separator
1167 replace( Qtopia::Emails, emailsStr );
1168
1169 // if default, then replace the default email with the first one
1170 if ( def == e ) {
1171 //qDebug("removeEmail is default; setting new default");
1172 if ( !emails.count() )
1173 clearEmails();
1174 else // setDefaultEmail will remove e from the list
1175 setDefaultEmail( emails.first() );
1176 }
1177}
1178void OContact::clearEmails()
1179{
1180 mMap.remove( Qtopia::DefaultEmail );
1181 mMap.remove( Qtopia::Emails );
1182}
1183void OContact::setDefaultEmail( const QString &v )
1184{
1185 QString e = v.simplifyWhiteSpace();
1186
1187 //qDebug("OContact::setDefaultEmail %s", e.latin1());
1188 replace( Qtopia::DefaultEmail, e );
1189
1190 if ( !e.isEmpty() )
1191 insertEmail( e );
1192
1193}
1194
1195void OContact::insertEmails( const QStringList &v )
1196{
1197 for ( QStringList::ConstIterator it = v.begin(); it != v.end(); ++it )
1198 insertEmail( *it );
1199}
1200int OContact::rtti() {
1201 return OPimResolver::AddressBook;
1202}
1203void OContact::setUid( int i )
1204{
1205 OPimRecord::setUid(i);
1206 replace( Qtopia::AddressUid , QString::number(i));
1207}
diff --git a/libopie/pim/ocontact.h b/libopie/pim/ocontact.h
deleted file mode 100644
index 1d46b81..0000000
--- a/libopie/pim/ocontact.h
+++ b/dev/null
@@ -1,240 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
4**
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
7** Foundation and appearing in the file LICENSE.GPL included in the
8** packaging of this file.
9**
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.
12**
13** See http://www.trolltech.com/gpl/ for GPL licensing information.
14**
15** Contact info@trolltech.com if any conditions of this licensing are
16** not clear to you.
17**
18**********************************************************************/
19
20#ifndef __OCONTACT_H__
21#define __OCONTACT_H__
22
23#include <opie/opimrecord.h>
24#include <qpe/recordfields.h>
25
26#include <qdatetime.h>
27#include <qstringlist.h>
28
29#if defined(QPC_TEMPLATEDLL)
30// MOC_SKIP_BEGIN
31QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>;
32// MOC_SKIP_END
33#endif
34
35class OContactPrivate;
36
37/**
38 * OContact class represents a specialised PIM Record for contacts.
39 * It does store all kind of persopn related information.
40 *
41 * @short Contact Container
42 * @author TT, Stefan Eiler, Holger Freyther
43 */
44class QPC_EXPORT OContact : public OPimRecord
45{
46 friend class DataSet;
47public:
48 OContact();
49 OContact( const QMap<int, QString> &fromMap );
50 virtual ~OContact();
51
52 enum DateFormat{
53 Zip_City_State = 0,
54 City_State_Zip
55 };
56
57 /*
58 * do we need to inline them
59 * if yes do we need to inline them this way?
60 * -zecke
61 */
62 void setTitle( const QString &v ) { replace( Qtopia::Title, v ); }
63 void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); }
64 void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); }
65 void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); }
66 void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); }
67 void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); }
68 void setFileAs();
69
70 // default email address
71 void setDefaultEmail( const QString &v );
72 // inserts email to list and ensure's doesn't already exist
73 void insertEmail( const QString &v );
74 void removeEmail( const QString &v );
75 void clearEmails();
76 void insertEmails( const QStringList &v );
77
78 // home
79 void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); }
80 void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); }
81 void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); }
82 void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); }
83 void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); }
84 void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); }
85 void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); }
86 void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); }
87 void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); }
88
89 // business
90 void setCompany( const QString &v ) { replace( Qtopia::Company, v ); }
91 void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); }
92 void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); }
93 void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); }
94 void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); }
95 void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); }
96 void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); }
97 void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); }
98 void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); }
99 void setOffice( const QString &v ) { replace( Qtopia::Office, v ); }
100 void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); }
101 void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); }
102 void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); }
103 void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); }
104 void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); }
105 void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); }
106 void setManager( const QString &v ) { replace( Qtopia::Manager, v ); }
107
108 // personal
109 void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); }
110 void setGender( const QString &v ) { replace( Qtopia::Gender, v ); }
111 void setBirthday( const QDate &v );
112 void setAnniversary( const QDate &v );
113 void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); }
114 void setChildren( const QString &v );
115
116 // other
117 void setNotes( const QString &v ) { replace( Qtopia::Notes, v); }
118
119 virtual bool match( const QRegExp &regexp ) const;
120
121// // custom
122// void setCustomField( const QString &key, const QString &v )
123// { replace(Custom- + key, v ); }
124
125 // name
126 QString fullName() const;
127 QString title() const { return find( Qtopia::Title ); }
128 QString firstName() const { return find( Qtopia::FirstName ); }
129 QString middleName() const { return find( Qtopia::MiddleName ); }
130 QString lastName() const { return find( Qtopia::LastName ); }
131 QString suffix() const { return find( Qtopia::Suffix ); }
132 QString fileAs() const { return find( Qtopia::FileAs ); }
133
134 // email
135 QString defaultEmail() const { return find( Qtopia::DefaultEmail ); }
136 QStringList emailList() const;
137
138 // home
139 /*
140 * OPimAddress address(enum Location)const;
141 * would be some how nicer...
142 * -zecke
143 */
144 QString homeStreet() const { return find( Qtopia::HomeStreet ); }
145 QString homeCity() const { return find( Qtopia::HomeCity ); }
146 QString homeState() const { return find( Qtopia::HomeState ); }
147 QString homeZip() const { return find( Qtopia::HomeZip ); }
148 QString homeCountry() const { return find( Qtopia::HomeCountry ); }
149 QString homePhone() const { return find( Qtopia::HomePhone ); }
150 QString homeFax() const { return find( Qtopia::HomeFax ); }
151 QString homeMobile() const { return find( Qtopia::HomeMobile ); }
152 QString homeWebpage() const { return find( Qtopia::HomeWebPage ); }
153 /** Multi line string containing all non-empty address info in the form
154 * Street
155 * City, State Zip
156 * Country
157 */
158 QString displayHomeAddress() const;
159
160 // business
161 QString company() const { return find( Qtopia::Company ); }
162 QString businessStreet() const { return find( Qtopia::BusinessStreet ); }
163 QString businessCity() const { return find( Qtopia::BusinessCity ); }
164 QString businessState() const { return find( Qtopia::BusinessState ); }
165 QString businessZip() const { return find( Qtopia::BusinessZip ); }
166 QString businessCountry() const { return find( Qtopia::BusinessCountry ); }
167 QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); }
168 QString jobTitle() const { return find( Qtopia::JobTitle ); }
169 QString department() const { return find( Qtopia::Department ); }
170 QString office() const { return find( Qtopia::Office ); }
171 QString businessPhone() const { return find( Qtopia::BusinessPhone ); }
172 QString businessFax() const { return find( Qtopia::BusinessFax ); }
173 QString businessMobile() const { return find( Qtopia::BusinessMobile ); }
174 QString businessPager() const { return find( Qtopia::BusinessPager ); }
175 QString profession() const { return find( Qtopia::Profession ); }
176 QString assistant() const { return find( Qtopia::Assistant ); }
177 QString manager() const { return find( Qtopia::Manager ); }
178 /** Multi line string containing all non-empty address info in the form
179 * Street
180 * City, State Zip
181 * Country
182 */
183 QString displayBusinessAddress() const;
184
185 //personal
186 QString spouse() const { return find( Qtopia::Spouse ); }
187 QString gender() const { return find( Qtopia::Gender ); }
188 QDate birthday() const;
189 QDate anniversary() const;
190 QString nickname() const { return find( Qtopia::Nickname ); }
191 QString children() const { return find( Qtopia::Children ); }
192 QStringList childrenList() const;
193
194 // other
195 QString notes() const { return find( Qtopia::Notes ); }
196 QString groups() const { return find( Qtopia::Groups ); }
197 QStringList groupList() const;
198
199 QString toRichText() const;
200 QMap<int, QString> toMap() const;
201 QString field( int key ) const { return find( key ); }
202
203
204 void setUid( int i );
205
206 QString toShortText()const;
207 QString type()const;
208 class QString recordField(int) const;
209
210 // Why private ? (eilers,se)
211 QString emailSeparator() const { return " "; }
212
213 // the emails should be seperated by a comma
214 void setEmails( const QString &v );
215 QString emails() const { return find( Qtopia::Emails ); }
216 static int rtti();
217
218private:
219 // The XML Backend needs some access to the private functions
220 friend class OContactAccessBackend_XML;
221
222 void insert( int key, const QString &value );
223 void replace( int key, const QString &value );
224 QString find( int key ) const;
225 static QStringList fields();
226
227 void save( QString &buf ) const;
228
229 QString displayAddress( const QString &street,
230 const QString &city,
231 const QString &state,
232 const QString &zip,
233 const QString &country ) const;
234
235 QMap<int, QString> mMap;
236 OContactPrivate *d;
237};
238
239
240#endif
diff --git a/libopie/pim/ocontactaccess.cpp b/libopie/pim/ocontactaccess.cpp
deleted file mode 100644
index bc359f7..0000000
--- a/libopie/pim/ocontactaccess.cpp
+++ b/dev/null
@@ -1,173 +0,0 @@
1/*
2 * Class to manage the Contacts.
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 * Info: This class could just work with a change in the header-file
13 * of the Contact class ! Therefore our libopie only compiles
14 * with our version of libqpe
15 * =====================================================================
16 * ToDo: XML-Backend: Automatic reload if something was changed...
17 *
18 *
19 * =====================================================================
20 * Version: $Id$
21 * =====================================================================
22 * History:
23 * $Log$
24 * Revision 1.9 2004/03/02 12:14:22 alwin
25 * run the optimize_connect script
26 * the whole cvs is tagged with "before_optimize_connect" if there are problems you
27 * can check the diff (but it had compiled and run here)
28 *
29 * Revision 1.8 2003/05/08 13:55:09 tille
30 * search stuff
31 * and match, toRichText & toShortText in oevent
32 *
33 * Revision 1.7 2002/11/13 14:14:51 eilers
34 * Added sorted for Contacts..
35 *
36 * Revision 1.6 2002/11/01 15:10:42 eilers
37 * Added regExp-search in database for all fields in a contact.
38 *
39 * Revision 1.5 2002/10/16 10:52:40 eilers
40 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
41 *
42 * Revision 1.4 2002/10/14 16:21:54 eilers
43 * Some minor interface updates
44 *
45 * Revision 1.3 2002/10/07 17:34:24 eilers
46 * added OBackendFactory for advanced backend access
47 *
48 * Revision 1.2 2002/10/02 16:18:11 eilers
49 * debugged and seems to work almost perfectly ..
50 *
51 * Revision 1.1 2002/09/27 17:11:44 eilers
52 * Added API for accessing the Contact-Database ! It is compiling, but
53 * please do not expect that anything is working !
54 * I will debug that stuff in the next time ..
55 * Please read README_COMPILE for compiling !
56 *
57 *
58 */
59
60#include "ocontactaccess.h"
61#include "obackendfactory.h"
62
63#include <qasciidict.h>
64#include <qdatetime.h>
65#include <qfile.h>
66#include <qregexp.h>
67#include <qlist.h>
68#include <qcopchannel_qws.h>
69
70//#include <qpe/qcopenvelope_qws.h>
71#include <qpe/global.h>
72
73#include <errno.h>
74#include <fcntl.h>
75#include <unistd.h>
76#include <stdlib.h>
77
78#include "ocontactaccessbackend_xml.h"
79
80
81OContactAccess::OContactAccess ( const QString appname, const QString ,
82 OContactAccessBackend* end, bool autosync ):
83 OPimAccessTemplate<OContact>( end )
84{
85 /* take care of the backend. If there is no one defined, we
86 * will use the XML-Backend as default (until we have a cute SQL-Backend..).
87 */
88 if( end == 0 ) {
89 qWarning ("Using BackendFactory !");
90 end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname );
91 }
92 // Set backend locally and in template
93 m_backEnd = end;
94 OPimAccessTemplate<OContact>::setBackEnd (end);
95
96
97 /* Connect signal of external db change to function */
98 QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this );
99 connect( dbchannel, SIGNAL(received(const QCString&,const QByteArray&)),
100 this, SLOT(copMessage(const QCString&,const QByteArray&)) );
101 if ( autosync ){
102 QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this );
103 connect( syncchannel, SIGNAL(received(const QCString&,const QByteArray&)),
104 this, SLOT(copMessage(const QCString&,const QByteArray&)) );
105 }
106
107
108}
109OContactAccess::~OContactAccess ()
110{
111 /* The user may forget to save the changed database, therefore try to
112 * do it for him..
113 */
114 save();
115 // delete m_backEnd; is done by template..
116}
117
118
119bool OContactAccess::save ()
120{
121 /* If the database was changed externally, we could not save the
122 * Data. This will remove added items which is unacceptable !
123 * Therefore: Reload database and merge the data...
124 */
125 if ( OPimAccessTemplate<OContact>::wasChangedExternally() )
126 reload();
127
128 bool status = OPimAccessTemplate<OContact>::save();
129 if ( !status ) return false;
130
131 /* Now tell everyone that new data is available.
132 */
133 QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
134
135 return true;
136}
137
138const uint OContactAccess::querySettings()
139{
140 return ( m_backEnd->querySettings() );
141}
142
143bool OContactAccess::hasQuerySettings ( int querySettings ) const
144{
145 return ( m_backEnd->hasQuerySettings ( querySettings ) );
146}
147ORecordList<OContact> OContactAccess::sorted( bool ascending, int sortOrder, int sortFilter, int cat ) const
148{
149 QArray<int> matchingContacts = m_backEnd -> sorted( ascending, sortOrder, sortFilter, cat );
150 return ( ORecordList<OContact>(matchingContacts, this) );
151}
152
153
154bool OContactAccess::wasChangedExternally()const
155{
156 return ( m_backEnd->wasChangedExternally() );
157}
158
159
160void OContactAccess::copMessage( const QCString &msg, const QByteArray & )
161{
162 if ( msg == "addressbookUpdated()" ){
163 qWarning ("OContactAccess: Received addressbokUpdated()");
164 emit signalChanged ( this );
165 } else if ( msg == "flush()" ) {
166 qWarning ("OContactAccess: Received flush()");
167 save ();
168 } else if ( msg == "reload()" ) {
169 qWarning ("OContactAccess: Received reload()");
170 reload ();
171 emit signalChanged ( this );
172 }
173}
diff --git a/libopie/pim/ocontactaccess.h b/libopie/pim/ocontactaccess.h
deleted file mode 100644
index bd6da40..0000000
--- a/libopie/pim/ocontactaccess.h
+++ b/dev/null
@@ -1,193 +0,0 @@
1/*
2 * Class to manage the Contacts.
3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
6 *
7 * =====================================================================
8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation;
11 * either version 2 of the License, or (at your option) any later
12 * version.
13 * =====================================================================
14 * ToDo: Define enum for query settings
15 * =====================================================================
16 * Version: $Id$
17 * =====================================================================
18 * History:
19 * $Log$
20 * Revision 1.10 2003/12/22 10:19:26 eilers
21 * Finishing implementation of sql-backend for datebook. But I have to
22 * port the PIM datebook application to use it, before I could debug the
23 * whole stuff.
24 * Thus, PIM-Database backend is finished, but highly experimental. And some
25 * parts are still generic. For instance, the "queryByExample()" methods are
26 * not (or not fully) implemented. Todo: custom-entries not stored.
27 * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
28 * expression search in the database, which is not supported by sqlite !
29 * Therefore we need either an extended sqlite or a workaround which would
30 * be very slow and memory consuming..
31 *
32 * Revision 1.9 2003/08/01 12:30:16 eilers
33 * Merging changes from BRANCH_1_0 to HEAD
34 *
35 * Revision 1.8.2.1 2003/06/30 14:34:19 eilers
36 * Patches from Zecke:
37 * Fixing and cleaning up extraMap handling
38 * Adding d_ptr for binary compatibility in the future
39 *
40 * Revision 1.8 2003/05/08 13:55:09 tille
41 * search stuff
42 * and match, toRichText & toShortText in oevent
43 *
44 * Revision 1.7 2003/04/13 18:07:10 zecke
45 * More API doc
46 * QString -> const QString&
47 * QString = 0l -> QString::null
48 *
49 * Revision 1.6 2003/01/02 14:27:12 eilers
50 * Improved query by example: Search by date is possible.. First step
51 * for a today plugin for birthdays..
52 *
53 * Revision 1.5 2002/11/13 14:14:51 eilers
54 * Added sorted for Contacts..
55 *
56 * Revision 1.4 2002/11/01 15:10:42 eilers
57 * Added regExp-search in database for all fields in a contact.
58 *
59 * Revision 1.3 2002/10/16 10:52:40 eilers
60 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
61 *
62 * Revision 1.2 2002/10/14 16:21:54 eilers
63 * Some minor interface updates
64 *
65 * Revision 1.1 2002/09/27 17:11:44 eilers
66 * Added API for accessing the Contact-Database ! It is compiling, but
67 * please do not expect that anything is working !
68 * I will debug that stuff in the next time ..
69 * Please read README_COMPILE for compiling !
70 *
71 * =====================================================================
72 */
73#ifndef _OCONTACTACCESS_H
74#define _OCONTACTACCESS_H
75
76#include <qobject.h>
77
78#include <qpe/qcopenvelope_qws.h>
79
80#include <qvaluelist.h>
81#include <qfileinfo.h>
82
83#include "ocontact.h"
84#include "ocontactaccessbackend.h"
85#include "opimaccesstemplate.h"
86
87/**
88 * Class to access the contacts database.
89 * This is just a frontend for the real database handling which is
90 * done by the backend.
91 * This class is used to access the Contacts on a system. This class as any OPIE PIM
92 * class is backend independent.
93 * @author Stefan Eilers, Holger Freyther
94 * @see OPimAccessTemplate
95 */
96class OContactAccess: public QObject, public OPimAccessTemplate<OContact>
97{
98 Q_OBJECT
99
100 public:
101 /**
102 * Create Database with contacts (addressbook).
103 * @param appname Name of application which wants access to the database
104 * (i.e. "todolist")
105 * @param filename The name of the database file. If not set, the default one
106 * is used.
107 * @param backend Pointer to an alternative Backend. If not set, we will use
108 * the default backend.
109 * @param handlesync If <b>true</b> the database stores the current state
110 * automatically if it receives the signals <i>flush()</i> and <i>reload()</i>
111 * which are used before and after synchronisation. If the application wants
112 * to react itself, it should be disabled by setting it to <b>false</b>
113 * @see OContactAccessBackend
114 */
115 OContactAccess (const QString appname, const QString filename = 0l,
116 OContactAccessBackend* backend = 0l, bool handlesync = true);
117 ~OContactAccess ();
118
119 /** Constants for query.
120 * Use this constants to set the query parameters.
121 * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes !
122 * @see queryByExample()
123 */
124 enum QuerySettings {
125 WildCards = 0x0001,
126 IgnoreCase = 0x0002,
127 RegExp = 0x0004,
128 ExactMatch = 0x0008,
129 MatchOne = 0x0010, // Only one Entry must match
130 DateDiff = 0x0020, // Find all entries from today until given date
131 DateYear = 0x0040, // The year matches
132 DateMonth = 0x0080, // The month matches
133 DateDay = 0x0100, // The day matches
134 };
135
136
137 /** Return all Contacts in a sorted manner.
138 * @param ascending true: Sorted in acending order.
139 * @param sortOrder Currently not implemented. Just defined to stay compatible to otodoaccess
140 * @param sortFilter Currently not implemented. Just defined to stay compatible to otodoaccess
141 * @param cat Currently not implemented. Just defined to stay compatible to otodoaccess
142 */
143 List sorted( bool ascending, int sortOrder, int sortFilter, int cat ) const;
144
145 /** Return all possible settings.
146 * @return All settings provided by the current backend
147 * (i.e.: query_WildCards & query_IgnoreCase)
148 */
149 const uint querySettings();
150
151 /** Check whether settings are correct.
152 * @return <i>true</i> if the given settings are correct and possible.
153 */
154 bool hasQuerySettings ( int querySettings ) const;
155
156 /**
157 * if the resource was changed externally.
158 * You should use the signal instead of polling possible changes !
159 */
160 bool wasChangedExternally()const;
161
162
163 /** Save contacts database.
164 * Save is more a "commit". After calling this function, all changes are public available.
165 * @return true if successful
166 */
167 bool save();
168
169 signals:
170 /* Signal is emitted if the database was changed. Therefore
171 * we may need to reload to stay consistent.
172 * @param which Pointer to the database who created this event. This pointer
173 * is useful if an application has to handle multiple databases at the same time.
174 * @see reload()
175 */
176 void signalChanged ( const OContactAccess *which );
177
178
179 private:
180 // class OContactAccessPrivate;
181 // OContactAccessPrivate* d;
182 OContactAccessBackend *m_backEnd;
183 bool m_loading:1;
184
185 private slots:
186 void copMessage( const QCString &msg, const QByteArray &data );
187
188 private:
189 class Private;
190 Private *d;
191
192};
193#endif
diff --git a/libopie/pim/ocontactaccessbackend.h b/libopie/pim/ocontactaccessbackend.h
deleted file mode 100644
index 0eac6dc..0000000
--- a/libopie/pim/ocontactaccessbackend.h
+++ b/dev/null
@@ -1,128 +0,0 @@
1/**
2 * The class responsible for managing a backend.
3 * The implementation of this abstract class contains
4 * the complete database handling.
5 *
6 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
7 * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
8 *
9 * =====================================================================
10 *This program is free software; you can redistribute it and/or
11 *modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation;
13 * either version 2 of the License, or (at your option) any later
14 * version.
15 * =====================================================================
16 * ToDo: Define enum for query settings
17 * =====================================================================
18 * Version: $Id$
19 * =====================================================================
20 * History:
21 * $Log$
22 * Revision 1.7 2004/02/19 02:05:37 zecke
23 * Add notes for API fixes and BC stuff
24 *
25 * Revision 1.6 2003/08/01 12:30:16 eilers
26 * Merging changes from BRANCH_1_0 to HEAD
27 *
28 * Revision 1.5.4.1 2003/06/30 14:34:19 eilers
29 * Patches from Zecke:
30 * Fixing and cleaning up extraMap handling
31 * Adding d_ptr for binary compatibility in the future
32 *
33 * Revision 1.5 2003/04/13 18:07:10 zecke
34 * More API doc
35 * QString -> const QString&
36 * QString = 0l -> QString::null
37 *
38 * Revision 1.4 2002/11/13 14:14:51 eilers
39 * Added sorted for Contacts..
40 *
41 * Revision 1.3 2002/11/01 15:10:42 eilers
42 * Added regExp-search in database for all fields in a contact.
43 *
44 * Revision 1.2 2002/10/07 17:34:24 eilers
45 * added OBackendFactory for advanced backend access
46 *
47 * Revision 1.1 2002/09/27 17:11:44 eilers
48 * Added API for accessing the Contact-Database ! It is compiling, but
49 * please do not expect that anything is working !
50 * I will debug that stuff in the next time ..
51 * Please read README_COMPILE for compiling !
52 *
53 * =====================================================================
54 *
55 */
56
57#ifndef _OCONTACTACCESSBACKEND_H_
58#define _OCONTACTACCESSBACKEND_H_
59
60#include "ocontact.h"
61#include "opimaccessbackend.h"
62
63#include <qregexp.h>
64
65/**
66 * This class represents the interface of all Contact Backends.
67 * Derivates of this class will be used to access the contacts.
68 * As implementation currently XML and vCard exist. This class needs to be implemented
69 * if you want to provide your own storage.
70 * In all queries a list of uids is passed on instead of loading the actual record!
71 *
72 * @see OContactAccessBackend_VCard
73 * @see OContactAccessBackend_XML
74 */
75class OContactAccessBackend: public OPimAccessBackend<OContact> {
76 public:
77 /**
78 * @todo make non line in regard to BC guide of KDE
79 */
80 OContactAccessBackend() {}
81 /**
82 * @todo make non inline in regard to the BC guide of KDE
83 */
84 virtual ~OContactAccessBackend() {}
85
86
87 /**
88 * Return if database was changed externally.
89 * This may just make sense on file based databases like a XML-File.
90 * It is used to prevent to overwrite the current database content
91 * if the file was already changed by something else !
92 * If this happens, we have to reload before save our data.
93 * If we use real databases, this should be handled by the database
94 * management system themselve, therefore this function should always return false in
95 * this case. It is not our problem to handle this conflict ...
96 * @return <i>true</i> if the database was changed and if save without reload will
97 * be dangerous. <i>false</i> if the database was not changed or it is save to write
98 * in this situation.
99 */
100 virtual bool wasChangedExternally() = 0;
101
102 virtual QArray<int> matchRegexp( const QRegExp &r ) const = 0;
103
104 /**
105 * Return all possible settings.
106 * @return All settings provided by the current backend
107 * (i.e.: query_WildCards & query_IgnoreCase)
108 */
109 virtual const uint querySettings() = 0;
110
111 /**
112 * Check whether settings are correct.
113 * @return <i>true</i> if the given settings are correct and possible.
114 */
115 virtual bool hasQuerySettings (uint querySettings) const = 0;
116
117 /**
118 * FIXME!!!
119 * Returns a sorted list of records either ascendinf or descending for a giving criteria and category
120 */
121 virtual QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat ) = 0;
122
123
124private:
125 class Private;
126 Private *d;
127};
128#endif
diff --git a/libopie/pim/ocontactaccessbackend_sql.cpp b/libopie/pim/ocontactaccessbackend_sql.cpp
deleted file mode 100644
index d20df56..0000000
--- a/libopie/pim/ocontactaccessbackend_sql.cpp
+++ b/dev/null
@@ -1,945 +0,0 @@
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.5 2004/03/14 13:50:35 alwin
18 * namespace correction
19 *
20 * Revision 1.4 2003/12/22 10:19:26 eilers
21 * Finishing implementation of sql-backend for datebook. But I have to
22 * port the PIM datebook application to use it, before I could debug the
23 * whole stuff.
24 * Thus, PIM-Database backend is finished, but highly experimental. And some
25 * parts are still generic. For instance, the "queryByExample()" methods are
26 * not (or not fully) implemented. Todo: custom-entries not stored.
27 * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
28 * expression search in the database, which is not supported by sqlite !
29 * Therefore we need either an extended sqlite or a workaround which would
30 * be very slow and memory consuming..
31 *
32 * Revision 1.3 2003/12/08 15:18:10 eilers
33 * Committing unfinished sql implementation before merging to libopie2 starts..
34 *
35 * Revision 1.2 2003/09/29 07:44:26 eilers
36 * Improvement of PIM-SQL Databases, but search queries are still limited.
37 * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space.
38 * Todo: Started to add new attributes. Some type conversions missing.
39 *
40 * Revision 1.1 2003/09/22 14:31:16 eilers
41 * Added first experimental incarnation of sql-backend for addressbook.
42 * Some modifications to be able to compile the todo sql-backend.
43 * A lot of changes fill follow...
44 *
45 */
46
47#include "ocontactaccessbackend_sql.h"
48
49#include <qarray.h>
50#include <qdatetime.h>
51#include <qstringlist.h>
52
53#include <qpe/global.h>
54#include <qpe/recordfields.h>
55
56#include <opie/ocontactfields.h>
57#include <opie/oconversion.h>
58#include <opie2/osqldriver.h>
59#include <opie2/osqlresult.h>
60#include <opie2/osqlmanager.h>
61#include <opie2/osqlquery.h>
62
63using namespace Opie::DB;
64
65
66// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead
67// vertical like "uid, type, value".
68// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !!
69#define __STORE_HORIZONTAL_
70
71// Distinct loading is not very fast. If I expect that every person has just
72// one (and always one) 'Last Name', I can request all uid's for existing lastnames,
73// which is faster..
74// But this may not be true for all entries, like company contacts..
75// The current AddressBook application handles this problem, but other may not.. (eilers)
76#define __USE_SUPERFAST_LOADQUERY
77
78
79/*
80 * Implementation of used query types
81 * CREATE query
82 * LOAD query
83 * INSERT
84 * REMOVE
85 * CLEAR
86 */
87namespace {
88 /**
89 * CreateQuery for the Todolist Table
90 */
91 class CreateQuery : public OSQLQuery {
92 public:
93 CreateQuery();
94 ~CreateQuery();
95 QString query()const;
96 };
97
98 /**
99 * Clears (delete) a Table
100 */
101 class ClearQuery : public OSQLQuery {
102 public:
103 ClearQuery();
104 ~ClearQuery();
105 QString query()const;
106
107 };
108
109
110 /**
111 * LoadQuery
112 * this one queries for all uids
113 */
114 class LoadQuery : public OSQLQuery {
115 public:
116 LoadQuery();
117 ~LoadQuery();
118 QString query()const;
119 };
120
121 /**
122 * inserts/adds a OContact to the table
123 */
124 class InsertQuery : public OSQLQuery {
125 public:
126 InsertQuery(const OContact& );
127 ~InsertQuery();
128 QString query()const;
129 private:
130 OContact m_contact;
131 };
132
133
134 /**
135 * removes one from the table
136 */
137 class RemoveQuery : public OSQLQuery {
138 public:
139 RemoveQuery(int uid );
140 ~RemoveQuery();
141 QString query()const;
142 private:
143 int m_uid;
144 };
145
146 /**
147 * a find query for noncustom elements
148 */
149 class FindQuery : public OSQLQuery {
150 public:
151 FindQuery(int uid);
152 FindQuery(const QArray<int>& );
153 ~FindQuery();
154 QString query()const;
155 private:
156 QString single()const;
157 QString multi()const;
158 QArray<int> m_uids;
159 int m_uid;
160 };
161
162 /**
163 * a find query for custom elements
164 */
165 class FindCustomQuery : public OSQLQuery {
166 public:
167 FindCustomQuery(int uid);
168 FindCustomQuery(const QArray<int>& );
169 ~FindCustomQuery();
170 QString query()const;
171 private:
172 QString single()const;
173 QString multi()const;
174 QArray<int> m_uids;
175 int m_uid;
176 };
177
178
179
180 // We using three tables to store the information:
181 // 1. addressbook : It contains General information about the contact (non custom)
182 // 2. custom_data : Not official supported entries
183 // All tables are connected by the uid of the contact.
184 // Maybe I should add a table for meta-information ?
185 CreateQuery::CreateQuery() : OSQLQuery() {}
186 CreateQuery::~CreateQuery() {}
187 QString CreateQuery::query()const {
188 QString qu;
189#ifdef __STORE_HORIZONTAL_
190
191 qu += "create table addressbook( uid PRIMARY KEY ";
192
193 QStringList fieldList = OContactFields::untrfields( false );
194 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
195 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it );
196 }
197 qu += " );";
198
199 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
200
201#else
202
203 qu += "create table addressbook( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id));";
204 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
205 // qu += "create table dates( uid PRIMARY KEY, type, day, month, year, hour, minute, second );";
206
207#endif // __STORE_HORIZONTAL_
208 return qu;
209 }
210
211 ClearQuery::ClearQuery()
212 : OSQLQuery() {}
213 ClearQuery::~ClearQuery() {}
214 QString ClearQuery::query()const {
215 QString qu = "drop table addressbook;";
216 qu += "drop table custom_data;";
217 // qu += "drop table dates;";
218 return qu;
219 }
220
221
222 LoadQuery::LoadQuery() : OSQLQuery() {}
223 LoadQuery::~LoadQuery() {}
224 QString LoadQuery::query()const {
225 QString qu;
226#ifdef __STORE_HORIZONTAL_
227 qu += "select uid from addressbook";
228#else
229# ifndef __USE_SUPERFAST_LOADQUERY
230 qu += "select distinct uid from addressbook";
231# else
232 qu += "select uid from addressbook where type = 'Last Name'";
233# endif // __USE_SUPERFAST_LOADQUERY
234#endif // __STORE_HORIZONTAL_
235
236 return qu;
237 }
238
239
240 InsertQuery::InsertQuery( const OContact& contact )
241 : OSQLQuery(), m_contact( contact ) {
242 }
243
244 InsertQuery::~InsertQuery() {
245 }
246
247 /*
248 * converts from a OContact to a query
249 */
250 QString InsertQuery::query()const{
251
252#ifdef __STORE_HORIZONTAL_
253 QString qu;
254 qu += "insert into addressbook VALUES( " +
255 QString::number( m_contact.uid() );
256
257 // Get all information out of the contact-class
258 // Remember: The category is stored in contactMap, too !
259 QMap<int, QString> contactMap = m_contact.toMap();
260
261 QStringList fieldList = OContactFields::untrfields( false );
262 QMap<QString, int> translate = OContactFields::untrFieldsToId();
263 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
264 // Convert Column-String to Id and get value for this id..
265 // Hmmm.. Maybe not very cute solution..
266 int id = translate[*it];
267 switch ( id ){
268 case Qtopia::Birthday:{
269 // These entries should stored in a special format
270 // year-month-day
271 QDate day = m_contact.birthday();
272 if ( day.isValid() ){
273 qu += QString(",\"%1-%2-%3\"")
274 .arg( day.year() )
275 .arg( day.month() )
276 .arg( day.day() );
277 } else {
278 qu += ",\"\"";
279 }
280 }
281 break;
282 case Qtopia::Anniversary:{
283 // These entries should stored in a special format
284 // year-month-day
285 QDate day = m_contact.anniversary();
286 if ( day.isValid() ){
287 qu += QString(",\"%1-%2-%3\"")
288 .arg( day.year() )
289 .arg( day.month() )
290 .arg( day.day() );
291 } else {
292 qu += ",\"\"";
293 }
294 }
295 break;
296
297 default:
298 qu += QString( ",\"%1\"" ).arg( contactMap[id] );
299 }
300 }
301 qu += " );";
302
303
304#else
305 // Get all information out of the contact-class
306 // Remember: The category is stored in contactMap, too !
307 QMap<int, QString> contactMap = m_contact.toMap();
308
309 QMap<QString, QString> addressbook_db;
310
311 // Get the translation from the ID to the String
312 QMap<int, QString> transMap = OContactFields::idToUntrFields();
313
314 for( QMap<int, QString>::Iterator it = contactMap.begin();
315 it != contactMap.end(); ++it ){
316 switch ( it.key() ){
317 case Qtopia::Birthday:{
318 // These entries should stored in a special format
319 // year-month-day
320 QDate day = m_contact.birthday();
321 addressbook_db.insert( transMap[it.key()],
322 QString("%1-%2-%3")
323 .arg( day.year() )
324 .arg( day.month() )
325 .arg( day.day() ) );
326 }
327 break;
328 case Qtopia::Anniversary:{
329 // These entries should stored in a special format
330 // year-month-day
331 QDate day = m_contact.anniversary();
332 addressbook_db.insert( transMap[it.key()],
333 QString("%1-%2-%3")
334 .arg( day.year() )
335 .arg( day.month() )
336 .arg( day.day() ) );
337 }
338 break;
339 case Qtopia::AddressUid: // Ignore UID
340 break;
341 default: // Translate id to String
342 addressbook_db.insert( transMap[it.key()], it.data() );
343 break;
344 }
345
346 }
347
348 // Now convert this whole stuff into a SQL String, beginning with
349 // the addressbook table..
350 QString qu;
351 // qu += "begin transaction;";
352 int id = 0;
353 for( QMap<QString, QString>::Iterator it = addressbook_db.begin();
354 it != addressbook_db.end(); ++it ){
355 qu += "insert into addressbook VALUES("
356 + QString::number( m_contact.uid() )
357 + ","
358 + QString::number( id++ )
359 + ",'"
360 + it.key() //.latin1()
361 + "',"
362 + "0" // Priority for future enhancements
363 + ",'"
364 + it.data() //.latin1()
365 + "');";
366 }
367
368 #endif //__STORE_HORIZONTAL_
369 // Now add custom data..
370#ifdef __STORE_HORIZONTAL_
371 int id = 0;
372#endif
373 id = 0;
374 QMap<QString, QString> customMap = m_contact.toExtraMap();
375 for( QMap<QString, QString>::Iterator it = customMap.begin();
376 it != customMap.end(); ++it ){
377 qu += "insert into custom_data VALUES("
378 + QString::number( m_contact.uid() )
379 + ","
380 + QString::number( id++ )
381 + ",'"
382 + it.key() //.latin1()
383 + "',"
384 + "0" // Priority for future enhancements
385 + ",'"
386 + it.data() //.latin1()
387 + "');";
388 }
389 // qu += "commit;";
390 qWarning("add %s", qu.latin1() );
391 return qu;
392 }
393
394
395 RemoveQuery::RemoveQuery(int uid )
396 : OSQLQuery(), m_uid( uid ) {}
397 RemoveQuery::~RemoveQuery() {}
398 QString RemoveQuery::query()const {
399 QString qu = "DELETE from addressbook where uid = "
400 + QString::number(m_uid) + ";";
401 qu += "DELETE from custom_data where uid = "
402 + QString::number(m_uid) + ";";
403 return qu;
404 }
405
406
407
408
409 FindQuery::FindQuery(int uid)
410 : OSQLQuery(), m_uid( uid ) {
411 }
412 FindQuery::FindQuery(const QArray<int>& ints)
413 : OSQLQuery(), m_uids( ints ){
414 }
415 FindQuery::~FindQuery() {
416 }
417 QString FindQuery::query()const{
418 // if ( m_uids.count() == 0 )
419 return single();
420 }
421 /*
422 else
423 return multi();
424 }
425 QString FindQuery::multi()const {
426 QString qu = "select uid, type, value from addressbook where";
427 for (uint i = 0; i < m_uids.count(); i++ ) {
428 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
429 }
430 qu.remove( qu.length()-2, 2 ); // Hmmmm..
431 return qu;
432 }
433 */
434#ifdef __STORE_HORIZONTAL_
435 QString FindQuery::single()const{
436 QString qu = "select *";
437 qu += " from addressbook where uid = " + QString::number(m_uid);
438
439 // qWarning("find query: %s", qu.latin1() );
440 return qu;
441 }
442#else
443 QString FindQuery::single()const{
444 QString qu = "select uid, type, value from addressbook where uid = ";
445 qu += QString::number(m_uid);
446 return qu;
447 }
448#endif
449
450
451 FindCustomQuery::FindCustomQuery(int uid)
452 : OSQLQuery(), m_uid( uid ) {
453 }
454 FindCustomQuery::FindCustomQuery(const QArray<int>& ints)
455 : OSQLQuery(), m_uids( ints ){
456 }
457 FindCustomQuery::~FindCustomQuery() {
458 }
459 QString FindCustomQuery::query()const{
460 // if ( m_uids.count() == 0 )
461 return single();
462 }
463 QString FindCustomQuery::single()const{
464 QString qu = "select uid, type, value from custom_data where uid = ";
465 qu += QString::number(m_uid);
466 return qu;
467 }
468
469};
470
471
472/* --------------------------------------------------------------------------- */
473
474OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */,
475 const QString& filename ):
476 OContactAccessBackend(), m_changed(false), m_driver( NULL )
477{
478 qWarning("C'tor OContactAccessBackend_SQL starts");
479 QTime t;
480 t.start();
481
482 /* Expecting to access the default filename if nothing else is set */
483 if ( filename.isEmpty() ){
484 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
485 } else
486 m_fileName = filename;
487
488 // Get the standart sql-driver from the OSQLManager..
489 OSQLManager man;
490 m_driver = man.standard();
491 m_driver->setUrl( m_fileName );
492
493 load();
494
495 qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() );
496}
497
498OContactAccessBackend_SQL::~OContactAccessBackend_SQL ()
499{
500 if( m_driver )
501 delete m_driver;
502}
503
504bool OContactAccessBackend_SQL::load ()
505{
506 if (!m_driver->open() )
507 return false;
508
509 // Don't expect that the database exists.
510 // It is save here to create the table, even if it
511 // do exist. ( Is that correct for all databases ?? )
512 CreateQuery creat;
513 OSQLResult res = m_driver->query( &creat );
514
515 update();
516
517 return true;
518
519}
520
521bool OContactAccessBackend_SQL::reload()
522{
523 return load();
524}
525
526bool OContactAccessBackend_SQL::save()
527{
528 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
529}
530
531
532void OContactAccessBackend_SQL::clear ()
533{
534 ClearQuery cle;
535 OSQLResult res = m_driver->query( &cle );
536
537 reload();
538}
539
540bool OContactAccessBackend_SQL::wasChangedExternally()
541{
542 return false;
543}
544
545QArray<int> OContactAccessBackend_SQL::allRecords() const
546{
547
548 // FIXME: Think about cute handling of changed tables..
549 // Thus, we don't have to call update here...
550 if ( m_changed )
551 ((OContactAccessBackend_SQL*)this)->update();
552
553 return m_uids;
554}
555
556bool OContactAccessBackend_SQL::add ( const OContact &newcontact )
557{
558 InsertQuery ins( newcontact );
559 OSQLResult res = m_driver->query( &ins );
560
561 if ( res.state() == OSQLResult::Failure )
562 return false;
563
564 int c = m_uids.count();
565 m_uids.resize( c+1 );
566 m_uids[c] = newcontact.uid();
567
568 return true;
569}
570
571
572bool OContactAccessBackend_SQL::remove ( int uid )
573{
574 RemoveQuery rem( uid );
575 OSQLResult res = m_driver->query(&rem );
576
577 if ( res.state() == OSQLResult::Failure )
578 return false;
579
580 m_changed = true;
581
582 return true;
583}
584
585bool OContactAccessBackend_SQL::replace ( const OContact &contact )
586{
587 if ( !remove( contact.uid() ) )
588 return false;
589
590 return add( contact );
591}
592
593
594OContact OContactAccessBackend_SQL::find ( int uid ) const
595{
596 qWarning("OContactAccessBackend_SQL::find()");
597 QTime t;
598 t.start();
599
600 OContact retContact( requestNonCustom( uid ) );
601 retContact.setExtraMap( requestCustom( uid ) );
602
603 qWarning("OContactAccessBackend_SQL::find() needed: %d ms", t.elapsed() );
604 return retContact;
605}
606
607
608
609QArray<int> OContactAccessBackend_SQL::queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() )
610{
611 QString qu = "SELECT uid FROM addressbook WHERE";
612
613 QMap<int, QString> queryFields = query.toMap();
614 QStringList fieldList = OContactFields::untrfields( false );
615 QMap<QString, int> translate = OContactFields::untrFieldsToId();
616
617 // Convert every filled field to a SQL-Query
618 bool isAnyFieldSelected = false;
619 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
620 int id = translate[*it];
621 QString queryStr = queryFields[id];
622 if ( !queryStr.isEmpty() ){
623 isAnyFieldSelected = true;
624 switch( id ){
625 default:
626 // Switching between case sensitive and insensitive...
627 // LIKE is not case sensitive, GLOB is case sensitive
628 // Do exist a better solution to switch this ?
629 if ( settings & OContactAccess::IgnoreCase )
630 qu += "(\"" + *it + "\"" + " LIKE " + "'"
631 + queryStr.replace(QRegExp("\\*"),"%") + "'" + ") AND ";
632 else
633 qu += "(\"" + *it + "\"" + " GLOB " + "'"
634 + queryStr + "'" + ") AND ";
635
636 }
637 }
638 }
639 // Skip trailing "AND"
640 if ( isAnyFieldSelected )
641 qu = qu.left( qu.length() - 4 );
642
643 qWarning( "queryByExample query: %s", qu.latin1() );
644
645 // Execute query and return the received uid's
646 OSQLRawQuery raw( qu );
647 OSQLResult res = m_driver->query( &raw );
648 if ( res.state() != OSQLResult::Success ){
649 QArray<int> empty;
650 return empty;
651 }
652
653 QArray<int> list = extractUids( res );
654
655 return list;
656}
657
658QArray<int> OContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
659{
660 QArray<int> nix(0);
661 return nix;
662}
663
664const uint OContactAccessBackend_SQL::querySettings()
665{
666 return OContactAccess::IgnoreCase
667 || OContactAccess::WildCards;
668}
669
670bool OContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const
671{
672 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
673 * may be added with any of the other settings. IgnoreCase should never used alone.
674 * Wildcards, RegExp, ExactMatch should never used at the same time...
675 */
676
677 // Step 1: Check whether the given settings are supported by this backend
678 if ( ( querySettings & (
679 OContactAccess::IgnoreCase
680 | OContactAccess::WildCards
681 // | OContactAccess::DateDiff
682 // | OContactAccess::DateYear
683 // | OContactAccess::DateMonth
684 // | OContactAccess::DateDay
685 // | OContactAccess::RegExp
686 // | OContactAccess::ExactMatch
687 ) ) != querySettings )
688 return false;
689
690 // Step 2: Check whether the given combinations are ok..
691
692 // IngoreCase alone is invalid
693 if ( querySettings == OContactAccess::IgnoreCase )
694 return false;
695
696 // WildCards, RegExp and ExactMatch should never used at the same time
697 switch ( querySettings & ~( OContactAccess::IgnoreCase
698 | OContactAccess::DateDiff
699 | OContactAccess::DateYear
700 | OContactAccess::DateMonth
701 | OContactAccess::DateDay
702 )
703 ){
704 case OContactAccess::RegExp:
705 return ( true );
706 case OContactAccess::WildCards:
707 return ( true );
708 case OContactAccess::ExactMatch:
709 return ( true );
710 case 0: // one of the upper removed bits were set..
711 return ( true );
712 default:
713 return ( false );
714 }
715
716}
717
718QArray<int> OContactAccessBackend_SQL::sorted( bool asc, int , int , int )
719{
720 QTime t;
721 t.start();
722
723#ifdef __STORE_HORIZONTAL_
724 QString query = "SELECT uid FROM addressbook ";
725 query += "ORDER BY \"Last Name\" ";
726#else
727 QString query = "SELECT uid FROM addressbook WHERE type = 'Last Name' ";
728 query += "ORDER BY upper( value )";
729#endif
730
731 if ( !asc )
732 query += "DESC";
733
734 // qWarning("sorted query is: %s", query.latin1() );
735
736 OSQLRawQuery raw( query );
737 OSQLResult res = m_driver->query( &raw );
738 if ( res.state() != OSQLResult::Success ){
739 QArray<int> empty;
740 return empty;
741 }
742
743 QArray<int> list = extractUids( res );
744
745 qWarning("sorted needed %d ms!", t.elapsed() );
746 return list;
747}
748
749
750void OContactAccessBackend_SQL::update()
751{
752 qWarning("Update starts");
753 QTime t;
754 t.start();
755
756 // Now load the database set and extract the uid's
757 // which will be held locally
758
759 LoadQuery lo;
760 OSQLResult res = m_driver->query(&lo);
761 if ( res.state() != OSQLResult::Success )
762 return;
763
764 m_uids = extractUids( res );
765
766 m_changed = false;
767
768 qWarning("Update ends %d ms", t.elapsed() );
769}
770
771QArray<int> OContactAccessBackend_SQL::extractUids( OSQLResult& res ) const
772{
773 qWarning("extractUids");
774 QTime t;
775 t.start();
776 OSQLResultItem::ValueList list = res.results();
777 OSQLResultItem::ValueList::Iterator it;
778 QArray<int> ints(list.count() );
779 qWarning(" count = %d", list.count() );
780
781 int i = 0;
782 for (it = list.begin(); it != list.end(); ++it ) {
783 ints[i] = (*it).data("uid").toInt();
784 i++;
785 }
786 qWarning("extractUids ready: count2 = %d needs %d ms", i, t.elapsed() );
787
788 return ints;
789
790}
791
792#ifdef __STORE_HORIZONTAL_
793QMap<int, QString> OContactAccessBackend_SQL::requestNonCustom( int uid ) const
794{
795 QTime t;
796 t.start();
797
798 QMap<int, QString> nonCustomMap;
799
800 int t2needed = 0;
801 int t3needed = 0;
802 QTime t2;
803 t2.start();
804 FindQuery query( uid );
805 OSQLResult res_noncustom = m_driver->query( &query );
806 t2needed = t2.elapsed();
807
808 OSQLResultItem resItem = res_noncustom.first();
809
810 QTime t3;
811 t3.start();
812 // Now loop through all columns
813 QStringList fieldList = OContactFields::untrfields( false );
814 QMap<QString, int> translate = OContactFields::untrFieldsToId();
815 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
816 // Get data for the selected column and store it with the
817 // corresponding id into the map..
818
819 int id = translate[*it];
820 QString value = resItem.data( (*it) );
821
822 // qWarning("Reading %s... found: %s", (*it).latin1(), value.latin1() );
823
824 switch( id ){
825 case Qtopia::Birthday:
826 case Qtopia::Anniversary:{
827 // Birthday and Anniversary are encoded special ( yyyy-mm-dd )
828 QStringList list = QStringList::split( '-', value );
829 QStringList::Iterator lit = list.begin();
830 int year = (*lit).toInt();
831 int month = (*(++lit)).toInt();
832 int day = (*(++lit)).toInt();
833 if ( ( day != 0 ) && ( month != 0 ) && ( year != 0 ) ){
834 QDate date( year, month, day );
835 nonCustomMap.insert( id, OConversion::dateToString( date ) );
836 }
837 }
838 break;
839 case Qtopia::AddressCategory:
840 qWarning("Category is: %s", value.latin1() );
841 default:
842 nonCustomMap.insert( id, value );
843 }
844 }
845
846 // First insert uid
847 nonCustomMap.insert( Qtopia::AddressUid, resItem.data( "uid" ) );
848 t3needed = t3.elapsed();
849
850 // qWarning("Adding UID: %s", resItem.data( "uid" ).latin1() );
851 qWarning("RequestNonCustom needed: insg.:%d ms, query: %d ms, mapping: %d ms",
852 t.elapsed(), t2needed, t3needed );
853
854 return nonCustomMap;
855}
856#else
857
858QMap<int, QString> OContactAccessBackend_SQL::requestNonCustom( int uid ) const
859{
860 QTime t;
861 t.start();
862
863 QMap<int, QString> nonCustomMap;
864
865 int t2needed = 0;
866 QTime t2;
867 t2.start();
868 FindQuery query( uid );
869 OSQLResult res_noncustom = m_driver->query( &query );
870 t2needed = t2.elapsed();
871
872 if ( res_noncustom.state() == OSQLResult::Failure ) {
873 qWarning("OSQLResult::Failure in find query !!");
874 QMap<int, QString> empty;
875 return empty;
876 }
877
878 int t3needed = 0;
879 QTime t3;
880 t3.start();
881 QMap<QString, int> translateMap = OContactFields::untrFieldsToId();
882
883 OSQLResultItem::ValueList list = res_noncustom.results();
884 OSQLResultItem::ValueList::Iterator it = list.begin();
885 for ( ; it != list.end(); ++it ) {
886 if ( (*it).data("type") != "" ){
887 int typeId = translateMap[(*it).data( "type" )];
888 switch( typeId ){
889 case Qtopia::Birthday:
890 case Qtopia::Anniversary:{
891 // Birthday and Anniversary are encoded special ( yyyy-mm-dd )
892 QStringList list = QStringList::split( '-', (*it).data( "value" ) );
893 QStringList::Iterator lit = list.begin();
894 int year = (*lit).toInt();
895 qWarning("1. %s", (*lit).latin1());
896 int month = (*(++lit)).toInt();
897 qWarning("2. %s", (*lit).latin1());
898 int day = (*(++lit)).toInt();
899 qWarning("3. %s", (*lit).latin1());
900 qWarning( "RequestNonCustom->Converting:%s to Year: %d, Month: %d, Day: %d ", (*it).data( "value" ).latin1(), year, month, day );
901 QDate date( year, month, day );
902 nonCustomMap.insert( typeId, OConversion::dateToString( date ) );
903 }
904 break;
905 default:
906 nonCustomMap.insert( typeId,
907 (*it).data( "value" ) );
908 }
909 }
910 }
911 // Add UID to Map..
912 nonCustomMap.insert( Qtopia::AddressUid, QString::number( uid ) );
913 t3needed = t3.elapsed();
914
915 qWarning("RequestNonCustom needed: insg.:%d ms, query: %d ms, mapping: %d ms", t.elapsed(), t2needed, t3needed );
916 return nonCustomMap;
917}
918
919#endif // __STORE_HORIZONTAL_
920
921QMap<QString, QString> OContactAccessBackend_SQL::requestCustom( int uid ) const
922{
923 QTime t;
924 t.start();
925
926 QMap<QString, QString> customMap;
927
928 FindCustomQuery query( uid );
929 OSQLResult res_custom = m_driver->query( &query );
930
931 if ( res_custom.state() == OSQLResult::Failure ) {
932 qWarning("OSQLResult::Failure in find query !!");
933 QMap<QString, QString> empty;
934 return empty;
935 }
936
937 OSQLResultItem::ValueList list = res_custom.results();
938 OSQLResultItem::ValueList::Iterator it = list.begin();
939 for ( ; it != list.end(); ++it ) {
940 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) );
941 }
942
943 qWarning("RequestCustom needed: %d ms", t.elapsed() );
944 return customMap;
945}
diff --git a/libopie/pim/ocontactaccessbackend_sql.h b/libopie/pim/ocontactaccessbackend_sql.h
deleted file mode 100644
index f553760..0000000
--- a/libopie/pim/ocontactaccessbackend_sql.h
+++ b/dev/null
@@ -1,107 +0,0 @@
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.3 2004/03/14 13:50:35 alwin
20 * namespace correction
21 *
22 * Revision 1.2 2003/12/08 15:18:11 eilers
23 * Committing unfinished sql implementation before merging to libopie2 starts..
24 *
25 * Revision 1.1 2003/09/22 14:31:16 eilers
26 * Added first experimental incarnation of sql-backend for addressbook.
27 * Some modifications to be able to compile the todo sql-backend.
28 * A lot of changes fill follow...
29 *
30 *
31 */
32
33#ifndef _OContactAccessBackend_SQL_
34#define _OContactAccessBackend_SQL_
35
36#include "ocontactaccessbackend.h"
37#include "ocontactaccess.h"
38
39#include <qlist.h>
40#include <qdict.h>
41
42namespace Opie { namespace DB {
43class OSQLDriver;
44class OSQLResult;
45class OSQLResultItem;
46
47}}
48
49/* the default xml implementation */
50/**
51 * This class is the SQL implementation of a Contact backend
52 * it does implement everything available for OContact.
53 * @see OPimAccessBackend for more information of available methods
54 */
55class OContactAccessBackend_SQL : public OContactAccessBackend {
56 public:
57 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null );
58
59 ~OContactAccessBackend_SQL ();
60
61 bool save();
62
63 bool load ();
64
65 void clear ();
66
67 bool wasChangedExternally();
68
69 QArray<int> allRecords() const;
70
71 OContact find ( int uid ) const;
72 // FIXME: Add lookahead-cache support !
73 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
74
75 QArray<int> queryByExample ( const OContact &query, int settings,
76 const QDateTime& d );
77
78 QArray<int> matchRegexp( const QRegExp &r ) const;
79
80 const uint querySettings();
81
82 bool hasQuerySettings (uint querySettings) const;
83
84 // Currently only asc implemented..
85 QArray<int> sorted( bool asc, int , int , int );
86 bool add ( const OContact &newcontact );
87
88 bool replace ( const OContact &contact );
89
90 bool remove ( int uid );
91 bool reload();
92
93 private:
94 QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
95 QMap<int, QString> requestNonCustom( int uid ) const;
96 QMap<QString, QString> requestCustom( int uid ) const;
97 void update();
98
99 protected:
100 bool m_changed;
101 QString m_fileName;
102 QArray<int> m_uids;
103
104 Opie::DB::OSQLDriver* m_driver;
105};
106
107#endif
diff --git a/libopie/pim/ocontactaccessbackend_vcard.cpp b/libopie/pim/ocontactaccessbackend_vcard.cpp
deleted file mode 100644
index b60c5be..0000000
--- a/libopie/pim/ocontactaccessbackend_vcard.cpp
+++ b/dev/null
@@ -1,646 +0,0 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (C) 2000 Trolltech AS. All rights reserved.
5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
6 *
7 * =====================================================================
8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 * =====================================================================
13 * ToDo:
14 *
15 * =====================================================================
16 * Version: $Id$
17 * =====================================================================
18 * History:
19 * $Log$
20 * Revision 1.11 2003/08/01 12:30:16 eilers
21 * Merging changes from BRANCH_1_0 to HEAD
22 *
23 * Revision 1.10.4.3 2003/07/23 08:54:37 eilers
24 * Default email was added to the list of all emails, which already contains
25 * the default email..
26 * This closes bug #1045
27 *
28 * Revision 1.10.4.2 2003/07/23 08:44:45 eilers
29 * Importing of Notes in vcard files wasn't implemented.
30 * Closes bug #1044
31 *
32 * Revision 1.10.4.1 2003/06/02 13:37:49 eilers
33 * Fixing memory leak
34 *
35 * Revision 1.10 2003/04/13 18:07:10 zecke
36 * More API doc
37 * QString -> const QString&
38 * QString = 0l -> QString::null
39 *
40 * Revision 1.9 2003/03/21 10:33:09 eilers
41 * Merged speed optimized xml backend for contacts to main.
42 * Added QDateTime to querybyexample. For instance, it is now possible to get
43 * all Birthdays/Anniversaries between two dates. This should be used
44 * to show all birthdays in the datebook..
45 * This change is sourcecode backward compatible but you have to upgrade
46 * the binaries for today-addressbook.
47 *
48 * Revision 1.8 2003/02/21 16:52:49 zecke
49 * -Remove old Todo classes they're deprecated and today I already using the
50 * new API
51 * -Guard against self assignment in OTodo
52 * -Add test apps for OPIM
53 * -Opiefied Event classes
54 * -Added TimeZone handling and pinning of TimeZones to OEvent
55 * -Adjust ORecur and the widget to better timezone behaviour
56 *
57 * Revision 1.7 2003/02/16 22:25:46 zecke
58 * 0000276 Fix for that bug.. or better temp workaround
59 * A Preferred Number is HOME|VOICE
60 * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test
61 * triggers both
62 * and the cell phone number overrides the other entries..
63 *
64 * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the
65 * number
66 *
67 * The right and final fix would be to reorder the if statement to make it
68 * if else based and the less common thing put to the bottom
69 *
70 * OTodoAccessVcal fix the date for beaming
71 *
72 * Revision 1.6 2003/01/13 15:49:31 eilers
73 * Fixing crash when businesscard.vcf is missing..
74 *
75 * Revision 1.5 2002/12/07 13:26:22 eilers
76 * Fixing bug in storing anniversary..
77 *
78 * Revision 1.4 2002/11/13 14:14:51 eilers
79 * Added sorted for Contacts..
80 *
81 * Revision 1.3 2002/11/11 16:41:09 kergoth
82 * no default arguments in implementation
83 *
84 * Revision 1.2 2002/11/10 15:41:53 eilers
85 * Bugfixes..
86 *
87 * Revision 1.1 2002/11/09 14:34:52 eilers
88 * Added VCard Backend.
89 *
90 */
91#include "ocontactaccessbackend_vcard.h"
92#include "../../library/backend/vobject_p.h"
93#include "../../library/backend/qfiledirect_p.h"
94
95#include <qpe/timeconversion.h>
96
97#include <qfile.h>
98
99OContactAccessBackend_VCard::OContactAccessBackend_VCard ( const QString& , const QString& filename ):
100 m_dirty( false ),
101 m_file( filename )
102{
103 load();
104}
105
106
107bool OContactAccessBackend_VCard::load ()
108{
109 m_map.clear();
110 m_dirty = false;
111
112 VObject* obj = 0l;
113
114 if ( QFile::exists(m_file) ){
115 obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
116 if ( !obj )
117 return false;
118 }else{
119 qWarning("File \"%s\" not found !", m_file.latin1() );
120 return false;
121 }
122
123 while ( obj ) {
124 OContact con = parseVObject( obj );
125 /*
126 * if uid is 0 assign a new one
127 * this at least happens on
128 * Nokia6210
129 */
130 if ( con.uid() == 0 ){
131 con.setUid( 1 );
132 qWarning("assigned new uid %d",con.uid() );
133 }
134
135 m_map.insert( con.uid(), con );
136
137 VObject *t = obj;
138 obj = nextVObjectInList(obj);
139 cleanVObject( t );
140 }
141
142 return true;
143
144}
145bool OContactAccessBackend_VCard::reload()
146{
147 return load();
148}
149bool OContactAccessBackend_VCard::save()
150{
151 if (!m_dirty )
152 return true;
153
154 QFileDirect file( m_file );
155 if (!file.open(IO_WriteOnly ) )
156 return false;
157
158 VObject *obj;
159 obj = newVObject( VCCalProp );
160 addPropValue( obj, VCVersionProp, "1.0" );
161
162 VObject *vo;
163 for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
164 vo = createVObject( *it );
165 writeVObject( file.directHandle() , vo );
166 cleanVObject( vo );
167 }
168 cleanStrTbl();
169 deleteVObject( obj );
170
171 m_dirty = false;
172 return true;
173
174
175}
176void OContactAccessBackend_VCard::clear ()
177{
178 m_map.clear();
179 m_dirty = true; // ??? sure ? (se)
180}
181
182bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
183{
184 m_map.insert( newcontact.uid(), newcontact );
185 m_dirty = true;
186 return true;
187}
188
189bool OContactAccessBackend_VCard::remove ( int uid )
190{
191 m_map.remove( uid );
192 m_dirty = true;
193 return true;
194}
195
196bool OContactAccessBackend_VCard::replace ( const OContact &contact )
197{
198 m_map.replace( contact.uid(), contact );
199 m_dirty = true;
200 return true;
201}
202
203OContact OContactAccessBackend_VCard::find ( int uid ) const
204{
205 return m_map[uid];
206}
207
208QArray<int> OContactAccessBackend_VCard::allRecords() const
209{
210 QArray<int> ar( m_map.count() );
211 QMap<int, OContact>::ConstIterator it;
212 int i = 0;
213 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
214 ar[i] = it.key();
215 i++;
216 }
217 return ar;
218}
219
220// Not implemented
221QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int, const QDateTime& )
222{
223 QArray<int> ar(0);
224 return ar;
225}
226
227// Not implemented
228QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
229{
230 QArray<int> ar(0);
231 return ar;
232}
233
234const uint OContactAccessBackend_VCard::querySettings()
235{
236 return 0; // No search possible
237}
238
239bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const
240{
241 return false; // No search possible, therefore all settings invalid ;)
242}
243
244bool OContactAccessBackend_VCard::wasChangedExternally()
245{
246 return false; // Don't expect concurrent access
247}
248
249// Not implemented
250QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int )
251{
252 QArray<int> ar(0);
253 return ar;
254}
255
256// *** Private stuff ***
257
258
259OContact OContactAccessBackend_VCard::parseVObject( VObject *obj )
260{
261 OContact c;
262
263 VObjectIterator it;
264 initPropIterator( &it, obj );
265 while( moreIteration( &it ) ) {
266 VObject *o = nextVObject( &it );
267 QCString name = vObjectName( o );
268 QCString value = vObjectStringZValue( o );
269 if ( name == VCNameProp ) {
270 VObjectIterator nit;
271 initPropIterator( &nit, o );
272 while( moreIteration( &nit ) ) {
273 VObject *o = nextVObject( &nit );
274 QCString name = vObjectTypeInfo( o );
275 QString value = vObjectStringZValue( o );
276 if ( name == VCNamePrefixesProp )
277 c.setTitle( value );
278 else if ( name == VCNameSuffixesProp )
279 c.setSuffix( value );
280 else if ( name == VCFamilyNameProp )
281 c.setLastName( value );
282 else if ( name == VCGivenNameProp )
283 c.setFirstName( value );
284 else if ( name == VCAdditionalNamesProp )
285 c.setMiddleName( value );
286 }
287 }
288 else if ( name == VCAdrProp ) {
289 bool work = TRUE; // default address is work address
290 QString street;
291 QString city;
292 QString region;
293 QString postal;
294 QString country;
295
296 VObjectIterator nit;
297 initPropIterator( &nit, o );
298 while( moreIteration( &nit ) ) {
299 VObject *o = nextVObject( &nit );
300 QCString name = vObjectName( o );
301 QString value = vObjectStringZValue( o );
302 if ( name == VCHomeProp )
303 work = FALSE;
304 else if ( name == VCWorkProp )
305 work = TRUE;
306 else if ( name == VCStreetAddressProp )
307 street = value;
308 else if ( name == VCCityProp )
309 city = value;
310 else if ( name == VCRegionProp )
311 region = value;
312 else if ( name == VCPostalCodeProp )
313 postal = value;
314 else if ( name == VCCountryNameProp )
315 country = value;
316 }
317 if ( work ) {
318 c.setBusinessStreet( street );
319 c.setBusinessCity( city );
320 c.setBusinessCountry( country );
321 c.setBusinessZip( postal );
322 c.setBusinessState( region );
323 } else {
324 c.setHomeStreet( street );
325 c.setHomeCity( city );
326 c.setHomeCountry( country );
327 c.setHomeZip( postal );
328 c.setHomeState( region );
329 }
330 }
331 else if ( name == VCTelephoneProp ) {
332 enum {
333 HOME = 0x01,
334 WORK = 0x02,
335 VOICE = 0x04,
336 CELL = 0x08,
337 FAX = 0x10,
338 PAGER = 0x20,
339 UNKNOWN = 0x80
340 };
341 int type = 0;
342
343 VObjectIterator nit;
344 initPropIterator( &nit, o );
345 while( moreIteration( &nit ) ) {
346 VObject *o = nextVObject( &nit );
347 QCString name = vObjectTypeInfo( o );
348 if ( name == VCHomeProp )
349 type |= HOME;
350 else if ( name == VCWorkProp )
351 type |= WORK;
352 else if ( name == VCVoiceProp )
353 type |= VOICE;
354 else if ( name == VCCellularProp )
355 type |= CELL;
356 else if ( name == VCFaxProp )
357 type |= FAX;
358 else if ( name == VCPagerProp )
359 type |= PAGER;
360 else if ( name == VCPreferredProp )
361 ;
362 else
363 type |= UNKNOWN;
364 }
365 if ( (type & UNKNOWN) != UNKNOWN ) {
366 if ( ( type & (HOME|WORK) ) == 0 ) // default
367 type |= HOME;
368 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
369 type |= VOICE;
370
371 qWarning("value %s %d", value.data(), type );
372 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) )
373 c.setHomePhone( value );
374 if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
375 c.setHomeFax( value );
376 if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
377 c.setHomeMobile( value );
378 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) )
379 c.setBusinessPhone( value );
380 if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
381 c.setBusinessFax( value );
382 if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
383 c.setBusinessMobile( value );
384 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
385 c.setBusinessPager( value );
386 }
387 }
388 else if ( name == VCEmailAddressProp ) {
389 QString email = vObjectStringZValue( o );
390 bool valid = TRUE;
391 VObjectIterator nit;
392 initPropIterator( &nit, o );
393 while( moreIteration( &nit ) ) {
394 VObject *o = nextVObject( &nit );
395 QCString name = vObjectTypeInfo( o );
396 if ( name != VCInternetProp && name != VCHomeProp &&
397 name != VCWorkProp &&
398 name != VCPreferredProp )
399 // ### preffered should map to default email
400 valid = FALSE;
401 }
402 if ( valid ) {
403 c.insertEmail( email );
404 }
405 }
406 else if ( name == VCURLProp ) {
407 VObjectIterator nit;
408 initPropIterator( &nit, o );
409 while( moreIteration( &nit ) ) {
410 VObject *o = nextVObject( &nit );
411 QCString name = vObjectTypeInfo( o );
412 if ( name == VCHomeProp )
413 c.setHomeWebpage( value );
414 else if ( name == VCWorkProp )
415 c.setBusinessWebpage( value );
416 }
417 }
418 else if ( name == VCOrgProp ) {
419 VObjectIterator nit;
420 initPropIterator( &nit, o );
421 while( moreIteration( &nit ) ) {
422 VObject *o = nextVObject( &nit );
423 QCString name = vObjectName( o );
424 QString value = vObjectStringZValue( o );
425 if ( name == VCOrgNameProp )
426 c.setCompany( value );
427 else if ( name == VCOrgUnitProp )
428 c.setDepartment( value );
429 else if ( name == VCOrgUnit2Prop )
430 c.setOffice( value );
431 }
432 }
433 else if ( name == VCTitleProp ) {
434 c.setJobTitle( value );
435 }
436 else if ( name == "X-Qtopia-Profession" ) {
437 c.setProfession( value );
438 }
439 else if ( name == "X-Qtopia-Manager" ) {
440 c.setManager( value );
441 }
442 else if ( name == "X-Qtopia-Assistant" ) {
443 c.setAssistant( value );
444 }
445 else if ( name == "X-Qtopia-Spouse" ) {
446 c.setSpouse( value );
447 }
448 else if ( name == "X-Qtopia-Gender" ) {
449 c.setGender( value );
450 }
451 else if ( name == "X-Qtopia-Anniversary" ) {
452 c.setAnniversary( convVCardDateToDate( value ) );
453 }
454 else if ( name == "X-Qtopia-Nickname" ) {
455 c.setNickname( value );
456 }
457 else if ( name == "X-Qtopia-Children" ) {
458 c.setChildren( value );
459 }
460 else if ( name == VCBirthDateProp ) {
461 // Reading Birthdate regarding RFC 2425 (5.8.4)
462 c.setBirthday( convVCardDateToDate( value ) );
463
464 }
465 else if ( name == VCCommentProp ) {
466 c.setNotes( value );
467 }
468#if 0
469 else {
470 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
471 VObjectIterator nit;
472 initPropIterator( &nit, o );
473 while( moreIteration( &nit ) ) {
474 VObject *o = nextVObject( &nit );
475 QCString name = vObjectName( o );
476 QString value = vObjectStringZValue( o );
477 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
478 }
479 }
480#endif
481 }
482 c.setFileAs();
483 return c;
484}
485
486
487VObject* OContactAccessBackend_VCard::createVObject( const OContact &c )
488{
489 VObject *vcard = newVObject( VCCardProp );
490 safeAddPropValue( vcard, VCVersionProp, "2.1" );
491 safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
492 safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
493
494 // full name
495 safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
496
497 // name properties
498 VObject *name = safeAddProp( vcard, VCNameProp );
499 safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
500 safeAddPropValue( name, VCGivenNameProp, c.firstName() );
501 safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
502 safeAddPropValue( name, VCNamePrefixesProp, c.title() );
503 safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
504
505 // home properties
506 VObject *home_adr= safeAddProp( vcard, VCAdrProp );
507 safeAddProp( home_adr, VCHomeProp );
508 safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
509 safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
510 safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
511 safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
512 safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
513
514 VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
515 safeAddProp( home_phone, VCHomeProp );
516 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
517 safeAddProp( home_phone, VCHomeProp );
518 safeAddProp( home_phone, VCCellularProp );
519 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
520 safeAddProp( home_phone, VCHomeProp );
521 safeAddProp( home_phone, VCFaxProp );
522
523 VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
524 safeAddProp( url, VCHomeProp );
525
526 // work properties
527 VObject *work_adr= safeAddProp( vcard, VCAdrProp );
528 safeAddProp( work_adr, VCWorkProp );
529 safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
530 safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
531 safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
532 safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
533 safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
534
535 VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
536 safeAddProp( work_phone, VCWorkProp );
537 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
538 safeAddProp( work_phone, VCWorkProp );
539 safeAddProp( work_phone, VCCellularProp );
540 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
541 safeAddProp( work_phone, VCWorkProp );
542 safeAddProp( work_phone, VCFaxProp );
543 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
544 safeAddProp( work_phone, VCWorkProp );
545 safeAddProp( work_phone, VCPagerProp );
546
547 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
548 safeAddProp( url, VCWorkProp );
549
550 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
551 safeAddProp( title, VCWorkProp );
552
553
554 QStringList emails = c.emailList();
555 // emails.prepend( c.defaultEmail() ); Fix for bugreport #1045
556 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
557 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
558 safeAddProp( email, VCInternetProp );
559 }
560
561 safeAddPropValue( vcard, VCNoteProp, c.notes() );
562
563 // Exporting Birthday regarding RFC 2425 (5.8.4)
564 if ( c.birthday().isValid() ){
565 qWarning("Exporting birthday as: %s", convDateToVCardDate( c.birthday() ).latin1() );
566 safeAddPropValue( vcard, VCBirthDateProp, convDateToVCardDate( c.birthday() ) );
567 }
568
569 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
570 VObject *org = safeAddProp( vcard, VCOrgProp );
571 safeAddPropValue( org, VCOrgNameProp, c.company() );
572 safeAddPropValue( org, VCOrgUnitProp, c.department() );
573 safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
574 }
575
576 // some values we have to export as custom fields
577 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
578 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
579 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
580
581 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
582 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
583 if ( c.anniversary().isValid() ){
584 qWarning("Exporting anniversary as: %s", convDateToVCardDate( c.anniversary() ).latin1() );
585 safeAddPropValue( vcard, "X-Qtopia-Anniversary", convDateToVCardDate( c.anniversary() ) );
586 }
587 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
588 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
589
590 return vcard;
591}
592
593QString OContactAccessBackend_VCard::convDateToVCardDate( const QDate& d ) const
594{
595 QString str_rfc2425 = QString("%1-%2-%3")
596 .arg( d.year() )
597 .arg( d.month(), 2 )
598 .arg( d.day(), 2 );
599 // Now replace spaces with "0"...
600 int pos = 0;
601 while ( ( pos = str_rfc2425.find (' ') ) > 0 )
602 str_rfc2425.replace( pos, 1, "0" );
603
604 return str_rfc2425;
605}
606
607QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr )
608{
609 int monthPos = datestr.find('-');
610 int dayPos = datestr.find('-', monthPos+1 );
611 int sep_ignore = 1;
612 if ( monthPos == -1 || dayPos == -1 ) {
613 qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
614 // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD )
615 if ( datestr.length() == 8 ){
616 monthPos = 4;
617 dayPos = 6;
618 sep_ignore = 0;
619 qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos );
620 } else {
621 return QDate();
622 }
623 }
624 int y = datestr.left( monthPos ).toInt();
625 int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt();
626 int d = datestr.mid( dayPos + sep_ignore ).toInt();
627 qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos);
628 QDate date ( y,m,d );
629 return date;
630}
631
632VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value )
633{
634 VObject *ret = 0;
635 if ( o && !value.isEmpty() )
636 ret = addPropValue( o, prop, value.latin1() );
637 return ret;
638}
639
640VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop)
641{
642 VObject *ret = 0;
643 if ( o )
644 ret = addProp( o, prop );
645 return ret;
646}
diff --git a/libopie/pim/ocontactaccessbackend_vcard.h b/libopie/pim/ocontactaccessbackend_vcard.h
deleted file mode 100644
index 712d769..0000000
--- a/libopie/pim/ocontactaccessbackend_vcard.h
+++ b/dev/null
@@ -1,96 +0,0 @@
1/*
2 * VCard Backend for the OPIE-Contact Database.
3 *
4 * Copyright (C) 2000 Trolltech AS. All rights reserved.
5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
6 *
7 * =====================================================================
8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 * =====================================================================
13 * ToDo:
14 *
15 * =====================================================================
16 * Version: $Id$
17 * =====================================================================
18 * History:
19 * $Log$
20 * Revision 1.6 2003/04/13 18:07:10 zecke
21 * More API doc
22 * QString -> const QString&
23 * QString = 0l -> QString::null
24 *
25 * Revision 1.5 2003/03/21 10:33:09 eilers
26 * Merged speed optimized xml backend for contacts to main.
27 * Added QDateTime to querybyexample. For instance, it is now possible to get
28 * all Birthdays/Anniversaries between two dates. This should be used
29 * to show all birthdays in the datebook..
30 * This change is sourcecode backward compatible but you have to upgrade
31 * the binaries for today-addressbook.
32 *
33 * Revision 1.4 2002/12/07 13:26:22 eilers
34 * Fixing bug in storing anniversary..
35 *
36 * Revision 1.3 2002/11/13 14:14:51 eilers
37 * Added sorted for Contacts..
38 *
39 * Revision 1.2 2002/11/10 15:41:53 eilers
40 * Bugfixes..
41 *
42 * Revision 1.1 2002/11/09 14:34:52 eilers
43 * Added VCard Backend.
44 *
45 */
46#ifndef __OCONTACTACCESSBACKEND_VCARD_H_
47#define __OCONTACTACCESSBACKEND_VCARD_H_
48
49#include <opie/ocontact.h>
50
51#include "ocontactaccessbackend.h"
52
53class VObject;
54
55/**
56 * This is the vCard 2.1 implementation of the Contact Storage
57 * @see OContactAccessBackend_XML
58 * @see OPimAccessBackend
59 */
60class OContactAccessBackend_VCard : public OContactAccessBackend {
61 public:
62 OContactAccessBackend_VCard ( const QString& appname, const QString& filename = QString::null );
63
64 bool load ();
65 bool reload();
66 bool save();
67 void clear ();
68
69 bool add ( const OContact& newcontact );
70 bool remove ( int uid );
71 bool replace ( const OContact& contact );
72
73 OContact find ( int uid ) const;
74 QArray<int> allRecords() const;
75 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
76 QArray<int> matchRegexp( const QRegExp &r ) const;
77
78 const uint querySettings();
79 bool hasQuerySettings (uint querySettings) const;
80 QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat );
81 bool wasChangedExternally();
82
83private:
84 OContact parseVObject( VObject* obj );
85 VObject* createVObject( const OContact& c );
86 QString convDateToVCardDate( const QDate& c ) const;
87 QDate convVCardDateToDate( const QString& datestr );
88 VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value );
89 VObject *safeAddProp( VObject* o, const char* prop);
90
91 bool m_dirty : 1;
92 QString m_file;
93 QMap<int, OContact> m_map;
94};
95
96#endif
diff --git a/libopie/pim/ocontactaccessbackend_xml.cpp b/libopie/pim/ocontactaccessbackend_xml.cpp
deleted file mode 100644
index 2373ad6..0000000
--- a/libopie/pim/ocontactaccessbackend_xml.cpp
+++ b/dev/null
@@ -1,821 +0,0 @@
1/*
2 * XML 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 * Version: $Id$
15 * =====================================================================
16 * History:
17 * $Log$
18 * Revision 1.10 2004/03/01 15:44:36 chicken
19 * fix includes
20 *
21 * Revision 1.9 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 *
26 * Revision 1.8 2003/08/30 15:28:26 eilers
27 * Removed some unimportant debug output which causes slow down..
28 *
29 * Revision 1.7 2003/08/01 12:30:16 eilers
30 * Merging changes from BRANCH_1_0 to HEAD
31 *
32 * Revision 1.6 2003/07/07 16:19:47 eilers
33 * Fixing serious bug in hasQuerySettings()
34 *
35 * Revision 1.5 2003/04/13 18:07:10 zecke
36 * More API doc
37 * QString -> const QString&
38 * QString = 0l -> QString::null
39 *
40 * Revision 1.4 2003/03/21 14:32:54 mickeyl
41 * g++ compliance fix: default arguments belong into the declaration, but not the definition
42 *
43 * Revision 1.3 2003/03/21 12:26:28 eilers
44 * Fixing small bug: If we search a birthday from today to today, it returned
45 * every contact ..
46 *
47 * Revision 1.2 2003/03/21 10:33:09 eilers
48 * Merged speed optimized xml backend for contacts to main.
49 * Added QDateTime to querybyexample. For instance, it is now possible to get
50 * all Birthdays/Anniversaries between two dates. This should be used
51 * to show all birthdays in the datebook..
52 * This change is sourcecode backward compatible but you have to upgrade
53 * the binaries for today-addressbook.
54 *
55 * Revision 1.1.2.2 2003/02/11 12:17:28 eilers
56 * Speed optimization. Removed the sequential search loops.
57 *
58 * Revision 1.1.2.1 2003/02/10 15:31:38 eilers
59 * Writing offsets to debug output..
60 *
61 * Revision 1.1 2003/02/09 15:05:01 eilers
62 * Nothing happened.. Just some cleanup before I will start..
63 *
64 * Revision 1.12 2003/01/03 16:58:03 eilers
65 * Reenable debug output
66 *
67 * Revision 1.11 2003/01/03 12:31:28 eilers
68 * Bugfix for calculating data diffs..
69 *
70 * Revision 1.10 2003/01/02 14:27:12 eilers
71 * Improved query by example: Search by date is possible.. First step
72 * for a today plugin for birthdays..
73 *
74 * Revision 1.9 2002/12/08 12:48:57 eilers
75 * Moved journal-enum from ocontact into i the xml-backend..
76 *
77 * Revision 1.8 2002/11/14 17:04:24 eilers
78 * Sorting will now work if fullname is identical on some entries
79 *
80 * Revision 1.7 2002/11/13 15:02:46 eilers
81 * Small Bug in sorted fixed
82 *
83 * Revision 1.6 2002/11/13 14:14:51 eilers
84 * Added sorted for Contacts..
85 *
86 * Revision 1.5 2002/11/01 15:10:42 eilers
87 * Added regExp-search in database for all fields in a contact.
88 *
89 * Revision 1.4 2002/10/16 10:52:40 eilers
90 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
91 *
92 * Revision 1.3 2002/10/14 16:21:54 eilers
93 * Some minor interface updates
94 *
95 * Revision 1.2 2002/10/07 17:34:24 eilers
96 * added OBackendFactory for advanced backend access
97 *
98 * Revision 1.1 2002/09/27 17:11:44 eilers
99 * Added API for accessing the Contact-Database ! It is compiling, but
100 * please do not expect that anything is working !
101 * I will debug that stuff in the next time ..
102 * Please read README_COMPILE for compiling !
103 *
104 *
105 */
106
107#include "ocontactaccessbackend_xml.h"
108
109#include <qasciidict.h>
110#include <qfile.h>
111#include <qfileinfo.h>
112#include <qregexp.h>
113#include <qarray.h>
114#include <qmap.h>
115
116#include <qpe/global.h>
117
118#include <opie/xmltree.h>
119#include "ocontactaccessbackend.h"
120#include "ocontactaccess.h"
121
122#include <stdlib.h>
123#include <errno.h>
124
125using namespace Opie;
126
127
128OContactAccessBackend_XML::OContactAccessBackend_XML ( const QString& appname, const QString& filename ):
129 m_changed( false )
130{
131 // Just m_contactlist should call delete if an entry
132 // is removed.
133 m_contactList.setAutoDelete( true );
134 m_uidToContact.setAutoDelete( false );
135
136 m_appName = appname;
137
138 /* Set journalfile name ... */
139 m_journalName = getenv("HOME");
140 m_journalName +="/.abjournal" + appname;
141
142 /* Expecting to access the default filename if nothing else is set */
143 if ( filename.isEmpty() ){
144 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
145 } else
146 m_fileName = filename;
147
148 /* Load Database now */
149 load ();
150}
151
152bool OContactAccessBackend_XML::save()
153{
154
155 if ( !m_changed )
156 return true;
157
158 QString strNewFile = m_fileName + ".new";
159 QFile f( strNewFile );
160 if ( !f.open( IO_WriteOnly|IO_Raw ) )
161 return false;
162
163 int total_written;
164 int idx_offset = 0;
165 QString out;
166
167 // Write Header
168 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
169 " <Groups>\n"
170 " </Groups>\n"
171 " <Contacts>\n";
172 QCString cstr = out.utf8();
173 f.writeBlock( cstr.data(), cstr.length() );
174 idx_offset += cstr.length();
175 out = "";
176
177 // Write all contacts
178 QListIterator<OContact> it( m_contactList );
179 for ( ; it.current(); ++it ) {
180 // qWarning(" Uid %d at Offset: %x", (*it)->uid(), idx_offset );
181 out += "<Contact ";
182 (*it)->save( out );
183 out += "/>\n";
184 cstr = out.utf8();
185 total_written = f.writeBlock( cstr.data(), cstr.length() );
186 idx_offset += cstr.length();
187 if ( total_written != int(cstr.length()) ) {
188 f.close();
189 QFile::remove( strNewFile );
190 return false;
191 }
192 out = "";
193 }
194 out += " </Contacts>\n</AddressBook>\n";
195
196 // Write Footer
197 cstr = out.utf8();
198 total_written = f.writeBlock( cstr.data(), cstr.length() );
199 if ( total_written != int( cstr.length() ) ) {
200 f.close();
201 QFile::remove( strNewFile );
202 return false;
203 }
204 f.close();
205
206 // move the file over, I'm just going to use the system call
207 // because, I don't feel like using QDir.
208 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
209 qWarning( "problem renaming file %s to %s, errno: %d",
210 strNewFile.latin1(), m_journalName.latin1(), errno );
211 // remove the tmp file...
212 QFile::remove( strNewFile );
213 }
214
215 /* The journalfile should be removed now... */
216 removeJournal();
217
218 m_changed = false;
219 return true;
220}
221
222bool OContactAccessBackend_XML::load ()
223{
224 m_contactList.clear();
225 m_uidToContact.clear();
226
227 /* Load XML-File and journal if it exists */
228 if ( !load ( m_fileName, false ) )
229 return false;
230 /* The returncode of the journalfile is ignored due to the
231 * fact that it does not exist when this class is instantiated !
232 * But there may such a file exist, if the application crashed.
233 * Therefore we try to load it to get the changes before the #
234 * crash happened...
235 */
236 load (m_journalName, true);
237
238 return true;
239}
240
241void OContactAccessBackend_XML::clear ()
242{
243 m_contactList.clear();
244 m_uidToContact.clear();
245
246 m_changed = false;
247}
248
249bool OContactAccessBackend_XML::wasChangedExternally()
250{
251 QFileInfo fi( m_fileName );
252
253 QDateTime lastmod = fi.lastModified ();
254
255 return (lastmod != m_readtime);
256}
257
258QArray<int> OContactAccessBackend_XML::allRecords() const
259{
260 QArray<int> uid_list( m_contactList.count() );
261
262 uint counter = 0;
263 QListIterator<OContact> it( m_contactList );
264 for( ; it.current(); ++it ){
265 uid_list[counter++] = (*it)->uid();
266 }
267
268 return ( uid_list );
269}
270
271OContact OContactAccessBackend_XML::find ( int uid ) const
272{
273 OContact foundContact; //Create empty contact
274
275 OContact* found = m_uidToContact.find( QString().setNum( uid ) );
276
277 if ( found ){
278 foundContact = *found;
279 }
280
281 return ( foundContact );
282}
283
284QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings,
285 const QDateTime& d )
286{
287
288 QArray<int> m_currentQuery( m_contactList.count() );
289 QListIterator<OContact> it( m_contactList );
290 uint arraycounter = 0;
291
292 for( ; it.current(); ++it ){
293 /* Search all fields and compare them with query object. Store them into list
294 * if all fields matches.
295 */
296 QDate* queryDate = 0l;
297 QDate* checkDate = 0l;
298 bool allcorrect = true;
299 for ( int i = 0; i < Qtopia::Groups; i++ ) {
300 // Birthday and anniversary are special nonstring fields and should
301 // be handled specially
302 switch ( i ){
303 case Qtopia::Birthday:
304 queryDate = new QDate( query.birthday() );
305 checkDate = new QDate( (*it)->birthday() );
306 case Qtopia::Anniversary:
307 if ( queryDate == 0l ){
308 queryDate = new QDate( query.anniversary() );
309 checkDate = new QDate( (*it)->anniversary() );
310 }
311
312 if ( queryDate->isValid() ){
313 if( checkDate->isValid() ){
314 if ( settings & OContactAccess::DateYear ){
315 if ( queryDate->year() != checkDate->year() )
316 allcorrect = false;
317 }
318 if ( settings & OContactAccess::DateMonth ){
319 if ( queryDate->month() != checkDate->month() )
320 allcorrect = false;
321 }
322 if ( settings & OContactAccess::DateDay ){
323 if ( queryDate->day() != checkDate->day() )
324 allcorrect = false;
325 }
326 if ( settings & OContactAccess::DateDiff ) {
327 QDate current;
328 // If we get an additional date, we
329 // will take this date instead of
330 // the current one..
331 if ( !d.date().isValid() )
332 current = QDate::currentDate();
333 else
334 current = d.date();
335
336 // We have to equalize the year, otherwise
337 // the search will fail..
338 checkDate->setYMD( current.year(),
339 checkDate->month(),
340 checkDate->day() );
341 if ( *checkDate < current )
342 checkDate->setYMD( current.year()+1,
343 checkDate->month(),
344 checkDate->day() );
345
346 // Check whether the birthday/anniversary date is between
347 // the current/given date and the maximum date
348 // ( maximum time range ) !
349 qWarning("Checking if %s is between %s and %s ! ",
350 checkDate->toString().latin1(),
351 current.toString().latin1(),
352 queryDate->toString().latin1() );
353 if ( current.daysTo( *queryDate ) >= 0 ){
354 if ( !( ( *checkDate >= current ) &&
355 ( *checkDate <= *queryDate ) ) ){
356 allcorrect = false;
357 qWarning (" Nope!..");
358 }
359 }
360 }
361 } else{
362 // checkDate is invalid. Therefore this entry is always rejected
363 allcorrect = false;
364 }
365 }
366
367 delete queryDate;
368 queryDate = 0l;
369 delete checkDate;
370 checkDate = 0l;
371 break;
372 default:
373 /* Just compare fields which are not empty in the query object */
374 if ( !query.field(i).isEmpty() ){
375 switch ( settings & ~( OContactAccess::IgnoreCase
376 | OContactAccess::DateDiff
377 | OContactAccess::DateYear
378 | OContactAccess::DateMonth
379 | OContactAccess::DateDay
380 | OContactAccess::MatchOne
381 ) ){
382
383 case OContactAccess::RegExp:{
384 QRegExp expr ( query.field(i),
385 !(settings & OContactAccess::IgnoreCase),
386 false );
387 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
388 allcorrect = false;
389 }
390 break;
391 case OContactAccess::WildCards:{
392 QRegExp expr ( query.field(i),
393 !(settings & OContactAccess::IgnoreCase),
394 true );
395 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
396 allcorrect = false;
397 }
398 break;
399 case OContactAccess::ExactMatch:{
400 if (settings & OContactAccess::IgnoreCase){
401 if ( query.field(i).upper() !=
402 (*it)->field(i).upper() )
403 allcorrect = false;
404 }else{
405 if ( query.field(i) != (*it)->field(i) )
406 allcorrect = false;
407 }
408 }
409 break;
410 }
411 }
412 }
413 }
414 if ( allcorrect ){
415 m_currentQuery[arraycounter++] = (*it)->uid();
416 }
417 }
418
419 // Shrink to fit..
420 m_currentQuery.resize(arraycounter);
421
422 return m_currentQuery;
423}
424
425QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
426{
427 QArray<int> m_currentQuery( m_contactList.count() );
428 QListIterator<OContact> it( m_contactList );
429 uint arraycounter = 0;
430
431 for( ; it.current(); ++it ){
432 if ( (*it)->match( r ) ){
433 m_currentQuery[arraycounter++] = (*it)->uid();
434 }
435
436 }
437 // Shrink to fit..
438 m_currentQuery.resize(arraycounter);
439
440 return m_currentQuery;
441}
442
443const uint OContactAccessBackend_XML::querySettings()
444{
445 return ( OContactAccess::WildCards
446 | OContactAccess::IgnoreCase
447 | OContactAccess::RegExp
448 | OContactAccess::ExactMatch
449 | OContactAccess::DateDiff
450 | OContactAccess::DateYear
451 | OContactAccess::DateMonth
452 | OContactAccess::DateDay
453 );
454}
455
456bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
457{
458 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
459 * may be added with any of the other settings. IgnoreCase should never used alone.
460 * Wildcards, RegExp, ExactMatch should never used at the same time...
461 */
462
463 // Step 1: Check whether the given settings are supported by this backend
464 if ( ( querySettings & (
465 OContactAccess::IgnoreCase
466 | OContactAccess::WildCards
467 | OContactAccess::DateDiff
468 | OContactAccess::DateYear
469 | OContactAccess::DateMonth
470 | OContactAccess::DateDay
471 | OContactAccess::RegExp
472 | OContactAccess::ExactMatch
473 ) ) != querySettings )
474 return false;
475
476 // Step 2: Check whether the given combinations are ok..
477
478 // IngoreCase alone is invalid
479 if ( querySettings == OContactAccess::IgnoreCase )
480 return false;
481
482 // WildCards, RegExp and ExactMatch should never used at the same time
483 switch ( querySettings & ~( OContactAccess::IgnoreCase
484 | OContactAccess::DateDiff
485 | OContactAccess::DateYear
486 | OContactAccess::DateMonth
487 | OContactAccess::DateDay
488 )
489 ){
490 case OContactAccess::RegExp:
491 return ( true );
492 case OContactAccess::WildCards:
493 return ( true );
494 case OContactAccess::ExactMatch:
495 return ( true );
496 case 0: // one of the upper removed bits were set..
497 return ( true );
498 default:
499 return ( false );
500 }
501}
502
503// Currently only asc implemented..
504QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int )
505{
506 QMap<QString, int> nameToUid;
507 QStringList names;
508 QArray<int> m_currentQuery( m_contactList.count() );
509
510 // First fill map and StringList with all Names
511 // Afterwards sort namelist and use map to fill array to return..
512 QListIterator<OContact> it( m_contactList );
513 for( ; it.current(); ++it ){
514 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
515 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
516 }
517 names.sort();
518
519 int i = 0;
520 if ( asc ){
521 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
522 m_currentQuery[i++] = nameToUid[ (*it) ];
523 }else{
524 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
525 m_currentQuery[i++] = nameToUid[ (*it) ];
526 }
527
528 return m_currentQuery;
529
530}
531
532bool OContactAccessBackend_XML::add ( const OContact &newcontact )
533{
534 //qWarning("odefaultbackend: ACTION::ADD");
535 updateJournal (newcontact, ACTION_ADD);
536 addContact_p( newcontact );
537
538 m_changed = true;
539
540 return true;
541}
542
543bool OContactAccessBackend_XML::replace ( const OContact &contact )
544{
545 m_changed = true;
546
547 OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
548
549 if ( found ) {
550 OContact* newCont = new OContact( contact );
551
552 updateJournal ( *newCont, ACTION_REPLACE);
553 m_contactList.removeRef ( found );
554 m_contactList.append ( newCont );
555 m_uidToContact.remove( QString().setNum( contact.uid() ) );
556 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
557
558 qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid());
559
560 return true;
561 } else
562 return false;
563}
564
565bool OContactAccessBackend_XML::remove ( int uid )
566{
567 m_changed = true;
568
569 OContact* found = m_uidToContact.find ( QString().setNum( uid ) );
570
571 if ( found ) {
572 updateJournal ( *found, ACTION_REMOVE);
573 m_contactList.removeRef ( found );
574 m_uidToContact.remove( QString().setNum( uid ) );
575
576 return true;
577 } else
578 return false;
579}
580
581bool OContactAccessBackend_XML::reload(){
582 /* Reload is the same as load in this implementation */
583 return ( load() );
584}
585
586void OContactAccessBackend_XML::addContact_p( const OContact &newcontact )
587{
588 OContact* contRef = new OContact( newcontact );
589
590 m_contactList.append ( contRef );
591 m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef );
592}
593
594/* This function loads the xml-database and the journalfile */
595bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
596{
597
598 /* We use the time of the last read to check if the file was
599 * changed externally.
600 */
601 if ( !isJournal ){
602 QFileInfo fi( filename );
603 m_readtime = fi.lastModified ();
604 }
605
606 const int JOURNALACTION = Qtopia::Notes + 1;
607 const int JOURNALROW = JOURNALACTION + 1;
608
609 bool foundAction = false;
610 journal_action action = ACTION_ADD;
611 int journalKey = 0;
612 QMap<int, QString> contactMap;
613 QMap<QString, QString> customMap;
614 QMap<QString, QString>::Iterator customIt;
615 QAsciiDict<int> dict( 47 );
616
617 dict.setAutoDelete( TRUE );
618 dict.insert( "Uid", new int(Qtopia::AddressUid) );
619 dict.insert( "Title", new int(Qtopia::Title) );
620 dict.insert( "FirstName", new int(Qtopia::FirstName) );
621 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
622 dict.insert( "LastName", new int(Qtopia::LastName) );
623 dict.insert( "Suffix", new int(Qtopia::Suffix) );
624 dict.insert( "FileAs", new int(Qtopia::FileAs) );
625 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
626 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
627 dict.insert( "Emails", new int(Qtopia::Emails) );
628 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
629 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
630 dict.insert( "HomeState", new int(Qtopia::HomeState) );
631 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
632 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
633 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
634 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
635 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
636 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
637 dict.insert( "Company", new int(Qtopia::Company) );
638 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
639 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
640 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
641 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
642 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
643 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
644 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
645 dict.insert( "Department", new int(Qtopia::Department) );
646 dict.insert( "Office", new int(Qtopia::Office) );
647 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
648 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
649 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
650 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
651 dict.insert( "Profession", new int(Qtopia::Profession) );
652 dict.insert( "Assistant", new int(Qtopia::Assistant) );
653 dict.insert( "Manager", new int(Qtopia::Manager) );
654 dict.insert( "Spouse", new int(Qtopia::Spouse) );
655 dict.insert( "Children", new int(Qtopia::Children) );
656 dict.insert( "Gender", new int(Qtopia::Gender) );
657 dict.insert( "Birthday", new int(Qtopia::Birthday) );
658 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
659 dict.insert( "Nickname", new int(Qtopia::Nickname) );
660 dict.insert( "Notes", new int(Qtopia::Notes) );
661 dict.insert( "action", new int(JOURNALACTION) );
662 dict.insert( "actionrow", new int(JOURNALROW) );
663
664 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
665
666 XMLElement *root = XMLElement::load( filename );
667 if(root != 0l ){ // start parsing
668 /* Parse all XML-Elements and put the data into the
669 * Contact-Class
670 */
671 XMLElement *element = root->firstChild();
672 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
673 element = element->firstChild();
674
675 /* Search Tag "Contacts" which is the parent of all Contacts */
676 while( element && !isJournal ){
677 if( element->tagName() != QString::fromLatin1("Contacts") ){
678 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
679 // element->tagName().latin1());
680 element = element->nextChild();
681 } else {
682 element = element->firstChild();
683 break;
684 }
685 }
686 /* Parse all Contacts and ignore unknown tags */
687 while( element ){
688 if( element->tagName() != QString::fromLatin1("Contact") ){
689 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
690 // element->tagName().latin1());
691 element = element->nextChild();
692 continue;
693 }
694 /* Found alement with tagname "contact", now parse and store all
695 * attributes contained
696 */
697 //qWarning("OContactDefBack::load element tagName() : %s",
698 // element->tagName().latin1() );
699 QString dummy;
700 foundAction = false;
701
702 XMLElement::AttributeMap aMap = element->attributes();
703 XMLElement::AttributeMap::Iterator it;
704 contactMap.clear();
705 customMap.clear();
706 for( it = aMap.begin(); it != aMap.end(); ++it ){
707 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
708
709 int *find = dict[ it.key() ];
710 /* Unknown attributes will be stored as "Custom" elements */
711 if ( !find ) {
712 // qWarning("Attribute %s not known.", it.key().latin1());
713 //contact.setCustomField(it.key(), it.data());
714 customMap.insert( it.key(), it.data() );
715 continue;
716 }
717
718 /* Check if special conversion is needed and add attribute
719 * into Contact class
720 */
721 switch( *find ) {
722 /*
723 case Qtopia::AddressUid:
724 contact.setUid( it.data().toInt() );
725 break;
726 case Qtopia::AddressCategory:
727 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
728 break;
729 */
730 case JOURNALACTION:
731 action = journal_action(it.data().toInt());
732 foundAction = true;
733 qWarning ("ODefBack(journal)::ACTION found: %d", action);
734 break;
735 case JOURNALROW:
736 journalKey = it.data().toInt();
737 break;
738 default: // no conversion needed add them to the map
739 contactMap.insert( *find, it.data() );
740 break;
741 }
742 }
743 /* now generate the Contact contact */
744 OContact contact( contactMap );
745
746 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
747 contact.setCustomField( customIt.key(), customIt.data() );
748 }
749
750 if (foundAction){
751 foundAction = false;
752 switch ( action ) {
753 case ACTION_ADD:
754 addContact_p (contact);
755 break;
756 case ACTION_REMOVE:
757 if ( !remove (contact.uid()) )
758 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
759 contact.uid() );
760 break;
761 case ACTION_REPLACE:
762 if ( !replace ( contact ) )
763 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
764 contact.uid() );
765 break;
766 default:
767 qWarning ("Unknown action: ignored !");
768 break;
769 }
770 }else{
771 /* Add contact to list */
772 addContact_p (contact);
773 }
774
775 /* Move to next element */
776 element = element->nextChild();
777 }
778 }else {
779 qWarning("ODefBack::could not load");
780 }
781 delete root;
782 qWarning("returning from loading" );
783 return true;
784}
785
786
787void OContactAccessBackend_XML::updateJournal( const OContact& cnt,
788 journal_action action )
789{
790 QFile f( m_journalName );
791 bool created = !f.exists();
792 if ( !f.open(IO_WriteOnly|IO_Append) )
793 return;
794
795 QString buf;
796 QCString str;
797
798 // if the file was created, we have to set the Tag "<CONTACTS>" to
799 // get a XML-File which is readable by our parser.
800 // This is just a cheat, but better than rewrite the parser.
801 if ( created ){
802 buf = "<Contacts>";
803 QCString cstr = buf.utf8();
804 f.writeBlock( cstr.data(), cstr.length() );
805 }
806
807 buf = "<Contact ";
808 cnt.save( buf );
809 buf += " action=\"" + QString::number( (int)action ) + "\" ";
810 buf += "/>\n";
811 QCString cstr = buf.utf8();
812 f.writeBlock( cstr.data(), cstr.length() );
813}
814
815void OContactAccessBackend_XML::removeJournal()
816{
817 QFile f ( m_journalName );
818 if ( f.exists() )
819 f.remove();
820}
821
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
deleted file mode 100644
index a0cae4d..0000000
--- a/libopie/pim/ocontactaccessbackend_xml.h
+++ b/dev/null
@@ -1,160 +0,0 @@
1/*
2 * XML 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 * ToDo: XML-Backend: Automatic reload if something was changed...
13 * File Locking to protect against concurrent access
14 *
15 *
16 * =====================================================================
17 * Version: $Id$
18 * =====================================================================
19 * History:
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 *
26 * Revision 1.14 2003/04/13 18:07:10 zecke
27 * More API doc
28 * QString -> const QString&
29 * QString = 0l -> QString::null
30 *
31 * Revision 1.13 2003/03/21 10:33:09 eilers
32 * Merged speed optimized xml backend for contacts to main.
33 * Added QDateTime to querybyexample. For instance, it is now possible to get
34 * all Birthdays/Anniversaries between two dates. This should be used
35 * to show all birthdays in the datebook..
36 * This change is sourcecode backward compatible but you have to upgrade
37 * the binaries for today-addressbook.
38 *
39 * Revision 1.12.2.2 2003/02/11 12:17:28 eilers
40 * Speed optimization. Removed the sequential search loops.
41 *
42 * Revision 1.12.2.1 2003/02/09 15:05:01 eilers
43 * Nothing happened.. Just some cleanup before I will start..
44 *
45 * Revision 1.12 2003/01/03 16:58:03 eilers
46 * Reenable debug output
47 *
48 * Revision 1.11 2003/01/03 12:31:28 eilers
49 * Bugfix for calculating data diffs..
50 *
51 * Revision 1.10 2003/01/02 14:27:12 eilers
52 * Improved query by example: Search by date is possible.. First step
53 * for a today plugin for birthdays..
54 *
55 * Revision 1.9 2002/12/08 12:48:57 eilers
56 * Moved journal-enum from ocontact into i the xml-backend..
57 *
58 * Revision 1.8 2002/11/14 17:04:24 eilers
59 * Sorting will now work if fullname is identical on some entries
60 *
61 * Revision 1.7 2002/11/13 15:02:46 eilers
62 * Small Bug in sorted fixed
63 *
64 * Revision 1.6 2002/11/13 14:14:51 eilers
65 * Added sorted for Contacts..
66 *
67 * Revision 1.5 2002/11/01 15:10:42 eilers
68 * Added regExp-search in database for all fields in a contact.
69 *
70 * Revision 1.4 2002/10/16 10:52:40 eilers
71 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
72 *
73 * Revision 1.3 2002/10/14 16:21:54 eilers
74 * Some minor interface updates
75 *
76 * Revision 1.2 2002/10/07 17:34:24 eilers
77 * added OBackendFactory for advanced backend access
78 *
79 * Revision 1.1 2002/09/27 17:11:44 eilers
80 * Added API for accessing the Contact-Database ! It is compiling, but
81 * please do not expect that anything is working !
82 * I will debug that stuff in the next time ..
83 * Please read README_COMPILE for compiling !
84 *
85 *
86 */
87
88#ifndef _OContactAccessBackend_XML_
89#define _OContactAccessBackend_XML_
90
91#include "ocontactaccessbackend.h"
92#include "ocontactaccess.h"
93
94#include <qlist.h>
95#include <qdict.h>
96
97/* the default xml implementation */
98/**
99 * This class is the XML implementation of a Contact backend
100 * it does implement everything available for OContact.
101 * @see OPimAccessBackend for more information of available methods
102 */
103class OContactAccessBackend_XML : public OContactAccessBackend {
104 public:
105 OContactAccessBackend_XML ( const QString& appname, const QString& filename = QString::null );
106
107 bool save();
108
109 bool load ();
110
111 void clear ();
112
113 bool wasChangedExternally();
114
115 QArray<int> allRecords() const;
116
117 OContact find ( int uid ) const;
118
119 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
120
121 QArray<int> matchRegexp( const QRegExp &r ) const;
122
123 const uint querySettings();
124
125 bool hasQuerySettings (uint querySettings) const;
126
127 // Currently only asc implemented..
128 QArray<int> sorted( bool asc, int , int , int );
129 bool add ( const OContact &newcontact );
130
131 bool replace ( const OContact &contact );
132
133 bool remove ( int uid );
134 bool reload();
135
136 private:
137
138 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
139
140 void addContact_p( const OContact &newcontact );
141
142 /* This function loads the xml-database and the journalfile */
143 bool load( const QString filename, bool isJournal );
144
145
146 void updateJournal( const OContact& cnt, journal_action action );
147 void removeJournal();
148
149 protected:
150 bool m_changed;
151 QString m_journalName;
152 QString m_fileName;
153 QString m_appName;
154 QList<OContact> m_contactList;
155 QDateTime m_readtime;
156
157 QDict<OContact> m_uidToContact;
158};
159
160#endif
diff --git a/libopie/pim/ocontactfields.cpp b/libopie/pim/ocontactfields.cpp
deleted file mode 100644
index 0f08a5a..0000000
--- a/libopie/pim/ocontactfields.cpp
+++ b/dev/null
@@ -1,477 +0,0 @@
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 personal field names for a contact.
15*/
16QStringList OContactFields::personalfields( bool sorted, bool translated )
17{
18 QStringList list;
19 QMap<int, QString> mapIdToStr;
20 if ( translated )
21 mapIdToStr = idToTrFields();
22 else
23 mapIdToStr = idToUntrFields();
24
25 list.append( mapIdToStr[ Qtopia::AddressUid ] );
26 list.append( mapIdToStr[ Qtopia::AddressCategory ] );
27
28 list.append( mapIdToStr[ Qtopia::Title ] );
29 list.append( mapIdToStr[ Qtopia::FirstName ] );
30 list.append( mapIdToStr[ Qtopia::MiddleName ] );
31 list.append( mapIdToStr[ Qtopia::LastName ] );
32 list.append( mapIdToStr[ Qtopia::Suffix ] );
33 list.append( mapIdToStr[ Qtopia::FileAs ] );
34
35 list.append( mapIdToStr[ Qtopia::JobTitle ] );
36 list.append( mapIdToStr[ Qtopia::Department ] );
37 list.append( mapIdToStr[ Qtopia::Company ] );
38
39 list.append( mapIdToStr[ Qtopia::Notes ] );
40 list.append( mapIdToStr[ Qtopia::Groups ] );
41
42 if (sorted) list.sort();
43 return list;
44}
45
46/*!
47 \internal
48 Returns a list of details field names for a contact.
49*/
50QStringList OContactFields::detailsfields( bool sorted, bool translated )
51{
52 QStringList list;
53 QMap<int, QString> mapIdToStr;
54 if ( translated )
55 mapIdToStr = idToTrFields();
56 else
57 mapIdToStr = idToUntrFields();
58
59 list.append( mapIdToStr[ Qtopia::Office ] );
60 list.append( mapIdToStr[ Qtopia::Profession ] );
61 list.append( mapIdToStr[ Qtopia::Assistant ] );
62 list.append( mapIdToStr[ Qtopia::Manager ] );
63
64 list.append( mapIdToStr[ Qtopia::Spouse ] );
65 list.append( mapIdToStr[ Qtopia::Gender ] );
66 list.append( mapIdToStr[ Qtopia::Birthday ] );
67 list.append( mapIdToStr[ Qtopia::Anniversary ] );
68 list.append( mapIdToStr[ Qtopia::Nickname ] );
69 list.append( mapIdToStr[ Qtopia::Children ] );
70
71 if (sorted) list.sort();
72 return list;
73}
74
75/*!
76 \internal
77 Returns a list of phone field names for a contact.
78*/
79QStringList OContactFields::phonefields( bool sorted, bool translated )
80{
81 QStringList list;
82 QMap<int, QString> mapIdToStr;
83 if ( translated )
84 mapIdToStr = idToTrFields();
85 else
86 mapIdToStr = idToUntrFields();
87
88 list.append( mapIdToStr[Qtopia::BusinessPhone] );
89 list.append( mapIdToStr[Qtopia::BusinessFax] );
90 list.append( mapIdToStr[Qtopia::BusinessMobile] );
91 list.append( mapIdToStr[Qtopia::BusinessPager] );
92 list.append( mapIdToStr[Qtopia::BusinessWebPage] );
93
94 list.append( mapIdToStr[Qtopia::DefaultEmail] );
95 list.append( mapIdToStr[Qtopia::Emails] );
96
97 list.append( mapIdToStr[Qtopia::HomePhone] );
98 list.append( mapIdToStr[Qtopia::HomeFax] );
99 list.append( mapIdToStr[Qtopia::HomeMobile] );
100 // list.append( mapIdToStr[Qtopia::HomePager] );
101 list.append( mapIdToStr[Qtopia::HomeWebPage] );
102
103 if (sorted) list.sort();
104
105 return list;
106}
107
108/*!
109 \internal
110 Returns a list of field names for a contact.
111*/
112QStringList OContactFields::fields( bool sorted, bool translated )
113{
114 QStringList list;
115 QMap<int, QString> mapIdToStr;
116 if ( translated )
117 mapIdToStr = idToTrFields();
118 else
119 mapIdToStr = idToUntrFields();
120
121 list += personalfields( sorted, translated );
122
123 list += phonefields( sorted, translated );
124
125 list.append( mapIdToStr[Qtopia::BusinessStreet] );
126 list.append( mapIdToStr[Qtopia::BusinessCity] );
127 list.append( mapIdToStr[Qtopia::BusinessState] );
128 list.append( mapIdToStr[Qtopia::BusinessZip] );
129 list.append( mapIdToStr[Qtopia::BusinessCountry] );
130
131 list.append( mapIdToStr[Qtopia::HomeStreet] );
132 list.append( mapIdToStr[Qtopia::HomeCity] );
133 list.append( mapIdToStr[Qtopia::HomeState] );
134 list.append( mapIdToStr[Qtopia::HomeZip] );
135 list.append( mapIdToStr[Qtopia::HomeCountry] );
136
137 list += detailsfields( sorted, translated );
138
139 if (sorted) list.sort();
140
141 return list;
142}
143
144
145/*!
146 \internal
147 Returns an untranslated list of personal field names for a contact.
148*/
149QStringList OContactFields::untrpersonalfields( bool sorted )
150{
151 return personalfields( sorted, false );
152}
153
154
155/*!
156 \internal
157 Returns a translated list of personal field names for a contact.
158*/
159QStringList OContactFields::trpersonalfields( bool sorted )
160{
161 return personalfields( sorted, true );
162}
163
164
165/*!
166 \internal
167 Returns an untranslated list of details field names for a contact.
168*/
169QStringList OContactFields::untrdetailsfields( bool sorted )
170{
171 return detailsfields( sorted, false );
172}
173
174
175/*!
176 \internal
177 Returns a translated list of details field names for a contact.
178*/
179QStringList OContactFields::trdetailsfields( bool sorted )
180{
181 return detailsfields( sorted, true );
182}
183
184
185/*!
186 \internal
187 Returns a translated list of phone field names for a contact.
188*/
189QStringList OContactFields::trphonefields( bool sorted )
190{
191 return phonefields( sorted, true );
192}
193
194/*!
195 \internal
196 Returns an untranslated list of phone field names for a contact.
197*/
198QStringList OContactFields::untrphonefields( bool sorted )
199{
200 return phonefields( sorted, false );
201}
202
203
204/*!
205 \internal
206 Returns a translated list of field names for a contact.
207*/
208QStringList OContactFields::trfields( bool sorted )
209{
210 return fields( sorted, true );
211}
212
213/*!
214 \internal
215 Returns an untranslated list of field names for a contact.
216*/
217QStringList OContactFields::untrfields( bool sorted )
218{
219 return fields( sorted, false );
220}
221
222QMap<int, QString> OContactFields::idToTrFields()
223{
224 QMap<int, QString> ret_map;
225
226 ret_map.insert( Qtopia::AddressUid, QObject::tr( "User Id" ) );
227 ret_map.insert( Qtopia::AddressCategory, QObject::tr( "Categories" ) );
228
229 ret_map.insert( Qtopia::Title, QObject::tr( "Name Title") );
230 ret_map.insert( Qtopia::FirstName, QObject::tr( "First Name" ) );
231 ret_map.insert( Qtopia::MiddleName, QObject::tr( "Middle Name" ) );
232 ret_map.insert( Qtopia::LastName, QObject::tr( "Last Name" ) );
233 ret_map.insert( Qtopia::Suffix, QObject::tr( "Suffix" ));
234 ret_map.insert( Qtopia::FileAs, QObject::tr( "File As" ) );
235
236 ret_map.insert( Qtopia::JobTitle, QObject::tr( "Job Title" ) );
237 ret_map.insert( Qtopia::Department, QObject::tr( "Department" ) );
238 ret_map.insert( Qtopia::Company, QObject::tr( "Company" ) );
239 ret_map.insert( Qtopia::BusinessPhone, QObject::tr( "Business Phone" ) );
240 ret_map.insert( Qtopia::BusinessFax, QObject::tr( "Business Fax" ) );
241 ret_map.insert( Qtopia::BusinessMobile, QObject::tr( "Business Mobile" ));
242
243 // email
244 ret_map.insert( Qtopia::DefaultEmail, QObject::tr( "Default Email" ) );
245 ret_map.insert( Qtopia::Emails, QObject::tr( "Emails" ) );
246
247 ret_map.insert( Qtopia::HomePhone, QObject::tr( "Home Phone" ) );
248 ret_map.insert( Qtopia::HomeFax, QObject::tr( "Home Fax" ) );
249 ret_map.insert( Qtopia::HomeMobile, QObject::tr( "Home Mobile" ) );
250
251 // business
252 ret_map.insert( Qtopia::BusinessStreet, QObject::tr( "Business Street" ) );
253 ret_map.insert( Qtopia::BusinessCity, QObject::tr( "Business City" ) );
254 ret_map.insert( Qtopia::BusinessState, QObject::tr( "Business State" ) );
255 ret_map.insert( Qtopia::BusinessZip, QObject::tr( "Business Zip" ) );
256 ret_map.insert( Qtopia::BusinessCountry, QObject::tr( "Business Country" ) );
257 ret_map.insert( Qtopia::BusinessPager, QObject::tr( "Business Pager" ) );
258 ret_map.insert( Qtopia::BusinessWebPage, QObject::tr( "Business WebPage" ) );
259
260 ret_map.insert( Qtopia::Office, QObject::tr( "Office" ) );
261 ret_map.insert( Qtopia::Profession, QObject::tr( "Profession" ) );
262 ret_map.insert( Qtopia::Assistant, QObject::tr( "Assistant" ) );
263 ret_map.insert( Qtopia::Manager, QObject::tr( "Manager" ) );
264
265 // home
266 ret_map.insert( Qtopia::HomeStreet, QObject::tr( "Home Street" ) );
267 ret_map.insert( Qtopia::HomeCity, QObject::tr( "Home City" ) );
268 ret_map.insert( Qtopia::HomeState, QObject::tr( "Home State" ) );
269 ret_map.insert( Qtopia::HomeZip, QObject::tr( "Home Zip" ) );
270 ret_map.insert( Qtopia::HomeCountry, QObject::tr( "Home Country" ) );
271 ret_map.insert( Qtopia::HomeWebPage, QObject::tr( "Home Web Page" ) );
272
273 //personal
274 ret_map.insert( Qtopia::Spouse, QObject::tr( "Spouse" ) );
275 ret_map.insert( Qtopia::Gender, QObject::tr( "Gender" ) );
276 ret_map.insert( Qtopia::Birthday, QObject::tr( "Birthday" ) );
277 ret_map.insert( Qtopia::Anniversary, QObject::tr( "Anniversary" ) );
278 ret_map.insert( Qtopia::Nickname, QObject::tr( "Nickname" ) );
279 ret_map.insert( Qtopia::Children, QObject::tr( "Children" ) );
280
281 // other
282 ret_map.insert( Qtopia::Notes, QObject::tr( "Notes" ) );
283
284
285 return ret_map;
286}
287
288QMap<int, QString> OContactFields::idToUntrFields()
289{
290 QMap<int, QString> ret_map;
291
292 ret_map.insert( Qtopia::AddressUid, "User Id" );
293 ret_map.insert( Qtopia::AddressCategory, "Categories" );
294
295 ret_map.insert( Qtopia::Title, "Name Title" );
296 ret_map.insert( Qtopia::FirstName, "First Name" );
297 ret_map.insert( Qtopia::MiddleName, "Middle Name" );
298 ret_map.insert( Qtopia::LastName, "Last Name" );
299 ret_map.insert( Qtopia::Suffix, "Suffix" );
300 ret_map.insert( Qtopia::FileAs, "File As" );
301
302 ret_map.insert( Qtopia::JobTitle, "Job Title" );
303 ret_map.insert( Qtopia::Department, "Department" );
304 ret_map.insert( Qtopia::Company, "Company" );
305 ret_map.insert( Qtopia::BusinessPhone, "Business Phone" );
306 ret_map.insert( Qtopia::BusinessFax, "Business Fax" );
307 ret_map.insert( Qtopia::BusinessMobile, "Business Mobile" );
308
309 // email
310 ret_map.insert( Qtopia::DefaultEmail, "Default Email" );
311 ret_map.insert( Qtopia::Emails, "Emails" );
312
313 ret_map.insert( Qtopia::HomePhone, "Home Phone" );
314 ret_map.insert( Qtopia::HomeFax, "Home Fax" );
315 ret_map.insert( Qtopia::HomeMobile, "Home Mobile" );
316
317 // business
318 ret_map.insert( Qtopia::BusinessStreet, "Business Street" );
319 ret_map.insert( Qtopia::BusinessCity, "Business City" );
320 ret_map.insert( Qtopia::BusinessState, "Business State" );
321 ret_map.insert( Qtopia::BusinessZip, "Business Zip" );
322 ret_map.insert( Qtopia::BusinessCountry, "Business Country" );
323 ret_map.insert( Qtopia::BusinessPager, "Business Pager" );
324 ret_map.insert( Qtopia::BusinessWebPage, "Business WebPage" );
325
326 ret_map.insert( Qtopia::Office, "Office" );
327 ret_map.insert( Qtopia::Profession, "Profession" );
328 ret_map.insert( Qtopia::Assistant, "Assistant" );
329 ret_map.insert( Qtopia::Manager, "Manager" );
330
331 // home
332 ret_map.insert( Qtopia::HomeStreet, "Home Street" );
333 ret_map.insert( Qtopia::HomeCity, "Home City" );
334 ret_map.insert( Qtopia::HomeState, "Home State" );
335 ret_map.insert( Qtopia::HomeZip, "Home Zip" );
336 ret_map.insert( Qtopia::HomeCountry, "Home Country" );
337 ret_map.insert( Qtopia::HomeWebPage, "Home Web Page" );
338
339 //personal
340 ret_map.insert( Qtopia::Spouse, "Spouse" );
341 ret_map.insert( Qtopia::Gender, "Gender" );
342 ret_map.insert( Qtopia::Birthday, "Birthday" );
343 ret_map.insert( Qtopia::Anniversary, "Anniversary" );
344 ret_map.insert( Qtopia::Nickname, "Nickname" );
345 ret_map.insert( Qtopia::Children, "Children" );
346
347 // other
348 ret_map.insert( Qtopia::Notes, "Notes" );
349 ret_map.insert( Qtopia::Groups, "Groups" );
350
351
352 return ret_map;
353}
354
355QMap<QString, int> OContactFields::trFieldsToId()
356{
357 QMap<int, QString> idtostr = idToTrFields();
358 QMap<QString, int> ret_map;
359
360
361 QMap<int, QString>::Iterator it;
362 for( it = idtostr.begin(); it != idtostr.end(); ++it )
363 ret_map.insert( *it, it.key() );
364
365
366 return ret_map;
367}
368
369/* ======================================================================= */
370
371QMap<QString, int> OContactFields::untrFieldsToId()
372{
373 QMap<int, QString> idtostr = idToUntrFields();
374 QMap<QString, int> ret_map;
375
376
377 QMap<int, QString>::Iterator it;
378 for( it = idtostr.begin(); it != idtostr.end(); ++it )
379 ret_map.insert( *it, it.key() );
380
381
382 return ret_map;
383}
384
385
386OContactFields::OContactFields():
387 fieldOrder( DEFAULT_FIELD_ORDER ),
388 changedFieldOrder( false )
389{
390 // Get the global field order from the config file and
391 // use it as a start pattern
392 Config cfg ( "AddressBook" );
393 cfg.setGroup( "ContactFieldOrder" );
394 globalFieldOrder = cfg.readEntry( "General", DEFAULT_FIELD_ORDER );
395}
396
397OContactFields::~OContactFields(){
398
399 // We will store the fieldorder into the config file
400 // to reuse it for the future..
401 if ( changedFieldOrder ){
402 Config cfg ( "AddressBook" );
403 cfg.setGroup( "ContactFieldOrder" );
404 cfg.writeEntry( "General", globalFieldOrder );
405 }
406}
407
408
409
410void OContactFields::saveToRecord( OContact &cnt ){
411
412 qDebug("ocontactfields saveToRecord: >%s<",fieldOrder.latin1());
413
414 // Store fieldorder into this contact.
415 cnt.setCustomField( CONTACT_FIELD_ORDER_NAME, fieldOrder );
416
417 globalFieldOrder = fieldOrder;
418 changedFieldOrder = true;
419
420}
421
422void OContactFields::loadFromRecord( const OContact &cnt ){
423 qDebug("ocontactfields loadFromRecord");
424 qDebug("loading >%s<",cnt.fullName().latin1());
425
426 // Get fieldorder for this contact. If none is defined,
427 // we will use the global one from the config file..
428
429 fieldOrder = cnt.customField( CONTACT_FIELD_ORDER_NAME );
430
431 qDebug("fieldOrder from contact>%s<",fieldOrder.latin1());
432
433 if (fieldOrder.isEmpty()){
434 fieldOrder = globalFieldOrder;
435 }
436
437
438 qDebug("effective fieldOrder in loadFromRecord >%s<",fieldOrder.latin1());
439}
440
441void OContactFields::setFieldOrder( int num, int index ){
442 qDebug("qcontactfields setfieldorder pos %i -> %i",num,index);
443
444 fieldOrder[num] = QString::number( index, 16 )[0];
445
446 // We will store this new fieldorder globally to
447 // remember it for contacts which have none
448 globalFieldOrder = fieldOrder;
449 changedFieldOrder = true;
450
451 qDebug("fieldOrder >%s<",fieldOrder.latin1());
452}
453
454int OContactFields::getFieldOrder( int num, int defIndex ){
455 qDebug("ocontactfields getFieldOrder");
456 qDebug("fieldOrder >%s<",fieldOrder.latin1());
457
458 // Get index of combo as char..
459 QChar poschar = fieldOrder[num];
460
461 bool ok;
462 int ret = 0;
463 // Convert char to number..
464 if ( !( poschar == QChar::null ) )
465 ret = QString( poschar ).toInt(&ok, 16);
466 else
467 ok = false;
468
469 // Return default value if index for
470 // num was not set or if anything else happened..
471 if ( !ok ) ret = defIndex;
472
473 qDebug("returning >%i<",ret);
474
475 return ret;
476
477}
diff --git a/libopie/pim/ocontactfields.h b/libopie/pim/ocontactfields.h
deleted file mode 100644
index f105de7..0000000
--- a/libopie/pim/ocontactfields.h
+++ b/dev/null
@@ -1,67 +0,0 @@
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 personalfields( bool sorted = true, bool translated = false );
47 static QStringList phonefields( bool sorted = true, bool translated = false );
48 static QStringList detailsfields( bool sorted = true, bool translated = false );
49 static QStringList fields( bool sorted = true, bool translated = false );
50
51 static QStringList trpersonalfields( bool sorted = true );
52 static QStringList untrpersonalfields( bool sorted = true );
53 static QStringList trphonefields( bool sorted = true );
54 static QStringList untrphonefields( bool sorted = true );
55 static QStringList trdetailsfields( bool sorted = true );
56 static QStringList untrdetailsfields( bool sorted = true );
57 static QStringList trfields( bool sorted = true );
58 static QStringList untrfields( bool sorted = true );
59
60 static QMap<int, QString> idToTrFields();
61 static QMap<QString, int> trFieldsToId();
62 static QMap<int, QString> idToUntrFields();
63 static QMap<QString, int> untrFieldsToId();
64
65};
66
67#endif
diff --git a/libopie/pim/oconversion.cpp b/libopie/pim/oconversion.cpp
deleted file mode 100644
index 0d15414..0000000
--- a/libopie/pim/oconversion.cpp
+++ b/dev/null
@@ -1,113 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2003 by Stefan Eilers (eilers.stefan@epost.de)
3**
4** This file may be distributed and/or modified under the terms of the
5** GNU Lesser General Public License version 2 as published by the Free Software
6** Foundation and appearing in the file LICENSE.GPL included in the
7** packaging of this file.
8**
9** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11**
12**********************************************************************/
13
14#include "oconversion.h"
15#include <qpe/timeconversion.h>
16
17
18QString OConversion::dateToString( const QDate &d )
19{
20 if ( d.isNull() || !d.isValid() )
21 return QString::null;
22
23 // ISO format in year, month, day (YYYYMMDD); e.g. 20021231
24 QString year = QString::number( d.year() );
25 QString month = QString::number( d.month() );
26 month = month.rightJustify( 2, '0' );
27 QString day = QString::number( d.day() );
28 day = day.rightJustify( 2, '0' );
29
30 QString str = year + month + day;
31 //qDebug( "\tPimContact dateToStr = %s", str.latin1() );
32
33 return str;
34}
35
36QDate OConversion::dateFromString( const QString& s )
37{
38 QDate date;
39
40 if ( s.isEmpty() )
41 return date;
42
43 // Be backward compatible to old Opie format:
44 // Try to load old format. If it fails, try new ISO-Format!
45 date = TimeConversion::fromString ( s );
46 if ( date.isValid() )
47 return date;
48
49 // Read ISO-Format (YYYYMMDD)
50 int year = s.mid(0, 4).toInt();
51 int month = s.mid(4,2).toInt();
52 int day = s.mid(6,2).toInt();
53
54 // do some quick sanity checking -eilers
55 // but we isValid() again? -zecke
56 if ( year < 1900 || year > 3000 ) {
57 qWarning( "PimContact year is not in range");
58 return date;
59 }
60 if ( month < 0 || month > 12 ) {
61 qWarning( "PimContact month is not in range");
62 return date;
63 }
64 if ( day < 0 || day > 31 ) {
65 qWarning( "PimContact day is not in range");
66 return date;
67 }
68
69 date.setYMD( year, month, day );
70 if ( !date.isValid() ) {
71 qWarning( "PimContact date is not valid");
72 return date;
73 }
74
75 return date;
76}
77QString OConversion::dateTimeToString( const QDateTime& dt ) {
78 if (!dt.isValid() || dt.isNull() ) return QString::null;
79
80 QString year = QString::number( dt.date().year() );
81 QString month = QString::number( dt.date().month() );
82 QString day = QString::number( dt.date().day() );
83
84 QString hour = QString::number( dt.time().hour() );
85 QString min = QString::number( dt.time().minute() );
86 QString sec = QString::number( dt.time().second() );
87
88 month = month.rightJustify( 2, '0' );
89 day = day. rightJustify( 2, '0' );
90 hour = hour. rightJustify( 2, '0' );
91 min = min. rightJustify( 2, '0' );
92 sec = sec. rightJustify( 2, '0' );
93
94 QString str = day + month + year + hour + min + sec;
95
96 return str;
97}
98QDateTime OConversion::dateTimeFromString( const QString& str) {
99
100 if ( str.isEmpty() ) return QDateTime();
101 int day = str.mid(0, 2).toInt();
102 int month = str.mid(2, 2).toInt();
103 int year = str.mid(4, 4).toInt();
104 int hour = str.mid(8, 2).toInt();
105 int min = str.mid(10, 2).toInt();
106 int sec = str.mid(12, 2).toInt();
107
108 QDate date( year, month, day );
109 QTime time( hour, min, sec );
110 QDateTime dt( date, time );
111 return dt;
112}
113
diff --git a/libopie/pim/oconversion.h b/libopie/pim/oconversion.h
deleted file mode 100644
index 4c0a497..0000000
--- a/libopie/pim/oconversion.h
+++ b/dev/null
@@ -1,48 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** Copyright (C) 2002-2003 by Stefan Eilers (eilers.stefan@epost.de)
4**
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
7** Foundation and appearing in the file LICENSE.GPL included in the
8** packaging of this file.
9**
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.
12**
13** See http://www.trolltech.com/gpl/ for GPL licensing information.
14**
15** Contact info@trolltech.com if any conditions of this licensing are
16** not clear to you.
17**********************************************************************/
18
19#ifndef __oconversion_h__
20#define __oconversion_h__
21
22/* #include <time.h> */
23/* #include <sys/types.h> */
24#include <qdatetime.h>
25
26/* FIXME namespace? -zecke */
27class OConversion
28{
29public:
30 static QString dateToString( const QDate &d );
31 static QDate dateFromString( const QString &datestr );
32
33 /**
34 * simple function to store DateTime as string and read from string
35 * no timezone changing is done
36 * DDMMYYYYHHMMSS is the simple format
37 */
38 static QString dateTimeToString( const QDateTime& );
39 static QDateTime dateTimeFromString( const QString& );
40
41private:
42 class Private;
43 Private* d;
44
45};
46
47#endif // __oconversion_h__
48
diff --git a/libopie/pim/odatebookaccess.cpp b/libopie/pim/odatebookaccess.cpp
deleted file mode 100644
index d95fed6..0000000
--- a/libopie/pim/odatebookaccess.cpp
+++ b/dev/null
@@ -1,81 +0,0 @@
1#include "obackendfactory.h"
2#include "odatebookaccess.h"
3
4/**
5 * Simple constructor
6 * It takes a ODateBookAccessBackend as parent. If it is 0 the default implementation
7 * will be used!
8 * @param back The backend to be used or 0 for the default backend
9 * @param ac What kind of access is intended
10 */
11ODateBookAccess::ODateBookAccess( ODateBookAccessBackend* back, enum Access ac )
12 : OPimAccessTemplate<OEvent>( back )
13{
14 if (!back )
15 back = OBackendFactory<ODateBookAccessBackend>::Default("datebook", QString::null );
16
17 m_backEnd = back;
18 setBackEnd( m_backEnd );
19}
20ODateBookAccess::~ODateBookAccess() {
21}
22
23/**
24 * @return all events available
25 */
26ODateBookAccess::List ODateBookAccess::rawEvents()const {
27 QArray<int> ints = m_backEnd->rawEvents();
28
29 List lis( ints, this );
30 return lis;
31}
32
33/**
34 * @return all repeating events
35 */
36ODateBookAccess::List ODateBookAccess::rawRepeats()const {
37 QArray<int> ints = m_backEnd->rawRepeats();
38
39 List lis( ints, this );
40 return lis;
41}
42
43/**
44 * @return all non repeating events
45 */
46ODateBookAccess::List ODateBookAccess::nonRepeats()const {
47 QArray<int> ints = m_backEnd->nonRepeats();
48
49 List lis( ints, this );
50 return lis;
51}
52
53/**
54 * @return dates in the time span between from and to
55 * @param from Include all events from...
56 * @param to Include all events to...
57 */
58OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDate& from, const QDate& to ) const {
59 return m_backEnd->effectiveEvents( from, to );
60}
61/**
62 * @return all events at a given datetime
63 */
64OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDateTime& start ) const {
65 return m_backEnd->effectiveEvents( start );
66}
67
68/**
69 * @return non repeating dates in the time span between from and to
70 * @param from Include all events from...
71 * @param to Include all events to...
72 */
73OEffectiveEvent::ValueList ODateBookAccess::effectiveNonRepeatingEvents( const QDate& from, const QDate& to ) const {
74 return m_backEnd->effectiveNonRepeatingEvents( from, to );
75}
76/**
77 * @return all non repeating events at a given datetime
78 */
79OEffectiveEvent::ValueList ODateBookAccess::effectiveNonRepeatingEvents( const QDateTime& start ) const {
80 return m_backEnd->effectiveNonRepeatingEvents( start );
81}
diff --git a/libopie/pim/odatebookaccess.h b/libopie/pim/odatebookaccess.h
deleted file mode 100644
index 62196da..0000000
--- a/libopie/pim/odatebookaccess.h
+++ b/dev/null
@@ -1,44 +0,0 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_H
2#define OPIE_DATE_BOOK_ACCESS_H
3
4#include "odatebookaccessbackend.h"
5#include "opimaccesstemplate.h"
6
7#include "oevent.h"
8
9/**
10 * This is the object orientated datebook database. It'll use OBackendFactory
11 * to query for a backend.
12 * All access to the datebook should be done via this class.
13 * Make sure to load and save the datebook this is not part of
14 * destructing and creating the object
15 *
16 * @author Holger Freyther, Stefan Eilers
17 */
18class ODateBookAccess : public OPimAccessTemplate<OEvent> {
19public:
20 ODateBookAccess( ODateBookAccessBackend* = 0l, enum Access acc = Random );
21 ~ODateBookAccess();
22
23 /* return all events */
24 List rawEvents()const;
25
26 /* return repeating events */
27 List rawRepeats()const;
28
29 /* return non repeating events */
30 List nonRepeats()const;
31
32 /* return non repeating events (from,to) */
33 OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to ) const;
34 OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start ) const;
35 OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDate& from, const QDate& to ) const;
36 OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDateTime& start ) const;
37
38private:
39 ODateBookAccessBackend* m_backEnd;
40 class Private;
41 Private* d;
42};
43
44#endif
diff --git a/libopie/pim/odatebookaccessbackend.cpp b/libopie/pim/odatebookaccessbackend.cpp
deleted file mode 100644
index f0c5d65..0000000
--- a/libopie/pim/odatebookaccessbackend.cpp
+++ b/dev/null
@@ -1,182 +0,0 @@
1#include <qtl.h>
2
3#include "orecur.h"
4
5#include "odatebookaccessbackend.h"
6
7namespace {
8/* a small helper to get all NonRepeating events for a range of time */
9 void events( OEffectiveEvent::ValueList& tmpList, const OEvent::ValueList& events,
10 const QDate& from, const QDate& to ) {
11 QDateTime dtStart, dtEnd;
12
13 for ( OEvent::ValueList::ConstIterator it = events.begin(); it != events.end(); ++it ) {
14 dtStart = (*it).startDateTime();
15 dtEnd = (*it).endDateTime();
16
17 /*
18 * If in range
19 */
20 if (dtStart.date() >= from && dtEnd.date() <= to ) {
21 OEffectiveEvent eff;
22 eff.setEvent( (*it) );
23 eff.setDate( dtStart.date() );
24 eff.setStartTime( dtStart.time() );
25
26 /* if not on the same day */
27 if ( dtStart.date() != dtEnd.date() )
28 eff.setEndTime( QTime(23, 59, 0 ) );
29 else
30 eff.setEndTime( dtEnd.time() );
31
32 tmpList.append( eff );
33 }
34
35 /* we must also check for end date information... */
36 if ( dtEnd.date() != dtStart.date() && dtEnd.date() >= from ) {
37 QDateTime dt = dtStart.addDays( 1 );
38 dt.setTime( QTime(0, 0, 0 ) );
39 QDateTime dtStop;
40 if ( dtEnd > to )
41 dtStop = to;
42 else
43 dtStop = dtEnd;
44
45 while ( dt <= dtStop ) {
46 OEffectiveEvent eff;
47 eff.setEvent( (*it) );
48 eff.setDate( dt.date() );
49
50 if ( dt >= from ) {
51 eff.setStartTime( QTime(0, 0, 0 ) );
52 if ( dt.date() == dtEnd.date() )
53 eff.setEndTime( dtEnd.time() );
54 else
55 eff.setEndTime( QTime(23, 59, 0 ) );
56 tmpList.append( eff );
57 }
58 dt = dt.addDays( 1 );
59 }
60 }
61 }
62 }
63
64 void repeat( OEffectiveEvent::ValueList& tmpList, const OEvent::ValueList& list,
65 const QDate& from, const QDate& to ) {
66 QDate repeat;
67 for ( OEvent::ValueList::ConstIterator it = list.begin(); it != list.end(); ++it ) {
68 int dur = (*it).startDateTime().date().daysTo( (*it).endDateTime().date() );
69 QDate itDate = from.addDays(-dur );
70 ORecur rec = (*it).recurrence();
71 if ( !rec.hasEndDate() || rec.endDate() > to ) {
72 rec.setEndDate( to );
73 rec.setHasEndDate( true );
74 }
75 while (rec.nextOcurrence(itDate, repeat ) ) {
76 if (repeat > to ) break;
77 OEffectiveEvent eff;
78 eff.setDate( repeat );
79 if ( (*it).isAllDay() ) {
80 eff.setStartTime( QTime(0, 0, 0 ) );
81 eff.setEndTime( QTime(23, 59, 59 ) );
82 }else {
83 /* we only occur by days, not hours/minutes/seconds. Hence
84 * the actual end and start times will be the same for
85 * every repeated event. For multi day events this is
86 * fixed up later if on wronge day span
87 */
88 eff.setStartTime( (*it).startDateTime().time() );
89 eff.setEndTime( (*it).endDateTime().time() );
90 }
91 if ( dur != 0 ) {
92 // multi-day repeating events
93 QDate sub_it = QMAX( repeat, from );
94 QDate startDate = repeat;
95 QDate endDate = startDate.addDays( dur );
96
97 while ( sub_it <= endDate && sub_it <= to ) {
98 OEffectiveEvent tmpEff = eff;
99 tmpEff.setEvent( (*it) );
100 if ( sub_it != startDate )
101 tmpEff.setStartTime( QTime(0, 0, 0 ) );
102 if ( sub_it != endDate )
103 tmpEff.setEndTime( QTime( 23, 59, 59 ) );
104
105 tmpEff.setDate( sub_it );
106 tmpEff.setEffectiveDates( startDate, endDate );
107 tmpList.append( tmpEff );
108
109 sub_it = sub_it.addDays( 1 );
110 }
111 itDate = endDate;
112 }else {
113 eff.setEvent( (*it) );
114 tmpList.append( eff );
115 itDate = repeat.addDays( 1 );
116 }
117 }
118 }
119 }
120}
121
122ODateBookAccessBackend::ODateBookAccessBackend()
123 : OPimAccessBackend<OEvent>()
124{
125
126}
127ODateBookAccessBackend::~ODateBookAccessBackend() {
128
129}
130OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveEvents( const QDate& from,
131 const QDate& to ) {
132 OEffectiveEvent::ValueList tmpList;
133 OEvent::ValueList list = directNonRepeats();
134
135 events( tmpList, list, from, to );
136 repeat( tmpList, directRawRepeats(),from,to );
137
138 list = directRawRepeats(); // Useless, isn't it ? (eilers)
139
140 qHeapSort( tmpList );
141 return tmpList;
142}
143OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveEvents( const QDateTime& dt ) {
144 OEffectiveEvent::ValueList day = effectiveEvents( dt.date(), dt.date() );
145 OEffectiveEvent::ValueList::Iterator it;
146
147 OEffectiveEvent::ValueList tmpList;
148 QDateTime dtTmp;
149 for ( it = day.begin(); it != day.end(); ++it ) {
150 dtTmp = QDateTime( (*it).date(), (*it).startTime() );
151 if ( QABS(dt.secsTo(dtTmp) ) < 60 )
152 tmpList.append( (*it) );
153 }
154
155 return tmpList;
156}
157
158OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDate& from,
159 const QDate& to ) {
160 OEffectiveEvent::ValueList tmpList;
161 OEvent::ValueList list = directNonRepeats();
162
163 events( tmpList, list, from, to );
164
165 qHeapSort( tmpList );
166 return tmpList;
167}
168
169OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDateTime& dt ) {
170 OEffectiveEvent::ValueList day = effectiveNonRepeatingEvents( dt.date(), dt.date() );
171 OEffectiveEvent::ValueList::Iterator it;
172
173 OEffectiveEvent::ValueList tmpList;
174 QDateTime dtTmp;
175 for ( it = day.begin(); it != day.end(); ++it ) {
176 dtTmp = QDateTime( (*it).date(), (*it).startTime() );
177 if ( QABS(dt.secsTo(dtTmp) ) < 60 )
178 tmpList.append( (*it) );
179 }
180
181 return tmpList;
182}
diff --git a/libopie/pim/odatebookaccessbackend.h b/libopie/pim/odatebookaccessbackend.h
deleted file mode 100644
index 3472ab3..0000000
--- a/libopie/pim/odatebookaccessbackend.h
+++ b/dev/null
@@ -1,90 +0,0 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_H
3
4#include <qarray.h>
5
6#include "opimaccessbackend.h"
7#include "oevent.h"
8
9/**
10 * This class is the interface to the storage of Events.
11 * @see OPimAccessBackend
12 *
13 */
14class ODateBookAccessBackend : public OPimAccessBackend<OEvent> {
15public:
16 typedef int UID;
17
18 /**
19 * c'tor without parameter
20 */
21 ODateBookAccessBackend();
22 ~ODateBookAccessBackend();
23
24 /**
25 * This method should return a list of UIDs containing
26 * all events. No filter should be applied
27 * @return list of events
28 */
29 virtual QArray<UID> rawEvents()const = 0;
30
31 /**
32 * This method should return a list of UIDs containing
33 * all repeating events. No filter should be applied
34 * @return list of repeating events
35 */
36 virtual QArray<UID> rawRepeats()const = 0;
37
38 /**
39 * This mthod should return a list of UIDs containing all non
40 * repeating events. No filter should be applied
41 * @return list of nonrepeating events
42 */
43 virtual QArray<UID> nonRepeats() const = 0;
44
45 /**
46 * If you do not want to implement the effectiveEvents methods below
47 * you need to supply it with directNonRepeats.
48 * This method can return empty lists if effectiveEvents is implememted
49 */
50 virtual OEvent::ValueList directNonRepeats() = 0;
51
52 /**
53 * Same as above but return raw repeats!
54 */
55 virtual OEvent::ValueList directRawRepeats() = 0;
56
57 /* is implemented by default but you can reimplement it*/
58 /**
59 * Effective Events are special event occuring during a time frame. This method does calcualte
60 * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method
61 * yourself
62 */
63 virtual OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to );
64
65 /**
66 * this is an overloaded member function
67 * @see effectiveEvents( const QDate& from, const QDate& to )
68 */
69 virtual OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start );
70
71 /**
72 * Effective Events are special event occuring during a time frame. This method does calcualte
73 * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method
74 * yourself
75 */
76 virtual OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDate& from, const QDate& to );
77
78 /**
79 * this is an overloaded member function
80 * @see effectiveNonRepeatingEvents( const QDate& from, const QDate& to )
81 */
82 virtual OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDateTime& start );
83
84private:
85 class Private;
86 Private *d;
87
88};
89
90#endif
diff --git a/libopie/pim/odatebookaccessbackend_sql.cpp b/libopie/pim/odatebookaccessbackend_sql.cpp
deleted file mode 100644
index 44dd2bc..0000000
--- a/libopie/pim/odatebookaccessbackend_sql.cpp
+++ b/dev/null
@@ -1,371 +0,0 @@
1/*
2 * SQL Backend for the OPIE-Calender Database.
3 *
4 * Copyright (c) 2003 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.4 2004/03/14 13:50:35 alwin
18 * namespace correction
19 *
20 * Revision 1.3 2003/12/22 11:41:39 eilers
21 * Fixing stupid bug, found by sourcode review..
22 *
23 * Revision 1.2 2003/12/22 10:19:26 eilers
24 * Finishing implementation of sql-backend for datebook. But I have to
25 * port the PIM datebook application to use it, before I could debug the
26 * whole stuff.
27 * Thus, PIM-Database backend is finished, but highly experimental. And some
28 * parts are still generic. For instance, the "queryByExample()" methods are
29 * not (or not fully) implemented. Todo: custom-entries not stored.
30 * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
31 * expression search in the database, which is not supported by sqlite !
32 * Therefore we need either an extended sqlite or a workaround which would
33 * be very slow and memory consuming..
34 *
35 * Revision 1.1 2003/12/08 15:18:12 eilers
36 * Committing unfinished sql implementation before merging to libopie2 starts..
37 *
38 *
39 */
40
41#include <stdio.h>
42#include <stdlib.h>
43
44#include <qarray.h>
45#include <qstringlist.h>
46
47#include <qpe/global.h>
48
49#include <opie2/osqldriver.h>
50#include <opie2/osqlmanager.h>
51#include <opie2/osqlquery.h>
52
53#include "orecur.h"
54#include "odatebookaccessbackend_sql.h"
55
56using namespace Opie::DB;
57
58
59ODateBookAccessBackend_SQL::ODateBookAccessBackend_SQL( const QString& ,
60 const QString& fileName )
61 : ODateBookAccessBackend(), m_driver( NULL )
62{
63 m_fileName = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.db" ) : fileName;
64
65 // Get the standart sql-driver from the OSQLManager..
66 OSQLManager man;
67 m_driver = man.standard();
68 m_driver->setUrl( m_fileName );
69
70 initFields();
71
72 load();
73}
74
75ODateBookAccessBackend_SQL::~ODateBookAccessBackend_SQL() {
76 if( m_driver )
77 delete m_driver;
78}
79
80void ODateBookAccessBackend_SQL::initFields()
81{
82
83 // This map contains the translation of the fieldtype id's to
84 // the names of the table columns
85 m_fieldMap.insert( OEvent::FUid, "uid" );
86 m_fieldMap.insert( OEvent::FCategories, "Categories" );
87 m_fieldMap.insert( OEvent::FDescription, "Description" );
88 m_fieldMap.insert( OEvent::FLocation, "Location" );
89 m_fieldMap.insert( OEvent::FType, "Type" );
90 m_fieldMap.insert( OEvent::FAlarm, "Alarm" );
91 m_fieldMap.insert( OEvent::FSound, "Sound" );
92 m_fieldMap.insert( OEvent::FRType, "RType" );
93 m_fieldMap.insert( OEvent::FRWeekdays, "RWeekdays" );
94 m_fieldMap.insert( OEvent::FRPosition, "RPosition" );
95 m_fieldMap.insert( OEvent::FRFreq, "RFreq" );
96 m_fieldMap.insert( OEvent::FRHasEndDate, "RHasEndDate" );
97 m_fieldMap.insert( OEvent::FREndDate, "REndDate" );
98 m_fieldMap.insert( OEvent::FRCreated, "RCreated" );
99 m_fieldMap.insert( OEvent::FRExceptions, "RExceptions" );
100 m_fieldMap.insert( OEvent::FStart, "Start" );
101 m_fieldMap.insert( OEvent::FEnd, "End" );
102 m_fieldMap.insert( OEvent::FNote, "Note" );
103 m_fieldMap.insert( OEvent::FTimeZone, "TimeZone" );
104 m_fieldMap.insert( OEvent::FRecParent, "RecParent" );
105 m_fieldMap.insert( OEvent::FRecChildren, "Recchildren" );
106
107 // Create a map that maps the column name to the id
108 QMapConstIterator<int, QString> it;
109 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
110 m_reverseFieldMap.insert( it.data(), it.key() );
111 }
112
113}
114
115bool ODateBookAccessBackend_SQL::load()
116{
117 if (!m_driver->open() )
118 return false;
119
120 // Don't expect that the database exists.
121 // It is save here to create the table, even if it
122 // do exist. ( Is that correct for all databases ?? )
123 QStringqu = "create table datebook( uid INTEGER PRIMARY KEY ";
124
125 QMap<int, QString>::Iterator it;
126 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
127 qu += QString( ",%1 VARCHAR(10)" ).arg( it.data() );
128 }
129 qu += " );";
130
131 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
132
133 qWarning( "command: %s", qu.latin1() );
134
135 OSQLRawQuery raw( qu );
136 OSQLResult res = m_driver->query( &raw );
137 if ( res.state() != OSQLResult::Success )
138 return false;
139
140 update();
141
142 return true;
143}
144
145void ODateBookAccessBackend_SQL::update()
146{
147
148 QString qu = "select uid from datebook";
149 OSQLRawQuery raw( qu );
150 OSQLResult res = m_driver->query( &raw );
151 if ( res.state() != OSQLResult::Success ){
152 // m_uids.clear();
153 return;
154 }
155
156 m_uids = extractUids( res );
157
158}
159
160bool ODateBookAccessBackend_SQL::reload()
161{
162 return load();
163}
164
165bool ODateBookAccessBackend_SQL::save()
166{
167 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
168}
169
170QArray<int> ODateBookAccessBackend_SQL::allRecords()const
171{
172 return m_uids;
173}
174
175QArray<int> ODateBookAccessBackend_SQL::queryByExample(const OEvent&, int, const QDateTime& ) {
176 return QArray<int>();
177}
178
179void ODateBookAccessBackend_SQL::clear()
180{
181 QString qu = "drop table datebook;";
182 qu += "drop table custom_data;";
183
184 OSQLRawQuery raw( qu );
185 OSQLResult res = m_driver->query( &raw );
186
187 reload();
188}
189
190
191OEvent ODateBookAccessBackend_SQL::find( int uid ) const{
192 QString qu = "select *";
193 qu += "from datebook where uid = " + QString::number(uid);
194
195 OSQLRawQuery raw( qu );
196 OSQLResult res = m_driver->query( &raw );
197
198 OSQLResultItem resItem = res.first();
199
200 // Create Map for date event and insert UID
201 QMap<int,QString> dateEventMap;
202 dateEventMap.insert( OEvent::FUid, QString::number( uid ) );
203
204 // Now insert the data out of the columns into the map.
205 QMapConstIterator<int, QString> it;
206 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
207 dateEventMap.insert( m_reverseFieldMap[*it], resItem.data( *it ) );
208 }
209
210 // Last step: Put map into date event and return it
211 OEvent retDate( dateEventMap );
212
213 return retDate;
214}
215
216// FIXME: Speed up update of uid's..
217bool ODateBookAccessBackend_SQL::add( const OEvent& ev )
218{
219 QMap<int,QString> eventMap = ev.toMap();
220
221 QString qu = "insert into datebook VALUES( " + QString::number( ev.uid() );
222 QMap<int, QString>::Iterator it;
223 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
224 if ( !eventMap[it.key()].isEmpty() )
225 qu += QString( ",\"%1\"" ).arg( eventMap[it.key()] );
226 else
227 qu += QString( ",\"\"" );
228 }
229 qu += " );";
230
231 // Add custom entries
232 int id = 0;
233 QMap<QString, QString> customMap = ev.toExtraMap();
234 for( QMap<QString, QString>::Iterator it = customMap.begin();
235 it != customMap.end(); ++it ){
236 qu += "insert into custom_data VALUES("
237 + QString::number( ev.uid() )
238 + ","
239 + QString::number( id++ )
240 + ",'"
241 + it.key() //.latin1()
242 + "',"
243 + "0" // Priority for future enhancements
244 + ",'"
245 + it.data() //.latin1()
246 + "');";
247 }
248 qWarning("add %s", qu.latin1() );
249
250 OSQLRawQuery raw( qu );
251 OSQLResult res = m_driver->query( &raw );
252 if ( res.state() != OSQLResult::Success ){
253 return false;
254 }
255
256 // Update list of uid's
257 update();
258
259 return true;
260}
261
262// FIXME: Speed up update of uid's..
263bool ODateBookAccessBackend_SQL::remove( int uid )
264{
265 QString qu = "DELETE from datebook where uid = "
266 + QString::number( uid ) + ";";
267 qu += "DELETE from custom_data where uid = "
268 + QString::number( uid ) + ";";
269
270 OSQLRawQuery raw( qu );
271 OSQLResult res = m_driver->query( &raw );
272 if ( res.state() != OSQLResult::Success ){
273 return false;
274 }
275
276 // Update list of uid's
277 update();
278
279 return true;
280}
281
282bool ODateBookAccessBackend_SQL::replace( const OEvent& ev )
283{
284 remove( ev.uid() );
285 return add( ev );
286}
287
288QArray<int> ODateBookAccessBackend_SQL::rawEvents()const
289{
290 return allRecords();
291}
292
293QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const
294{
295 QString qu = "select uid from datebook where RType!=\"\" AND RType!=\"NoRepeat\"";
296 OSQLRawQuery raw( qu );
297 OSQLResult res = m_driver->query( &raw );
298 if ( res.state() != OSQLResult::Success ){
299 QArray<int> nix;
300 return nix;
301 }
302
303 return extractUids( res );
304}
305
306QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const
307{
308 QString qu = "select uid from datebook where RType=\"\" or RType=\"NoRepeat\"";
309 OSQLRawQuery raw( qu );
310 OSQLResult res = m_driver->query( &raw );
311 if ( res.state() != OSQLResult::Success ){
312 QArray<int> nix;
313 return nix;
314 }
315
316 return extractUids( res );
317}
318
319OEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats()
320{
321 QArray<int> nonRepUids = nonRepeats();
322 OEvent::ValueList list;
323
324 for (uint i = 0; i < nonRepUids.count(); ++i ){
325 list.append( find( nonRepUids[i] ) );
326 }
327
328 return list;
329
330}
331OEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats()
332{
333 QArray<int> rawRepUids = rawRepeats();
334 OEvent::ValueList list;
335
336 for (uint i = 0; i < rawRepUids.count(); ++i ){
337 list.append( find( rawRepUids[i] ) );
338 }
339
340 return list;
341}
342
343
344QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
345{
346 QArray<int> null;
347 return null;
348}
349
350/* ===== Private Functions ========================================== */
351
352QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const
353{
354 qWarning("extractUids");
355 QTime t;
356 t.start();
357 OSQLResultItem::ValueList list = res.results();
358 OSQLResultItem::ValueList::Iterator it;
359 QArray<int> ints(list.count() );
360 qWarning(" count = %d", list.count() );
361
362 int i = 0;
363 for (it = list.begin(); it != list.end(); ++it ) {
364 ints[i] = (*it).data("uid").toInt();
365 i++;
366 }
367 qWarning("extractUids ready: count2 = %d needs %d ms", i, t.elapsed() );
368
369 return ints;
370
371}
diff --git a/libopie/pim/odatebookaccessbackend_sql.h b/libopie/pim/odatebookaccessbackend_sql.h
deleted file mode 100644
index ba514bc..0000000
--- a/libopie/pim/odatebookaccessbackend_sql.h
+++ b/dev/null
@@ -1,65 +0,0 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
3
4#include <qmap.h>
5#include <opie2/osqlresult.h>
6
7#include "odatebookaccessbackend.h"
8
9namespace Opie { namespace DB {
10class OSQLDriver;
11
12}}
13
14/**
15 * This is the default SQL implementation for DateBoook SQL storage
16 * It fully implements the interface
17 * @see ODateBookAccessBackend
18 * @see OPimAccessBackend
19 */
20class ODateBookAccessBackend_SQL : public ODateBookAccessBackend {
21public:
22 ODateBookAccessBackend_SQL( const QString& appName,
23 const QString& fileName = QString::null);
24 ~ODateBookAccessBackend_SQL();
25
26 bool load();
27 bool reload();
28 bool save();
29
30 QArray<int> allRecords()const;
31 QArray<int> matchRegexp(const QRegExp &r) const;
32 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
33 OEvent find( int uid )const;
34 void clear();
35 bool add( const OEvent& ev );
36 bool remove( int uid );
37 bool replace( const OEvent& ev );
38
39 QArray<UID> rawEvents()const;
40 QArray<UID> rawRepeats()const;
41 QArray<UID> nonRepeats()const;
42
43 OEvent::ValueList directNonRepeats();
44 OEvent::ValueList directRawRepeats();
45
46private:
47 bool loadFile();
48 QString m_fileName;
49 QArray<int> m_uids;
50
51 QMap<int, QString> m_fieldMap;
52 QMap<QString, int> m_reverseFieldMap;
53
54 Opie::DB::OSQLDriver* m_driver;
55
56 class Private;
57 Private *d;
58
59 void initFields();
60 void update();
61 QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
62
63};
64
65#endif
diff --git a/libopie/pim/odatebookaccessbackend_xml.cpp b/libopie/pim/odatebookaccessbackend_xml.cpp
deleted file mode 100644
index 929d004..0000000
--- a/libopie/pim/odatebookaccessbackend_xml.cpp
+++ b/dev/null
@@ -1,612 +0,0 @@
1#include <errno.h>
2#include <fcntl.h>
3
4#include <stdio.h>
5#include <stdlib.h>
6
7#include <sys/types.h>
8#include <sys/mman.h>
9#include <sys/stat.h>
10
11#include <unistd.h>
12
13#include <qasciidict.h>
14#include <qfile.h>
15
16#include <qtopia/global.h>
17#include <qtopia/stringutil.h>
18#include <qtopia/timeconversion.h>
19
20#include "opimnotifymanager.h"
21#include "orecur.h"
22#include "otimezone.h"
23#include "odatebookaccessbackend_xml.h"
24
25namespace {
26 // FROM TT again
27char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
28{
29 char needleChar;
30 char haystackChar;
31 if (!needle || !haystack || !hLen || !nLen)
32 return 0;
33
34 const char* hsearch = haystack;
35
36 if ((needleChar = *needle++) != 0) {
37 nLen--; //(to make up for needle++)
38 do {
39 do {
40 if ((haystackChar = *hsearch++) == 0)
41 return (0);
42 if (hsearch >= haystack + hLen)
43 return (0);
44 } while (haystackChar != needleChar);
45 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
46 hsearch--;
47 }
48 return ((char *)hsearch);
49}
50}
51
52namespace {
53 time_t start, end, created, rp_end;
54 ORecur* rec;
55 ORecur* recur() {
56 if (!rec)
57 rec = new ORecur;
58
59 return rec;
60 }
61 int alarmTime;
62 int snd;
63 enum Attribute{
64 FDescription = 0,
65 FLocation,
66 FCategories,
67 FUid,
68 FType,
69 FAlarm,
70 FSound,
71 FRType,
72 FRWeekdays,
73 FRPosition,
74 FRFreq,
75 FRHasEndDate,
76 FREndDate,
77 FRStart,
78 FREnd,
79 FNote,
80 FCreated, // Should't this be called FRCreated ?
81 FTimeZone,
82 FRecParent,
83 FRecChildren,
84 FExceptions
85 };
86
87 // FIXME: Use OEvent::toMap() here !! (eilers)
88 inline void save( const OEvent& ev, QString& buf ) {
89 qWarning("Saving %d %s", ev.uid(), ev.description().latin1() );
90 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
91 if (!ev.location().isEmpty() )
92 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
93
94 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
95 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
96
97 if (ev.isAllDay() )
98 buf += " type=\"AllDay\""; // is that all ?? (eilers)
99
100 if (ev.hasNotifiers() ) {
101 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
102 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
103 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
104 if ( alarm.sound() == OPimAlarm::Loud )
105 buf += "loud";
106 else
107 buf += "silent";
108 buf += "\"";
109 }
110 if ( ev.hasRecurrence() ) {
111 buf += ev.recurrence().toString();
112 }
113
114 /*
115 * fscking timezones :) well, we'll first convert
116 * the QDateTime to a QDateTime in UTC time
117 * and then we'll create a nice time_t
118 */
119 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
120 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
121 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
122 if (!ev.note().isEmpty() ) {
123 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
124 }
125
126 buf += " timezone=\"";
127 if ( ev.timeZone().isEmpty() )
128 buf += "None";
129 else
130 buf += ev.timeZone();
131 buf += "\"";
132
133 if (ev.parent() != 0 ) {
134 buf += " recparent=\""+QString::number(ev.parent() )+"\"";
135 }
136
137 if (ev.children().count() != 0 ) {
138 QArray<int> children = ev.children();
139 buf += " recchildren=\"";
140 for ( uint i = 0; i < children.count(); i++ ) {
141 if ( i != 0 ) buf += " ";
142 buf += QString::number( children[i] );
143 }
144 buf+= "\"";
145 }
146
147 // skip custom writing
148 }
149
150 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
151 QMap<int, OEvent>::ConstIterator it;
152 QString buf;
153 QCString str;
154 int total_written;
155 for ( it = list.begin(); it != list.end(); ++it ) {
156 buf = "<event";
157 save( it.data(), buf );
158 buf += " />\n";
159 str = buf.utf8();
160
161 total_written = file.writeBlock(str.data(), str.length() );
162 if ( total_written != int(str.length() ) )
163 return false;
164 }
165 return true;
166 }
167}
168
169ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
170 const QString& fileName )
171 : ODateBookAccessBackend() {
172 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
173 m_changed = false;
174}
175ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() {
176}
177bool ODateBookAccessBackend_XML::load() {
178 return loadFile();
179}
180bool ODateBookAccessBackend_XML::reload() {
181 clear();
182 return load();
183}
184bool ODateBookAccessBackend_XML::save() {
185 if (!m_changed) return true;
186
187 int total_written;
188 QString strFileNew = m_name + ".new";
189
190 QFile f( strFileNew );
191 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
192
193 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
194 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
195 buf += "<events>\n";
196 QCString str = buf.utf8();
197 total_written = f.writeBlock( str.data(), str.length() );
198 if ( total_written != int(str.length() ) ) {
199 f.close();
200 QFile::remove( strFileNew );
201 return false;
202 }
203
204 if (!forAll( m_raw, f ) ) {
205 f.close();
206 QFile::remove( strFileNew );
207 return false;
208 }
209 if (!forAll( m_rep, f ) ) {
210 f.close();
211 QFile::remove( strFileNew );
212 return false;
213 }
214
215 buf = "</events>\n</DATEBOOK>\n";
216 str = buf.utf8();
217 total_written = f.writeBlock( str.data(), str.length() );
218 if ( total_written != int(str.length() ) ) {
219 f.close();
220 QFile::remove( strFileNew );
221 return false;
222 }
223 f.close();
224
225 if ( ::rename( strFileNew, m_name ) < 0 ) {
226 QFile::remove( strFileNew );
227 return false;
228 }
229
230 m_changed = false;
231 return true;
232}
233QArray<int> ODateBookAccessBackend_XML::allRecords()const {
234 QArray<int> ints( m_raw.count()+ m_rep.count() );
235 uint i = 0;
236 QMap<int, OEvent>::ConstIterator it;
237
238 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
239 ints[i] = it.key();
240 i++;
241 }
242 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
243 ints[i] = it.key();
244 i++;
245 }
246
247 return ints;
248}
249QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) {
250 return QArray<int>();
251}
252void ODateBookAccessBackend_XML::clear() {
253 m_changed = true;
254 m_raw.clear();
255 m_rep.clear();
256}
257OEvent ODateBookAccessBackend_XML::find( int uid ) const{
258 if ( m_raw.contains( uid ) )
259 return m_raw[uid];
260 else
261 return m_rep[uid];
262}
263bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
264 m_changed = true;
265 if (ev.hasRecurrence() )
266 m_rep.insert( ev.uid(), ev );
267 else
268 m_raw.insert( ev.uid(), ev );
269
270 return true;
271}
272bool ODateBookAccessBackend_XML::remove( int uid ) {
273 m_changed = true;
274 m_rep.remove( uid );
275 m_rep.remove( uid );
276
277 return true;
278}
279bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
280 replace( ev.uid() ); // ??? Shouldn't this be "remove( ev.uid() ) ??? (eilers)
281 return add( ev );
282}
283QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
284 return allRecords();
285}
286QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
287 QArray<int> ints( m_rep.count() );
288 uint i = 0;
289 QMap<int, OEvent>::ConstIterator it;
290
291 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
292 ints[i] = it.key();
293 i++;
294 }
295
296 return ints;
297}
298QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
299 QArray<int> ints( m_raw.count() );
300 uint i = 0;
301 QMap<int, OEvent>::ConstIterator it;
302
303 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
304 ints[i] = it.key();
305 i++;
306 }
307
308 return ints;
309}
310OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() {
311 OEvent::ValueList list;
312 QMap<int, OEvent>::ConstIterator it;
313 for (it = m_raw.begin(); it != m_raw.end(); ++it )
314 list.append( it.data() );
315
316 return list;
317}
318OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
319 OEvent::ValueList list;
320 QMap<int, OEvent>::ConstIterator it;
321 for (it = m_rep.begin(); it != m_rep.end(); ++it )
322 list.append( it.data() );
323
324 return list;
325}
326
327// FIXME: Use OEvent::fromMap() (eilers)
328bool ODateBookAccessBackend_XML::loadFile() {
329 m_changed = false;
330
331 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
332 if ( fd < 0 ) return false;
333
334 struct stat attribute;
335 if ( ::fstat(fd, &attribute ) == -1 ) {
336 ::close( fd );
337 return false;
338 }
339 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
340 if ( map_addr == ( (caddr_t)-1) ) {
341 ::close( fd );
342 return false;
343 }
344
345 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
346 ::close( fd );
347
348 QAsciiDict<int> dict(FExceptions+1);
349 dict.setAutoDelete( true );
350 dict.insert( "description", new int(FDescription) );
351 dict.insert( "location", new int(FLocation) );
352 dict.insert( "categories", new int(FCategories) );
353 dict.insert( "uid", new int(FUid) );
354 dict.insert( "type", new int(FType) );
355 dict.insert( "alarm", new int(FAlarm) );
356 dict.insert( "sound", new int(FSound) );
357 dict.insert( "rtype", new int(FRType) );
358 dict.insert( "rweekdays", new int(FRWeekdays) );
359 dict.insert( "rposition", new int(FRPosition) );
360 dict.insert( "rfreq", new int(FRFreq) );
361 dict.insert( "rhasenddate", new int(FRHasEndDate) );
362 dict.insert( "enddt", new int(FREndDate) );
363 dict.insert( "start", new int(FRStart) );
364 dict.insert( "end", new int(FREnd) );
365 dict.insert( "note", new int(FNote) );
366 dict.insert( "created", new int(FCreated) ); // Shouldn't this be FRCreated ??
367 dict.insert( "recparent", new int(FRecParent) );
368 dict.insert( "recchildren", new int(FRecChildren) );
369 dict.insert( "exceptions", new int(FExceptions) );
370 dict.insert( "timezone", new int(FTimeZone) );
371
372 char* dt = (char*)map_addr;
373 int len = attribute.st_size;
374 int i = 0;
375 char* point;
376 const char* collectionString = "<event ";
377 int strLen = ::strlen(collectionString);
378 int *find;
379 while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) {
380 i = point -dt;
381 i+= strLen;
382
383 alarmTime = -1;
384 snd = 0; // silent
385
386 OEvent ev;
387 rec = 0;
388
389 while ( TRUE ) {
390 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
391 ++i;
392 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
393 break;
394
395
396 // we have another attribute, read it.
397 int j = i;
398 while ( j < len && dt[j] != '=' )
399 ++j;
400 QCString attr( dt+i, j-i+1);
401
402 i = ++j; // skip =
403
404 // find the start of quotes
405 while ( i < len && dt[i] != '"' )
406 ++i;
407 j = ++i;
408
409 bool haveUtf = FALSE;
410 bool haveEnt = FALSE;
411 while ( j < len && dt[j] != '"' ) {
412 if ( ((unsigned char)dt[j]) > 0x7f )
413 haveUtf = TRUE;
414 if ( dt[j] == '&' )
415 haveEnt = TRUE;
416 ++j;
417 }
418 if ( i == j ) {
419 // empty value
420 i = j + 1;
421 continue;
422 }
423
424 QCString value( dt+i, j-i+1 );
425 i = j + 1;
426
427 QString str = (haveUtf ? QString::fromUtf8( value )
428 : QString::fromLatin1( value ) );
429 if ( haveEnt )
430 str = Qtopia::plainString( str );
431
432 /*
433 * add key + value
434 */
435 find = dict[attr.data()];
436 if (!find)
437 ev.setCustomField( attr, str );
438 else {
439 setField( ev, *find, str );
440 }
441 }
442 /* time to finalize */
443 finalizeRecord( ev );
444 delete rec;
445 }
446 ::munmap(map_addr, attribute.st_size );
447 m_changed = false; // changed during add
448
449 return true;
450}
451
452// FIXME: Use OEvent::fromMap() which makes this obsolete.. (eilers)
453void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
454 /* AllDay is alway in UTC */
455 if ( ev.isAllDay() ) {
456 OTimeZone utc = OTimeZone::utc();
457 ev.setStartDateTime( utc.fromUTCDateTime( start ) );
458 ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
459 ev.setTimeZone( "UTC"); // make sure it is really utc
460 }else {
461 /* to current date time */
462 // qWarning(" Start is %d", start );
463 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
464 QDateTime date = zone.toDateTime( start );
465 qWarning(" Start is %s", date.toString().latin1() );
466 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
467
468 date = zone.toDateTime( end );
469 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
470 }
471 if ( rec && rec->doesRecur() ) {
472 OTimeZone utc = OTimeZone::utc();
473 ORecur recu( *rec ); // call copy c'tor;
474 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
475 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
476 recu.setStart( ev.startDateTime().date() );
477 ev.setRecurrence( recu );
478 }
479
480 if (alarmTime != -1 ) {
481 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
482 OPimAlarm al( snd , dt );
483 ev.notifiers().add( al );
484 }
485 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
486 qWarning("already contains assign uid");
487 ev.setUid( 1 );
488 }
489 qWarning("addind %d %s", ev.uid(), ev.description().latin1() );
490 if ( ev.hasRecurrence() )
491 m_rep.insert( ev.uid(), ev );
492 else
493 m_raw.insert( ev.uid(), ev );
494
495}
496void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) {
497// qWarning(" setting %s", value.latin1() );
498 switch( id ) {
499 case FDescription:
500 e.setDescription( value );
501 break;
502 case FLocation:
503 e.setLocation( value );
504 break;
505 case FCategories:
506 e.setCategories( e.idsFromString( value ) );
507 break;
508 case FUid:
509 e.setUid( value.toInt() );
510 break;
511 case FType:
512 if ( value == "AllDay" ) {
513 e.setAllDay( true );
514 e.setTimeZone( "UTC" );
515 }
516 break;
517 case FAlarm:
518 alarmTime = value.toInt();
519 break;
520 case FSound:
521 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
522 break;
523 // recurrence stuff
524 case FRType:
525 if ( value == "Daily" )
526 recur()->setType( ORecur::Daily );
527 else if ( value == "Weekly" )
528 recur()->setType( ORecur::Weekly);
529 else if ( value == "MonthlyDay" )
530 recur()->setType( ORecur::MonthlyDay );
531 else if ( value == "MonthlyDate" )
532 recur()->setType( ORecur::MonthlyDate );
533 else if ( value == "Yearly" )
534 recur()->setType( ORecur::Yearly );
535 else
536 recur()->setType( ORecur::NoRepeat );
537 break;
538 case FRWeekdays:
539 recur()->setDays( value.toInt() );
540 break;
541 case FRPosition:
542 recur()->setPosition( value.toInt() );
543 break;
544 case FRFreq:
545 recur()->setFrequency( value.toInt() );
546 break;
547 case FRHasEndDate:
548 recur()->setHasEndDate( value.toInt() );
549 break;
550 case FREndDate: {
551 rp_end = (time_t) value.toLong();
552 break;
553 }
554 case FRStart: {
555 start = (time_t) value.toLong();
556 break;
557 }
558 case FREnd: {
559 end = ( (time_t) value.toLong() );
560 break;
561 }
562 case FNote:
563 e.setNote( value );
564 break;
565 case FCreated:
566 created = value.toInt();
567 break;
568 case FRecParent:
569 e.setParent( value.toInt() );
570 break;
571 case FRecChildren:{
572 QStringList list = QStringList::split(' ', value );
573 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
574 e.addChild( (*it).toInt() );
575 }
576 }
577 break;
578 case FExceptions:{
579 QStringList list = QStringList::split(' ', value );
580 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
581 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
582 qWarning("adding exception %s", date.toString().latin1() );
583 recur()->exceptions().append( date );
584 }
585 }
586 break;
587 case FTimeZone:
588 if ( value != "None" )
589 e.setTimeZone( value );
590 break;
591 default:
592 break;
593 }
594}
595QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const
596{
597 QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() );
598 uint arraycounter = 0;
599 QMap<int, OEvent>::ConstIterator it;
600
601 for ( it = m_raw.begin(); it != m_raw.end(); ++it )
602 if ( it.data().match( r ) )
603 m_currentQuery[arraycounter++] = it.data().uid();
604 for ( it = m_rep.begin(); it != m_rep.end(); ++it )
605 if ( it.data().match( r ) )
606 m_currentQuery[arraycounter++] = it.data().uid();
607
608 // Shrink to fit..
609 m_currentQuery.resize(arraycounter);
610
611 return m_currentQuery;
612}
diff --git a/libopie/pim/odatebookaccessbackend_xml.h b/libopie/pim/odatebookaccessbackend_xml.h
deleted file mode 100644
index a5cc0fc..0000000
--- a/libopie/pim/odatebookaccessbackend_xml.h
+++ b/dev/null
@@ -1,55 +0,0 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H
3
4#include <qmap.h>
5
6#include "odatebookaccessbackend.h"
7
8/**
9 * This is the default XML implementation for DateBoook XML storage
10 * It fully implements the interface
11 * @see ODateBookAccessBackend
12 * @see OPimAccessBackend
13 */
14class ODateBookAccessBackend_XML : public ODateBookAccessBackend {
15public:
16 ODateBookAccessBackend_XML( const QString& appName,
17 const QString& fileName = QString::null);
18 ~ODateBookAccessBackend_XML();
19
20 bool load();
21 bool reload();
22 bool save();
23
24 QArray<int> allRecords()const;
25 QArray<int> matchRegexp(const QRegExp &r) const;
26 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
27 OEvent find( int uid )const;
28 void clear();
29 bool add( const OEvent& ev );
30 bool remove( int uid );
31 bool replace( const OEvent& ev );
32
33 QArray<UID> rawEvents()const;
34 QArray<UID> rawRepeats()const;
35 QArray<UID> nonRepeats()const;
36
37 OEvent::ValueList directNonRepeats();
38 OEvent::ValueList directRawRepeats();
39
40private:
41 bool m_changed :1 ;
42 bool loadFile();
43 inline void finalizeRecord( OEvent& ev );
44 inline void setField( OEvent&, int field, const QString& val );
45 QString m_name;
46 QMap<int, OEvent> m_raw;
47 QMap<int, OEvent> m_rep;
48
49 struct Data;
50 Data* data;
51 class Private;
52 Private *d;
53};
54
55#endif
diff --git a/libopie/pim/oevent.cpp b/libopie/pim/oevent.cpp
deleted file mode 100644
index 9b31957..0000000
--- a/libopie/pim/oevent.cpp
+++ b/dev/null
@@ -1,717 +0,0 @@
1#include <qshared.h>
2#include <qarray.h>
3
4#include <qpe/palmtopuidgen.h>
5#include <qpe/categories.h>
6#include <qpe/stringutil.h>
7
8#include "orecur.h"
9#include "opimresolver.h"
10#include "opimnotifymanager.h"
11
12#include "oevent.h"
13
14int OCalendarHelper::week( const QDate& date) {
15 // Calculates the week this date is in within that
16 // month. Equals the "row" is is in in the month view
17 int week = 1;
18 QDate tmp( date.year(), date.month(), 1 );
19 if ( date.dayOfWeek() < tmp.dayOfWeek() )
20 ++week;
21
22 week += ( date.day() - 1 ) / 7;
23
24 return week;
25}
26int OCalendarHelper::ocurrence( const QDate& date) {
27 // calculates the number of occurrances of this day of the
28 // week till the given date (e.g 3rd Wednesday of the month)
29 return ( date.day() - 1 ) / 7 + 1;
30}
31int OCalendarHelper::dayOfWeek( char day ) {
32 int dayOfWeek = 1;
33 char i = ORecur::MON;
34 while ( !( i & day ) && i <= ORecur::SUN ) {
35 i <<= 1;
36 ++dayOfWeek;
37 }
38 return dayOfWeek;
39}
40int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) {
41 return ( second.year() - first.year() ) * 12 +
42 second.month() - first.month();
43}
44
45struct OEvent::Data : public QShared {
46 Data() : QShared() {
47 child = 0;
48 recur = 0;
49 manager = 0;
50 isAllDay = false;
51 parent = 0;
52 }
53 ~Data() {
54 delete manager;
55 delete recur;
56 }
57 QString description;
58 QString location;
59 OPimNotifyManager* manager;
60 ORecur* recur;
61 QString note;
62 QDateTime created;
63 QDateTime start;
64 QDateTime end;
65 bool isAllDay : 1;
66 QString timezone;
67 QArray<int>* child;
68 int parent;
69};
70
71OEvent::OEvent( int uid )
72 : OPimRecord( uid ) {
73 data = new Data;
74}
75OEvent::OEvent( const OEvent& ev)
76 : OPimRecord( ev ), data( ev.data )
77{
78 data->ref();
79}
80
81OEvent::OEvent( const QMap<int, QString> map )
82 : OPimRecord( 0 )
83{
84 data = new Data;
85
86 fromMap( map );
87}
88
89OEvent::~OEvent() {
90 if ( data->deref() ) {
91 delete data;
92 data = 0;
93 }
94}
95OEvent& OEvent::operator=( const OEvent& ev) {
96 if ( this == &ev ) return *this;
97
98 OPimRecord::operator=( ev );
99 ev.data->ref();
100 deref();
101 data = ev.data;
102
103
104 return *this;
105}
106QString OEvent::description()const {
107 return data->description;
108}
109void OEvent::setDescription( const QString& description ) {
110 changeOrModify();
111 data->description = description;
112}
113void OEvent::setLocation( const QString& loc ) {
114 changeOrModify();
115 data->location = loc;
116}
117QString OEvent::location()const {
118 return data->location;
119}
120OPimNotifyManager &OEvent::notifiers()const {
121 // I hope we can skip the changeOrModify here
122 // the notifier should take care of it
123 // and OPimNotify is shared too
124 if (!data->manager )
125 data->manager = new OPimNotifyManager;
126
127 return *data->manager;
128}
129bool OEvent::hasNotifiers()const {
130 if (!data->manager )
131 return false;
132 if (data->manager->reminders().isEmpty() &&
133 data->manager->alarms().isEmpty() )
134 return false;
135
136 return true;
137}
138ORecur OEvent::recurrence()const {
139 if (!data->recur)
140 data->recur = new ORecur;
141
142 return *data->recur;
143}
144void OEvent::setRecurrence( const ORecur& rec) {
145 changeOrModify();
146 if (data->recur )
147 (*data->recur) = rec;
148 else
149 data->recur = new ORecur( rec );
150}
151bool OEvent::hasRecurrence()const {
152 if (!data->recur ) return false;
153 return data->recur->doesRecur();
154}
155QString OEvent::note()const {
156 return data->note;
157}
158void OEvent::setNote( const QString& note ) {
159 changeOrModify();
160 data->note = note;
161}
162QDateTime OEvent::createdDateTime()const {
163 return data->created;
164}
165void OEvent::setCreatedDateTime( const QDateTime& time ) {
166 changeOrModify();
167 data->created = time;
168}
169QDateTime OEvent::startDateTime()const {
170 if ( data->isAllDay )
171 return QDateTime( data->start.date(), QTime(0, 0, 0 ) );
172 return data->start;
173}
174QDateTime OEvent::startDateTimeInZone()const {
175 /* if no timezone, or all day event or if the current and this timeZone match... */
176 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime();
177
178 OTimeZone zone(data->timezone );
179 return zone.toDateTime( data->start, OTimeZone::current() );
180}
181void OEvent::setStartDateTime( const QDateTime& dt ) {
182 changeOrModify();
183 data->start = dt;
184}
185QDateTime OEvent::endDateTime()const {
186 /*
187 * if all Day event the end time needs
188 * to be on the same day as the start
189 */
190 if ( data->isAllDay )
191 return QDateTime( data->start.date(), QTime(23, 59, 59 ) );
192 return data->end;
193}
194QDateTime OEvent::endDateTimeInZone()const {
195 /* if no timezone, or all day event or if the current and this timeZone match... */
196 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime();
197
198 OTimeZone zone(data->timezone );
199 return zone.toDateTime( data->end, OTimeZone::current() );
200}
201void OEvent::setEndDateTime( const QDateTime& dt ) {
202 changeOrModify();
203 data->end = dt;
204}
205bool OEvent::isMultipleDay()const {
206 return data->end.date().day() - data->start.date().day();
207}
208bool OEvent::isAllDay()const {
209 return data->isAllDay;
210}
211void OEvent::setAllDay( bool allDay ) {
212 changeOrModify();
213 data->isAllDay = allDay;
214 if (allDay ) data->timezone = "UTC";
215}
216void OEvent::setTimeZone( const QString& tz ) {
217 changeOrModify();
218 data->timezone = tz;
219}
220QString OEvent::timeZone()const {
221 if (data->isAllDay ) return QString::fromLatin1("UTC");
222 return data->timezone;
223}
224bool OEvent::match( const QRegExp& re )const {
225 if ( re.match( data->description ) != -1 ){
226 setLastHitField( Qtopia::DatebookDescription );
227 return true;
228 }
229 if ( re.match( data->note ) != -1 ){
230 setLastHitField( Qtopia::Note );
231 return true;
232 }
233 if ( re.match( data->location ) != -1 ){
234 setLastHitField( Qtopia::Location );
235 return true;
236 }
237 if ( re.match( data->start.toString() ) != -1 ){
238 setLastHitField( Qtopia::StartDateTime );
239 return true;
240 }
241 if ( re.match( data->end.toString() ) != -1 ){
242 setLastHitField( Qtopia::EndDateTime );
243 return true;
244 }
245 return false;
246}
247QString OEvent::toRichText()const {
248 QString text, value;
249
250 // description
251 text += "<b><h3><img src=\"datebook/DateBook\">";
252 if ( !description().isEmpty() ) {
253 text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "" );
254 }
255 text += "</h3></b><br><hr><br>";
256
257 // location
258 if ( !(value = location()).isEmpty() ) {
259 text += "<b>" + QObject::tr( "Location:" ) + "</b> ";
260 text += Qtopia::escapeString(value) + "<br>";
261 }
262
263 // all day event
264 if ( isAllDay() ) {
265 text += "<b><i>" + QObject::tr( "This is an all day event" ) + "</i></b><br>";
266 }
267 // multiple day event
268 else if ( isMultipleDay () ) {
269 text += "<b><i>" + QObject::tr( "This is a multiple day event" ) + "</i></b><br>";
270 }
271 // start & end times
272 else {
273 // start time
274 if ( startDateTime().isValid() ) {
275 text += "<b>" + QObject::tr( "Start:") + "</b> ";
276 text += Qtopia::escapeString(startDateTime().toString() ).
277 replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
278 }
279
280 // end time
281 if ( endDateTime().isValid() ) {
282 text += "<b>" + QObject::tr( "End:") + "</b> ";
283 text += Qtopia::escapeString(endDateTime().toString() ).
284 replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
285 }
286 }
287
288 // categories
289 if ( categoryNames("Calendar").count() ){
290 text += "<b>" + QObject::tr( "Category:") + "</b> ";
291 text += categoryNames("Calendar").join(", ");
292 text += "<br>";
293 }
294
295 //notes
296 if ( !note().isEmpty() ) {
297 text += "<b>" + QObject::tr( "Note:") + "</b><br>";
298 text += note();
299// text += Qtopia::escapeString(note() ).
300// replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
301 }
302 return text;
303}
304QString OEvent::toShortText()const {
305 QString text;
306 text += QString::number( startDateTime().date().day() );
307 text += ".";
308 text += QString::number( startDateTime().date().month() );
309 text += ".";
310 text += QString::number( startDateTime().date().year() );
311 text += " ";
312 text += QString::number( startDateTime().time().hour() );
313 text += ":";
314 text += QString::number( startDateTime().time().minute() );
315 text += " - ";
316 text += description();
317 return text;
318}
319QString OEvent::type()const {
320 return QString::fromLatin1("OEvent");
321}
322QString OEvent::recordField( int /*id */ )const {
323 return QString::null;
324}
325int OEvent::rtti() {
326 return OPimResolver::DateBook;
327}
328bool OEvent::loadFromStream( QDataStream& ) {
329 return true;
330}
331bool OEvent::saveToStream( QDataStream& )const {
332 return true;
333}
334void OEvent::changeOrModify() {
335 if ( data->count != 1 ) {
336 data->deref();
337 Data* d2 = new Data;
338 d2->description = data->description;
339 d2->location = data->location;
340
341 if (data->manager )
342 d2->manager = new OPimNotifyManager( *data->manager );
343
344 if ( data->recur )
345 d2->recur = new ORecur( *data->recur );
346
347 d2->note = data->note;
348 d2->created = data->created;
349 d2->start = data->start;
350 d2->end = data->end;
351 d2->isAllDay = data->isAllDay;
352 d2->timezone = data->timezone;
353 d2->parent = data->parent;
354
355 if ( data->child ) {
356 d2->child = new QArray<int>( *data->child );
357 d2->child->detach();
358 }
359
360 data = d2;
361 }
362}
363void OEvent::deref() {
364 if ( data->deref() ) {
365 delete data;
366 data = 0;
367 }
368}
369// Exporting Event data to map. Using the same
370// encoding as ODateBookAccessBackend_xml does..
371// Thus, we could remove the stuff there and use this
372// for it and for all other places..
373// Encoding should happen at one place, only ! (eilers)
374QMap<int, QString> OEvent::toMap()const {
375 QMap<int, QString> retMap;
376
377 retMap.insert( OEvent::FUid, QString::number( uid() ) );
378 retMap.insert( OEvent::FCategories, Qtopia::escapeString( Qtopia::Record::idsToString( categories() ) ));
379 retMap.insert( OEvent::FDescription, Qtopia::escapeString( description() ) );
380 retMap.insert( OEvent::FLocation, Qtopia::escapeString( location() ) );
381 retMap.insert( OEvent::FType, isAllDay() ? "AllDay" : "" );
382 OPimAlarm alarm = notifiers().alarms()[0];
383 retMap.insert( OEvent::FAlarm, QString::number( alarm.dateTime().secsTo( startDateTime() ) / 60 ) );
384 retMap.insert( OEvent::FSound, (alarm.sound() == OPimAlarm::Loud) ? "loud" : "silent" );
385
386 OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
387 retMap.insert( OEvent::FStart, QString::number( zone.fromUTCDateTime( zone.toDateTime( startDateTime(), OTimeZone::utc() ) ) ) );
388 retMap.insert( OEvent::FEnd, QString::number( zone.fromUTCDateTime( zone.toDateTime( endDateTime(), OTimeZone::utc() ) ) ) );
389 retMap.insert( OEvent::FNote, Qtopia::escapeString( note() ) );
390 retMap.insert( OEvent::FTimeZone, timeZone().isEmpty() ? QString( "None" ) : timeZone() );
391 if( parent() )
392 retMap.insert( OEvent::FRecParent, QString::number( parent() ) );
393 if( children().count() ){
394 QArray<int> childr = children();
395 QString buf;
396 for ( uint i = 0; i < childr.count(); i++ ) {
397 if ( i != 0 ) buf += " ";
398 buf += QString::number( childr[i] );
399 }
400 retMap.insert( OEvent::FRecChildren, buf );
401 }
402
403 // Add recurrence stuff
404 if( hasRecurrence() ){
405 ORecur recur = recurrence();
406 QMap<int, QString> recFields = recur.toMap();
407 retMap.insert( OEvent::FRType, recFields[ORecur::RType] );
408 retMap.insert( OEvent::FRWeekdays, recFields[ORecur::RWeekdays] );
409 retMap.insert( OEvent::FRPosition, recFields[ORecur::RPosition] );
410 retMap.insert( OEvent::FRFreq, recFields[ORecur::RFreq] );
411 retMap.insert( OEvent::FRHasEndDate, recFields[ORecur::RHasEndDate] );
412 retMap.insert( OEvent::FREndDate, recFields[ORecur::EndDate] );
413 retMap.insert( OEvent::FRCreated, recFields[ORecur::Created] );
414 retMap.insert( OEvent::FRExceptions, recFields[ORecur::Exceptions] );
415 } else {
416 ORecur recur = recurrence();
417 QMap<int, QString> recFields = recur.toMap();
418 retMap.insert( OEvent::FRType, recFields[ORecur::RType] );
419 }
420
421 return retMap;
422}
423
424void OEvent::fromMap( const QMap<int, QString>& map )
425{
426
427 // We just want to set the UID if it is really stored.
428 if ( !map[OEvent::FUid].isEmpty() )
429 setUid( map[OEvent::FUid].toInt() );
430
431 setCategories( idsFromString( map[OEvent::FCategories] ) );
432 setDescription( map[OEvent::FDescription] );
433 setLocation( map[OEvent::FLocation] );
434
435 if ( map[OEvent::FType] == "AllDay" )
436 setAllDay( true );
437 else
438 setAllDay( false );
439
440 int alarmTime = -1;
441 if( !map[OEvent::FAlarm].isEmpty() )
442 alarmTime = map[OEvent::FAlarm].toInt();
443
444 int sound = ( ( map[OEvent::FSound] == "loud" ) ? OPimAlarm::Loud : OPimAlarm::Silent );
445 if ( ( alarmTime != -1 ) ){
446 QDateTime dt = startDateTime().addSecs( -1*alarmTime*60 );
447 OPimAlarm al( sound , dt );
448 notifiers().add( al );
449 }
450 if ( !map[OEvent::FTimeZone].isEmpty() && ( map[OEvent::FTimeZone] != "None" ) ){
451 setTimeZone( map[OEvent::FTimeZone] );
452 }
453
454 time_t start = (time_t) map[OEvent::FStart].toLong();
455 time_t end = (time_t) map[OEvent::FEnd].toLong();
456
457 /* AllDay is always in UTC */
458 if ( isAllDay() ) {
459 OTimeZone utc = OTimeZone::utc();
460 setStartDateTime( utc.fromUTCDateTime( start ) );
461 setEndDateTime ( utc.fromUTCDateTime( end ) );
462 setTimeZone( "UTC"); // make sure it is really utc
463 }else {
464 /* to current date time */
465 // qWarning(" Start is %d", start );
466 OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
467 QDateTime date = zone.toDateTime( start );
468 qWarning(" Start is %s", date.toString().latin1() );
469 setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
470
471 date = zone.toDateTime( end );
472 setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
473 }
474
475 if ( !map[OEvent::FRecParent].isEmpty() )
476 setParent( map[OEvent::FRecParent].toInt() );
477
478 if ( !map[OEvent::FRecChildren].isEmpty() ){
479 QStringList list = QStringList::split(' ', map[OEvent::FRecChildren] );
480 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
481 addChild( (*it).toInt() );
482 }
483 }
484
485 // Fill recurrence stuff and put it directly into the ORecur-Object using fromMap..
486 if( !map[OEvent::FRType].isEmpty() ){
487 QMap<int, QString> recFields;
488 recFields.insert( ORecur::RType, map[OEvent::FRType] );
489 recFields.insert( ORecur::RWeekdays, map[OEvent::FRWeekdays] );
490 recFields.insert( ORecur::RPosition, map[OEvent::FRPosition] );
491 recFields.insert( ORecur::RFreq, map[OEvent::FRFreq] );
492 recFields.insert( ORecur::RHasEndDate, map[OEvent::FRHasEndDate] );
493 recFields.insert( ORecur::EndDate, map[OEvent::FREndDate] );
494 recFields.insert( ORecur::Created, map[OEvent::FRCreated] );
495 recFields.insert( ORecur::Exceptions, map[OEvent::FRExceptions] );
496 ORecur recur( recFields );
497 setRecurrence( recur );
498 }
499
500}
501
502
503int OEvent::parent()const {
504 return data->parent;
505}
506void OEvent::setParent( int uid ) {
507 changeOrModify();
508 data->parent = uid;
509}
510QArray<int> OEvent::children() const{
511 if (!data->child) return QArray<int>();
512 else
513 return data->child->copy();
514}
515void OEvent::setChildren( const QArray<int>& arr ) {
516 changeOrModify();
517 if (data->child) delete data->child;
518
519 data->child = new QArray<int>( arr );
520 data->child->detach();
521}
522void OEvent::addChild( int uid ) {
523 changeOrModify();
524 if (!data->child ) {
525 data->child = new QArray<int>(1);
526 (*data->child)[0] = uid;
527 }else{
528 int count = data->child->count();
529 data->child->resize( count + 1 );
530 (*data->child)[count] = uid;
531 }
532}
533void OEvent::removeChild( int uid ) {
534 if (!data->child || !data->child->contains( uid ) ) return;
535 changeOrModify();
536 QArray<int> newAr( data->child->count() - 1 );
537 int j = 0;
538 uint count = data->child->count();
539 for ( uint i = 0; i < count; i++ ) {
540 if ( (*data->child)[i] != uid ) {
541 newAr[j] = (*data->child)[i];
542 j++;
543 }
544 }
545 (*data->child) = newAr;
546}
547struct OEffectiveEvent::Data : public QShared {
548 Data() : QShared() {
549 }
550 OEvent event;
551 QDate date;
552 QTime start, end;
553 QDate startDate, endDate;
554 bool dates : 1;
555};
556
557OEffectiveEvent::OEffectiveEvent() {
558 data = new Data;
559 data->date = QDate::currentDate();
560 data->start = data->end = QTime::currentTime();
561 data->dates = false;
562}
563OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate,
564 Position pos ) {
565 data = new Data;
566 data->event = ev;
567 data->date = startDate;
568 if ( pos & Start )
569 data->start = ev.startDateTime().time();
570 else
571 data->start = QTime( 0, 0, 0 );
572
573 if ( pos & End )
574 data->end = ev.endDateTime().time();
575 else
576 data->end = QTime( 23, 59, 59 );
577
578 data->dates = false;
579}
580OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) {
581 data = ev.data;
582 data->ref();
583}
584OEffectiveEvent::~OEffectiveEvent() {
585 if ( data->deref() ) {
586 delete data;
587 data = 0;
588 }
589}
590OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) {
591 if ( *this == ev ) return *this;
592
593 ev.data->ref();
594 deref();
595 data = ev.data;
596
597 return *this;
598}
599
600void OEffectiveEvent::setStartTime( const QTime& ti) {
601 changeOrModify();
602 data->start = ti;
603}
604void OEffectiveEvent::setEndTime( const QTime& en) {
605 changeOrModify();
606 data->end = en;
607}
608void OEffectiveEvent::setEvent( const OEvent& ev) {
609 changeOrModify();
610 data->event = ev;
611}
612void OEffectiveEvent::setDate( const QDate& da) {
613 changeOrModify();
614 data->date = da;
615}
616void OEffectiveEvent::setEffectiveDates( const QDate& from,
617 const QDate& to ) {
618 if (!from.isValid() ) {
619 data->dates = false;
620 return;
621 }
622
623 data->startDate = from;
624 data->endDate = to;
625}
626QString OEffectiveEvent::description()const {
627 return data->event.description();
628}
629QString OEffectiveEvent::location()const {
630 return data->event.location();
631}
632QString OEffectiveEvent::note()const {
633 return data->event.note();
634}
635OEvent OEffectiveEvent::event()const {
636 return data->event;
637}
638QTime OEffectiveEvent::startTime()const {
639 return data->start;
640}
641QTime OEffectiveEvent::endTime()const {
642 return data->end;
643}
644QDate OEffectiveEvent::date()const {
645 return data->date;
646}
647int OEffectiveEvent::length()const {
648 return (data->end.hour() * 60 - data->start.hour() * 60)
649 + QABS(data->start.minute() - data->end.minute() );
650}
651int OEffectiveEvent::size()const {
652 return ( data->end.hour() - data->start.hour() ) * 3600
653 + (data->end.minute() - data->start.minute() * 60
654 + data->end.second() - data->start.second() );
655}
656QDate OEffectiveEvent::startDate()const {
657 if ( data->dates )
658 return data->startDate;
659 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer
660 return data->date;
661 else
662 return data->event.startDateTime().date();
663}
664QDate OEffectiveEvent::endDate()const {
665 if ( data->dates )
666 return data->endDate;
667 else if ( data->event.hasRecurrence() )
668 return data->date;
669 else
670 return data->event.endDateTime().date();
671}
672void OEffectiveEvent::deref() {
673 if ( data->deref() ) {
674 delete data;
675 data = 0;
676 }
677}
678void OEffectiveEvent::changeOrModify() {
679 if ( data->count != 1 ) {
680 data->deref();
681 Data* d2 = new Data;
682 d2->event = data->event;
683 d2->date = data->date;
684 d2->start = data->start;
685 d2->end = data->end;
686 d2->startDate = data->startDate;
687 d2->endDate = data->endDate;
688 d2->dates = data->dates;
689 data = d2;
690 }
691}
692bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{
693 if ( data->date < e.date() )
694 return TRUE;
695 if ( data->date == e.date() )
696 return ( startTime() < e.startTime() );
697 else
698 return FALSE;
699}
700bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{
701 return (data->date <= e.date() );
702}
703bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const {
704 return ( date() == e.date()
705 && startTime() == e.startTime()
706 && endTime()== e.endTime()
707 && event() == e.event() );
708}
709bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const {
710 return !(*this == e );
711}
712bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const {
713 return !(*this <= e );
714}
715bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const {
716 return !(*this < e);
717}
diff --git a/libopie/pim/oevent.h b/libopie/pim/oevent.h
deleted file mode 100644
index 9eb948f..0000000
--- a/libopie/pim/oevent.h
+++ b/dev/null
@@ -1,236 +0,0 @@
1// CONTAINS GPLed code of TT
2
3#ifndef OPIE_PIM_EVENT_H
4#define OPIE_PIM_EVENT_H
5
6#include <qstring.h>
7#include <qdatetime.h>
8#include <qvaluelist.h>
9
10#include <qpe/recordfields.h>
11#include <qpe/palmtopuidgen.h>
12
13#include "otimezone.h"
14#include "opimrecord.h"
15
16struct OCalendarHelper {
17 /** calculate the week number of the date */
18 static int week( const QDate& );
19 /** calculate the occurence of week days since the start of the month */
20 static int ocurrence( const QDate& );
21
22 // returns the dayOfWeek for the *first* day it finds (ignores
23 // any further days!). Returns 1 (Monday) if there isn't any day found
24 static int dayOfWeek( char day );
25
26 /** returns the diff of month */
27 static int monthDiff( const QDate& first, const QDate& second );
28
29};
30
31class OPimNotifyManager;
32class ORecur;
33
34/**
35 * This is the container for all Events. It encapsules all
36 * available information for a single Event
37 * @short container for events.
38 */
39class OEvent : public OPimRecord {
40public:
41 typedef QValueList<OEvent> ValueList;
42 /**
43 * RecordFields contain possible attributes
44 * used in the Results of toMap()..
45 */
46 enum RecordFields {
47 FUid = Qtopia::UID_ID,
48 FCategories = Qtopia::CATEGORY_ID,
49 FDescription = 0,
50 FLocation,
51 FType,
52 FAlarm,
53 FSound,
54 FRType,
55 FRWeekdays,
56 FRPosition,
57 FRFreq,
58 FRHasEndDate,
59 FREndDate,
60 FRCreated,
61 FRExceptions,
62 FStart,
63 FEnd,
64 FNote,
65 FTimeZone,
66 FRecParent,
67 FRecChildren,
68 };
69
70 /**
71 * Start with an Empty OEvent. UID == 0 means that it is empty
72 */
73 OEvent(int uid = 0);
74
75 /**
76 * copy c'tor
77 */
78 OEvent( const OEvent& );
79
80 /**
81 * Create OEvent, initialized by map
82 * @see enum RecordFields
83 */
84 OEvent( const QMap<int, QString> map );
85 ~OEvent();
86 OEvent &operator=( const OEvent& );
87
88 QString description()const;
89 void setDescription( const QString& description );
90
91 QString location()const;
92 void setLocation( const QString& loc );
93
94 bool hasNotifiers()const;
95 OPimNotifyManager &notifiers()const;
96
97 ORecur recurrence()const;
98 void setRecurrence( const ORecur& );
99 bool hasRecurrence()const;
100
101 QString note()const;
102 void setNote( const QString& note );
103
104
105 QDateTime createdDateTime()const;
106 void setCreatedDateTime( const QDateTime& dt);
107
108 /** set the date to dt. dt is the QDateTime in localtime */
109 void setStartDateTime( const QDateTime& );
110 /** returns the datetime in the local timeZone */
111 QDateTime startDateTime()const;
112
113 /** returns the start datetime in the current zone */
114 QDateTime startDateTimeInZone()const;
115
116 /** in current timezone */
117 void setEndDateTime( const QDateTime& );
118 /** in current timezone */
119 QDateTime endDateTime()const;
120 QDateTime endDateTimeInZone()const;
121
122 bool isMultipleDay()const;
123 bool isAllDay()const;
124 void setAllDay( bool isAllDay );
125
126 /* pin this event to a timezone! FIXME */
127 void setTimeZone( const QString& timeZone );
128 QString timeZone()const;
129
130
131 virtual bool match( const QRegExp& )const;
132
133 /** For exception to recurrence here is a list of children... */
134 QArray<int> children()const;
135 void setChildren( const QArray<int>& );
136 void addChild( int uid );
137 void removeChild( int uid );
138
139 /** return the parent OEvent */
140 int parent()const;
141 void setParent( int uid );
142
143
144 /* needed reimp */
145 QString toRichText()const;
146 QString toShortText()const;
147 QString type()const;
148
149 QMap<int, QString> toMap()const;
150 void fromMap( const QMap<int, QString>& map );
151 QString recordField(int )const;
152
153 static int rtti();
154
155 bool loadFromStream( QDataStream& );
156 bool saveToStream( QDataStream& )const;
157
158/* bool operator==( const OEvent& );
159 bool operator!=( const OEvent& );
160 bool operator<( const OEvent& );
161 bool operator<=( const OEvent& );
162 bool operator>( const OEvent& );
163 bool operator>=(const OEvent& );
164*/
165private:
166 inline void changeOrModify();
167 void deref();
168 struct Data;
169 Data* data;
170 class Private;
171 Private* priv;
172
173};
174
175/**
176 * AN Event can span through multiple days. We split up a multiday eve
177 */
178class OEffectiveEvent {
179public:
180 typedef QValueList<OEffectiveEvent> ValueList;
181 enum Position { MidWay, Start, End, StartEnd };
182 // If we calculate the effective event of a multi-day event
183 // we have to figure out whether we are at the first day,
184 // at the end, or anywhere else ("middle"). This is important
185 // for the start/end times (00:00/23:59)
186 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
187 // day event
188 // Start: start time -> 23:59
189 // End: 00:00 -> end time
190 // Start | End == StartEnd: for single-day events (default)
191 // here we draw start time -> end time
192 OEffectiveEvent();
193 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd );
194 OEffectiveEvent( const OEffectiveEvent& );
195 OEffectiveEvent &operator=(const OEffectiveEvent& );
196 ~OEffectiveEvent();
197
198 void setStartTime( const QTime& );
199 void setEndTime( const QTime& );
200 void setEvent( const OEvent& );
201 void setDate( const QDate& );
202
203 void setEffectiveDates( const QDate& from, const QDate& to );
204
205 QString description()const;
206 QString location()const;
207 QString note()const;
208 OEvent event()const;
209 QTime startTime()const;
210 QTime endTime()const;
211 QDate date()const;
212
213 /* return the length in hours */
214 int length()const;
215 int size()const;
216
217 QDate startDate()const;
218 QDate endDate()const;
219
220 bool operator<( const OEffectiveEvent &e ) const;
221 bool operator<=( const OEffectiveEvent &e ) const;
222 bool operator==( const OEffectiveEvent &e ) const;
223 bool operator!=( const OEffectiveEvent &e ) const;
224 bool operator>( const OEffectiveEvent &e ) const;
225 bool operator>= ( const OEffectiveEvent &e ) const;
226
227private:
228 void deref();
229 inline void changeOrModify();
230 class Private;
231 Private* priv;
232 struct Data;
233 Data* data;
234
235};
236#endif
diff --git a/libopie/pim/opimaccessbackend.h b/libopie/pim/opimaccessbackend.h
deleted file mode 100644
index fd264fc..0000000
--- a/libopie/pim/opimaccessbackend.h
+++ b/dev/null
@@ -1,160 +0,0 @@
1#ifndef OPIE_PIM_ACCESS_BACKEND
2#define OPIE_PIM_ACCESS_BACKEND
3
4#include <qarray.h>
5#include <qdatetime.h>
6
7#include <opie/otemplatebase.h>
8#include <opie/opimrecord.h>
9
10
11class OPimAccessBackendPrivate;
12/**
13 * OPimAccessBackend is the base class
14 * for all private backends
15 * it operates on OPimRecord as the base class
16 * and it's responsible for fast manipulating
17 * the resource the implementation takes care
18 * of
19 */
20template <class T = OPimRecord>
21class OPimAccessBackend {
22public:
23 typedef OTemplateBase<T> Frontend;
24
25 /** The access hint from the frontend */
26 OPimAccessBackend(int access = 0);
27 virtual ~OPimAccessBackend();
28
29 /**
30 * load the resource
31 */
32 virtual bool load() = 0;
33
34 /**
35 * reload the resource
36 */
37 virtual bool reload() = 0;
38
39 /**
40 * save the resource and
41 * all it's changes
42 */
43 virtual bool save() = 0;
44
45 /**
46 * return an array of
47 * all available uids
48 */
49 virtual QArray<int> allRecords()const = 0;
50
51 /**
52 * return a List of records
53 * that match the regex
54 */
55 virtual QArray<int> matchRegexp(const QRegExp &r) const = 0;
56
57 /**
58 * queryByExample for T with the given Settings
59 *
60 */
61 virtual QArray<int> queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() ) = 0;
62
63 /**
64 * find the OPimRecord with uid @param uid
65 * returns T and T.isEmpty() if nothing was found
66 */
67 virtual T find(int uid )const = 0;
68
69 virtual T find(int uid, const QArray<int>& items,
70 uint current, typename Frontend::CacheDirection )const ;
71 /**
72 * clear the back end
73 */
74 virtual void clear() = 0;
75
76 /**
77 * add T
78 */
79 virtual bool add( const T& t ) = 0;
80
81 /**
82 * remove
83 */
84 virtual bool remove( int uid ) = 0;
85
86 /**
87 * replace a record with T.uid()
88 */
89 virtual bool replace( const T& t ) = 0;
90
91 /*
92 * setTheFrontEnd!!!
93 */
94 void setFrontend( Frontend* front );
95
96 /**
97 * set the read ahead count
98 */
99 void setReadAhead( uint count );
100protected:
101 int access()const;
102 void cache( const T& t )const;
103
104 /**
105 * use a prime number here!
106 */
107 void setSaneCacheSize( int );
108
109 uint readAhead()const;
110
111private:
112 OPimAccessBackendPrivate *d;
113 Frontend* m_front;
114 uint m_read;
115 int m_acc;
116
117};
118
119template <class T>
120OPimAccessBackend<T>::OPimAccessBackend(int acc)
121 : m_acc( acc )
122{
123 m_front = 0l;
124}
125template <class T>
126OPimAccessBackend<T>::~OPimAccessBackend() {
127
128}
129template <class T>
130void OPimAccessBackend<T>::setFrontend( Frontend* fr ) {
131 m_front = fr;
132}
133template <class T>
134void OPimAccessBackend<T>::cache( const T& t )const {
135 if (m_front )
136 m_front->cache( t );
137}
138template <class T>
139void OPimAccessBackend<T>::setSaneCacheSize( int size) {
140 if (m_front )
141 m_front->setSaneCacheSize( size );
142}
143template <class T>
144T OPimAccessBackend<T>::find( int uid, const QArray<int>&,
145 uint, typename Frontend::CacheDirection )const {
146 return find( uid );
147}
148template <class T>
149void OPimAccessBackend<T>::setReadAhead( uint count ) {
150 m_read = count;
151}
152template <class T>
153uint OPimAccessBackend<T>::readAhead()const {
154 return m_read;
155}
156template <class T>
157int OPimAccessBackend<T>::access()const {
158 return m_acc;
159}
160#endif
diff --git a/libopie/pim/opimaccesstemplate.h b/libopie/pim/opimaccesstemplate.h
deleted file mode 100644
index ecbeb68..0000000
--- a/libopie/pim/opimaccesstemplate.h
+++ b/dev/null
@@ -1,302 +0,0 @@
1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
2#define OPIE_PIM_ACCESS_TEMPLATE_H
3
4#include <qarray.h>
5
6#include <opie/opimrecord.h>
7#include <opie/opimaccessbackend.h>
8#include <opie/orecordlist.h>
9
10#include "opimcache.h"
11#include "otemplatebase.h"
12
13class OPimAccessTemplatePrivate;
14/**
15 * Thats the frontend to our OPIE PIM
16 * Library. Either you want to use it's
17 * interface or you want to implement
18 * your own Access lib
19 * Just create a OPimRecord and inherit from
20 * the plugins
21 */
22
23template <class T = OPimRecord >
24class OPimAccessTemplate : public OTemplateBase<T> {
25public:
26 enum Access {
27 Random = 0,
28 SortedAccess
29 };
30 typedef ORecordList<T> List;
31 typedef OPimAccessBackend<T> BackEnd;
32 typedef OPimCache<T> Cache;
33
34 /**
35 * c'tor BackEnd
36 * enum Access a small hint on how to handle the backend
37 */
38 OPimAccessTemplate( BackEnd* end);
39
40 virtual ~OPimAccessTemplate();
41
42 /**
43 * load from the backend
44 */
45 bool load();
46
47 /** Reload database.
48 * You should execute this function if the external database
49 * was changed.
50 * This function will load the external database and afterwards
51 * rejoin the local changes. Therefore the local database will be set consistent.
52 */
53 virtual bool reload();
54
55 /** Save contacts database.
56 * Save is more a "commit". After calling this function, all changes are public available.
57 * @return true if successful
58 */
59 bool save();
60
61 /**
62 * if the resource was changed externally
63 * You should use the signal handling instead of polling possible changes !
64 * zecke: Do you implement a signal for otodoaccess ?
65 */
66 bool wasChangedExternally()const;
67
68 /**
69 * return a List of records
70 * you can iterate over them
71 */
72 virtual List allRecords()const;
73
74 /**
75 * return a List of records
76 * that match the regex
77 */
78 virtual List matchRegexp( const QRegExp &r ) const;
79
80 /**
81 * queryByExample.
82 * @see otodoaccess, ocontactaccess
83 */
84 virtual List queryByExample( const T& t, int querySettings, const QDateTime& d = QDateTime() );
85
86 /**
87 * find the OPimRecord uid
88 */
89 virtual T find( int uid )const;
90
91 /**
92 * read ahead cache find method ;)
93 */
94 virtual T find( int uid, const QArray<int>&,
95 uint current, typename OTemplateBase<T>::CacheDirection dir = OTemplateBase<T>::Forward )const;
96
97 /* invalidate cache here */
98 /**
99 * clears the backend and invalidates the backend
100 */
101 void clear() ;
102
103 /**
104 * add T to the backend
105 * @param t The item to add.
106 * @return <i>true</i> if added successfully.
107 */
108 virtual bool add( const T& t ) ;
109 bool add( const OPimRecord& );
110
111 /* only the uid matters */
112 /**
113 * remove T from the backend
114 * @param t The item to remove
115 * @return <i>true</i> if successful.
116 */
117 virtual bool remove( const T& t );
118
119 /**
120 * remove the OPimRecord with uid
121 * @param uid The ID of the item to remove
122 * @return <i>true</i> if successful.
123 */
124 bool remove( int uid );
125 bool remove( const OPimRecord& );
126
127 /**
128 * replace T from backend
129 * @param t The item to replace
130 * @return <i>true</i> if successful.
131 */
132 virtual bool replace( const T& t) ;
133
134 void setReadAhead( uint count );
135 /**
136 * @internal
137 */
138 void cache( const T& )const;
139 void setSaneCacheSize( int );
140
141 QArray<int> records()const;
142protected:
143 /**
144 * invalidate the cache
145 */
146 void invalidateCache();
147
148 void setBackEnd( BackEnd* end );
149 /**
150 * returns the backend
151 */
152 BackEnd* backEnd();
153 BackEnd* m_backEnd;
154 Cache m_cache;
155
156private:
157 OPimAccessTemplatePrivate *d;
158
159};
160
161template <class T>
162OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
163 : OTemplateBase<T>(), m_backEnd( end )
164{
165 if (end )
166 end->setFrontend( this );
167}
168template <class T>
169OPimAccessTemplate<T>::~OPimAccessTemplate() {
170 qWarning("~OPimAccessTemplate<T>");
171 delete m_backEnd;
172}
173template <class T>
174bool OPimAccessTemplate<T>::load() {
175 invalidateCache();
176 return m_backEnd->load();
177}
178template <class T>
179bool OPimAccessTemplate<T>::reload() {
180 invalidateCache(); // zecke: I think this should be added (se)
181 return m_backEnd->reload();
182}
183template <class T>
184bool OPimAccessTemplate<T>::save() {
185 return m_backEnd->save();
186}
187template <class T>
188typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
189 QArray<int> ints = m_backEnd->allRecords();
190 List lis(ints, this );
191 return lis;
192}
193template <class T>
194typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::matchRegexp( const QRegExp &r )const {
195 QArray<int> ints = m_backEnd->matchRegexp( r );
196 List lis(ints, this );
197 return lis;
198}
199template <class T>
200QArray<int> OPimAccessTemplate<T>::records()const {
201 return m_backEnd->allRecords();
202}
203template <class T>
204typename OPimAccessTemplate<T>::List
205OPimAccessTemplate<T>::queryByExample( const T& t, int settings, const QDateTime& d ) {
206 QArray<int> ints = m_backEnd->queryByExample( t, settings, d );
207
208 List lis(ints, this );
209 return lis;
210}
211template <class T>
212T OPimAccessTemplate<T>::find( int uid ) const{
213 T t = m_backEnd->find( uid );
214 cache( t );
215 return t;
216}
217template <class T>
218T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
219 uint current, typename OTemplateBase<T>::CacheDirection dir )const {
220 /*
221 * better do T.isEmpty()
222 * after a find this way we would
223 * avoid two finds in QCache...
224 */
225 // qWarning("find it now %d", uid );
226 if (m_cache.contains( uid ) ) {
227 return m_cache.find( uid );
228 }
229
230 T t = m_backEnd->find( uid, ar, current, dir );
231 cache( t );
232 return t;
233}
234template <class T>
235void OPimAccessTemplate<T>::clear() {
236 invalidateCache();
237 m_backEnd->clear();
238}
239template <class T>
240bool OPimAccessTemplate<T>::add( const T& t ) {
241 cache( t );
242 return m_backEnd->add( t );
243}
244template <class T>
245bool OPimAccessTemplate<T>::add( const OPimRecord& rec) {
246 /* same type */
247 if ( rec.rtti() == T::rtti() ) {
248 const T &t = static_cast<const T&>(rec);
249 return add(t);
250 }
251 return false;
252}
253template <class T>
254bool OPimAccessTemplate<T>::remove( const T& t ) {
255 return remove( t.uid() );
256}
257template <class T>
258bool OPimAccessTemplate<T>::remove( int uid ) {
259 m_cache.remove( uid );
260 return m_backEnd->remove( uid );
261}
262template <class T>
263bool OPimAccessTemplate<T>::remove( const OPimRecord& rec) {
264 return remove( rec.uid() );
265}
266template <class T>
267bool OPimAccessTemplate<T>::replace( const T& t ) {
268 m_cache.replace( t );
269 return m_backEnd->replace( t );
270}
271template <class T>
272void OPimAccessTemplate<T>::invalidateCache() {
273 m_cache.invalidate();
274}
275template <class T>
276typename OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() {
277 return m_backEnd;
278}
279template <class T>
280bool OPimAccessTemplate<T>::wasChangedExternally()const {
281 return false;
282}
283template <class T>
284void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) {
285 m_backEnd = end;
286 if (m_backEnd )
287 m_backEnd->setFrontend( this );
288}
289template <class T>
290void OPimAccessTemplate<T>::cache( const T& t ) const{
291 /* hacky we need to work around the const*/
292 ((OPimAccessTemplate<T>*)this)->m_cache.add( t );
293}
294template <class T>
295void OPimAccessTemplate<T>::setSaneCacheSize( int size ) {
296 m_cache.setSize( size );
297}
298template <class T>
299void OPimAccessTemplate<T>::setReadAhead( uint count ) {
300 m_backEnd->setReadAhead( count );
301}
302#endif
diff --git a/libopie/pim/opimcache.h b/libopie/pim/opimcache.h
deleted file mode 100644
index 7f7cff5..0000000
--- a/libopie/pim/opimcache.h
+++ b/dev/null
@@ -1,131 +0,0 @@
1#ifndef OPIE_PIM_CACHE_H
2#define OPIE_PIM_CACHE_H
3
4#include <qintcache.h>
5
6#include "opimrecord.h"
7
8class OPimCacheItemPrivate;
9
10template <class T = OPimRecord>
11class OPimCacheItem {
12public:
13 OPimCacheItem( const T& t = T() );
14 OPimCacheItem( const OPimCacheItem& );
15 ~OPimCacheItem();
16
17 OPimCacheItem &operator=( const OPimCacheItem& );
18
19 T record()const;
20 void setRecord( const T& );
21private:
22 T m_t;
23 OPimCacheItemPrivate *d;
24};
25
26
27class OPimCachePrivate;
28/**
29 * OPimCache for caching the items
30 * We support adding, removing
31 * and finding
32 */
33template <class T = OPimRecord>
34class OPimCache {
35public:
36 typedef OPimCacheItem<T> Item;
37 OPimCache();
38 OPimCache( const OPimCache& );
39 ~OPimCache();
40
41 OPimCache &operator=( const OPimCache& );
42
43 bool contains(int uid)const;
44 void invalidate();
45 void setSize( int size );
46
47 T find(int uid )const;
48 void add( const T& );
49 void remove( int uid );
50 void replace( const T& );
51
52private:
53 QIntCache<Item> m_cache;
54 OPimCachePrivate* d;
55};
56
57// Implementation
58template <class T>
59OPimCacheItem<T>::OPimCacheItem( const T& t )
60 : m_t(t) {
61}
62template <class T>
63OPimCacheItem<T>::~OPimCacheItem() {
64
65}
66template <class T>
67T OPimCacheItem<T>::record()const {
68 return m_t;
69}
70template <class T>
71void OPimCacheItem<T>::setRecord( const T& t ) {
72 m_t = t;
73}
74// Cache
75template <class T>
76OPimCache<T>::OPimCache()
77 : m_cache(100, 53 )
78{
79 m_cache.setAutoDelete( TRUE );
80}
81template <class T>
82OPimCache<T>::~OPimCache() {
83
84}
85template <class T>
86bool OPimCache<T>::contains(int uid )const {
87 Item* it = m_cache.find( uid, FALSE );
88 if (!it)
89 return false;
90 return true;
91}
92template <class T>
93void OPimCache<T>::invalidate() {
94 m_cache.clear();
95}
96template <class T>
97void OPimCache<T>::setSize( int size ) {
98 m_cache.setMaxCost( size );
99}
100template <class T>
101T OPimCache<T>::find(int uid )const {
102 Item *it = m_cache.find( uid );
103 if (it)
104 return it->record();
105 return T();
106}
107template <class T>
108void OPimCache<T>::add( const T& t ) {
109 Item* it = 0l;
110 it = m_cache.find(t.uid(), FALSE );
111
112 if (it )
113 it->setRecord( t );
114
115 it = new Item( t );
116 if (!m_cache.insert( t.uid(), it ) )
117 delete it;
118}
119template <class T>
120void OPimCache<T>::remove( int uid ) {
121 m_cache.remove( uid );
122}
123template <class T>
124void OPimCache<T>::replace( const T& t) {
125 Item *it = m_cache.find( t.uid() );
126 if ( it ) {
127 it->setRecord( t );
128 }
129}
130
131#endif
diff --git a/libopie/pim/opimmaintainer.cpp b/libopie/pim/opimmaintainer.cpp
deleted file mode 100644
index 92cb25a..0000000
--- a/libopie/pim/opimmaintainer.cpp
+++ b/dev/null
@@ -1,37 +0,0 @@
1#include "opimmaintainer.h"
2
3OPimMaintainer::OPimMaintainer( int mode, int uid )
4 : m_mode(mode), m_uid(uid )
5{}
6OPimMaintainer::~OPimMaintainer() {
7}
8OPimMaintainer::OPimMaintainer( const OPimMaintainer& main ) {
9 *this = main;
10}
11OPimMaintainer &OPimMaintainer::operator=( const OPimMaintainer& main ) {
12 m_mode = main.m_mode;
13 m_uid = main.m_uid;
14
15 return *this;
16}
17bool OPimMaintainer::operator==( const OPimMaintainer& main ) {
18 if (m_mode != main.m_mode ) return false;
19 if (m_uid != main.m_uid ) return false;
20
21 return true;
22}
23bool OPimMaintainer::operator!=( const OPimMaintainer& main ) {
24 return !(*this == main );
25}
26int OPimMaintainer::mode()const {
27 return m_mode;
28}
29int OPimMaintainer::uid()const {
30 return m_uid;
31}
32void OPimMaintainer::setMode( int mo) {
33 m_mode = mo;
34}
35void OPimMaintainer::setUid( int uid ) {
36 m_uid = uid;
37}
diff --git a/libopie/pim/opimmaintainer.h b/libopie/pim/opimmaintainer.h
deleted file mode 100644
index 793d066..0000000
--- a/libopie/pim/opimmaintainer.h
+++ b/dev/null
@@ -1,40 +0,0 @@
1#ifndef OPIE_PIM_MAINTAINER_H
2#define OPIE_PIM_MAINTAINER_H
3
4#include <qstring.h>
5
6/**
7 * Who maintains what?
8 */
9class OPimMaintainer {
10public:
11 enum Mode { Undefined = -1,
12 Nothing = 0,
13 Responsible,
14 DoneBy,
15 Coordinating,
16 };
17 OPimMaintainer( int mode = Undefined, int uid = 0);
18 OPimMaintainer( const OPimMaintainer& );
19 ~OPimMaintainer();
20
21 OPimMaintainer &operator=( const OPimMaintainer& );
22 bool operator==( const OPimMaintainer& );
23 bool operator!=( const OPimMaintainer& );
24
25
26 int mode()const;
27 int uid()const;
28
29 void setMode( int mode );
30 void setUid( int uid );
31
32private:
33 int m_mode;
34 int m_uid;
35 class Private;
36 Private *d;
37
38};
39
40#endif
diff --git a/libopie/pim/opimmainwindow.cpp b/libopie/pim/opimmainwindow.cpp
deleted file mode 100644
index 99a0333..0000000
--- a/libopie/pim/opimmainwindow.cpp
+++ b/dev/null
@@ -1,150 +0,0 @@
1#include <qapplication.h>
2#include <qdatetime.h>
3#include <qcopchannel_qws.h>
4
5#include <qpe/sound.h>
6#include <qpe/qcopenvelope_qws.h>
7#include <qpe/qpeapplication.h>
8
9#include "opimresolver.h"
10#include "opimmainwindow.h"
11
12OPimMainWindow::OPimMainWindow( const QString& service, QWidget* parent,
13 const char* name, WFlags flag )
14 : QMainWindow( parent, name, flag ), m_rtti(-1), m_service( service ), m_fallBack(0l) {
15
16 /*
17 * let's generate our QCopChannel
18 */
19 m_str = QString("QPE/"+m_service).local8Bit();
20 m_channel= new QCopChannel(m_str, this );
21 connect(m_channel, SIGNAL(received(const QCString&,const QByteArray&) ),
22 this, SLOT( appMessage(const QCString&,const QByteArray&) ) );
23 connect(qApp, SIGNAL(appMessage(const QCString&,const QByteArray&) ),
24 this, SLOT( appMessage(const QCString&,const QByteArray&) ) );
25
26 /* connect flush and reload */
27 connect(qApp, SIGNAL(flush() ),
28 this, SLOT(flush() ) );
29 connect(qApp, SIGNAL(reload() ),
30 this, SLOT(reload() ) );
31}
32OPimMainWindow::~OPimMainWindow() {
33 delete m_channel;
34}
35QCopChannel* OPimMainWindow::channel() {
36 return m_channel;
37}
38void OPimMainWindow::doSetDocument( const QString& ) {
39
40}
41void OPimMainWindow::appMessage( const QCString& cmd, const QByteArray& array ) {
42 bool needShow = false;
43 /*
44 * create demands to create
45 * a new record...
46 */
47 QDataStream stream(array, IO_ReadOnly);
48 if ( cmd == "create()" ) {
49 raise();
50 int uid = create();
51 QCopEnvelope e(m_str, "created(int)" );
52 e << uid;
53 needShow = true;
54 }else if ( cmd == "remove(int)" ) {
55 int uid;
56 stream >> uid;
57 bool rem = remove( uid );
58 QCopEnvelope e(m_str, "removed(bool)" );
59 e << rem;
60 needShow = true;
61 }else if ( cmd == "beam(int)" ) {
62 int uid;
63 stream >> uid;
64 beam( uid);
65 }else if ( cmd == "show(int)" ) {
66 raise();
67 int uid;
68 stream >> uid;
69 show( uid );
70 needShow = true;
71 }else if ( cmd == "edit(int)" ) {
72 raise();
73 int uid;
74 stream >> uid;
75 edit( uid );
76 }else if ( cmd == "add(int,QByteArray)" ) {
77 int rtti;
78 QByteArray array;
79 stream >> rtti;
80 stream >> array;
81 m_fallBack = record(rtti, array );
82 if (!m_fallBack) return;
83 add( *m_fallBack );
84 delete m_fallBack;
85 }else if ( cmd == "alarm(QDateTime,int)" ) {
86 raise();
87 QDateTime dt; int uid;
88 stream >> dt;
89 stream >> uid;
90 qWarning(" Date: %s Uid: %d", dt.toString().latin1(), uid );
91 QDateTime current = QDateTime::currentDateTime();
92 if ( current.time().hour() != dt.time().hour() && current.time().minute() != dt.time().minute() )
93 return;
94 doAlarm( dt, uid );
95 needShow = true;
96 }
97
98 if (needShow )
99 QPEApplication::setKeepRunning();
100}
101/* implement the url scripting here */
102void OPimMainWindow::setDocument( const QString& str) {
103 doSetDocument( str );
104}
105/*
106 * we now try to get the array demarshalled
107 * check if the rtti matches this one
108 */
109OPimRecord* OPimMainWindow::record( int rtti, const QByteArray& array ) {
110 if ( service() != rtti )
111 return 0l;
112
113 OPimRecord* record = OPimResolver::self()->record( rtti );
114 QDataStream str(array, IO_ReadOnly );
115 if ( !record || !record->loadFromStream(str) ) {
116 delete record;
117 record = 0l;
118 }
119
120 return record;
121}
122/*
123 * get the rtti for the service
124 */
125int OPimMainWindow::service() {
126 if ( m_rtti == -1 )
127 m_rtti = OPimResolver::self()->serviceId( m_service );
128
129 return m_rtti;
130}
131void OPimMainWindow::doAlarm( const QDateTime&, int ) {
132
133}
134void OPimMainWindow::startAlarm(int count ) {
135 m_alarmCount = count;
136 m_playedCount = 0;
137 Sound::soundAlarm();
138 m_timerId = startTimer( 5000 );
139}
140void OPimMainWindow::killAlarm() {
141 killTimer( m_timerId );
142}
143void OPimMainWindow::timerEvent( QTimerEvent* e) {
144 if ( m_playedCount <m_alarmCount ) {
145 m_playedCount++;
146 Sound::soundAlarm();
147 }else {
148 killTimer( e->timerId() );
149 }
150}
diff --git a/libopie/pim/opimmainwindow.h b/libopie/pim/opimmainwindow.h
deleted file mode 100644
index 855d364..0000000
--- a/libopie/pim/opimmainwindow.h
+++ b/dev/null
@@ -1,99 +0,0 @@
1#ifndef OPIE_PIM_MAINWINDOW_H
2#define OPIE_PIM_MAINWINDOW_H
3
4#include <qmainwindow.h>
5
6#include <opie/opimrecord.h>
7
8/**
9 * This is a common Opie PIM MainWindow
10 * it takes care of the QCOP internals
11 * and implements some functions
12 * for the URL scripting schema
13 */
14/*
15 * due Qt and Templates with signal and slots
16 * do not work that good :(
17 * (Ok how to moc a template ;) )
18 * We will have the mainwindow which calls a struct which
19 * is normally reimplemented as a template ;)
20 */
21
22class QCopChannel;
23class QDateTime;
24class OPimMainWindow : public QMainWindow {
25 Q_OBJECT
26public:
27 enum TransPort { BlueTooth=0,
28 IrDa };
29
30 OPimMainWindow( const QString& service, QWidget *parent = 0, const char* name = 0,
31 WFlags f = WType_TopLevel);
32 virtual ~OPimMainWindow();
33
34
35protected slots:
36 /*
37 * called when a setDocument
38 * couldn't be handled by this window
39 */
40 virtual void doSetDocument( const QString& );
41 /* for syncing */
42 virtual void flush() = 0;
43 virtual void reload() = 0;
44
45 /** create a new Records and return the uid */
46 virtual int create() = 0;
47 /** remove a record with UID == uid */
48 virtual bool remove( int uid ) = 0;
49 /** beam the record with UID = uid */
50 virtual void beam( int uid ) = 0;
51
52 /** show the record with UID == uid */
53 virtual void show( int uid ) = 0;
54 /** edit the record */
55 virtual void edit( int uid ) = 0;
56
57 /** make a copy of it! */
58 virtual void add( const OPimRecord& ) = 0;
59
60 virtual void doAlarm( const QDateTime&, int uid );
61
62 QCopChannel* channel();
63
64protected:
65 /**
66 * start to play soundAlarm()
67 * @param count How many times the alarm is played
68 */
69 void startAlarm(int count = 10);
70 void killAlarm();
71 void timerEvent( QTimerEvent* );
72
73private slots:
74 void appMessage( const QCString&, const QByteArray& );
75 void setDocument( const QString& );
76
77
78private:
79 class Private;
80 Private* d;
81
82 int m_rtti;
83 QCopChannel* m_channel;
84 QString m_service;
85 QCString m_str;
86 OPimRecord* m_fallBack;
87 int m_alarmCount;
88 int m_playedCount;
89 int m_timerId;
90 /* I would love to do this as a template
91 * but can't think of a right way
92 * because I need signal and slots -zecke
93 */
94 virtual OPimRecord* record( int rtti, const QByteArray& ) ;
95 int service();
96};
97
98
99#endif
diff --git a/libopie/pim/opimnotify.cpp b/libopie/pim/opimnotify.cpp
deleted file mode 100644
index af5514b..0000000
--- a/libopie/pim/opimnotify.cpp
+++ b/dev/null
@@ -1,227 +0,0 @@
1#include <qshared.h>
2
3#include "opimnotify.h"
4
5struct OPimNotify::Data : public QShared {
6 Data() : QShared(),dur(-1),parent(0) {
7
8 }
9 QDateTime start;
10 int dur;
11 QString application;
12 int parent;
13};
14
15OPimNotify::OPimNotify( const QDateTime& start, int duration, int parent ) {
16 data = new Data;
17 data->start = start;
18 data->dur = duration;
19 data->parent = parent;
20}
21OPimNotify::OPimNotify( const OPimNotify& noti)
22 : data( noti.data )
23{
24 data->ref();
25}
26OPimNotify::~OPimNotify() {
27 if ( data->deref() ) {
28 delete data;
29 data = 0l;
30 }
31}
32
33OPimNotify &OPimNotify::operator=( const OPimNotify& noti) {
34 noti.data->ref();
35 deref();
36 data = noti.data;
37
38 return *this;
39}
40bool OPimNotify::operator==( const OPimNotify& noti ) {
41 if ( data == noti.data ) return true;
42 if ( data->dur != noti.data->dur ) return false;
43 if ( data->parent != noti.data->parent ) return false;
44 if ( data->application != noti.data->application ) return false;
45 if ( data->start != noti.data->start ) return false;
46
47 return true;
48}
49QDateTime OPimNotify::dateTime()const {
50 return data->start;
51}
52QString OPimNotify::service()const {
53 return data->application;
54}
55int OPimNotify::parent()const {
56 return data->parent;
57}
58int OPimNotify::duration()const {
59 return data->dur;
60}
61QDateTime OPimNotify::endTime()const {
62 return QDateTime( data->start.date(), data->start.time().addSecs( data->dur) );
63}
64void OPimNotify::setDateTime( const QDateTime& time ) {
65 copyIntern();
66 data->start = time;
67}
68void OPimNotify::setDuration( int dur ) {
69 copyIntern();
70 data->dur = dur;
71}
72void OPimNotify::setParent( int uid ) {
73 copyIntern();
74 data->parent = uid;
75}
76void OPimNotify::setService( const QString& str ) {
77 copyIntern();
78 data->application = str;
79}
80void OPimNotify::copyIntern() {
81 if ( data->count != 1 ) {
82 data->deref();
83 Data* dat = new Data;
84 dat->start = data->start;
85 dat->dur = data->dur;
86 dat->application = data->application;
87 dat->parent = data->parent;
88 data = dat;
89 }
90}
91void OPimNotify::deref() {
92 if ( data->deref() ) {
93 delete data;
94 data = 0;
95 }
96}
97
98/***********************************************************/
99struct OPimAlarm::Data : public QShared {
100 Data() : QShared() {
101 sound = 1;
102 }
103 int sound;
104 QString file;
105};
106OPimAlarm::OPimAlarm( int sound, const QDateTime& start, int duration, int parent )
107 : OPimNotify( start, duration, parent )
108{
109 data = new Data;
110 data->sound = sound;
111}
112OPimAlarm::OPimAlarm( const OPimAlarm& al)
113 : OPimNotify(al), data( al.data )
114{
115 data->ref();
116}
117OPimAlarm::~OPimAlarm() {
118 if ( data->deref() ) {
119 delete data;
120 data = 0l;
121 }
122}
123OPimAlarm &OPimAlarm::operator=( const OPimAlarm& al)
124{
125 OPimNotify::operator=( al );
126 deref();
127 al.data->ref();
128
129 data = al.data;
130
131
132 return *this;
133}
134bool OPimAlarm::operator==( const OPimAlarm& al) {
135 if ( data->sound != al.data->sound ) return false;
136 else if ( data->sound == Custom && data->file != al.data->file )
137 return false;
138
139 return OPimNotify::operator==( al );
140}
141QString OPimAlarm::type()const {
142 return QString::fromLatin1("OPimAlarm");
143}
144int OPimAlarm::sound()const {
145 return data->sound;
146}
147QString OPimAlarm::file()const {
148 return data->file;
149}
150void OPimAlarm::setSound( int snd) {
151 copyIntern();
152 data->sound = snd;
153}
154void OPimAlarm::setFile( const QString& sound ) {
155 copyIntern();
156 data->file = sound;
157}
158void OPimAlarm::deref() {
159 if ( data->deref() ) {
160 delete data;
161 data = 0l;
162 }
163}
164void OPimAlarm::copyIntern() {
165 if ( data->count != 1 ) {
166 data->deref();
167 Data *newDat = new Data;
168 newDat->sound = data->sound;
169 newDat->file = data->file;
170 data = newDat;
171 }
172}
173/************************/
174struct OPimReminder::Data : public QShared {
175 Data() : QShared(), record( 0) {
176 }
177 int record;
178
179};
180OPimReminder::OPimReminder( int uid, const QDateTime& start, int dur, int parent )
181 : OPimNotify( start, dur, parent )
182{
183 data = new Data;
184 data->record = uid;
185}
186OPimReminder::OPimReminder( const OPimReminder& rem )
187 : OPimNotify( rem ), data( rem.data )
188{
189 data->ref();
190}
191OPimReminder& OPimReminder::operator=( const OPimReminder& rem) {
192 OPimNotify::operator=(rem );
193
194 deref();
195 rem.data->ref();
196 data = rem.data;
197
198 return *this;
199}
200bool OPimReminder::operator==( const OPimReminder& rem) {
201 if ( data->record != rem.data->record ) return false;
202
203 return OPimNotify::operator==( rem );
204}
205QString OPimReminder::type()const {
206 return QString::fromLatin1("OPimReminder");
207}
208int OPimReminder::recordUid()const {
209 return data->record;
210}
211void OPimReminder::setRecordUid( int uid ) {
212 copyIntern();
213 data->record = uid;
214}
215void OPimReminder::deref() {
216 if ( data->deref() ) {
217 delete data;
218 data = 0l;
219 }
220}
221void OPimReminder::copyIntern() {
222 if ( data->count != 1 ) {
223 Data* da = new Data;
224 da->record = data->record;
225 data = da;
226 }
227}
diff --git a/libopie/pim/opimnotify.h b/libopie/pim/opimnotify.h
deleted file mode 100644
index 58417db..0000000
--- a/libopie/pim/opimnotify.h
+++ b/dev/null
@@ -1,144 +0,0 @@
1#ifndef OPIE_PIM_NOTIFY_H
2#define OPIE_PIM_NOTIFY_H
3
4#include <qdatetime.h>
5#include <qvaluelist.h>
6
7/**
8 * This is the base class of Notifiers. Possible
9 * notifiers would be Alarms, Reminders
10 * What they share is that they have
11 * A DateTime, Type, Duration
12 * This is what this base class takes care of
13 * on top of that it's shared
14 */
15/*
16 * TALK to eilers: have a class OPimDuration which sets the Duration
17 * given on the Due/Start Date? -zecke
18 * discuss: do we need a uid for the notify? -zecke
19 */
20class OPimNotify {
21public:
22 typedef QValueList<OPimNotify> ValueList;
23 OPimNotify( const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 );
24 OPimNotify( const OPimNotify& );
25 virtual ~OPimNotify();
26
27 OPimNotify &operator=(const OPimNotify& );
28 bool operator==( const OPimNotify& );
29
30 virtual QString type()const = 0;
31
32 /** start date */
33 QDateTime dateTime()const;
34 QString service()const;
35
36 /**
37 * RETURN the parent uid
38 */
39 int parent()const;
40
41 /**
42 * in Seconds
43 */
44 int duration()const;
45
46 /**
47 * Start Time + Duration
48 */
49 QDateTime endTime()const;
50
51 void setDateTime( const QDateTime& );
52 void setDuration( int dur );
53 void setParent(int uid );
54 void setService( const QString& );
55
56
57private:
58 inline void copyIntern();
59 void deref();
60 struct Data;
61 Data* data;
62
63 /* d-pointer */
64 class NotifyPrivate;
65 NotifyPrivate* d;
66
67};
68/**
69 * An alarm is a sound/mail/buzzer played/send
70 * at a given time to inform about
71 * an Event
72 */
73class OPimAlarm : public OPimNotify {
74public:
75 enum Sound{Loud=1, Silent=0, Custom=2 };
76 OPimAlarm( int sound = Silent, const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 );
77 OPimAlarm( const OPimAlarm& );
78 ~OPimAlarm();
79
80 OPimAlarm &operator=( const OPimAlarm& );
81 bool operator==( const OPimAlarm& );
82 QString type()const;
83
84 int sound()const;
85 QString file()const;
86
87 void setSound( int );
88 /* only when sound is custom... */
89 void setFile( const QString& sound );
90
91private:
92 void deref();
93 void copyIntern();
94 struct Data;
95 Data * data;
96
97 class Private;
98 Private* d;
99
100};
101
102/**
103 * A Reminder will be put into the
104 * datebook
105 * Note that the returned dateTime() may be not valid.
106 * In these cases one must resolve the uid and get the OEvent
107 */
108class OPimReminder : public OPimNotify {
109public:
110
111 /**
112 * c'tor of a reminder
113 * @param uid The uid of the Record inside the Datebook
114 * @param start the StartDate invalid for all day...
115 * @param duration The duration of the event ( -1 for all day )
116 * @param parent The 'parent' record of this reminder
117 */
118 OPimReminder( int uid = 0, const QDateTime& start = QDateTime(),
119 int duration = 0, int parent = 0 );
120 OPimReminder( const OPimReminder& );
121 OPimReminder &operator=(const OPimReminder& );
122
123 QString type()const;
124
125 bool operator==( const OPimReminder& );
126
127 /**
128 * the uid of the alarm
129 * inside the 'datebook' application
130 */
131 int recordUid()const;
132 void setRecordUid( int uid );
133
134private:
135 void deref();
136 void copyIntern();
137
138 struct Data;
139 Data* data;
140 class Private;
141 Private *d;
142};
143
144#endif
diff --git a/libopie/pim/opimnotifymanager.cpp b/libopie/pim/opimnotifymanager.cpp
deleted file mode 100644
index d6f0ead..0000000
--- a/libopie/pim/opimnotifymanager.cpp
+++ b/dev/null
@@ -1,162 +0,0 @@
1#include "opimnotifymanager.h"
2
3#include "oconversion.h"
4
5#include <qstringlist.h>
6
7OPimNotifyManager::OPimNotifyManager( const Reminders& rem, const Alarms& al)
8 : m_rem( rem ), m_al( al )
9{}
10OPimNotifyManager::~OPimNotifyManager() {
11}
12/* use static_cast and type instead of dynamic... */
13void OPimNotifyManager::add( const OPimNotify& noti) {
14 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
15 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
16 m_rem.append( rem );
17 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
18 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
19 m_al.append( al );
20 }
21}
22void OPimNotifyManager::remove( const OPimNotify& noti) {
23 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
24 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
25 m_rem.remove( rem );
26 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
27 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
28 m_al.remove( al );
29 }
30}
31void OPimNotifyManager::replace( const OPimNotify& noti) {
32 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
33 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
34 m_rem.remove( rem );
35 m_rem.append( rem );
36 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
37 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
38 m_al.remove( al );
39 m_al.append( al );
40 }
41}
42OPimNotifyManager::Reminders OPimNotifyManager::reminders()const {
43 return m_rem;
44}
45OPimNotifyManager::Alarms OPimNotifyManager::alarms()const {
46 return m_al;
47}
48OPimAlarm OPimNotifyManager::alarmAtDateTime( const QDateTime& when, bool& found ) const {
49 Alarms::ConstIterator it;
50 found = true;
51
52 for ( it = m_al.begin(); it != m_al.end(); ++it ){
53 if ( (*it).dateTime() == when )
54 return (*it);
55 }
56
57 // Fall through if nothing could be found
58 found = false;
59 OPimAlarm empty;
60 return empty;
61}
62
63
64void OPimNotifyManager::setAlarms( const Alarms& al) {
65 m_al = al;
66}
67void OPimNotifyManager::setReminders( const Reminders& rem) {
68 m_rem = rem;
69}
70/* FIXME!!! */
71/**
72 * The idea is to check if the provider for our service
73 * is online
74 * if it is we will use QCOP
75 * if not the Factory to get the backend...
76 * Qtopia1.6 services would be kewl to have here....
77 */
78void OPimNotifyManager::registerNotify( const OPimNotify& ) {
79
80}
81/* FIXME!!! */
82/**
83 * same as above...
84 * Also implement Url model
85 * have a MainWindow....
86 */
87void OPimNotifyManager::deregister( const OPimNotify& ) {
88
89}
90
91bool OPimNotifyManager::isEmpty()const {
92 qWarning("is Empty called on OPimNotifyManager %d %d", m_rem.count(), m_al.count() );
93 if ( m_rem.isEmpty() && m_al.isEmpty() ) return true;
94 else return false;
95}
96
97// Taken from otodoaccessxml..
98QString OPimNotifyManager::alarmsToString() const
99{
100 QString str;
101
102 OPimNotifyManager::Alarms alarms = m_al;
103 if ( !alarms.isEmpty() ) {
104 QStringList als;
105 OPimNotifyManager::Alarms::Iterator it = alarms.begin();
106 for ( ; it != alarms.end(); ++it ) {
107 /* only if time is valid */
108 if ( (*it).dateTime().isValid() ) {
109 als << OConversion::dateTimeToString( (*it).dateTime() )
110 + ":" + QString::number( (*it).duration() )
111 + ":" + QString::number( (*it).sound() )
112 + ":";
113 }
114 }
115 // now write the list
116 qWarning("als: %s", als.join("____________").latin1() );
117 str = als.join(";");
118 }
119
120 return str;
121}
122QString OPimNotifyManager::remindersToString() const
123{
124 QString str;
125
126 OPimNotifyManager::Reminders reminders = m_rem;
127 if (!reminders.isEmpty() ) {
128 OPimNotifyManager::Reminders::Iterator it = reminders.begin();
129 QStringList records;
130 for ( ; it != reminders.end(); ++it ) {
131 records << QString::number( (*it).recordUid() );
132 }
133 str = records.join(";");
134 }
135
136 return str;
137}
138
139void OPimNotifyManager::alarmsFromString( const QString& str )
140{
141 QStringList als = QStringList::split(";", str );
142 for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) {
143 QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty
144 qWarning("alarm: %s", alarm.join("___").latin1() );
145 qWarning("alarm[0]: %s %s", alarm[0].latin1(),
146 OConversion::dateTimeFromString( alarm[0] ).toString().latin1() );
147 OPimAlarm al( alarm[2].toInt(), OConversion::dateTimeFromString( alarm[0] ),
148 alarm[1].toInt() );
149 add( al );
150 }
151}
152
153void OPimNotifyManager::remindersFromString( const QString& str )
154{
155
156 QStringList rems = QStringList::split(";", str );
157 for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) {
158 OPimReminder rem( (*it).toInt() );
159 add( rem );
160 }
161
162}
diff --git a/libopie/pim/opimnotifymanager.h b/libopie/pim/opimnotifymanager.h
deleted file mode 100644
index f3c22f9..0000000
--- a/libopie/pim/opimnotifymanager.h
+++ b/dev/null
@@ -1,91 +0,0 @@
1#ifndef OPIE_PIM_NOTIFY_MANAGER_H
2#define OPIE_PIM_NOTIFY_MANAGER_H
3
4#include <qvaluelist.h>
5
6#include <opie/opimnotify.h>
7
8/**
9 * The notify manager keeps track of the Notifiers....
10 */
11class OPimNotifyManager {
12public:
13 typedef QValueList<OPimReminder> Reminders;
14 typedef QValueList<OPimAlarm> Alarms;
15 OPimNotifyManager( const Reminders& rems = Reminders(), const Alarms& alarms = Alarms() );
16 ~OPimNotifyManager();
17
18 /* we will cast it for you ;) */
19 void add( const OPimNotify& );
20 void remove( const OPimNotify& );
21 /* replaces all with this one! */
22 void replace( const OPimNotify& );
23
24 Reminders reminders()const;
25
26 /**
27 * Return
28 */
29 Alarms alarms()const;
30
31 /**
32 * Return alarm at DateTime "when". If more than one is registered at this
33 * DateTime, the first one is returned.
34 * If none was found, an empty Alarm is returned.
35 * @param when The date and time of the returned alarm
36 * @param found Returns true if anything was found.
37 * @return Returns the found alarm at given DateTime. It is empty if found is false
38 * (nothing could be found at given date and time)
39 */
40 OPimAlarm alarmAtDateTime( const QDateTime& when, bool& found ) const;
41
42 void setAlarms( const Alarms& );
43 void setReminders( const Reminders& );
44
45 /* register is a Ansi C keyword... */
46 /**
47 * This function will register the Notify to the Alarm Server
48 * or datebook depending on the type of the notify
49 */
50 void registerNotify( const OPimNotify& );
51
52 /**
53 * this will do the opposite..
54 */
55 void deregister( const OPimNotify& );
56
57 bool isEmpty()const;
58
59 /**
60 * Return all alarms as string
61 */
62 QString alarmsToString() const;
63 /**
64 * Return all notifiers as string
65 */
66 QString remindersToString() const;
67
68 /**
69 * Convert string to alarms
70 * @param str String created by alarmsToString()
71 */
72 void alarmsFromString( const QString& str );
73
74 /**
75 * Convert string to reminders
76 * @param str String created by remindersToString()
77 */
78 void remindersFromString( const QString& str );
79
80
81
82private:
83 Reminders m_rem;
84 Alarms m_al;
85
86 class Private;
87 Private *d;
88
89};
90
91#endif
diff --git a/libopie/pim/opimrecord.cpp b/libopie/pim/opimrecord.cpp
deleted file mode 100644
index 2365748..0000000
--- a/libopie/pim/opimrecord.cpp
+++ b/dev/null
@@ -1,182 +0,0 @@
1#include <qarray.h>
2
3#include <qpe/categories.h>
4#include <qpe/categoryselect.h>
5
6#include "opimrecord.h"
7
8Qtopia::UidGen OPimRecord::m_uidGen( Qtopia::UidGen::Qtopia );
9
10
11OPimRecord::OPimRecord( int uid )
12 : Qtopia::Record() {
13
14 m_lastHit = -1;
15 setUid( uid );
16}
17OPimRecord::~OPimRecord() {
18}
19OPimRecord::OPimRecord( const OPimRecord& rec )
20 : Qtopia::Record( rec )
21{
22 (*this) = rec;
23}
24
25OPimRecord &OPimRecord::operator=( const OPimRecord& rec) {
26 if ( this == &rec ) return *this;
27
28 Qtopia::Record::operator=( rec );
29 m_xrefman = rec.m_xrefman;
30 m_lastHit = rec.m_lastHit;
31
32 return *this;
33}
34/*
35 * category names
36 */
37QStringList OPimRecord::categoryNames( const QString& appname ) const {
38 QStringList list;
39 QArray<int> cats = categories();
40 Categories catDB;
41 catDB.load( categoryFileName() );
42
43 for (uint i = 0; i < cats.count(); i++ ) {
44 list << catDB.label( appname, cats[i] );
45 }
46
47 return list;
48}
49void OPimRecord::setCategoryNames( const QStringList& ) {
50
51}
52void OPimRecord::addCategoryName( const QString& ) {
53 Categories catDB;
54 catDB.load( categoryFileName() );
55
56
57}
58bool OPimRecord::isEmpty()const {
59 return ( uid() == 0 );
60}
61/*QString OPimRecord::crossToString()const {
62 QString str;
63 QMap<QString, QArray<int> >::ConstIterator it;
64 for (it = m_relations.begin(); it != m_relations.end(); ++it ) {
65 QArray<int> id = it.data();
66 for ( uint i = 0; i < id.size(); ++i ) {
67 str += it.key() + "," + QString::number( i ) + ";";
68 }
69 }
70 str = str.remove( str.length()-1, 1); // strip the ;
71 //qWarning("IDS " + str );
72
73 return str;
74 }*/
75/* if uid = 1 assign a new one */
76void OPimRecord::setUid( int uid ) {
77 if ( uid == 1)
78 uid = uidGen().generate();
79
80 Qtopia::Record::setUid( uid );
81};
82Qtopia::UidGen &OPimRecord::uidGen() {
83 return m_uidGen;
84}
85OPimXRefManager &OPimRecord::xrefmanager() {
86 return m_xrefman;
87}
88int OPimRecord::rtti(){
89 return 0;
90}
91
92/**
93 * now let's put our data into the stream
94 */
95/*
96 * First read UID
97 * Categories
98 * XRef
99 */
100bool OPimRecord::loadFromStream( QDataStream& stream ) {
101 int Int;
102 uint UInt;
103 stream >> Int;
104 setUid(Int);
105
106 /** Categories */
107 stream >> UInt;
108 QArray<int> array(UInt);
109 for (uint i = 0; i < UInt; i++ ) {
110 stream >> array[i];
111 }
112 setCategories( array );
113
114 /*
115 * now we do the X-Ref stuff
116 */
117 OPimXRef xref;
118 stream >> UInt;
119 for ( uint i = 0; i < UInt; i++ ) {
120 xref.setPartner( OPimXRef::One, partner( stream ) );
121 xref.setPartner( OPimXRef::Two, partner( stream ) );
122 m_xrefman.add( xref );
123 }
124
125 return true;
126}
127bool OPimRecord::saveToStream( QDataStream& stream )const {
128 /** UIDs */
129
130 stream << uid();
131
132 /** Categories */
133 stream << categories().count();
134 for ( uint i = 0; i < categories().count(); i++ ) {
135 stream << categories()[i];
136 }
137
138 /*
139 * first the XRef count
140 * then the xrefs
141 */
142 stream << m_xrefman.list().count();
143 for ( OPimXRef::ValueList::ConstIterator it = m_xrefman.list().begin();
144 it != m_xrefman.list().end(); ++it ) {
145 flush( (*it).partner( OPimXRef::One), stream );
146 flush( (*it).partner( OPimXRef::Two), stream );
147 }
148 return true;
149}
150void OPimRecord::flush( const OPimXRefPartner& par, QDataStream& str ) const{
151 str << par.service();
152 str << par.uid();
153 str << par.field();
154}
155OPimXRefPartner OPimRecord::partner( QDataStream& stream ) {
156 OPimXRefPartner par;
157 QString str;
158 int i;
159
160 stream >> str;
161 par.setService( str );
162
163 stream >> i;
164 par.setUid( i );
165
166 stream >> i ;
167 par.setField( i );
168
169 return par;
170}
171void OPimRecord::setLastHitField( int lastHit )const {
172 m_lastHit = lastHit;
173}
174int OPimRecord::lastHitField()const{
175 return m_lastHit;
176}
177QMap<QString, QString> OPimRecord::toExtraMap()const {
178 return customMap;
179}
180void OPimRecord::setExtraMap( const QMap<QString, QString>& map) {
181 customMap = map;
182}
diff --git a/libopie/pim/opimrecord.h b/libopie/pim/opimrecord.h
deleted file mode 100644
index 3d774e2..0000000
--- a/libopie/pim/opimrecord.h
+++ b/dev/null
@@ -1,158 +0,0 @@
1#ifndef OPIE_PIM_RECORD_H
2#define OPIE_PIM_RECORD_H
3
4#include <qdatastream.h>
5#include <qmap.h>
6#include <qstring.h>
7#include <qstringlist.h>
8
9/*
10 * we need to get customMap which is private...
11 */
12#define private protected
13#include <qpe/palmtoprecord.h>
14#undef private
15
16#include <opie/opimxrefmanager.h>
17
18/**
19 * This is the base class for
20 * all PIM Records
21 *
22 */
23class OPimRecord : public Qtopia::Record {
24public:
25 /**
26 * c'tor
27 * uid of 0 isEmpty
28 * uid of 1 will be assigned a new one
29 */
30 OPimRecord(int uid = 0);
31 ~OPimRecord();
32
33 /**
34 * copy c'tor
35 */
36 OPimRecord( const OPimRecord& rec );
37
38 /**
39 * copy operator
40 */
41 OPimRecord &operator=( const OPimRecord& );
42
43 /**
44 * category names resolved
45 */
46 QStringList categoryNames( const QString& appname )const;
47
48 /**
49 * set category names they will be resolved
50 */
51 void setCategoryNames( const QStringList& );
52
53 /**
54 * addCategoryName adds a name
55 * to the internal category list
56 */
57 void addCategoryName( const QString& );
58
59 /**
60 * if a Record isEmpty
61 * it's empty if it's 0
62 */
63 virtual bool isEmpty()const;
64
65 /**
66 * toRichText summary
67 */
68 virtual QString toRichText()const = 0;
69
70 /**
71 * a small one line summary
72 */
73 virtual QString toShortText()const = 0;
74
75 /**
76 * the name of the Record
77 */
78 virtual QString type()const = 0;
79
80 /**
81 * matches the Records the regular expression?
82 */
83 virtual bool match( const QString &regexp ) const
84 {setLastHitField( -1 );
85 return Qtopia::Record::match(QRegExp(regexp));};
86
87 /**
88 * if implemented this function returns which item has been
89 * last hit by the match() function.
90 * or -1 if not implemented or no hit has occured
91 */
92 int lastHitField()const;
93
94 /**
95 * converts the internal structure to a map
96 */
97 virtual QMap<int, QString> toMap()const = 0;
98 // virtual fromMap( const <int, QString>& map ) = 0; // Should be added in the future (eilers)
99
100 /**
101 * key value representation of extra items
102 */
103 QMap<QString, QString> toExtraMap()const;
104 void setExtraMap( const QMap<QString, QString>& );
105
106 /**
107 * the name for a recordField
108 */
109 virtual QString recordField(int)const = 0;
110
111 /**
112 * returns a reference of the
113 * Cross Reference Manager
114 * Partner 'One' is THIS PIM RECORD!
115 * 'Two' is the Partner where we link to
116 */
117 OPimXRefManager& xrefmanager();
118
119 /**
120 * set the uid
121 */
122 virtual void setUid( int uid );
123
124 /*
125 * used inside the Templates for casting
126 * REIMPLEMENT in your ....
127 */
128 static int rtti();
129
130 /**
131 * some marshalling and de marshalling code
132 * saves the OPimRecord
133 * to and from a DataStream
134 */
135 virtual bool loadFromStream(QDataStream& );
136 virtual bool saveToStream( QDataStream& stream )const;
137
138protected:
139 // need to be const cause it is called from const methods
140 mutable int m_lastHit;
141 void setLastHitField( int lastHit )const;
142 Qtopia::UidGen &uidGen();
143// QString crossToString()const;
144
145private:
146 class OPimRecordPrivate;
147 OPimRecordPrivate *d;
148 OPimXRefManager m_xrefman;
149 static Qtopia::UidGen m_uidGen;
150
151private:
152 void flush( const OPimXRefPartner&, QDataStream& stream )const;
153 OPimXRefPartner partner( QDataStream& );
154};
155
156
157
158#endif
diff --git a/libopie/pim/opimresolver.cpp b/libopie/pim/opimresolver.cpp
deleted file mode 100644
index 4ebbd6e..0000000
--- a/libopie/pim/opimresolver.cpp
+++ b/dev/null
@@ -1,198 +0,0 @@
1#include <qcopchannel_qws.h>
2
3#include <qpe/qcopenvelope_qws.h>
4
5#include "otodoaccess.h"
6#include "ocontactaccess.h"
7
8//#include "opimfactory.h"
9#include "opimresolver.h"
10
11OPimResolver* OPimResolver::m_self = 0l;
12
13OPimResolver::OPimResolver() {
14 /* the built in channels */
15 m_builtIns << "Todolist" << "Addressbook" << "Datebook";
16}
17OPimResolver* OPimResolver::self() {
18 if (!m_self)
19 m_self = new OPimResolver();
20
21 return m_self;
22}
23
24/*
25 * FIXME use a cache here too
26 */
27OPimRecord* OPimResolver::record( const QString& service, int uid ) {
28 OPimRecord* rec = 0l;
29 OPimBase* base = backend( service );
30
31 if ( base )
32 rec = base->record( uid );
33 delete base;
34
35 return rec;
36}
37OPimRecord* OPimResolver::record( const QString& service ) {
38 return record( serviceId( service ) );
39}
40OPimRecord* OPimResolver::record( int rtti ) {
41 OPimRecord* rec = 0l;
42 switch( rtti ) {
43 case 1: /* todolist */
44 rec = new OTodo();
45 case 2: /* contact */
46 rec = new OContact();
47 default:
48 break;
49 }
50 /*
51 * FIXME resolve externally
52 */
53 if (!rec ) {
54 ;
55 }
56 return 0l;
57}
58bool OPimResolver::isBuiltIn( const QString& str) const{
59 return m_builtIns.contains( str );
60}
61QCString OPimResolver::qcopChannel( enum BuiltIn& built)const {
62 QCString str("QPE/");
63 switch( built ) {
64 case TodoList:
65 str += "Todolist";
66 break;
67 case DateBook:
68 str += "Datebook";
69 break;
70 case AddressBook:
71 str += "Addressbook";
72 break;
73 default:
74 break;
75 }
76
77 return str;
78}
79QCString OPimResolver::qcopChannel( const QString& service )const {
80 QCString str("QPE/");
81 str += service.latin1();
82 return str;
83}
84/*
85 * Implement services!!
86 * FIXME
87 */
88QCString OPimResolver::applicationChannel( enum BuiltIn& built)const {
89 QCString str("QPE/Application/");
90 switch( built ) {
91 case TodoList:
92 str += "todolist";
93 break;
94 case DateBook:
95 str += "datebook";
96 break;
97 case AddressBook:
98 str += "addressbook";
99 break;
100 }
101
102 return str;
103}
104QCString OPimResolver::applicationChannel( const QString& service )const {
105 QCString str("QPE/Application/");
106
107 if ( isBuiltIn( service ) ) {
108 if ( service == "Todolist" )
109 str += "todolist";
110 else if ( service == "Datebook" )
111 str += "datebook";
112 else if ( service == "Addressbook" )
113 str += "addressbook";
114 }else
115 ; // FIXME for additional stuff
116
117 return str;
118}
119QStringList OPimResolver::services()const {
120 return m_builtIns;
121}
122QString OPimResolver::serviceName( int rtti ) const{
123 QString str;
124 switch ( rtti ) {
125 case TodoList:
126 str = "Todolist";
127 break;
128 case DateBook:
129 str = "Datebook";
130 break;
131 case AddressBook:
132 str = "Addressbook";
133 break;
134 default:
135 break;
136 }
137 return str;
138 // FIXME me for 3rd party
139}
140int OPimResolver::serviceId( const QString& service ) {
141 int rtti = 0;
142 if ( service == "Todolist" )
143 rtti = TodoList;
144 else if ( service == "Datebook" )
145 rtti = DateBook;
146 else if ( service == "Addressbook" )
147 rtti = AddressBook;
148
149 return rtti;
150}
151/**
152 * check if the 'service' is registered and if so we'll
153 */
154bool OPimResolver::add( const QString& service, const OPimRecord& rec) {
155 if ( QCopChannel::isRegistered( applicationChannel( service ) ) ) {
156 QByteArray data;
157 QDataStream arg(data, IO_WriteOnly );
158 if ( rec.saveToStream( arg ) ) {
159 QCopEnvelope env( applicationChannel( service ), "add(int,QByteArray)" );
160 env << rec.rtti();
161 env << data;
162 }else
163 return false;
164 }else{
165 OPimBase* base = backend( service );
166 if (!base ) return false;
167
168 base->load();
169 base->add( rec );
170 base->save();
171 delete base;
172 }
173
174 return true;
175}
176OPimBase* OPimResolver::backend( const QString& service ) {
177 return backend( serviceId( service ) );
178}
179OPimBase* OPimResolver::backend( int rtti ) {
180 OPimBase* base = 0l;
181 switch( rtti ) {
182 case TodoList:
183 base = new OTodoAccess();
184 break;
185 case DateBook:
186 break;
187 case AddressBook:
188 base = new OContactAccess("Resolver");
189 break;
190 default:
191 break;
192 }
193 // FIXME for 3rd party
194 if (!base )
195 ;
196
197 return base;
198}
diff --git a/libopie/pim/opimresolver.h b/libopie/pim/opimresolver.h
deleted file mode 100644
index 1ce1619..0000000
--- a/libopie/pim/opimresolver.h
+++ b/dev/null
@@ -1,90 +0,0 @@
1#ifndef OPIE_PIM_RESOLVER
2#define OPIE_PIM_RESOLVER
3
4#include <qstring.h>
5#include <qvaluelist.h>
6
7#include <opie/otemplatebase.h>
8
9/**
10 * OPimResolver is a MetaClass to access
11 * available backends read only.
12 * It will be used to resolve uids + app names
13 * to full informations
14 * to traverse through a list of alarms, reminders
15 * to get access to built in PIM functionality
16 * and to more stuff
17 * THE PERFORMANCE will depend on THE BACKEND
18 * USING XML is a waste of memory!!!!!
19 */
20class OPimResolver {
21public:
22 enum BuiltIn { TodoList = 0,
23 DateBook,
24 AddressBook
25 };
26 static OPimResolver* self();
27
28
29 /**
30 * return a record for a uid
31 * and an service
32 * You've THE OWNERSHIP NOW!
33 */
34 OPimRecord *record( const QString& service, int uid );
35
36 /**
37 * return the QCopChannel for service
38 * When we will use Qtopia Services it will be used here
39 */
40 QCString qcopChannel( enum BuiltIn& )const;
41 QCString qcopChannel( const QString& service )const;
42
43 /**
44 * The Application channel (QPE/Application/name)
45 */
46 QCString applicationChannel( enum BuiltIn& )const;
47 QCString applicationChannel( const QString& service )const;
48
49 /**
50 * return a list of available services
51 */
52 QStringList services()const;
53 inline QString serviceName(int rrti )const;
54 int serviceId( const QString& Service);
55 /**
56 * add a record to a service... ;)
57 */
58 bool add( const QString& service, const OPimRecord& );
59
60
61 /**
62 * record returns an empty record for a given service.
63 * Be sure to delete it!!!
64 *
65 */
66 OPimRecord* record( const QString& service );
67 OPimRecord* record( int rtti );
68
69 /**
70 * you can cast to your
71 */
72 OPimBase* backend( const QString& service );
73 OPimBase* backend( int rtti );
74private:
75 OPimResolver();
76 void loadData();
77 inline bool isBuiltIn( const QString& )const;
78 OPimRecord* recordExtern( const QString&, int );
79 OPimRecord* recordExtern( const QString& );
80
81 static OPimResolver* m_self;
82 struct Data;
83 class Private;
84
85 Data* data;
86 Private* d;
87 QStringList m_builtIns;
88};
89
90#endif
diff --git a/libopie/pim/opimstate.cpp b/libopie/pim/opimstate.cpp
deleted file mode 100644
index 6fb2feb..0000000
--- a/libopie/pim/opimstate.cpp
+++ b/dev/null
@@ -1,64 +0,0 @@
1#include <qshared.h>
2
3#include "opimstate.h"
4
5/*
6 * for one int this does not make
7 * much sense but never the less
8 * we will do it for the future
9 */
10struct OPimState::Data : public QShared {
11 Data() : QShared(),state(Undefined) {
12 }
13 int state;
14};
15
16OPimState::OPimState( int state ) {
17 data = new Data;
18 data->state = state;
19}
20OPimState::OPimState( const OPimState& st) :
21 data( st.data ) {
22 /* ref up */
23 data->ref();
24}
25OPimState::~OPimState() {
26 if ( data->deref() ) {
27 delete data ;
28 data = 0;
29 }
30}
31bool OPimState::operator==( const OPimState& st) {
32 if ( data->state == st.data->state ) return true;
33
34 return false;
35}
36OPimState &OPimState::operator=( const OPimState& st) {
37 st.data->ref();
38 deref();
39 data = st.data;
40
41 return *this;
42}
43void OPimState::setState( int st) {
44 copyInternally();
45 data->state = st;
46}
47int OPimState::state()const {
48 return data->state;
49}
50void OPimState::deref() {
51 if ( data->deref() ) {
52 delete data;
53 data = 0l;
54 }
55}
56void OPimState::copyInternally() {
57 /* we need to change it */
58 if ( data->count != 1 ) {
59 data->deref();
60 Data* d2 = new Data;
61 d2->state = data->state;
62 data = d2;
63 }
64}
diff --git a/libopie/pim/opimstate.h b/libopie/pim/opimstate.h
deleted file mode 100644
index cf6af46..0000000
--- a/libopie/pim/opimstate.h
+++ b/dev/null
@@ -1,46 +0,0 @@
1#ifndef OPIE_PIM_STATE_H
2#define OPIE_PIM_STATE_H
3
4#include <qstring.h>
5
6/**
7 * The State of a Task
8 * This class encapsules the state of a todo
9 * and it's shared too
10 */
11/*
12 * in c a simple struct would be enough ;)
13 * g_new_state();
14 * g_do_some_thing( state_t* );
15 * ;)
16 */
17class OPimState {
18public:
19 enum State {
20 Started = 0,
21 Postponed,
22 Finished,
23 NotStarted,
24 Undefined
25 };
26 OPimState( int state = Undefined );
27 OPimState( const OPimState& );
28 ~OPimState();
29
30 bool operator==( const OPimState& );
31 OPimState &operator=( const OPimState& );
32 void setState( int state);
33 int state()const;
34private:
35 void deref();
36 inline void copyInternally();
37
38 struct Data;
39 Data* data;
40
41 class Private;
42 Private *d;
43};
44
45
46#endif
diff --git a/libopie/pim/opimxref.cpp b/libopie/pim/opimxref.cpp
deleted file mode 100644
index 8eefbd8..0000000
--- a/libopie/pim/opimxref.cpp
+++ b/dev/null
@@ -1,47 +0,0 @@
1#include "opimxref.h"
2
3OPimXRef::OPimXRef( const OPimXRefPartner& one, const OPimXRefPartner& two )
4 : m_partners(2)
5{
6 m_partners[0] = one;
7 m_partners[1] = two;
8}
9OPimXRef::OPimXRef()
10 : m_partners(2)
11{
12
13}
14OPimXRef::OPimXRef( const OPimXRef& ref) {
15 *this = ref;
16}
17OPimXRef::~OPimXRef() {
18}
19OPimXRef &OPimXRef::operator=( const OPimXRef& ref) {
20 m_partners = ref.m_partners;
21 m_partners.detach();
22
23 return* this;
24}
25bool OPimXRef::operator==( const OPimXRef& oper ) {
26 if ( m_partners == oper.m_partners ) return true;
27
28 return false;
29}
30OPimXRefPartner OPimXRef::partner( enum Partners par) const{
31 return m_partners[par];
32}
33void OPimXRef::setPartner( enum Partners par, const OPimXRefPartner& part) {
34 m_partners[par] = part;
35}
36bool OPimXRef::containsString( const QString& string ) const{
37 if ( m_partners[One].service() == string ||
38 m_partners[Two].service() == string ) return true;
39
40 return false;
41}
42bool OPimXRef::containsUid( int uid ) const{
43 if ( m_partners[One].uid() == uid ||
44 m_partners[Two].uid() == uid ) return true;
45
46 return false;
47}
diff --git a/libopie/pim/opimxref.h b/libopie/pim/opimxref.h
deleted file mode 100644
index 6852651..0000000
--- a/libopie/pim/opimxref.h
+++ b/dev/null
@@ -1,39 +0,0 @@
1#ifndef OPIM_XREF_H
2#define OPIM_XREF_H
3
4#include <qarray.h>
5#include <qvaluelist.h>
6
7#include <opie/opimxrefpartner.h>
8
9/**
10 * this is a Cross Referecne between
11 * two Cross Reference Partners
12 */
13class OPimXRef {
14public:
15 typedef QValueList<OPimXRef> ValueList;
16 enum Partners { One, Two };
17 OPimXRef( const OPimXRefPartner& ONE, const OPimXRefPartner& );
18 OPimXRef();
19 OPimXRef( const OPimXRef& );
20 ~OPimXRef();
21
22 OPimXRef &operator=( const OPimXRef& );
23 bool operator==( const OPimXRef& );
24
25 OPimXRefPartner partner( enum Partners )const;
26
27 void setPartner( enum Partners, const OPimXRefPartner& );
28
29 bool containsString( const QString& service)const;
30 bool containsUid( int uid )const;
31
32private:
33 QArray<OPimXRefPartner> m_partners;
34
35 class Private;
36 Private *d;
37};
38
39#endif
diff --git a/libopie/pim/opimxrefmanager.cpp b/libopie/pim/opimxrefmanager.cpp
deleted file mode 100644
index 58bfd24..0000000
--- a/libopie/pim/opimxrefmanager.cpp
+++ b/dev/null
@@ -1,71 +0,0 @@
1#include "opimxrefmanager.h"
2
3
4OPimXRefManager::OPimXRefManager() {
5}
6OPimXRefManager::OPimXRefManager( const OPimXRefManager& ref) {
7 m_list = ref.m_list;
8}
9OPimXRefManager::~OPimXRefManager() {
10}
11OPimXRefManager &OPimXRefManager::operator=( const OPimXRefManager& ref) {
12 m_list = ref.m_list;
13 return *this;
14}
15bool OPimXRefManager::operator==( const OPimXRefManager& /*ref*/) {
16 // if ( m_list == ref.m_list ) return true;
17
18 return false;
19}
20void OPimXRefManager::add( const OPimXRef& ref) {
21 m_list.append( ref );
22}
23void OPimXRefManager::remove( const OPimXRef& ref) {
24 m_list.remove( ref );
25}
26void OPimXRefManager::replace( const OPimXRef& ref) {
27 m_list.remove( ref );
28 m_list.append( ref );
29}
30void OPimXRefManager::clear() {
31 m_list.clear();
32}
33QStringList OPimXRefManager::apps()const {
34 OPimXRef::ValueList::ConstIterator it;
35 QStringList list;
36
37 QString str;
38 for ( it = m_list.begin(); it != m_list.end(); ++it ) {
39 str = (*it).partner( OPimXRef::One ).service();
40 if ( !list.contains( str ) ) list << str;
41
42 str = (*it).partner( OPimXRef::Two ).service();
43 if ( !list.contains( str ) ) list << str;
44 }
45 return list;
46}
47OPimXRef::ValueList OPimXRefManager::list()const {
48 return m_list;
49}
50OPimXRef::ValueList OPimXRefManager::list( const QString& appName )const{
51 OPimXRef::ValueList list;
52 OPimXRef::ValueList::ConstIterator it;
53
54 for ( it = m_list.begin(); it != m_list.end(); ++it ) {
55 if ( (*it).containsString( appName ) )
56 list.append( (*it) );
57 }
58
59 return list;
60}
61OPimXRef::ValueList OPimXRefManager::list( int uid )const {
62 OPimXRef::ValueList list;
63 OPimXRef::ValueList::ConstIterator it;
64
65 for ( it = m_list.begin(); it != m_list.end(); ++it ) {
66 if ( (*it).containsUid( uid ) )
67 list.append( (*it) );
68 }
69
70 return list;
71}
diff --git a/libopie/pim/opimxrefmanager.h b/libopie/pim/opimxrefmanager.h
deleted file mode 100644
index c485e98..0000000
--- a/libopie/pim/opimxrefmanager.h
+++ b/dev/null
@@ -1,43 +0,0 @@
1#ifndef OPIM_XREF_MANAGER_H
2#define OPIM_XREF_MANAGER_H
3
4#include <qstringlist.h>
5
6#include <opie/opimxref.h>
7
8/**
9 * This is a simple manager for
10 * OPimXRefs.
11 * It allows addition, removing, replacing
12 * clearing and 'querying' the XRef...
13 */
14class OPimXRefManager {
15public:
16 OPimXRefManager();
17 OPimXRefManager( const OPimXRefManager& );
18 ~OPimXRefManager();
19
20 OPimXRefManager& operator=( const OPimXRefManager& );
21 bool operator==( const OPimXRefManager& );
22
23 void add( const OPimXRef& );
24 void remove( const OPimXRef& );
25 void replace( const OPimXRef& );
26
27 void clear();
28
29 /**
30 * apps participating
31 */
32 QStringList apps()const;
33 OPimXRef::ValueList list()const;
34 OPimXRef::ValueList list( const QString& service )const;
35 OPimXRef::ValueList list( int uid )const;
36
37private:
38 OPimXRef::ValueList m_list;
39 class Private;
40 Private *d;
41};
42
43#endif
diff --git a/libopie/pim/opimxrefpartner.cpp b/libopie/pim/opimxrefpartner.cpp
deleted file mode 100644
index 6ef3efb..0000000
--- a/libopie/pim/opimxrefpartner.cpp
+++ b/dev/null
@@ -1,43 +0,0 @@
1#include "opimxrefpartner.h"
2
3OPimXRefPartner::OPimXRefPartner( const QString& appName,
4 int uid, int field )
5 : m_app(appName), m_uid(uid), m_field( field ) {
6}
7OPimXRefPartner::OPimXRefPartner( const OPimXRefPartner& ref ) {
8 *this = ref;
9}
10OPimXRefPartner::~OPimXRefPartner() {
11}
12OPimXRefPartner &OPimXRefPartner::operator=( const OPimXRefPartner& par ) {
13 m_app = par.m_app;
14 m_uid = par.m_uid;
15 m_field = par.m_field;
16
17 return *this;
18}
19bool OPimXRefPartner::operator==( const OPimXRefPartner& par ) {
20 if ( m_app != par.m_app ) return false;
21 if ( m_uid != par.m_uid ) return false;
22 if ( m_field != par.m_field ) return false;
23
24 return true;
25}
26QString OPimXRefPartner::service()const {
27 return m_app;
28}
29int OPimXRefPartner::uid()const {
30 return m_uid;
31}
32int OPimXRefPartner::field()const {
33 return m_field;
34}
35void OPimXRefPartner::setService( const QString& appName ) {
36 m_app = appName;
37}
38void OPimXRefPartner::setUid( int uid ) {
39 m_uid = uid;
40}
41void OPimXRefPartner::setField( int field ) {
42 m_field = field;
43}
diff --git a/libopie/pim/opimxrefpartner.h b/libopie/pim/opimxrefpartner.h
deleted file mode 100644
index d76e384..0000000
--- a/libopie/pim/opimxrefpartner.h
+++ b/dev/null
@@ -1,40 +0,0 @@
1#ifndef OPIM_XREF_PARTNER_H
2#define OPIM_XREF_PARTNER_H
3
4#include <qstring.h>
5
6/**
7 * This class represents one partner
8 * of a Cross Reference.
9 * In Opie one application
10 * can link one uid
11 * with one tableId( fieldId ) to another.
12 */
13class OPimXRefPartner {
14public:
15 OPimXRefPartner( const QString& service = QString::null,
16 int uid = 0, int field = -1 );
17 OPimXRefPartner( const OPimXRefPartner& );
18 OPimXRefPartner& operator=( const OPimXRefPartner& );
19 ~OPimXRefPartner();
20
21 bool operator==(const OPimXRefPartner& );
22
23 QString service()const;
24 int uid()const;
25 int field()const;
26
27 void setService( const QString& service );
28 void setUid( int uid );
29 void setField( int field );
30private:
31 QString m_app;
32 int m_uid;
33 int m_field;
34
35 class Private;
36 Private* d;
37};
38
39
40#endif
diff --git a/libopie/pim/orecordlist.h b/libopie/pim/orecordlist.h
deleted file mode 100644
index 5211f57..0000000
--- a/libopie/pim/orecordlist.h
+++ b/dev/null
@@ -1,306 +0,0 @@
1
2#ifndef OPIE_RECORD_LIST_H
3#define OPIE_RECORD_LIST_H
4
5#include <qarray.h>
6
7#include "otemplatebase.h"
8#include "opimrecord.h"
9
10class ORecordListIteratorPrivate;
11/**
12 * Our List Iterator
13 * it behaves like STL or Qt
14 *
15 * for(it = list.begin(); it != list.end(); ++it )
16 * doSomeCoolStuff( (*it) );
17 */
18template <class T> class ORecordList;
19template <class T = OPimRecord>
20class ORecordListIterator {
21 friend class ORecordList<T>;
22public:
23 typedef OTemplateBase<T> Base;
24
25 /**
26 * The c'tor used internally from
27 * ORecordList
28 */
29 ORecordListIterator( const QArray<int>, const Base* );
30
31 /**
32 * The standard c'tor
33 */
34 ORecordListIterator();
35 ~ORecordListIterator();
36
37 ORecordListIterator( const ORecordListIterator& );
38 ORecordListIterator &operator=(const ORecordListIterator& );
39
40 /**
41 * a * operator ;)
42 * use it like this T = (*it);
43 */
44 T operator*();
45 ORecordListIterator &operator++();
46 ORecordListIterator &operator--();
47
48 bool operator==( const ORecordListIterator& it );
49 bool operator!=( const ORecordListIterator& it );
50
51 /**
52 * the current item
53 */
54 uint current()const;
55
56 /**
57 * the number of items
58 */
59 uint count()const;
60
61 /**
62 * sets the current item
63 */
64 void setCurrent( uint cur );
65
66private:
67 QArray<int> m_uids;
68 uint m_current;
69 const Base* m_temp;
70 bool m_end : 1;
71 T m_record;
72 bool m_direction :1;
73
74 /* d pointer for future versions */
75 ORecordListIteratorPrivate *d;
76};
77
78class ORecordListPrivate;
79/**
80 * The recordlist used as a return type
81 * from OPimAccessTemplate
82 */
83template <class T = OPimRecord >
84class ORecordList {
85public:
86 typedef OTemplateBase<T> Base;
87 typedef ORecordListIterator<T> Iterator;
88
89 /**
90 * c'tor
91 */
92 ORecordList () {
93 }
94ORecordList( const QArray<int>& ids,
95 const Base* );
96 ~ORecordList();
97
98 /**
99 * the first iterator
100 */
101 Iterator begin();
102
103 /**
104 * the end
105 */
106 Iterator end();
107
108 /**
109 * the number of items in the list
110 */
111 uint count()const;
112
113 T operator[]( uint i );
114 int uidAt(uint i );
115
116 /**
117 * Remove the contact with given uid
118 */
119 bool remove( int uid );
120
121 /*
122 ConstIterator begin()const;
123 ConstIterator end()const;
124 */
125private:
126 QArray<int> m_ids;
127 const Base* m_acc;
128 ORecordListPrivate *d;
129};
130
131/* ok now implement it */
132template <class T>
133ORecordListIterator<T>::ORecordListIterator() {
134 m_current = 0;
135 m_temp = 0l;
136 m_end = true;
137 m_record = T();
138 /* forward */
139 m_direction = TRUE;
140}
141template <class T>
142ORecordListIterator<T>::~ORecordListIterator() {
143/* nothing to delete */
144}
145
146template <class T>
147ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) {
148// qWarning("ORecordListIterator copy c'tor");
149 m_uids = it.m_uids;
150 m_current = it.m_current;
151 m_temp = it.m_temp;
152 m_end = it.m_end;
153 m_record = it.m_record;
154 m_direction = it.m_direction;
155}
156
157template <class T>
158ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) {
159 m_uids = it.m_uids;
160 m_current = it.m_current;
161 m_temp = it.m_temp;
162 m_end = it.m_end;
163 m_record = it.m_record;
164
165 return *this;
166}
167
168template <class T>
169T ORecordListIterator<T>::operator*() {
170 //qWarning("operator* %d %d", m_current, m_uids[m_current] );
171 if (!m_end )
172 m_record = m_temp->find( m_uids[m_current], m_uids, m_current,
173 m_direction ? Base::Forward :
174 Base::Reverse );
175 else
176 m_record = T();
177
178 return m_record;
179}
180
181template <class T>
182ORecordListIterator<T> &ORecordListIterator<T>::operator++() {
183 m_direction = true;
184 if (m_current < m_uids.count() ) {
185 m_end = false;
186 ++m_current;
187 }else
188 m_end = true;
189
190 return *this;
191}
192template <class T>
193ORecordListIterator<T> &ORecordListIterator<T>::operator--() {
194 m_direction = false;
195 if ( m_current > 0 ) {
196 --m_current;
197 m_end = false;
198 } else
199 m_end = true;
200
201 return *this;
202}
203
204template <class T>
205bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) {
206
207 /* if both are at we're the same.... */
208 if ( m_end == it.m_end ) return true;
209
210 if ( m_uids != it.m_uids ) return false;
211 if ( m_current != it.m_current ) return false;
212 if ( m_temp != it.m_temp ) return false;
213
214 return true;
215}
216template <class T>
217bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) {
218 return !(*this == it );
219}
220template <class T>
221ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids,
222 const Base* t )
223 : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ),
224 m_direction( false )
225{
226 /* if the list is empty we're already at the end of the list */
227 if (uids.count() == 0 )
228 m_end = true;
229}
230template <class T>
231uint ORecordListIterator<T>::current()const {
232 return m_current;
233}
234template <class T>
235void ORecordListIterator<T>::setCurrent( uint cur ) {
236 if( cur < m_uids.count() ) {
237 m_end = false;
238 m_current= cur;
239 }
240}
241template <class T>
242uint ORecordListIterator<T>::count()const {
243 return m_uids.count();
244}
245template <class T>
246ORecordList<T>::ORecordList( const QArray<int>& ids,
247 const Base* acc )
248 : m_ids( ids ), m_acc( acc )
249{
250}
251template <class T>
252ORecordList<T>::~ORecordList() {
253/* nothing to do here */
254}
255template <class T>
256typename ORecordList<T>::Iterator ORecordList<T>::begin() {
257 Iterator it( m_ids, m_acc );
258 return it;
259}
260template <class T>
261typename ORecordList<T>::Iterator ORecordList<T>::end() {
262 Iterator it( m_ids, m_acc );
263 it.m_end = true;
264 it.m_current = m_ids.count();
265
266 return it;
267}
268template <class T>
269uint ORecordList<T>::count()const {
270return m_ids.count();
271}
272template <class T>
273T ORecordList<T>::operator[]( uint i ) {
274 if ( i >= m_ids.count() )
275 return T();
276 /* forward */
277 return m_acc->find( m_ids[i], m_ids, i );
278}
279template <class T>
280int ORecordList<T>::uidAt( uint i ) {
281 return m_ids[i];
282}
283
284template <class T>
285bool ORecordList<T>::remove( int uid ) {
286 QArray<int> copy( m_ids.count() );
287 int counter = 0;
288 bool ret_val = false;
289
290 for (uint i = 0; i < m_ids.count(); i++){
291 if ( m_ids[i] != uid ){
292 copy[counter++] = m_ids[i];
293
294 }else
295 ret_val = true;
296 }
297
298 copy.resize( counter );
299 m_ids = copy;
300
301
302 return ret_val;
303}
304
305
306#endif
diff --git a/libopie/pim/orecur.cpp b/libopie/pim/orecur.cpp
deleted file mode 100644
index f46f22e..0000000
--- a/libopie/pim/orecur.cpp
+++ b/dev/null
@@ -1,593 +0,0 @@
1#include <time.h>
2
3#include <qshared.h>
4
5#include <qtopia/timeconversion.h>
6
7#include "otimezone.h"
8#include "orecur.h"
9
10struct ORecur::Data : public QShared {
11 Data() : QShared() {
12 type = ORecur::NoRepeat;
13 freq = -1;
14 days = 0;
15 pos = 0;
16 create = QDateTime::currentDateTime();
17 hasEnd = FALSE;
18 end = QDate::currentDate();
19 }
20 char days; // Q_UINT8 for 8 seven days;)
21 ORecur::RepeatType type;
22 int freq;
23 int pos;
24 bool hasEnd : 1;
25 QDate end;
26 QDateTime create;
27 int rep;
28 QString app;
29 ExceptionList list;
30 QDate start;
31};
32
33
34ORecur::ORecur() {
35 data = new Data;
36}
37
38ORecur::ORecur( const QMap<int, QString>& map )
39{
40 ORecur();
41 fromMap( map );
42}
43
44
45ORecur::ORecur( const ORecur& rec)
46 : data( rec.data )
47{
48 data->ref();
49}
50ORecur::~ORecur() {
51 if ( data->deref() ) {
52 delete data;
53 data = 0l;
54 }
55}
56void ORecur::deref() {
57 if ( data->deref() ) {
58 delete data;
59 data = 0l;
60 }
61}
62bool ORecur::operator==( const ORecur& )const {
63 return false;
64}
65ORecur &ORecur::operator=( const ORecur& re) {
66 if ( *this == re ) return *this;
67
68 re.data->ref();
69 deref();
70 data = re.data;
71
72 return *this;
73}
74bool ORecur::doesRecur()const {
75 return !( type() == NoRepeat );
76}
77/*
78 * we try to be smart here
79 *
80 */
81bool ORecur::doesRecur( const QDate& date ) {
82 /* the day before the recurrance */
83 QDate da = date.addDays(-1);
84
85 QDate recur;
86 if (!nextOcurrence( da, recur ) )
87 return false;
88
89 return (recur == date);
90}
91// FIXME unuglify!
92// GPL from Datebookdb.cpp
93// FIXME exception list!
94bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
95 bool stillLooking;
96 stillLooking = p_nextOccurrence( from, next );
97 while ( stillLooking && data->list.contains(next) )
98 stillLooking = p_nextOccurrence( next.addDays(1), next );
99
100 return stillLooking;
101}
102bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
103
104 // easy checks, first are we too far in the future or too far in the past?
105 QDate tmpDate;
106 int freq = frequency();
107 int diff, diff2, a;
108 int iday, imonth, iyear;
109 int dayOfWeek = 0;
110 int firstOfWeek = 0;
111 int weekOfMonth;
112
113
114 if (hasEndDate() && endDate() < from)
115 return FALSE;
116
117 if (start() >= from ) {
118 next = start();
119 return TRUE;
120 }
121
122 switch ( type() ) {
123 case Weekly:
124 /* weekly is just daily by 7 */
125 /* first convert the repeatPattern.Days() mask to the next
126 day of week valid after from */
127 dayOfWeek = from.dayOfWeek();
128 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
129
130 /* this is done in case freq > 1 and from in week not
131 for this round */
132 // firstOfWeek = 0; this is already done at decl.
133 while(!((1 << firstOfWeek) & days() ))
134 firstOfWeek++;
135
136 /* there is at least one 'day', or there would be no event */
137 while(!((1 << (dayOfWeek % 7)) & days() ))
138 dayOfWeek++;
139
140 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
141 dayOfWeek -= start().dayOfWeek() -1;
142
143 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
144 firstOfWeek -= start().dayOfWeek() -1;
145
146 // dayOfWeek may be negitive now
147 // day of week is number of days to add to start day
148
149 freq *= 7;
150 // FALL-THROUGH !!!!!
151 case Daily:
152 // the add is for the possible fall through from weekly */
153 if(start().addDays(dayOfWeek) > from) {
154 /* first week exception */
155 next = QDate(start().addDays(dayOfWeek) );
156 if ((next > endDate())
157 && hasEndDate() )
158 return FALSE;
159 return TRUE;
160 }
161 /* if from is middle of a non-week */
162
163 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
164 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
165
166 if(diff != 0)
167 diff = freq - diff;
168 if(diff2 != 0)
169 diff2 = freq - diff2;
170 diff = QMIN(diff, diff2);
171
172 next = QDate(from.addDays(diff));
173 if ( (next > endDate())
174 && hasEndDate() )
175 return FALSE;
176 return TRUE;
177 case MonthlyDay:
178 iday = from.day();
179 iyear = from.year();
180 imonth = from.month();
181 /* find equivelent day of month for this month */
182 dayOfWeek = start().dayOfWeek();
183 weekOfMonth = (start().day() - 1) / 7;
184
185 /* work out when the next valid month is */
186 a = from.year() - start().year();
187 a *= 12;
188 a = a + (imonth - start().month());
189 /* a is e.start()monthsFrom(from); */
190 if(a % freq) {
191 a = freq - (a % freq);
192 imonth = from.month() + a;
193 if (imonth > 12) {
194 imonth--;
195 iyear += imonth / 12;
196 imonth = imonth % 12;
197 imonth++;
198 }
199 }
200 /* imonth is now the first month after or on
201 from that matches the frequency given */
202
203 /* find for this month */
204 tmpDate = QDate( iyear, imonth, 1 );
205
206 iday = 1;
207 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
208 iday += 7 * weekOfMonth;
209 while (iday > tmpDate.daysInMonth()) {
210 imonth += freq;
211 if (imonth > 12) {
212 imonth--;
213 iyear += imonth / 12;
214 imonth = imonth % 12;
215 imonth++;
216 }
217 tmpDate = QDate( iyear, imonth, 1 );
218 /* these loops could go for a while, check end case now */
219 if ((tmpDate > endDate()) && hasEndDate() )
220 return FALSE;
221 iday = 1;
222 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
223 iday += 7 * weekOfMonth;
224 }
225 tmpDate = QDate(iyear, imonth, iday);
226
227 if (tmpDate >= from) {
228 next = tmpDate;
229 if ((next > endDate() ) && hasEndDate() )
230 return FALSE;
231 return TRUE;
232 }
233
234 /* need to find the next iteration */
235 do {
236 imonth += freq;
237 if (imonth > 12) {
238 imonth--;
239 iyear += imonth / 12;
240 imonth = imonth % 12;
241 imonth++;
242 }
243 tmpDate = QDate( iyear, imonth, 1 );
244 /* these loops could go for a while, check end case now */
245 if ((tmpDate > endDate()) && hasEndDate() )
246 return FALSE;
247 iday = 1;
248 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
249 iday += 7 * weekOfMonth;
250 } while (iday > tmpDate.daysInMonth());
251 tmpDate = QDate(iyear, imonth, iday);
252
253 next = tmpDate;
254 if ((next > endDate()) && hasEndDate() )
255 return FALSE;
256 return TRUE;
257 case MonthlyDate:
258 iday = start().day();
259 iyear = from.year();
260 imonth = from.month();
261
262 a = from.year() - start().year();
263 a *= 12;
264 a = a + (imonth - start().month());
265 /* a is e.start()monthsFrom(from); */
266 if(a % freq) {
267 a = freq - (a % freq);
268 imonth = from.month() + a;
269 if (imonth > 12) {
270 imonth--;
271 iyear += imonth / 12;
272 imonth = imonth % 12;
273 imonth++;
274 }
275 }
276 /* imonth is now the first month after or on
277 from that matches the frequencey given */
278
279 /* this could go for a while, worse case, 4*12 iterations, probably */
280 while(!QDate::isValid(iyear, imonth, iday) ) {
281 imonth += freq;
282 if (imonth > 12) {
283 imonth--;
284 iyear += imonth / 12;
285 imonth = imonth % 12;
286 imonth++;
287 }
288 /* these loops could go for a while, check end case now */
289 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
290 return FALSE;
291 }
292
293 if(QDate(iyear, imonth, iday) >= from) {
294 /* done */
295 next = QDate(iyear, imonth, iday);
296 if ((next > endDate()) && hasEndDate() )
297 return FALSE;
298 return TRUE;
299 }
300
301 /* ok, need to cycle */
302 imonth += freq;
303 imonth--;
304 iyear += imonth / 12;
305 imonth = imonth % 12;
306 imonth++;
307
308 while(!QDate::isValid(iyear, imonth, iday) ) {
309 imonth += freq;
310 imonth--;
311 iyear += imonth / 12;
312 imonth = imonth % 12;
313 imonth++;
314 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
315 return FALSE;
316 }
317
318 next = QDate(iyear, imonth, iday);
319 if ((next > endDate()) && hasEndDate() )
320 return FALSE;
321 return TRUE;
322 case Yearly:
323 iday = start().day();
324 imonth = start().month();
325 iyear = from.year(); // after all, we want to start in this year
326
327 diff = 1;
328 if(imonth == 2 && iday > 28) {
329 /* leap year, and it counts, calculate actual frequency */
330 if(freq % 4)
331 if (freq % 2)
332 freq = freq * 4;
333 else
334 freq = freq * 2;
335 /* else divides by 4 already, leave freq alone */
336 diff = 4;
337 }
338
339 a = from.year() - start().year();
340 if(a % freq) {
341 a = freq - (a % freq);
342 iyear = iyear + a;
343 }
344
345 /* under the assumption we won't hit one of the special not-leap years twice */
346 if(!QDate::isValid(iyear, imonth, iday)) {
347 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
348 iyear += freq;
349 }
350
351 if(QDate(iyear, imonth, iday) >= from) {
352 next = QDate(iyear, imonth, iday);
353
354 if ((next > endDate()) && hasEndDate() )
355 return FALSE;
356 return TRUE;
357 }
358 /* iyear == from.year(), need to advance again */
359 iyear += freq;
360 /* under the assumption we won't hit one of the special not-leap years twice */
361 if(!QDate::isValid(iyear, imonth, iday)) {
362 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
363 iyear += freq;
364 }
365
366 next = QDate(iyear, imonth, iday);
367 if ((next > endDate()) && hasEndDate() )
368 return FALSE;
369 return TRUE;
370 default:
371 return FALSE;
372 }
373}
374ORecur::RepeatType ORecur::type()const{
375 return data->type;
376}
377int ORecur::frequency()const {
378 return data->freq;
379}
380int ORecur::position()const {
381 return data->pos;
382}
383char ORecur::days() const{
384 return data->days;
385}
386bool ORecur::hasEndDate()const {
387 return data->hasEnd;
388}
389QDate ORecur::endDate()const {
390 return data->end;
391}
392QDate ORecur::start()const{
393 return data->start;
394}
395QDateTime ORecur::createdDateTime()const {
396 return data->create;
397}
398int ORecur::repetition()const {
399 return data->rep;
400}
401QString ORecur::service()const {
402 return data->app;
403}
404ORecur::ExceptionList& ORecur::exceptions() {
405 return data->list;
406}
407void ORecur::setType( const RepeatType& z) {
408 checkOrModify();
409 data->type = z;
410}
411void ORecur::setFrequency( int freq ) {
412 checkOrModify();
413 data->freq = freq;
414}
415void ORecur::setPosition( int pos ) {
416 checkOrModify();
417 data->pos = pos;
418}
419void ORecur::setDays( char c ) {
420 checkOrModify();
421 data->days = c;
422}
423void ORecur::setEndDate( const QDate& dt) {
424 checkOrModify();
425 data->end = dt;
426}
427void ORecur::setCreatedDateTime( const QDateTime& t) {
428 checkOrModify();
429 data->create = t;
430}
431void ORecur::setHasEndDate( bool b) {
432 checkOrModify();
433 data->hasEnd = b;
434}
435void ORecur::setRepitition( int rep ) {
436 checkOrModify();
437 data->rep = rep;
438}
439void ORecur::setService( const QString& app ) {
440 checkOrModify();
441 data->app = app;
442}
443void ORecur::setStart( const QDate& dt ) {
444 checkOrModify();
445 data->start = dt;
446}
447void ORecur::checkOrModify() {
448 if ( data->count != 1 ) {
449 data->deref();
450 Data* d2 = new Data;
451 d2->days = data->days;
452 d2->type = data->type;
453 d2->freq = data->freq;
454 d2->pos = data->pos;
455 d2->hasEnd = data->hasEnd;
456 d2->end = data->end;
457 d2->create = data->create;
458 d2->rep = data->rep;
459 d2->app = data->app;
460 d2->list = data->list;
461 d2->start = data->start;
462 data = d2;
463 }
464}
465QString ORecur::toString()const {
466 QString buf;
467 QMap<int, QString> recMap = toMap();
468
469 buf += " rtype=\"";
470 buf += recMap[ORecur::RType];
471 buf += "\"";
472 if (data->days > 0 )
473 buf += " rweekdays=\"" + recMap[ORecur::RWeekdays] + "\"";
474 if ( data->pos != 0 )
475 buf += " rposition=\"" + recMap[ORecur::RPosition] + "\"";
476
477 buf += " rfreq=\"" + recMap[ORecur::RFreq] + "\"";
478 buf += " rhasenddate=\"" + recMap[ORecur::RHasEndDate]+ "\"";
479 if ( data->hasEnd )
480 buf += " enddt=\""
481 + recMap[ORecur::EndDate]
482 + "\"";
483 buf += " created=\"" + recMap[ORecur::Created] + "\"";
484
485 if ( data->list.isEmpty() ) return buf;
486 buf += " exceptions=\"";
487 buf += recMap[ORecur::Exceptions];
488 buf += "\" ";
489
490 return buf;
491}
492
493QString ORecur::rTypeString() const
494{
495 QString retString;
496 switch ( data->type ) {
497 case ORecur::Daily:
498 retString = "Daily";
499 break;
500 case ORecur::Weekly:
501 retString = "Weekly";
502 break;
503 case ORecur::MonthlyDay:
504 retString = "MonthlyDay";
505 break;
506 case ORecur::MonthlyDate:
507 retString = "MonthlyDate";
508 break;
509 case ORecur::Yearly:
510 retString = "Yearly";
511 break;
512 default:
513 retString = "NoRepeat";
514 break;
515
516 }
517
518 return retString;
519}
520
521QMap<QString, ORecur::RepeatType> ORecur::rTypeValueConvertMap() const
522{
523 QMap<QString, RepeatType> convertMap;
524
525 convertMap.insert( QString( "Daily" ), ORecur::Daily );
526 convertMap.insert( QString( "Weekly" ), ORecur::Weekly );
527 convertMap.insert( QString( "MonthlyDay" ), ORecur::MonthlyDay );
528 convertMap.insert( QString( "MonthlyDate" ), ORecur::MonthlyDate );
529 convertMap.insert( QString( "Yearly" ), ORecur::Yearly );
530 convertMap.insert( QString( "NoRepeat" ), ORecur::NoRepeat );
531
532 return convertMap;
533}
534
535
536QMap<int, QString> ORecur::toMap() const
537{
538 QMap<int, QString> retMap;
539
540 retMap.insert( ORecur::RType, rTypeString() );
541 retMap.insert( ORecur::RWeekdays, QString::number( static_cast<int>( data->days ) ) );
542 retMap.insert( ORecur::RPosition, QString::number(data->pos ) );
543 retMap.insert( ORecur::RFreq, QString::number( data->freq ) );
544 retMap.insert( ORecur::RHasEndDate, QString::number( static_cast<int>( data->hasEnd ) ) );
545 if( data -> hasEnd )
546 retMap.insert( ORecur::EndDate, QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) ) );
547 retMap.insert( ORecur::Created, QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) );
548
549 if ( data->list.isEmpty() ) return retMap;
550
551 // save exceptions list here!!
552 ExceptionList::ConstIterator it;
553 ExceptionList list = data->list;
554 QString exceptBuf;
555 QDate date;
556 for ( it = list.begin(); it != list.end(); ++it ) {
557 date = (*it);
558 if ( it != list.begin() ) exceptBuf += " ";
559
560 exceptBuf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() );
561 }
562
563 retMap.insert( ORecur::Exceptions, exceptBuf );
564
565 return retMap;
566}
567
568void ORecur::fromMap( const QMap<int, QString>& map )
569{
570 QMap<QString, RepeatType> repTypeMap = rTypeValueConvertMap();
571
572 data -> type = repTypeMap[ map [ORecur::RType] ];
573 data -> days = (char) map[ ORecur::RWeekdays ].toInt();
574 data -> pos = map[ ORecur::RPosition ].toInt();
575 data -> freq = map[ ORecur::RFreq ].toInt();
576 data -> hasEnd= map[ ORecur::RHasEndDate ].toInt() ? true : false;
577 OTimeZone utc = OTimeZone::utc();
578 if ( data -> hasEnd ){
579 data -> end = utc.fromUTCDateTime( (time_t) map[ ORecur::EndDate ].toLong() ).date();
580 }
581 data -> create = utc.fromUTCDateTime( (time_t) map[ ORecur::Created ].toLong() ).date();
582
583#if 0
584 // FIXME: Exceptions currently not supported...
585 // Convert the list of exceptions from QString into ExceptionList
586 data -> list.clear();
587 QString exceptStr = map[ ORecur::Exceptions ];
588 QStringList exceptList = QStringList::split( " ", exceptStr );
589 ...
590#endif
591
592
593}
diff --git a/libopie/pim/orecur.h b/libopie/pim/orecur.h
deleted file mode 100644
index d7ecd90..0000000
--- a/libopie/pim/orecur.h
+++ b/dev/null
@@ -1,107 +0,0 @@
1/*
2 * GPL from TT
3 */
4
5#ifndef OPIE_RECUR_H
6#define OPIE_RECUR_H
7
8#include <sys/types.h>
9
10#include <qdatetime.h>
11#include <qvaluelist.h>
12#include <qmap.h>
13
14
15/**
16 * Class to handle Recurrencies..
17 */
18
19class ORecur {
20public:
21 typedef QValueList<QDate> ExceptionList;
22 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay,
23 MonthlyDate, Yearly };
24 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
25 FRI = 0x10, SAT = 0x20, SUN = 0x40 };
26 enum Fields{ RType = 0, RWeekdays, RPosition, RFreq, RHasEndDate,
27 EndDate, Created, Exceptions };
28
29 ORecur();
30 ORecur( const QMap<int, QString>& map );
31 ORecur( const ORecur& );
32 ~ORecur();
33
34 ORecur &operator=( const ORecur& );
35 bool operator==(const ORecur& )const;
36
37 bool doesRecur()const;
38 /* if it recurrs on that day */
39 bool doesRecur( const QDate& );
40 RepeatType type()const;
41 int frequency()const;
42 int position()const;
43 char days()const;
44 bool hasEndDate()const;
45 QDate start()const;
46 QDate endDate()const;
47 QDateTime createdDateTime()const;
48 /**
49 * starting on monday=0, sunday=6
50 * for convience
51 */
52 bool repeatOnWeekDay( int day )const;
53
54 /**
55 * FromWhereToStart is not included!!!
56 */
57 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate );
58
59 /**
60 * The module this ORecur belongs to
61 */
62 QString service()const;
63
64 /*
65 * reference to the exception list
66 */
67 ExceptionList &exceptions();
68
69 /**
70 * the current repetition
71 */
72 int repetition()const;
73
74 void setType( const RepeatType& );
75 void setFrequency( int freq );
76 void setPosition( int pos );
77 void setDays( char c);
78 void setEndDate( const QDate& dt );
79 void setStart( const QDate& dt );
80 void setCreatedDateTime( const QDateTime& );
81 void setHasEndDate( bool b );
82 void setRepitition(int );
83
84 void setService( const QString& ser );
85
86 QMap<int, QString> toMap() const;
87 void fromMap( const QMap<int, QString>& map );
88
89 /* almost internal */
90 QString toString()const;
91private:
92 bool p_nextOccurrence( const QDate& from, QDate& next );
93 void deref();
94 inline void checkOrModify();
95
96 /* Converts rType to String */
97 QString rTypeString() const;
98 /* Returns a map to convert Stringname for RType to RepeatType */
99 QMap<QString, RepeatType> rTypeValueConvertMap() const;
100
101 class Data;
102 Data* data;
103 class ORecurPrivate;
104 ORecurPrivate *d;
105};
106
107#endif
diff --git a/libopie/pim/otemplatebase.h b/libopie/pim/otemplatebase.h
deleted file mode 100644
index cadac74..0000000
--- a/libopie/pim/otemplatebase.h
+++ b/dev/null
@@ -1,98 +0,0 @@
1#ifndef OPIE_TEMPLATE_BASE_H
2#define OPIE_TEMPLATE_BASE_H
3
4#include <qarray.h>
5
6#include <opie/opimrecord.h>
7
8
9/**
10 * Templates do not have a base class, This is why
11 * we've this class
12 * this is here to give us the possibility
13 * to have a common base class
14 * You may not want to use that interface internaly
15 * POOR mans interface
16 */
17class OPimBasePrivate;
18struct OPimBase {
19 /**
20 * return the rtti
21 */
22 virtual int rtti()= 0;
23 virtual OPimRecord* record()const = 0;
24 virtual OPimRecord* record(int uid)const = 0;
25 virtual bool add( const OPimRecord& ) = 0;
26 virtual bool remove( int uid ) = 0;
27 virtual bool remove( const OPimRecord& ) = 0;
28 virtual void clear() = 0;
29 virtual bool load() = 0;
30 virtual bool save() = 0;
31 virtual QArray<int> records()const = 0;
32 /*
33 * ADD editing here?
34 * -zecke
35 */
36private:
37 OPimBasePrivate* d;
38
39};
40/**
41 * internal template base
42 * T needs to implement the copy c'tor!!!
43 */
44class OTemplateBasePrivate;
45template <class T = OPimRecord>
46class OTemplateBase : public OPimBase {
47public:
48 enum CacheDirection { Forward=0, Reverse };
49 OTemplateBase() {
50 };
51 virtual ~OTemplateBase() {
52 }
53 virtual T find( int uid )const = 0;
54
55 /**
56 * read ahead find
57 */
58 virtual T find( int uid, const QArray<int>& items,
59 uint current, CacheDirection dir = Forward )const = 0;
60 virtual void cache( const T& )const = 0;
61 virtual void setSaneCacheSize( int ) = 0;
62
63 /* reimplement of OPimBase */
64 int rtti();
65 OPimRecord* record()const;
66 OPimRecord* record(int uid )const;
67 static T* rec();
68
69private:
70 OTemplateBasePrivate *d;
71};
72
73/*
74 * implementation
75 */
76template <class T>
77int
78OTemplateBase<T>::rtti() {
79 return T::rtti();
80}
81template <class T>
82OPimRecord* OTemplateBase<T>::record()const {
83 T* t = new T;
84 return t;
85}
86template <class T>
87OPimRecord* OTemplateBase<T>::record(int uid )const {
88 T t2 = find(uid );
89 T* t1 = new T(t2);
90
91 return t1;
92};
93template <class T>
94T* OTemplateBase<T>::rec() {
95 return new T;
96}
97
98#endif
diff --git a/libopie/pim/otimezone.cpp b/libopie/pim/otimezone.cpp
deleted file mode 100644
index 34659c3..0000000
--- a/libopie/pim/otimezone.cpp
+++ b/dev/null
@@ -1,113 +0,0 @@
1#include <stdio.h>
2#include <stdlib.h>
3
4#include <sys/types.h>
5
6#include "otimezone.h"
7
8namespace {
9
10 QDateTime utcTime( time_t t) {
11 tm* broken = ::gmtime( &t );
12 QDateTime ret;
13 ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) );
14 ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) );
15 return ret;
16 }
17 QDateTime utcTime( time_t t, const QString& zone) {
18 QCString org = ::getenv( "TZ" );
19#ifndef Q_OS_MACX // Following line causes bus errors on Mac
20 ::setenv( "TZ", zone.latin1(), true );
21 ::tzset();
22
23 tm* broken = ::localtime( &t );
24 ::setenv( "TZ", org, true );
25#else
26#warning "Need a replacement for MacOSX!!"
27 tm* broken = ::localtime( &t );
28#endif
29
30 QDateTime ret;
31 ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) );
32 ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) );
33
34 return ret;
35 }
36 time_t to_Time_t( const QDateTime& utc, const QString& str ) {
37 QDate d = utc.date();
38 QTime t = utc.time();
39
40 tm broken;
41 broken.tm_year = d.year() - 1900;
42 broken.tm_mon = d.month() - 1;
43 broken.tm_mday = d.day();
44 broken.tm_hour = t.hour();
45 broken.tm_min = t.minute();
46 broken.tm_sec = t.second();
47
48 QCString org = ::getenv( "TZ" );
49#ifndef Q_OS_MACX // Following line causes bus errors on Mac
50 ::setenv( "TZ", str.latin1(), true );
51 ::tzset();
52
53 time_t ti = ::mktime( &broken );
54 ::setenv( "TZ", org, true );
55#else
56#warning "Need a replacement for MacOSX!!"
57 time_t ti = ::mktime( &broken );
58#endif
59 return ti;
60 }
61}
62OTimeZone::OTimeZone( const ZoneName& zone )
63 : m_name(zone) {
64}
65OTimeZone::~OTimeZone() {
66}
67
68bool OTimeZone::isValid()const {
69 return !m_name.isEmpty();
70}
71
72/*
73 * we will get the current timezone
74 * and ask it to convert to the timezone date
75 */
76QDateTime OTimeZone::toLocalDateTime( const QDateTime& dt) {
77 return OTimeZone::current().toDateTime( dt, *this );
78}
79QDateTime OTimeZone::toUTCDateTime( const QDateTime& dt ) {
80 return OTimeZone::utc().toDateTime( dt, *this );
81}
82QDateTime OTimeZone::fromUTCDateTime( time_t t) {
83 return utcTime( t );
84}
85QDateTime OTimeZone::toDateTime( time_t t) {
86 return utcTime( t, m_name );
87}
88/*
89 * convert dt to utc using zone.m_name
90 * convert utc -> timeZoneDT using this->m_name
91 */
92QDateTime OTimeZone::toDateTime( const QDateTime& dt, const OTimeZone& zone ) {
93 time_t utc = to_Time_t( dt, zone.m_name );
94 qWarning("%d %s", utc, zone.m_name.latin1() );
95 return utcTime( utc, m_name );
96}
97time_t OTimeZone::fromDateTime( const QDateTime& time ) {
98 return to_Time_t( time, m_name );
99}
100time_t OTimeZone::fromUTCDateTime( const QDateTime& time ) {
101 return to_Time_t( time, "UTC" );
102}
103OTimeZone OTimeZone::current() {
104 QCString str = ::getenv("TZ");
105 OTimeZone zone( str );
106 return zone;
107}
108OTimeZone OTimeZone::utc() {
109 return OTimeZone("UTC");
110}
111QString OTimeZone::timeZone()const {
112 return m_name;
113}
diff --git a/libopie/pim/otimezone.h b/libopie/pim/otimezone.h
deleted file mode 100644
index bb08349..0000000
--- a/libopie/pim/otimezone.h
+++ b/dev/null
@@ -1,71 +0,0 @@
1#ifndef OPIE_TIME_ZONE_H
2#define OPIE_TIME_ZONE_H
3
4#include <time.h>
5#include <qdatetime.h>
6
7/**
8 * A very primitive class to convert time
9 * from one timezone to another
10 * and to localtime
11 * and time_t
12 */
13class OTimeZone {
14 public:
15 typedef QString ZoneName;
16 OTimeZone( const ZoneName& = ZoneName::null );
17 virtual ~OTimeZone(); // just in case.
18
19 bool isValid()const;
20
21 /**
22 * converts the QDateTime to a DateTime
23 * in the local timezone
24 * if QDateTime is 25th Jan and takes place in Europe/Berlin at 12h
25 * and the current timezone is Europe/London the returned
26 * time will be 11h.
27 */
28 QDateTime toLocalDateTime( const QDateTime& dt );
29
30 /**
31 * converts the QDateTime to UTC time
32 */
33 QDateTime toUTCDateTime( const QDateTime& dt );
34
35 /**
36 * reads the time_t into a QDateTime using UTC as timezone!
37 */
38 QDateTime fromUTCDateTime( time_t );
39
40 /**
41 * converts the time_t to the time in the timezone
42 */
43 QDateTime toDateTime( time_t );
44
45 /**
46 * converts the QDateTime from one timezone to this timeZone
47 */
48 QDateTime toDateTime( const QDateTime&, const OTimeZone& timeZone );
49
50 /**
51 * converts the date time into a time_t. It takes the timezone into account
52 */
53 time_t fromDateTime( const QDateTime& );
54
55 /**
56 * converts the datetime with timezone UTC
57 */
58 time_t fromUTCDateTime( const QDateTime& );
59
60 static OTimeZone current();
61 static OTimeZone utc();
62
63 QString timeZone()const;
64 private:
65 ZoneName m_name;
66 class Private;
67 Private* d;
68};
69
70
71#endif
diff --git a/libopie/pim/otodo.cpp b/libopie/pim/otodo.cpp
deleted file mode 100644
index b2c76f8..0000000
--- a/libopie/pim/otodo.cpp
+++ b/dev/null
@@ -1,519 +0,0 @@
1
2#include <qobject.h>
3#include <qshared.h>
4
5
6
7#include <qpe/palmtopuidgen.h>
8#include <qpe/palmtoprecord.h>
9#include <qpe/categories.h>
10#include <qpe/categoryselect.h>
11#include <qpe/stringutil.h>
12
13
14#include "opimstate.h"
15#include "orecur.h"
16#include "opimmaintainer.h"
17#include "opimnotifymanager.h"
18#include "opimresolver.h"
19
20#include "otodo.h"
21
22
23struct OTodo::OTodoData : public QShared {
24 OTodoData() : QShared() {
25 recur = 0;
26 state = 0;
27 maintainer = 0;
28 notifiers = 0;
29 };
30 ~OTodoData() {
31 delete recur;
32 delete maintainer;
33 delete notifiers;
34 }
35
36 QDate date;
37 bool isCompleted:1;
38 bool hasDate:1;
39 int priority;
40 QString desc;
41 QString sum;
42 QMap<QString, QString> extra;
43 ushort prog;
44 OPimState *state;
45 ORecur *recur;
46 OPimMaintainer *maintainer;
47 QDate start;
48 QDate completed;
49 OPimNotifyManager *notifiers;
50};
51
52OTodo::OTodo(const OTodo &event )
53 : OPimRecord( event ), data( event.data )
54{
55 data->ref();
56// qWarning("ref up");
57}
58OTodo::~OTodo() {
59
60// qWarning("~OTodo " );
61 if ( data->deref() ) {
62// qWarning("OTodo::dereffing");
63 delete data;
64 data = 0l;
65 }
66}
67OTodo::OTodo(bool completed, int priority,
68 const QArray<int> &category,
69 const QString& summary,
70 const QString &description,
71 ushort progress,
72 bool hasDate, QDate date, int uid )
73 : OPimRecord( uid )
74{
75// qWarning("OTodoData " + summary);
76 setCategories( category );
77
78 data = new OTodoData;
79
80 data->date = date;
81 data->isCompleted = completed;
82 data->hasDate = hasDate;
83 data->priority = priority;
84 data->sum = summary;
85 data->prog = progress;
86 data->desc = Qtopia::simplifyMultiLineSpace(description );
87}
88OTodo::OTodo(bool completed, int priority,
89 const QStringList &category,
90 const QString& summary,
91 const QString &description,
92 ushort progress,
93 bool hasDate, QDate date, int uid )
94 : OPimRecord( uid )
95{
96// qWarning("OTodoData" + summary);
97 setCategories( idsFromString( category.join(";") ) );
98
99 data = new OTodoData;
100
101 data->date = date;
102 data->isCompleted = completed;
103 data->hasDate = hasDate;
104 data->priority = priority;
105 data->sum = summary;
106 data->prog = progress;
107 data->desc = Qtopia::simplifyMultiLineSpace(description );
108}
109bool OTodo::match( const QRegExp &regExp )const
110{
111 if( QString::number( data->priority ).find( regExp ) != -1 ){
112 setLastHitField( Priority );
113 return true;
114 }else if( data->hasDate && data->date.toString().find( regExp) != -1 ){
115 setLastHitField( HasDate );
116 return true;
117 }else if(data->desc.find( regExp ) != -1 ){
118 setLastHitField( Description );
119 return true;
120 }else if(data->sum.find( regExp ) != -1 ) {
121 setLastHitField( Summary );
122 return true;
123 }
124 return false;
125}
126bool OTodo::isCompleted() const
127{
128 return data->isCompleted;
129}
130bool OTodo::hasDueDate() const
131{
132 return data->hasDate;
133}
134bool OTodo::hasStartDate()const {
135 return data->start.isValid();
136}
137bool OTodo::hasCompletedDate()const {
138 return data->completed.isValid();
139}
140int OTodo::priority()const
141{
142 return data->priority;
143}
144QString OTodo::summary() const
145{
146 return data->sum;
147}
148ushort OTodo::progress() const
149{
150 return data->prog;
151}
152QDate OTodo::dueDate()const
153{
154 return data->date;
155}
156QDate OTodo::startDate()const {
157 return data->start;
158}
159QDate OTodo::completedDate()const {
160 return data->completed;
161}
162QString OTodo::description()const
163{
164 return data->desc;
165}
166bool OTodo::hasState() const{
167 if (!data->state ) return false;
168 return ( data->state->state() != OPimState::Undefined );
169}
170OPimState OTodo::state()const {
171 if (!data->state ) {
172 OPimState state;
173 return state;
174 }
175
176 return (*data->state);
177}
178bool OTodo::hasRecurrence()const {
179 if (!data->recur) return false;
180 return data->recur->doesRecur();
181}
182ORecur OTodo::recurrence()const {
183 if (!data->recur) return ORecur();
184
185 return (*data->recur);
186}
187bool OTodo::hasMaintainer()const {
188 if (!data->maintainer) return false;
189
190 return (data->maintainer->mode() != OPimMaintainer::Undefined );
191}
192OPimMaintainer OTodo::maintainer()const {
193 if (!data->maintainer) return OPimMaintainer();
194
195 return (*data->maintainer);
196}
197void OTodo::setCompleted( bool completed )
198{
199 changeOrModify();
200 data->isCompleted = completed;
201}
202void OTodo::setHasDueDate( bool hasDate )
203{
204 changeOrModify();
205 data->hasDate = hasDate;
206}
207void OTodo::setDescription(const QString &desc )
208{
209// qWarning( "desc " + desc );
210 changeOrModify();
211 data->desc = Qtopia::simplifyMultiLineSpace(desc );
212}
213void OTodo::setSummary( const QString& sum )
214{
215 changeOrModify();
216 data->sum = sum;
217}
218void OTodo::setPriority(int prio )
219{
220 changeOrModify();
221 data->priority = prio;
222}
223void OTodo::setDueDate( const QDate& date )
224{
225 changeOrModify();
226 data->date = date;
227}
228void OTodo::setStartDate( const QDate& date ) {
229 changeOrModify();
230 data->start = date;
231}
232void OTodo::setCompletedDate( const QDate& date ) {
233 changeOrModify();
234 data->completed = date;
235}
236void OTodo::setState( const OPimState& state ) {
237 changeOrModify();
238 if (data->state )
239 (*data->state) = state;
240 else
241 data->state = new OPimState( state );
242}
243void OTodo::setRecurrence( const ORecur& rec) {
244 changeOrModify();
245 if (data->recur )
246 (*data->recur) = rec;
247 else
248 data->recur = new ORecur( rec );
249}
250void OTodo::setMaintainer( const OPimMaintainer& pim ) {
251 changeOrModify();
252
253 if (data->maintainer )
254 (*data->maintainer) = pim;
255 else
256 data->maintainer = new OPimMaintainer( pim );
257}
258bool OTodo::isOverdue( )
259{
260 if( data->hasDate && !data->isCompleted)
261 return QDate::currentDate() > data->date;
262 return false;
263}
264void OTodo::setProgress(ushort progress )
265{
266 changeOrModify();
267 data->prog = progress;
268}
269QString OTodo::toShortText() const {
270 return summary();
271}
272/*!
273 Returns a richt text string
274*/
275QString OTodo::toRichText() const
276{
277 QString text;
278 QStringList catlist;
279
280 // summary
281 text += "<b><h3><img src=\"todo/TodoList\"> ";
282 if ( !summary().isEmpty() ) {
283 text += Qtopia::escapeString(summary() ).replace(QRegExp( "[\n]"), "" );
284 }
285 text += "</h3></b><br><hr><br>";
286
287 // description
288 if( !description().isEmpty() ){
289 text += "<b>" + QObject::tr( "Description:" ) + "</b><br>";
290 text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
291 }
292
293 // priority
294 int priorityval = priority();
295 text += "<b>" + QObject::tr( "Priority:") +" </b><img src=\"todo/priority" +
296 QString::number( priorityval ) + "\"> ";
297
298 switch ( priorityval )
299 {
300 case 1 : text += QObject::tr( "Very high" );
301 break;
302 case 2 : text += QObject::tr( "High" );
303 break;
304 case 3 : text += QObject::tr( "Normal" );
305 break;
306 case 4 : text += QObject::tr( "Low" );
307 break;
308 case 5 : text += QObject::tr( "Very low" );
309 break;
310 };
311 text += "<br>";
312
313 // progress
314 text += "<b>" + QObject::tr( "Progress:") + " </b>"
315 + QString::number( progress() ) + " %<br>";
316
317 // due date
318 if (hasDueDate() ){
319 QDate dd = dueDate();
320 int off = QDate::currentDate().daysTo( dd );
321
322 text += "<b>" + QObject::tr( "Deadline:" ) + " </b><font color=\"";
323 if ( off < 0 )
324 text += "#FF0000";
325 else if ( off == 0 )
326 text += "#FFFF00";
327 else if ( off > 0 )
328 text += "#00FF00";
329
330 text += "\">" + dd.toString() + "</font><br>";
331 }
332
333 // categories
334 text += "<b>" + QObject::tr( "Category:") + "</b> ";
335 text += categoryNames( "Todo List" ).join(", ");
336 text += "<br>";
337
338 return text;
339}
340bool OTodo::hasNotifiers()const {
341 if (!data->notifiers) return false;
342 return !data->notifiers->isEmpty();
343}
344OPimNotifyManager& OTodo::notifiers() {
345 if (!data->notifiers )
346 data->notifiers = new OPimNotifyManager;
347 return (*data->notifiers);
348}
349const OPimNotifyManager& OTodo::notifiers()const{
350 if (!data->notifiers )
351 data->notifiers = new OPimNotifyManager;
352
353 return (*data->notifiers);
354}
355
356bool OTodo::operator<( const OTodo &toDoEvent )const{
357 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
358 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
359 if( hasDueDate() && toDoEvent.hasDueDate() ){
360 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
361 return priority() < toDoEvent.priority();
362 }else{
363 return dueDate() < toDoEvent.dueDate();
364 }
365 }
366 return false;
367}
368bool OTodo::operator<=(const OTodo &toDoEvent )const
369{
370 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
371 if( !hasDueDate() && toDoEvent.hasDueDate() ) return true;
372 if( hasDueDate() && toDoEvent.hasDueDate() ){
373 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
374 return priority() <= toDoEvent.priority();
375 }else{
376 return dueDate() <= toDoEvent.dueDate();
377 }
378 }
379 return true;
380}
381bool OTodo::operator>(const OTodo &toDoEvent )const
382{
383 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return false;
384 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
385 if( hasDueDate() && toDoEvent.hasDueDate() ){
386 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
387 return priority() > toDoEvent.priority();
388 }else{
389 return dueDate() > toDoEvent.dueDate();
390 }
391 }
392 return false;
393}
394bool OTodo::operator>=(const OTodo &toDoEvent )const
395{
396 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
397 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
398 if( hasDueDate() && toDoEvent.hasDueDate() ){
399 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
400 return priority() > toDoEvent.priority();
401 }else{
402 return dueDate() > toDoEvent.dueDate();
403 }
404 }
405 return true;
406}
407bool OTodo::operator==(const OTodo &toDoEvent )const
408{
409 if ( data->priority != toDoEvent.data->priority ) return false;
410 if ( data->priority != toDoEvent.data->prog ) return false;
411 if ( data->isCompleted != toDoEvent.data->isCompleted ) return false;
412 if ( data->hasDate != toDoEvent.data->hasDate ) return false;
413 if ( data->date != toDoEvent.data->date ) return false;
414 if ( data->sum != toDoEvent.data->sum ) return false;
415 if ( data->desc != toDoEvent.data->desc ) return false;
416 if ( data->maintainer != toDoEvent.data->maintainer )
417 return false;
418
419 return OPimRecord::operator==( toDoEvent );
420}
421void OTodo::deref() {
422
423// qWarning("deref in ToDoEvent");
424 if ( data->deref() ) {
425// qWarning("deleting");
426 delete data;
427 data= 0;
428 }
429}
430OTodo &OTodo::operator=(const OTodo &item )
431{
432 if ( this == &item ) return *this;
433
434 OPimRecord::operator=( item );
435 //qWarning("operator= ref ");
436 item.data->ref();
437 deref();
438 data = item.data;
439
440 return *this;
441}
442
443QMap<int, QString> OTodo::toMap() const {
444 QMap<int, QString> map;
445
446 map.insert( Uid, QString::number( uid() ) );
447 map.insert( Category, idsToString( categories() ) );
448 map.insert( HasDate, QString::number( data->hasDate ) );
449 map.insert( Completed, QString::number( data->isCompleted ) );
450 map.insert( Description, data->desc );
451 map.insert( Summary, data->sum );
452 map.insert( Priority, QString::number( data->priority ) );
453 map.insert( DateDay, QString::number( data->date.day() ) );
454 map.insert( DateMonth, QString::number( data->date.month() ) );
455 map.insert( DateYear, QString::number( data->date.year() ) );
456 map.insert( Progress, QString::number( data->prog ) );
457// map.insert( CrossReference, crossToString() );
458 /* FIXME!!! map.insert( State, );
459 map.insert( Recurrence, );
460 map.insert( Reminders, );
461 map.
462 */
463 return map;
464}
465
466/**
467 * change or modify looks at the ref count and either
468 * creates a new QShared Object or it can modify it
469 * right in place
470 */
471void OTodo::changeOrModify() {
472 if ( data->count != 1 ) {
473 qWarning("changeOrModify");
474 data->deref();
475 OTodoData* d2 = new OTodoData();
476 copy(data, d2 );
477 data = d2;
478 }
479}
480// WATCHOUT
481/*
482 * if you add something to the Data struct
483 * be sure to copy it here
484 */
485void OTodo::copy( OTodoData* src, OTodoData* dest ) {
486 dest->date = src->date;
487 dest->isCompleted = src->isCompleted;
488 dest->hasDate = src->hasDate;
489 dest->priority = src->priority;
490 dest->desc = src->desc;
491 dest->sum = src->sum;
492 dest->extra = src->extra;
493 dest->prog = src->prog;
494
495 if (src->state )
496 dest->state = new OPimState( *src->state );
497
498 if (src->recur )
499 dest->recur = new ORecur( *src->recur );
500
501 if (src->maintainer )
502 dest->maintainer = new OPimMaintainer( *src->maintainer )
503 ;
504 dest->start = src->start;
505 dest->completed = src->completed;
506
507 if (src->notifiers )
508 dest->notifiers = new OPimNotifyManager( *src->notifiers );
509}
510QString OTodo::type() const {
511 return QString::fromLatin1("OTodo");
512}
513QString OTodo::recordField(int /*id*/ )const {
514 return QString::null;
515}
516
517int OTodo::rtti(){
518 return OPimResolver::TodoList;
519}
diff --git a/libopie/pim/otodo.h b/libopie/pim/otodo.h
deleted file mode 100644
index 6df98b9..0000000
--- a/libopie/pim/otodo.h
+++ b/dev/null
@@ -1,285 +0,0 @@
1
2#ifndef OPIE_TODO_EVENT_H
3#define OPIE_TODO_EVENT_H
4
5
6#include <qarray.h>
7#include <qmap.h>
8#include <qregexp.h>
9#include <qstringlist.h>
10#include <qdatetime.h>
11#include <qvaluelist.h>
12
13#include <qpe/recordfields.h>
14#include <qpe/palmtopuidgen.h>
15
16#include <opie/opimrecord.h>
17
18
19class OPimState;
20class ORecur;
21class OPimMaintainer;
22class OPimNotifyManager;
23class OTodo : public OPimRecord {
24public:
25 typedef QValueList<OTodo> ValueList;
26 enum RecordFields {
27 Uid = Qtopia::UID_ID,
28 Category = Qtopia::CATEGORY_ID,
29 HasDate,
30 Completed,
31 Description,
32 Summary,
33 Priority,
34 DateDay,
35 DateMonth,
36 DateYear,
37 Progress,
38 CrossReference,
39 State,
40 Recurrence,
41 Alarms,
42 Reminders,
43 Notifiers,
44 Maintainer,
45 StartDate,
46 CompletedDate
47 };
48 public:
49 // priorities from Very low to very high
50 enum TaskPriority { VeryHigh=1, High, Normal, Low, VeryLow };
51
52 /* Constructs a new ToDoEvent
53 @param completed Is the TodoEvent completed
54 @param priority What is the priority of this ToDoEvent
55 @param category Which category does it belong( uid )
56 @param summary A small summary of the todo
57 @param description What is this ToDoEvent about
58 @param hasDate Does this Event got a deadline
59 @param date what is the deadline?
60 @param uid what is the UUID of this Event
61 **/
62 OTodo( bool completed = false, int priority = Normal,
63 const QStringList &category = QStringList(),
64 const QString &summary = QString::null ,
65 const QString &description = QString::null,
66 ushort progress = 0,
67 bool hasDate = false, QDate date = QDate::currentDate(),
68 int uid = 0 /*empty*/ );
69
70 OTodo( bool completed, int priority,
71 const QArray<int>& category,
72 const QString& summary = QString::null,
73 const QString& description = QString::null,
74 ushort progress = 0,
75 bool hasDate = false, QDate date = QDate::currentDate(),
76 int uid = 0 /* empty */ );
77
78 /** Copy c'tor
79 *
80 */
81 OTodo(const OTodo & );
82
83 /**
84 *destructor
85 */
86 ~OTodo();
87
88 /**
89 * Is this event completed?
90 */
91 bool isCompleted() const;
92
93 /**
94 * Does this Event have a deadline
95 */
96 bool hasDueDate() const;
97 bool hasStartDate()const;
98 bool hasCompletedDate()const;
99
100 /**
101 * What is the priority?
102 */
103 int priority()const ;
104
105 /**
106 * progress as ushort 0, 20, 40, 60, 80 or 100%
107 */
108 ushort progress() const;
109
110 /**
111 * The due Date
112 */
113 QDate dueDate()const;
114
115 /**
116 * When did it start?
117 */
118 QDate startDate()const;
119
120 /**
121 * When was it completed?
122 */
123 QDate completedDate()const;
124
125 /**
126 * does it have a state?
127 */
128 bool hasState()const;
129
130 /**
131 * What is the state of this OTodo?
132 */
133 OPimState state()const;
134
135 /**
136 * has recurrence?
137 */
138 bool hasRecurrence()const;
139
140 /**
141 * the recurrance of this
142 */
143 ORecur recurrence()const;
144
145 /**
146 * does this OTodo have a maintainer?
147 */
148 bool hasMaintainer()const;
149
150 /**
151 * the Maintainer of this OTodo
152 */
153 OPimMaintainer maintainer()const;
154
155 /**
156 * The description of the todo
157 */
158 QString description()const;
159
160 /**
161 * A small summary of the todo
162 */
163 QString summary() const;
164
165 /**
166 * @reimplemented
167 * Return this todoevent in a RichText formatted QString
168 */
169 QString toRichText() const;
170
171 bool hasNotifiers()const;
172 /*
173 * FIXME check if the sharing is still fine!! -zecke
174 * ### CHECK If API is fine
175 */
176 /**
177 * return a reference to our notifiers...
178 */
179 OPimNotifyManager &notifiers();
180
181 /**
182 *
183 */
184 const OPimNotifyManager &notifiers()const;
185
186 /**
187 * reimplementations
188 */
189 QString type()const;
190 QString toShortText()const;
191 QString recordField(int id )const;
192
193 /**
194 * toMap puts all data into the map. int relates
195 * to ToDoEvent RecordFields enum
196 */
197 QMap<int, QString> toMap()const;
198
199 /**
200 * Set if this Todo is completed
201 */
202 void setCompleted(bool completed );
203
204 /**
205 * set if this todo got an end data
206 */
207 void setHasDueDate( bool hasDate );
208 // FIXME we do not have these for start, completed
209 // cause we'll use the isNull() of QDate for figuring
210 // out if it's has a date...
211 // decide what to do here? -zecke
212
213 /**
214 * Set the priority of the Todo
215 */
216 void setPriority(int priority );
217
218 /**
219 * Set the progress.
220 */
221 void setProgress( ushort progress );
222
223 /**
224 * set the end date
225 */
226 void setDueDate( const QDate& date );
227
228 /**
229 * set the start date
230 */
231 void setStartDate( const QDate& date );
232
233 /**
234 * set the completed date
235 */
236 void setCompletedDate( const QDate& date );
237
238 void setRecurrence( const ORecur& );
239
240 void setDescription(const QString& );
241 void setSummary(const QString& );
242
243 /**
244 * set the state of a Todo
245 * @param state State what the todo should take
246 */
247 void setState( const OPimState& state);
248
249 /**
250 * set the Maintainer Mode
251 */
252 void setMaintainer( const OPimMaintainer& );
253
254 bool isOverdue();
255
256
257 virtual bool match( const QRegExp &r )const;
258
259 bool operator<(const OTodo &toDoEvent )const;
260 bool operator<=(const OTodo &toDoEvent )const;
261 bool operator!=(const OTodo &toDoEvent )const;
262 bool operator>(const OTodo &toDoEvent )const;
263 bool operator>=(const OTodo &toDoEvent)const;
264 bool operator==(const OTodo &toDoEvent )const;
265 OTodo &operator=(const OTodo &toDoEvent );
266
267 static int rtti();
268
269 private:
270 class OTodoPrivate;
271 struct OTodoData;
272
273 void deref();
274 inline void changeOrModify();
275 void copy( OTodoData* src, OTodoData* dest );
276 OTodoPrivate *d;
277 OTodoData *data;
278
279};
280inline bool OTodo::operator!=(const OTodo &toDoEvent )const {
281 return !(*this == toDoEvent);
282}
283
284
285#endif
diff --git a/libopie/pim/otodoaccess.cpp b/libopie/pim/otodoaccess.cpp
deleted file mode 100644
index 37f6fbc..0000000
--- a/libopie/pim/otodoaccess.cpp
+++ b/dev/null
@@ -1,62 +0,0 @@
1#include <qdatetime.h>
2
3#include <qpe/alarmserver.h>
4
5// #include "otodoaccesssql.h"
6#include "otodoaccess.h"
7#include "obackendfactory.h"
8
9OTodoAccess::OTodoAccess( OTodoAccessBackend* end, enum Access )
10 : QObject(), OPimAccessTemplate<OTodo>( end ), m_todoBackEnd( end )
11{
12// if (end == 0l )
13// m_todoBackEnd = new OTodoAccessBackendSQL( QString::null);
14
15 // Zecke: Du musst hier noch für das XML-Backend einen Appnamen übergeben !
16 if (end == 0l )
17 m_todoBackEnd = OBackendFactory<OTodoAccessBackend>::Default ("todo", QString::null);
18
19 setBackEnd( m_todoBackEnd );
20}
21OTodoAccess::~OTodoAccess() {
22// qWarning("~OTodoAccess");
23}
24void OTodoAccess::mergeWith( const QValueList<OTodo>& list ) {
25 QValueList<OTodo>::ConstIterator it;
26 for ( it = list.begin(); it != list.end(); ++it ) {
27 replace( (*it) );
28 }
29}
30OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start,
31 const QDate& end,
32 bool includeNoDates ) {
33 QArray<int> ints = m_todoBackEnd->effectiveToDos( start, end, includeNoDates );
34
35 List lis( ints, this );
36 return lis;
37}
38OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start,
39 bool includeNoDates ) {
40 return effectiveToDos( start, QDate::currentDate(),
41 includeNoDates );
42}
43OTodoAccess::List OTodoAccess::overDue() {
44 List lis( m_todoBackEnd->overDue(), this );
45 return lis;
46}
47/* sort order */
48OTodoAccess::List OTodoAccess::sorted( bool ascending, int sort,int filter, int cat ) {
49 QArray<int> ints = m_todoBackEnd->sorted( ascending, sort,
50 filter, cat );
51 OTodoAccess::List list( ints, this );
52 return list;
53}
54void OTodoAccess::removeAllCompleted() {
55 m_todoBackEnd->removeAllCompleted();
56}
57QBitArray OTodoAccess::backendSupport( const QString& ) const{
58 return m_todoBackEnd->supports();
59}
60bool OTodoAccess::backendSupports( int attr, const QString& ar) const{
61 return backendSupport(ar).testBit( attr );
62}
diff --git a/libopie/pim/otodoaccess.h b/libopie/pim/otodoaccess.h
deleted file mode 100644
index 916923f..0000000
--- a/libopie/pim/otodoaccess.h
+++ b/dev/null
@@ -1,105 +0,0 @@
1#ifndef OPIE_TODO_ACCESS_H
2#define OPIE_TODO_ACCESS_H
3
4#include <qobject.h>
5#include <qvaluelist.h>
6
7#include "otodo.h"
8#include "otodoaccessbackend.h"
9#include "opimaccesstemplate.h"
10
11
12/**
13 * OTodoAccess
14 * the class to get access to
15 * the todolist
16 */
17class OTodoAccess : public QObject, public OPimAccessTemplate<OTodo> {
18 Q_OBJECT
19public:
20 enum SortOrder { Completed = 0,
21 Priority,
22 Description,
23 Deadline };
24 enum SortFilter{ Category =1,
25 OnlyOverDue= 2,
26 DoNotShowCompleted =4 };
27 /**
28 * if you use 0l
29 * the default resource will be
30 * picked up
31 */
32 OTodoAccess( OTodoAccessBackend* = 0l, enum Access acc = Random );
33 ~OTodoAccess();
34
35
36 /* our functions here */
37 /**
38 * include todos from start to end
39 * includeNoDates whether or not to include
40 * events with no dates
41 */
42 List effectiveToDos( const QDate& start,
43 const QDate& end,
44 bool includeNoDates = true );
45
46 /**
47 * start
48 * end date taken from the currentDate()
49 */
50 List effectiveToDos( const QDate& start,
51 bool includeNoDates = true );
52
53
54 /**
55 * return overdue OTodos
56 */
57 List overDue();
58
59 /**
60 *
61 */
62 List sorted( bool ascending, int sortOrder, int sortFilter, int cat );
63
64 /**
65 * merge a list of OTodos into
66 * the resource
67 */
68 void mergeWith( const QValueList<OTodo>& );
69
70 /**
71 * delete all already completed items
72 */
73 void removeAllCompleted();
74
75 /**
76 * request information about what a backend supports.
77 * Supports in the sense of beeing able to store.
78 * This is related to the enum in OTodo
79 *
80 * @param backend Will be used in the future when we support multiple backend
81 */
82 QBitArray backendSupport( const QString& backend = QString::null )const;
83
84 /**
85 * see above but for a specefic attribute. This method was added for convience
86 * @param attr The attribute to be queried for
87 * @param backend Will be used in the future when we support multiple backends
88 */
89 bool backendSupports( int attr, const QString& backend = QString::null )const;
90signals:
91 /**
92 * if the OTodoAccess was changed
93 */
94 void changed( const OTodoAccess* );
95 void changed( const OTodoAccess*, int uid );
96 void added( const OTodoAccess*, int uid );
97 void removed( const OTodoAccess*, int uid );
98private:
99 int m_cat;
100 OTodoAccessBackend* m_todoBackEnd;
101 class OTodoAccessPrivate;
102 OTodoAccessPrivate* d;
103};
104
105#endif
diff --git a/libopie/pim/otodoaccessbackend.cpp b/libopie/pim/otodoaccessbackend.cpp
deleted file mode 100644
index baaeecc..0000000
--- a/libopie/pim/otodoaccessbackend.cpp
+++ b/dev/null
@@ -1,10 +0,0 @@
1
2#include "otodoaccessbackend.h"
3
4OTodoAccessBackend::OTodoAccessBackend()
5 : OPimAccessBackend<OTodo>()
6{
7}
8OTodoAccessBackend::~OTodoAccessBackend() {
9
10}
diff --git a/libopie/pim/otodoaccessbackend.h b/libopie/pim/otodoaccessbackend.h
deleted file mode 100644
index 6be95bc..0000000
--- a/libopie/pim/otodoaccessbackend.h
+++ b/dev/null
@@ -1,28 +0,0 @@
1#ifndef OPIE_TODO_ACCESS_BACKEND_H
2#define OPIE_TODO_ACCESS_BACKEND_H
3
4#include <qbitarray.h>
5
6#include "otodo.h"
7#include "opimaccessbackend.h"
8
9class OTodoAccessBackend : public OPimAccessBackend<OTodo> {
10public:
11 OTodoAccessBackend();
12 ~OTodoAccessBackend();
13 virtual QArray<int> effectiveToDos( const QDate& start,
14 const QDate& end,
15 bool includeNoDates ) = 0;
16 virtual QArray<int> overDue() = 0;
17 virtual QArray<int> sorted( bool asc, int sortOrder, int sortFilter,
18 int cat ) = 0;
19 virtual void removeAllCompleted() = 0;
20 virtual QBitArray supports()const = 0;
21
22private:
23 class Private;
24 Private *d;
25
26};
27
28#endif
diff --git a/libopie/pim/otodoaccesssql.cpp b/libopie/pim/otodoaccesssql.cpp
deleted file mode 100644
index fd01a42..0000000
--- a/libopie/pim/otodoaccesssql.cpp
+++ b/dev/null
@@ -1,694 +0,0 @@
1
2#include <qdatetime.h>
3
4#include <qpe/global.h>
5
6#include <opie2/osqldriver.h>
7#include <opie2/osqlresult.h>
8#include <opie2/osqlmanager.h>
9#include <opie2/osqlquery.h>
10
11#include "otodoaccesssql.h"
12#include "opimstate.h"
13#include "opimnotifymanager.h"
14#include "orecur.h"
15
16using namespace Opie::DB;
17/*
18 * first some query
19 * CREATE query
20 * LOAD query
21 * INSERT
22 * REMOVE
23 * CLEAR
24 */
25namespace {
26 /**
27 * CreateQuery for the Todolist Table
28 */
29 class CreateQuery : public OSQLQuery {
30 public:
31 CreateQuery();
32 ~CreateQuery();
33 QString query()const;
34 };
35
36 /**
37 * LoadQuery
38 * this one queries for all uids
39 */
40 class LoadQuery : public OSQLQuery {
41 public:
42 LoadQuery();
43 ~LoadQuery();
44 QString query()const;
45 };
46
47 /**
48 * inserts/adds a OTodo to the table
49 */
50 class InsertQuery : public OSQLQuery {
51 public:
52 InsertQuery(const OTodo& );
53 ~InsertQuery();
54 QString query()const;
55 private:
56 OTodo m_todo;
57 };
58
59 /**
60 * removes one from the table
61 */
62 class RemoveQuery : public OSQLQuery {
63 public:
64 RemoveQuery(int uid );
65 ~RemoveQuery();
66 QString query()const;
67 private:
68 int m_uid;
69 };
70
71 /**
72 * Clears (delete) a Table
73 */
74 class ClearQuery : public OSQLQuery {
75 public:
76 ClearQuery();
77 ~ClearQuery();
78 QString query()const;
79
80 };
81
82 /**
83 * a find query
84 */
85 class FindQuery : public OSQLQuery {
86 public:
87 FindQuery(int uid);
88 FindQuery(const QArray<int>& );
89 ~FindQuery();
90 QString query()const;
91 private:
92 QString single()const;
93 QString multi()const;
94 QArray<int> m_uids;
95 int m_uid;
96 };
97
98 /**
99 * overdue query
100 */
101 class OverDueQuery : public OSQLQuery {
102 public:
103 OverDueQuery();
104 ~OverDueQuery();
105 QString query()const;
106 };
107 class EffQuery : public OSQLQuery {
108 public:
109 EffQuery( const QDate&, const QDate&, bool inc );
110 ~EffQuery();
111 QString query()const;
112 private:
113 QString with()const;
114 QString out()const;
115 QDate m_start;
116 QDate m_end;
117 bool m_inc :1;
118 };
119
120
121 CreateQuery::CreateQuery() : OSQLQuery() {}
122 CreateQuery::~CreateQuery() {}
123 QString CreateQuery::query()const {
124 QString qu;
125 qu += "create table todolist( uid PRIMARY KEY, categories, completed, ";
126 qu += "description, summary, priority, DueDate, progress , state, ";
127 // This is the recurrance-stuff .. Exceptions are currently not supported (see ORecur.cpp) ! (eilers)
128 qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, ";
129 qu += "reminders, alarms, maintainer, startdate, completeddate);";
130 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
131 return qu;
132 }
133
134 LoadQuery::LoadQuery() : OSQLQuery() {}
135 LoadQuery::~LoadQuery() {}
136 QString LoadQuery::query()const {
137 QString qu;
138 // We do not need "distinct" here. The primary key is always unique..
139 //qu += "select distinct uid from todolist";
140 qu += "select uid from todolist";
141
142 return qu;
143 }
144
145 InsertQuery::InsertQuery( const OTodo& todo )
146 : OSQLQuery(), m_todo( todo ) {
147 }
148 InsertQuery::~InsertQuery() {
149 }
150 /*
151 * converts from a OTodo to a query
152 * we leave out X-Ref + Alarms
153 */
154 QString InsertQuery::query()const{
155
156 int year, month, day;
157 year = month = day = 0;
158 if (m_todo.hasDueDate() ) {
159 QDate date = m_todo.dueDate();
160 year = date.year();
161 month = date.month();
162 day = date.day();
163 }
164 int sYear = 0, sMonth = 0, sDay = 0;
165 if( m_todo.hasStartDate() ){
166 QDate sDate = m_todo.startDate();
167 sYear = sDate.year();
168 sMonth= sDate.month();
169 sDay = sDate.day();
170 }
171
172 int eYear = 0, eMonth = 0, eDay = 0;
173 if( m_todo.hasCompletedDate() ){
174 QDate eDate = m_todo.completedDate();
175 eYear = eDate.year();
176 eMonth= eDate.month();
177 eDay = eDate.day();
178 }
179 QString qu;
180 QMap<int, QString> recMap = m_todo.recurrence().toMap();
181 qu = "insert into todolist VALUES("
182 + QString::number( m_todo.uid() ) + ","
183 + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + ","
184 + QString::number( m_todo.isCompleted() ) + ","
185 + "'" + m_todo.description() + "'" + ","
186 + "'" + m_todo.summary() + "'" + ","
187 + QString::number(m_todo.priority() ) + ","
188 + "'" + QString::number(year) + "-"
189 + QString::number(month)
190 + "-" + QString::number( day ) + "'" + ","
191 + QString::number( m_todo.progress() ) + ","
192 + QString::number( m_todo.state().state() ) + ","
193 + "'" + recMap[ ORecur::RType ] + "'" + ","
194 + "'" + recMap[ ORecur::RWeekdays ] + "'" + ","
195 + "'" + recMap[ ORecur::RPosition ] + "'" + ","
196 + "'" + recMap[ ORecur::RFreq ] + "'" + ","
197 + "'" + recMap[ ORecur::RHasEndDate ] + "'" + ","
198 + "'" + recMap[ ORecur::EndDate ] + "'" + ","
199 + "'" + recMap[ ORecur::Created ] + "'" + ","
200 + "'" + recMap[ ORecur::Exceptions ] + "'" + ",";
201
202 if ( m_todo.hasNotifiers() ) {
203 OPimNotifyManager manager = m_todo.notifiers();
204 qu += "'" + manager.remindersToString() + "'" + ","
205 + "'" + manager.alarmsToString() + "'" + ",";
206 }
207 else{
208 qu += QString( "''" ) + ","
209 + "''" + ",";
210 }
211
212 qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !)
213 + "'" + QString::number(sYear) + "-"
214 + QString::number(sMonth)
215 + "-" + QString::number(sDay) + "'" + ","
216 + "'" + QString::number(eYear) + "-"
217 + QString::number(eMonth)
218 + "-"+QString::number(eDay) + "'"
219 + ")";
220
221 qWarning("add %s", qu.latin1() );
222 return qu;
223 }
224
225 RemoveQuery::RemoveQuery(int uid )
226 : OSQLQuery(), m_uid( uid ) {}
227 RemoveQuery::~RemoveQuery() {}
228 QString RemoveQuery::query()const {
229 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
230 return qu;
231 }
232
233
234 ClearQuery::ClearQuery()
235 : OSQLQuery() {}
236 ClearQuery::~ClearQuery() {}
237 QString ClearQuery::query()const {
238 QString qu = "drop table todolist";
239 return qu;
240 }
241 FindQuery::FindQuery(int uid)
242 : OSQLQuery(), m_uid(uid ) {
243 }
244 FindQuery::FindQuery(const QArray<int>& ints)
245 : OSQLQuery(), m_uids(ints){
246 }
247 FindQuery::~FindQuery() {
248 }
249 QString FindQuery::query()const{
250 if (m_uids.count() == 0 )
251 return single();
252 else
253 return multi();
254 }
255 QString FindQuery::single()const{
256 QString qu = "select * from todolist where uid = " + QString::number(m_uid);
257 return qu;
258 }
259 QString FindQuery::multi()const {
260 QString qu = "select * from todolist where ";
261 for (uint i = 0; i < m_uids.count(); i++ ) {
262 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
263 }
264 qu.remove( qu.length()-2, 2 );
265 return qu;
266 }
267
268 OverDueQuery::OverDueQuery(): OSQLQuery() {}
269 OverDueQuery::~OverDueQuery() {}
270 QString OverDueQuery::query()const {
271 QDate date = QDate::currentDate();
272 QString str;
273 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
274
275 return str;
276 }
277
278
279 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
280 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
281 EffQuery::~EffQuery() {}
282 QString EffQuery::query()const {
283 return m_inc ? with() : out();
284 }
285 QString EffQuery::with()const {
286 QString str;
287 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
288 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
289 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
290 return str;
291 }
292 QString EffQuery::out()const {
293 QString str;
294 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
295 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
296 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
297
298 return str;
299 }
300};
301
302OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
303 : OTodoAccessBackend(), m_dict(15), m_driver(NULL), m_dirty(true)
304{
305 QString fi = file;
306 if ( fi.isEmpty() )
307 fi = Global::applicationFileName( "todolist", "todolist.db" );
308 OSQLManager man;
309 m_driver = man.standard();
310 m_driver->setUrl(fi);
311 // fillDict();
312}
313
314OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
315 if( m_driver )
316 delete m_driver;
317}
318
319bool OTodoAccessBackendSQL::load(){
320 if (!m_driver->open() )
321 return false;
322
323 CreateQuery creat;
324 OSQLResult res = m_driver->query(&creat );
325
326 m_dirty = true;
327 return true;
328}
329bool OTodoAccessBackendSQL::reload(){
330 return load();
331}
332
333bool OTodoAccessBackendSQL::save(){
334 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
335}
336QArray<int> OTodoAccessBackendSQL::allRecords()const {
337 if (m_dirty )
338 update();
339
340 return m_uids;
341}
342QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
343 QArray<int> ints(0);
344 return ints;
345}
346OTodo OTodoAccessBackendSQL::find(int uid ) const{
347 FindQuery query( uid );
348 return todo( m_driver->query(&query) );
349
350}
351OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
352 uint cur, Frontend::CacheDirection dir ) const{
353 uint CACHE = readAhead();
354 qWarning("searching for %d", uid );
355 QArray<int> search( CACHE );
356 uint size =0;
357 OTodo to;
358
359 // we try to cache CACHE items
360 switch( dir ) {
361 /* forward */
362 case 0: // FIXME: Not a good style to use magic numbers here (eilers)
363 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
364 qWarning("size %d %d", size, ints[i] );
365 search[size] = ints[i];
366 size++;
367 }
368 break;
369 /* reverse */
370 case 1: // FIXME: Not a good style to use magic numbers here (eilers)
371 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
372 search[size] = ints[i];
373 size++;
374 }
375 break;
376 }
377 search.resize( size );
378 FindQuery query( search );
379 OSQLResult res = m_driver->query( &query );
380 if ( res.state() != OSQLResult::Success )
381 return to;
382
383 return todo( res );
384}
385void OTodoAccessBackendSQL::clear() {
386 ClearQuery cle;
387 OSQLResult res = m_driver->query( &cle );
388 CreateQuery qu;
389 res = m_driver->query(&qu);
390}
391bool OTodoAccessBackendSQL::add( const OTodo& t) {
392 InsertQuery ins( t );
393 OSQLResult res = m_driver->query( &ins );
394
395 if ( res.state() == OSQLResult::Failure )
396 return false;
397 int c = m_uids.count();
398 m_uids.resize( c+1 );
399 m_uids[c] = t.uid();
400
401 return true;
402}
403bool OTodoAccessBackendSQL::remove( int uid ) {
404 RemoveQuery rem( uid );
405 OSQLResult res = m_driver->query(&rem );
406
407 if ( res.state() == OSQLResult::Failure )
408 return false;
409
410 m_dirty = true;
411 return true;
412}
413/*
414 * FIXME better set query
415 * but we need the cache for that
416 * now we remove
417 */
418bool OTodoAccessBackendSQL::replace( const OTodo& t) {
419 remove( t.uid() );
420 bool b= add(t);
421 m_dirty = false; // we changed some stuff but the UID stayed the same
422 return b;
423}
424QArray<int> OTodoAccessBackendSQL::overDue() {
425 OverDueQuery qu;
426 return uids( m_driver->query(&qu ) );
427}
428QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s,
429 const QDate& t,
430 bool u) {
431 EffQuery ef(s, t, u );
432 return uids (m_driver->query(&ef) );
433}
434/*
435 *
436 */
437QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
438 int sortFilter, int cat ) {
439 qWarning("sorted %d, %d", asc, sortOrder );
440 QString query;
441 query = "select uid from todolist WHERE ";
442
443 /*
444 * Sort Filter stuff
445 * not that straight forward
446 * FIXME: Replace magic numbers
447 *
448 */
449 /* Category */
450 if ( sortFilter & 1 ) {
451 QString str;
452 if (cat != 0 ) str = QString::number( cat );
453 query += " categories like '%" +str+"%' AND";
454 }
455 /* Show only overdue */
456 if ( sortFilter & 2 ) {
457 QDate date = QDate::currentDate();
458 QString due;
459 QString base;
460 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() );
461 query += " " + base + " AND";
462 }
463 /* not show completed */
464 if ( sortFilter & 4 ) {
465 query += " completed = 0 AND";
466 }else{
467 query += " ( completed = 1 OR completed = 0) AND";
468 }
469 /* srtip the end */
470 query = query.remove( query.length()-3, 3 );
471
472
473 /*
474 * sort order stuff
475 * quite straight forward
476 */
477 query += "ORDER BY ";
478 switch( sortOrder ) {
479 /* completed */
480 case 0:
481 query += "completed";
482 break;
483 case 1:
484 query += "priority";
485 break;
486 case 2:
487 query += "summary";
488 break;
489 case 3:
490 query += "DueDate";
491 break;
492 }
493
494 if ( !asc ) {
495 qWarning("not ascending!");
496 query += " DESC";
497 }
498
499 qWarning( query );
500 OSQLRawQuery raw(query );
501 return uids( m_driver->query(&raw) );
502}
503bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
504 if ( str == "0-0-0" )
505 return false;
506 else{
507 int day, year, month;
508 QStringList list = QStringList::split("-", str );
509 year = list[0].toInt();
510 month = list[1].toInt();
511 day = list[2].toInt();
512 da.setYMD( year, month, day );
513 return true;
514 }
515}
516OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{
517 if ( res.state() == OSQLResult::Failure ) {
518 OTodo to;
519 return to;
520 }
521
522 OSQLResultItem::ValueList list = res.results();
523 OSQLResultItem::ValueList::Iterator it = list.begin();
524 qWarning("todo1");
525 OTodo to = todo( (*it) );
526 cache( to );
527 ++it;
528
529 for ( ; it != list.end(); ++it ) {
530 qWarning("caching");
531 cache( todo( (*it) ) );
532 }
533 return to;
534}
535OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
536 qWarning("todo");
537 bool hasDueDate = false; QDate dueDate = QDate::currentDate();
538 hasDueDate = date( dueDate, item.data("DueDate") );
539 QStringList cats = QStringList::split(";", item.data("categories") );
540
541 qWarning("Item is completed: %d", item.data("completed").toInt() );
542
543 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(),
544 cats, item.data("summary"), item.data("description"),
545 item.data("progress").toUShort(), hasDueDate, dueDate,
546 item.data("uid").toInt() );
547
548 bool isOk;
549 int prioInt = QString( item.data("priority") ).toInt( &isOk );
550 if ( isOk )
551 to.setPriority( prioInt );
552
553 bool hasStartDate = false; QDate startDate = QDate::currentDate();
554 hasStartDate = date( startDate, item.data("startdate") );
555 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate();
556 hasCompletedDate = date( completedDate, item.data("completeddate") );
557
558 if ( hasStartDate )
559 to.setStartDate( startDate );
560 if ( hasCompletedDate )
561 to.setCompletedDate( completedDate );
562
563 OPimNotifyManager& manager = to.notifiers();
564 manager.alarmsFromString( item.data("alarms") );
565 manager.remindersFromString( item.data("reminders") );
566
567 OPimState pimState;
568 pimState.setState( QString( item.data("state") ).toInt() );
569 to.setState( pimState );
570
571 QMap<int, QString> recMap;
572 recMap.insert( ORecur::RType , item.data("RType") );
573 recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") );
574 recMap.insert( ORecur::RPosition , item.data("RPosition") );
575 recMap.insert( ORecur::RFreq , item.data("RFreq") );
576 recMap.insert( ORecur::RHasEndDate, item.data("RHasEndDate") );
577 recMap.insert( ORecur::EndDate , item.data("EndDate") );
578 recMap.insert( ORecur::Created , item.data("Created") );
579 recMap.insert( ORecur::Exceptions , item.data("Exceptions") );
580
581 ORecur recur;
582 recur.fromMap( recMap );
583 to.setRecurrence( recur );
584
585 return to;
586}
587OTodo OTodoAccessBackendSQL::todo( int uid )const {
588 FindQuery find( uid );
589 return todo( m_driver->query(&find) );
590}
591/*
592 * update the dict
593 */
594void OTodoAccessBackendSQL::fillDict() {
595 /* initialize dict */
596 /*
597 * UPDATE dict if you change anything!!!
598 * FIXME: Isn't this dict obsolete ? (eilers)
599 */
600 m_dict.setAutoDelete( TRUE );
601 m_dict.insert("Categories" , new int(OTodo::Category) );
602 m_dict.insert("Uid" , new int(OTodo::Uid) );
603 m_dict.insert("HasDate" , new int(OTodo::HasDate) );
604 m_dict.insert("Completed" , new int(OTodo::Completed) );
605 m_dict.insert("Description" , new int(OTodo::Description) );
606 m_dict.insert("Summary" , new int(OTodo::Summary) );
607 m_dict.insert("Priority" , new int(OTodo::Priority) );
608 m_dict.insert("DateDay" , new int(OTodo::DateDay) );
609 m_dict.insert("DateMonth" , new int(OTodo::DateMonth) );
610 m_dict.insert("DateYear" , new int(OTodo::DateYear) );
611 m_dict.insert("Progress" , new int(OTodo::Progress) );
612 m_dict.insert("Completed", new int(OTodo::Completed) ); // Why twice ? (eilers)
613 m_dict.insert("CrossReference", new int(OTodo::CrossReference) );
614// m_dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); // old stuff (eilers)
615// m_dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); // old stuff (eilers)
616}
617/*
618 * need to be const so let's fool the
619 * compiler :(
620 */
621void OTodoAccessBackendSQL::update()const {
622 ((OTodoAccessBackendSQL*)this)->m_dirty = false;
623 LoadQuery lo;
624 OSQLResult res = m_driver->query(&lo);
625 if ( res.state() != OSQLResult::Success )
626 return;
627
628 ((OTodoAccessBackendSQL*)this)->m_uids = uids( res );
629}
630QArray<int> OTodoAccessBackendSQL::uids( const OSQLResult& res) const{
631
632 OSQLResultItem::ValueList list = res.results();
633 OSQLResultItem::ValueList::Iterator it;
634 QArray<int> ints(list.count() );
635 qWarning(" count = %d", list.count() );
636
637 int i = 0;
638 for (it = list.begin(); it != list.end(); ++it ) {
639 ints[i] = (*it).data("uid").toInt();
640 i++;
641 }
642 return ints;
643}
644
645QArray<int> OTodoAccessBackendSQL::matchRegexp( const QRegExp &r ) const
646{
647
648#warning OTodoAccessBackendSQL::matchRegexp() not implemented !!
649
650#if 0
651
652 Copied from xml-backend by not adapted to sql (eilers)
653
654 QArray<int> m_currentQuery( m_events.count() );
655 uint arraycounter = 0;
656
657
658
659 QMap<int, OTodo>::ConstIterator it;
660 for (it = m_events.begin(); it != m_events.end(); ++it ) {
661 if ( it.data().match( r ) )
662 m_currentQuery[arraycounter++] = it.data().uid();
663
664 }
665 // Shrink to fit..
666 m_currentQuery.resize(arraycounter);
667
668 return m_currentQuery;
669#endif
670 QArray<int> empty;
671 return empty;
672}
673QBitArray OTodoAccessBackendSQL::supports()const {
674
675 return sup();
676}
677
678QBitArray OTodoAccessBackendSQL::sup() const{
679
680 QBitArray ar( OTodo::CompletedDate + 1 );
681 ar.fill( true );
682 ar[OTodo::CrossReference] = false;
683 ar[OTodo::State ] = false;
684 ar[OTodo::Reminders] = false;
685 ar[OTodo::Notifiers] = false;
686 ar[OTodo::Maintainer] = false;
687
688 return ar;
689}
690
691void OTodoAccessBackendSQL::removeAllCompleted(){
692#warning OTodoAccessBackendSQL::removeAllCompleted() not implemented !!
693
694}
diff --git a/libopie/pim/otodoaccesssql.h b/libopie/pim/otodoaccesssql.h
deleted file mode 100644
index 72214de..0000000
--- a/libopie/pim/otodoaccesssql.h
+++ b/dev/null
@@ -1,61 +0,0 @@
1#ifndef OPIE_PIM_ACCESS_SQL_H
2#define OPIE_PIM_ACCESS_SQL_H
3
4#include <qasciidict.h>
5
6#include "otodoaccessbackend.h"
7
8namespace Opie{
9namespace DB {
10class OSQLDriver;
11class OSQLResult;
12class OSQLResultItem;
13}
14}
15
16class OTodoAccessBackendSQL : public OTodoAccessBackend {
17public:
18 OTodoAccessBackendSQL( const QString& file );
19 ~OTodoAccessBackendSQL();
20
21 bool load();
22 bool reload();
23 bool save();
24 QArray<int> allRecords()const;
25
26 QArray<int> queryByExample( const OTodo& t, int settings, const QDateTime& d = QDateTime() );
27 OTodo find(int uid)const;
28 OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
29 void clear();
30 bool add( const OTodo& t );
31 bool remove( int uid );
32 bool replace( const OTodo& t );
33
34 QArray<int> overDue();
35 QArray<int> effectiveToDos( const QDate& start,
36 const QDate& end, bool includeNoDates );
37 QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat );
38
39 QBitArray supports()const;
40 QArray<int> matchRegexp( const QRegExp &r ) const;
41 void removeAllCompleted();
42
43
44private:
45 void update()const;
46 void fillDict();
47 inline bool date( QDate& date, const QString& )const;
48 inline OTodo todo( const Opie::DB::OSQLResult& )const;
49 inline OTodo todo( Opie::DB::OSQLResultItem& )const;
50 inline QArray<int> uids( const Opie::DB::OSQLResult& )const;
51 OTodo todo( int uid )const;
52 QBitArray sup() const;
53
54 QAsciiDict<int> m_dict;
55 Opie::DB::OSQLDriver* m_driver;
56 QArray<int> m_uids;
57 bool m_dirty : 1;
58};
59
60
61#endif
diff --git a/libopie/pim/otodoaccessvcal.cpp b/libopie/pim/otodoaccessvcal.cpp
deleted file mode 100644
index 6415952..0000000
--- a/libopie/pim/otodoaccessvcal.cpp
+++ b/dev/null
@@ -1,249 +0,0 @@
1#include <qfile.h>
2
3#include <qtopia/private/vobject_p.h>
4#include <qtopia/timeconversion.h>
5#include <qtopia/private/qfiledirect_p.h>
6
7#include "otodoaccessvcal.h"
8
9namespace {
10 static OTodo eventByVObj( VObject *obj ){
11 OTodo event;
12 VObject *ob;
13 QCString name;
14 // no uid, attendees, ... and no fun
15 // description
16 if( ( ob = isAPropertyOf( obj, VCDescriptionProp )) != 0 ){
17 name = vObjectStringZValue( ob );
18#if 0
19 event.setDescription( name );
20#else
21 event.setSummary( name );
22#endif
23 }
24 // summary
25 if ( ( ob = isAPropertyOf( obj, VCSummaryProp ) ) != 0 ) {
26 name = vObjectStringZValue( ob );
27#if 0
28 event.setSummary( name );
29#else
30 event.setDescription( name );
31#endif
32 }
33 // completed
34 if( ( ob = isAPropertyOf( obj, VCStatusProp )) != 0 ){
35 name = vObjectStringZValue( ob );
36 if( name == "COMPLETED" ){
37 event.setCompleted( true );
38 }else{
39 event.setCompleted( false );
40 }
41 }else
42 event.setCompleted( false );
43 // priority
44 if ((ob = isAPropertyOf(obj, VCPriorityProp))) {
45 name = vObjectStringZValue( ob );
46 bool ok;
47 event.setPriority(name.toInt(&ok) );
48 }
49 //due date
50 if((ob = isAPropertyOf(obj, VCDueProp)) ){
51 event.setHasDueDate( true );
52 name = vObjectStringZValue( ob );
53 event.setDueDate( TimeConversion::fromISO8601( name).date() );
54 }
55 // categories
56 if((ob = isAPropertyOf( obj, VCCategoriesProp )) != 0 ){
57 name = vObjectStringZValue( ob );
58 qWarning("Categories:%s", name.data() );
59 }
60
61 event.setUid( 1 );
62 return event;
63 };
64 static VObject *vobjByEvent( const OTodo &event ) {
65 VObject *task = newVObject( VCTodoProp );
66 if( task == 0 )
67 return 0l;
68
69 if( event.hasDueDate() ) {
70 QTime time(0, 0, 0);
71 QDateTime date(event.dueDate(), time );
72 addPropValue( task, VCDueProp,
73 TimeConversion::toISO8601( date ) );
74 }
75
76 if( event.isCompleted() )
77 addPropValue( task, VCStatusProp, "COMPLETED");
78
79 QString string = QString::number(event.priority() );
80 addPropValue( task, VCPriorityProp, string.local8Bit() );
81
82 addPropValue( task, VCCategoriesProp,
83 event.idsToString( event.categories() ).local8Bit() );
84
85#if 0
86
87 // There seems a misrepresentation between summary in otodoevent
88 // and summary in vcard.
89 // The same with description..
90 // Description is summary and vice versa.. Argh.. (eilers)
91
92
93 addPropValue( task, VCDescriptionProp,
94 event.description().local8Bit() );
95
96 addPropValue( task, VCSummaryProp,
97 event.summary().local8Bit() );
98
99#else
100 addPropValue( task, VCDescriptionProp,
101 event.summary().local8Bit() );
102
103 addPropValue( task, VCSummaryProp,
104 event.description().local8Bit() );
105#endif
106 return task;
107};
108}
109
110OTodoAccessVCal::OTodoAccessVCal( const QString& path )
111 : m_dirty(false), m_file( path )
112{
113}
114OTodoAccessVCal::~OTodoAccessVCal() {
115}
116bool OTodoAccessVCal::load() {
117 m_map.clear();
118 m_dirty = false;
119
120 VObject* vcal = 0l;
121 vcal = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
122 if (!vcal )
123 return false;
124
125 // Iterate over the list
126 VObjectIterator it;
127 VObject* vobj;
128
129 initPropIterator(&it, vcal);
130
131 while( moreIteration( &it ) ) {
132 vobj = ::nextVObject( &it );
133 QCString name = ::vObjectName( vobj );
134 if( name == VCTodoProp ){
135 OTodo to = eventByVObj( vobj );
136 m_map.insert( to.uid(), to );
137 }
138 }
139
140 // Should I do a delete vcal?
141
142 return true;
143}
144bool OTodoAccessVCal::reload() {
145 return load();
146}
147bool OTodoAccessVCal::save() {
148 if (!m_dirty )
149 return true;
150
151 QFileDirect file( m_file );
152 if (!file.open(IO_WriteOnly ) )
153 return false;
154
155 VObject *obj;
156 obj = newVObject( VCCalProp );
157 addPropValue( obj, VCVersionProp, "1.0" );
158 VObject *vo;
159 for(QMap<int, OTodo>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
160 vo = vobjByEvent( it.data() );
161 addVObjectProp(obj, vo );
162 }
163 writeVObject( file.directHandle(), obj );
164 cleanVObject( obj );
165 cleanStrTbl();
166
167 m_dirty = false;
168 return true;
169}
170void OTodoAccessVCal::clear() {
171 m_map.clear();
172 m_dirty = true;
173}
174bool OTodoAccessVCal::add( const OTodo& to ) {
175 m_map.insert( to.uid(), to );
176 m_dirty = true;
177 return true;
178}
179bool OTodoAccessVCal::remove( int uid ) {
180 m_map.remove( uid );
181 m_dirty = true;
182 return true;
183}
184void OTodoAccessVCal::removeAllCompleted() {
185 for ( QMap<int, OTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) {
186 if ( (*it).isCompleted() )
187 m_map.remove( it );
188 }
189}
190bool OTodoAccessVCal::replace( const OTodo& to ) {
191 m_map.replace( to.uid(), to );
192 m_dirty = true;
193 return true;
194}
195OTodo OTodoAccessVCal::find(int uid )const {
196 return m_map[uid];
197}
198QArray<int> OTodoAccessVCal::sorted( bool, int, int, int ) {
199 QArray<int> ar(0);
200 return ar;
201}
202QArray<int> OTodoAccessVCal::allRecords()const {
203 QArray<int> ar( m_map.count() );
204 QMap<int, OTodo>::ConstIterator it;
205 int i = 0;
206 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
207 ar[i] = it.key();
208 i++;
209 }
210 return ar;
211}
212QArray<int> OTodoAccessVCal::matchRegexp(const QRegExp& /* r */)const {
213 QArray<int> ar(0);
214 return ar;
215}
216QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int, const QDateTime& ) {
217 QArray<int> ar(0);
218 return ar;
219}
220QArray<int> OTodoAccessVCal::effectiveToDos( const QDate& ,
221 const QDate& ,
222 bool ) {
223 QArray<int> ar(0);
224 return ar;
225}
226QArray<int> OTodoAccessVCal::overDue() {
227 QArray<int> ar(0);
228 return ar;
229}
230QBitArray OTodoAccessVCal::supports()const {
231 static QBitArray ar = sup();
232
233 return ar;
234}
235QBitArray OTodoAccessVCal::sup() {
236 QBitArray ar ( OTodo::CompletedDate +1 );
237 ar.fill( true );
238
239 ar[OTodo::CrossReference] = false;
240 ar[OTodo::State ] = false;
241 ar[OTodo::Reminders] = false;
242 ar[OTodo::Notifiers] = false;
243 ar[OTodo::Maintainer] = false;
244 ar[OTodo::Progress] = false;
245 ar[OTodo::Alarms ] = false;
246 ar[OTodo::Recurrence] = false;
247
248 return ar;
249}
diff --git a/libopie/pim/otodoaccessvcal.h b/libopie/pim/otodoaccessvcal.h
deleted file mode 100644
index 2b17147..0000000
--- a/libopie/pim/otodoaccessvcal.h
+++ b/dev/null
@@ -1,40 +0,0 @@
1#ifndef OPIE_OTODO_ACCESS_VCAL_H
2#define OPIE_OTODO_ACCESS_VCAL_H
3
4#include "otodoaccessbackend.h"
5
6class OTodoAccessVCal : public OTodoAccessBackend {
7public:
8 OTodoAccessVCal(const QString& );
9 ~OTodoAccessVCal();
10
11 bool load();
12 bool reload();
13 bool save();
14
15 QArray<int> allRecords()const;
16 QArray<int> matchRegexp(const QRegExp &r) const;
17 QArray<int> queryByExample( const OTodo& t, int sort, const QDateTime& d = QDateTime() );
18 QArray<int> effectiveToDos( const QDate& start,
19 const QDate& end,
20 bool includeNoDates );
21 QArray<int> overDue();
22 QArray<int> sorted( bool asc, int sortOrder, int sortFilter,
23 int cat );
24 OTodo find(int uid)const;
25 void clear();
26 bool add( const OTodo& );
27 bool remove( int uid );
28 bool replace( const OTodo& );
29
30 void removeAllCompleted();
31 virtual QBitArray supports()const;
32
33private:
34 static QBitArray sup();
35 bool m_dirty : 1;
36 QString m_file;
37 QMap<int, OTodo> m_map;
38};
39
40#endif
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
deleted file mode 100644
index 4a5cb33..0000000
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/dev/null
@@ -1,876 +0,0 @@
1#include <errno.h>
2#include <fcntl.h>
3
4#include <sys/mman.h>
5#include <sys/stat.h>
6#include <sys/types.h>
7
8#include <unistd.h>
9
10
11#include <qfile.h>
12#include <qvector.h>
13
14#include <qpe/global.h>
15#include <qpe/stringutil.h>
16#include <qpe/timeconversion.h>
17
18#include "oconversion.h"
19#include "opimstate.h"
20#include "otimezone.h"
21#include "opimnotifymanager.h"
22#include "orecur.h"
23#include "otodoaccessxml.h"
24
25namespace {
26 time_t rp_end;
27 ORecur* rec;
28 ORecur *recur() {
29 if (!rec ) rec = new ORecur;
30 return rec;
31 }
32 int snd;
33 enum MoreAttributes {
34 FRType = OTodo::CompletedDate + 2,
35 FRWeekdays,
36 FRPosition,
37 FRFreq,
38 FRHasEndDate,
39 FREndDate,
40 FRStart,
41 FREnd
42 };
43 // FROM TT again
44char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
45{
46 char needleChar;
47 char haystackChar;
48 if (!needle || !haystack || !hLen || !nLen)
49 return 0;
50
51 const char* hsearch = haystack;
52
53 if ((needleChar = *needle++) != 0) {
54 nLen--; //(to make up for needle++)
55 do {
56 do {
57 if ((haystackChar = *hsearch++) == 0)
58 return (0);
59 if (hsearch >= haystack + hLen)
60 return (0);
61 } while (haystackChar != needleChar);
62 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
63 hsearch--;
64 }
65 return ((char *)hsearch);
66}
67}
68
69
70OTodoAccessXML::OTodoAccessXML( const QString& appName,
71 const QString& fileName )
72 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
73{
74 if (!fileName.isEmpty() )
75 m_file = fileName;
76 else
77 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
78}
79OTodoAccessXML::~OTodoAccessXML() {
80
81}
82bool OTodoAccessXML::load() {
83 rec = 0;
84 m_opened = true;
85 m_changed = false;
86 /* initialize dict */
87 /*
88 * UPDATE dict if you change anything!!!
89 */
90 QAsciiDict<int> dict(26);
91 dict.setAutoDelete( TRUE );
92 dict.insert("Categories" , new int(OTodo::Category) );
93 dict.insert("Uid" , new int(OTodo::Uid) );
94 dict.insert("HasDate" , new int(OTodo::HasDate) );
95 dict.insert("Completed" , new int(OTodo::Completed) );
96 dict.insert("Description" , new int(OTodo::Description) );
97 dict.insert("Summary" , new int(OTodo::Summary) );
98 dict.insert("Priority" , new int(OTodo::Priority) );
99 dict.insert("DateDay" , new int(OTodo::DateDay) );
100 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
101 dict.insert("DateYear" , new int(OTodo::DateYear) );
102 dict.insert("Progress" , new int(OTodo::Progress) );
103 dict.insert("CompletedDate", new int(OTodo::CompletedDate) );
104 dict.insert("StartDate", new int(OTodo::StartDate) );
105 dict.insert("CrossReference", new int(OTodo::CrossReference) );
106 dict.insert("State", new int(OTodo::State) );
107 dict.insert("Alarms", new int(OTodo::Alarms) );
108 dict.insert("Reminders", new int(OTodo::Reminders) );
109 dict.insert("Notifiers", new int(OTodo::Notifiers) );
110 dict.insert("Maintainer", new int(OTodo::Maintainer) );
111 dict.insert("rtype", new int(FRType) );
112 dict.insert("rweekdays", new int(FRWeekdays) );
113 dict.insert("rposition", new int(FRPosition) );
114 dict.insert("rfreq", new int(FRFreq) );
115 dict.insert("start", new int(FRStart) );
116 dict.insert("rhasenddate", new int(FRHasEndDate) );
117 dict.insert("enddt", new int(FREndDate) );
118
119 // here the custom XML parser from TT it's GPL
120 // but we want to push OpiePIM... to TT.....
121 // mmap part from zecke :)
122 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
123 struct stat attribut;
124 if ( fd < 0 ) return false;
125
126 if ( fstat(fd, &attribut ) == -1 ) {
127 ::close( fd );
128 return false;
129 }
130 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
131 if ( map_addr == ( (caddr_t)-1) ) {
132 ::close(fd );
133 return false;
134 }
135 /* advise the kernel who we want to read it */
136 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
137 /* we do not the file any more */
138 ::close( fd );
139
140 char* dt = (char*)map_addr;
141 int len = attribut.st_size;
142 int i = 0;
143 char *point;
144 const char* collectionString = "<Task ";
145 int strLen = strlen(collectionString);
146 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) {
147 i = point -dt;
148 i+= strLen;
149 qWarning("Found a start at %d %d", i, (point-dt) );
150
151 OTodo ev;
152 m_year = m_month = m_day = 0;
153
154 while ( TRUE ) {
155 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
156 ++i;
157 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
158 break;
159
160 // we have another attribute, read it.
161 int j = i;
162 while ( j < len && dt[j] != '=' )
163 ++j;
164 QCString attr( dt+i, j-i+1);
165
166 i = ++j; // skip =
167
168 // find the start of quotes
169 while ( i < len && dt[i] != '"' )
170 ++i;
171 j = ++i;
172
173 bool haveUtf = FALSE;
174 bool haveEnt = FALSE;
175 while ( j < len && dt[j] != '"' ) {
176 if ( ((unsigned char)dt[j]) > 0x7f )
177 haveUtf = TRUE;
178 if ( dt[j] == '&' )
179 haveEnt = TRUE;
180 ++j;
181 }
182 if ( i == j ) {
183 // empty value
184 i = j + 1;
185 continue;
186 }
187
188 QCString value( dt+i, j-i+1 );
189 i = j + 1;
190
191 QString str = (haveUtf ? QString::fromUtf8( value )
192 : QString::fromLatin1( value ) );
193 if ( haveEnt )
194 str = Qtopia::plainString( str );
195
196 /*
197 * add key + value
198 */
199 todo( &dict, ev, attr, str );
200
201 }
202 /*
203 * now add it
204 */
205 qWarning("End at %d", i );
206 if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
207 ev.setUid( 1 );
208 m_changed = true;
209 }
210 if ( ev.hasDueDate() ) {
211 ev.setDueDate( QDate(m_year, m_month, m_day) );
212 }
213 if ( rec && rec->doesRecur() ) {
214 OTimeZone utc = OTimeZone::utc();
215 ORecur recu( *rec ); // call copy c'tor
216 recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() );
217 recu.setStart( ev.dueDate() );
218 ev.setRecurrence( recu );
219 }
220 m_events.insert(ev.uid(), ev );
221 m_year = m_month = m_day = -1;
222 delete rec;
223 rec = 0;
224 }
225
226 munmap(map_addr, attribut.st_size );
227
228 qWarning("counts %d records loaded!", m_events.count() );
229 return true;
230}
231bool OTodoAccessXML::reload() {
232 m_events.clear();
233 return load();
234}
235bool OTodoAccessXML::save() {
236// qWarning("saving");
237 if (!m_opened || !m_changed ) {
238// qWarning("not saving");
239 return true;
240 }
241 QString strNewFile = m_file + ".new";
242 QFile f( strNewFile );
243 if (!f.open( IO_WriteOnly|IO_Raw ) )
244 return false;
245
246 int written;
247 QString out;
248 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
249
250 // for all todos
251 QMap<int, OTodo>::Iterator it;
252 for (it = m_events.begin(); it != m_events.end(); ++it ) {
253 out+= "<Task " + toString( (*it) ) + " />\n";
254 QCString cstr = out.utf8();
255 written = f.writeBlock( cstr.data(), cstr.length() );
256
257 /* less written then we wanted */
258 if ( written != (int)cstr.length() ) {
259 f.close();
260 QFile::remove( strNewFile );
261 return false;
262 }
263 out = QString::null;
264 }
265
266 out += "</Tasks>";
267 QCString cstr = out.utf8();
268 written = f.writeBlock( cstr.data(), cstr.length() );
269
270 if ( written != (int)cstr.length() ) {
271 f.close();
272 QFile::remove( strNewFile );
273 return false;
274 }
275 /* flush before renaming */
276 f.close();
277
278 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
279// qWarning("error renaming");
280 QFile::remove( strNewFile );
281 }
282
283 m_changed = false;
284 return true;
285}
286QArray<int> OTodoAccessXML::allRecords()const {
287 QArray<int> ids( m_events.count() );
288 QMap<int, OTodo>::ConstIterator it;
289 int i = 0;
290
291 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
292 ids[i] = it.key();
293 i++;
294 }
295 return ids;
296}
297QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) {
298 QArray<int> ids(0);
299 return ids;
300}
301OTodo OTodoAccessXML::find( int uid )const {
302 OTodo todo;
303 todo.setUid( 0 ); // isEmpty()
304 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
305 if ( it != m_events.end() )
306 todo = it.data();
307
308 return todo;
309}
310void OTodoAccessXML::clear() {
311 if (m_opened )
312 m_changed = true;
313
314 m_events.clear();
315}
316bool OTodoAccessXML::add( const OTodo& todo ) {
317// qWarning("add");
318 m_changed = true;
319 m_events.insert( todo.uid(), todo );
320
321 return true;
322}
323bool OTodoAccessXML::remove( int uid ) {
324 m_changed = true;
325 m_events.remove( uid );
326
327 return true;
328}
329bool OTodoAccessXML::replace( const OTodo& todo) {
330 m_changed = true;
331 m_events.replace( todo.uid(), todo );
332
333 return true;
334}
335QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
336 const QDate& end,
337 bool includeNoDates ) {
338 QArray<int> ids( m_events.count() );
339 QMap<int, OTodo>::Iterator it;
340
341 int i = 0;
342 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
343 if ( !it.data().hasDueDate() ) {
344 if ( includeNoDates ) {
345 ids[i] = it.key();
346 i++;
347 }
348 }else if ( it.data().dueDate() >= start &&
349 it.data().dueDate() <= end ) {
350 ids[i] = it.key();
351 i++;
352 }
353 }
354 ids.resize( i );
355 return ids;
356}
357QArray<int> OTodoAccessXML::overDue() {
358 QArray<int> ids( m_events.count() );
359 int i = 0;
360
361 QMap<int, OTodo>::Iterator it;
362 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
363 if ( it.data().isOverdue() ) {
364 ids[i] = it.key();
365 i++;
366 }
367 }
368 ids.resize( i );
369 return ids;
370}
371
372
373/* private */
374void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
375 const QCString& attr, const QString& val) {
376// qWarning("parse to do from XMLElement" );
377
378 int *find=0;
379
380 find = (*dict)[ attr.data() ];
381 if (!find ) {
382// qWarning("Unknown option" + it.key() );
383 ev.setCustomField( attr, val );
384 return;
385 }
386
387 switch( *find ) {
388 case OTodo::Uid:
389 ev.setUid( val.toInt() );
390 break;
391 case OTodo::Category:
392 ev.setCategories( ev.idsFromString( val ) );
393 break;
394 case OTodo::HasDate:
395 ev.setHasDueDate( val.toInt() );
396 break;
397 case OTodo::Completed:
398 ev.setCompleted( val.toInt() );
399 break;
400 case OTodo::Description:
401 ev.setDescription( val );
402 break;
403 case OTodo::Summary:
404 ev.setSummary( val );
405 break;
406 case OTodo::Priority:
407 ev.setPriority( val.toInt() );
408 break;
409 case OTodo::DateDay:
410 m_day = val.toInt();
411 break;
412 case OTodo::DateMonth:
413 m_month = val.toInt();
414 break;
415 case OTodo::DateYear:
416 m_year = val.toInt();
417 break;
418 case OTodo::Progress:
419 ev.setProgress( val.toInt() );
420 break;
421 case OTodo::CompletedDate:
422 ev.setCompletedDate( OConversion::dateFromString( val ) );
423 break;
424 case OTodo::StartDate:
425 ev.setStartDate( OConversion::dateFromString( val ) );
426 break;
427 case OTodo::State:
428 ev.setState( val.toInt() );
429 break;
430 case OTodo::Alarms:{
431 OPimNotifyManager &manager = ev.notifiers();
432 QStringList als = QStringList::split(";", val );
433 for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) {
434 QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty
435 qWarning("alarm: %s", alarm.join("___").latin1() );
436 qWarning("alarm[0]: %s %s", alarm[0].latin1(), OConversion::dateTimeFromString( alarm[0] ).toString().latin1() );
437 OPimAlarm al( alarm[2].toInt(), OConversion::dateTimeFromString( alarm[0] ), alarm[1].toInt() );
438 manager.add( al );
439 }
440 }
441 break;
442 case OTodo::Reminders:{
443 OPimNotifyManager &manager = ev.notifiers();
444 QStringList rems = QStringList::split(";", val );
445 for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) {
446 OPimReminder rem( (*it).toInt() );
447 manager.add( rem );
448 }
449 }
450 break;
451 case OTodo::CrossReference:
452 {
453 /*
454 * A cross refernce looks like
455 * appname,id;appname,id
456 * we need to split it up
457 */
458 QStringList refs = QStringList::split(';', val );
459 QStringList::Iterator strIt;
460 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
461 int pos = (*strIt).find(',');
462 if ( pos > -1 )
463 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
464
465 }
466 break;
467 }
468 /* Recurrence stuff below + post processing later */
469 case FRType:
470 if ( val == "Daily" )
471 recur()->setType( ORecur::Daily );
472 else if ( val == "Weekly" )
473 recur()->setType( ORecur::Weekly);
474 else if ( val == "MonthlyDay" )
475 recur()->setType( ORecur::MonthlyDay );
476 else if ( val == "MonthlyDate" )
477 recur()->setType( ORecur::MonthlyDate );
478 else if ( val == "Yearly" )
479 recur()->setType( ORecur::Yearly );
480 else
481 recur()->setType( ORecur::NoRepeat );
482 break;
483 case FRWeekdays:
484 recur()->setDays( val.toInt() );
485 break;
486 case FRPosition:
487 recur()->setPosition( val.toInt() );
488 break;
489 case FRFreq:
490 recur()->setFrequency( val.toInt() );
491 break;
492 case FRHasEndDate:
493 recur()->setHasEndDate( val.toInt() );
494 break;
495 case FREndDate: {
496 rp_end = (time_t) val.toLong();
497 break;
498 }
499 default:
500 ev.setCustomField( attr, val );
501 break;
502 }
503}
504
505// from PalmtopRecord... GPL ### FIXME
506namespace {
507QString customToXml(const QMap<QString, QString>& customMap )
508{
509 //qWarning(QString("writing custom %1").arg(customMap.count()));
510 QString buf(" ");
511 for ( QMap<QString, QString>::ConstIterator cit = customMap.begin();
512 cit != customMap.end(); ++cit) {
513 // qWarning(".ITEM.");
514 buf += cit.key();
515 buf += "=\"";
516 buf += Qtopia::escapeString(cit.data());
517 buf += "\" ";
518 }
519 return buf;
520}
521
522
523}
524
525QString OTodoAccessXML::toString( const OTodo& ev )const {
526 QString str;
527
528 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
529 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
530 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
531 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
532
533 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
534 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
535 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
536
537 if ( ev.hasDueDate() ) {
538 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
539 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
540 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
541 }
542// qWarning( "Uid %d", ev.uid() );
543 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
544
545// append the extra options
546 /* FIXME Qtopia::Record this is currently not
547 * possible you can set custom fields
548 * but don' iterate over the list
549 * I may do #define private protected
550 * for this case - cough --zecke
551 */
552 /*
553 QMap<QString, QString> extras = ev.extras();
554 QMap<QString, QString>::Iterator extIt;
555 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
556 str += extIt.key() + "=\"" + extIt.data() + "\" ";
557 */
558 // cross refernce
559 if ( ev.hasRecurrence() ) {
560 str += ev.recurrence().toString();
561 }
562 if ( ev.hasStartDate() )
563 str += "StartDate=\""+ OConversion::dateToString( ev.startDate() ) +"\" ";
564 if ( ev.hasCompletedDate() )
565 str += "CompletedDate=\""+ OConversion::dateToString( ev.completedDate() ) +"\" ";
566 if ( ev.hasState() )
567 str += "State=\""+QString::number( ev.state().state() )+"\" ";
568
569 /*
570 * save reminders and notifiers!
571 * DATE_TIME:DURATION:SOUND:NOT_USED_YET;OTHER_DATE_TIME:OTHER_DURATION:SOUND:....
572 */
573 if ( ev.hasNotifiers() ) {
574 OPimNotifyManager manager = ev.notifiers();
575 OPimNotifyManager::Alarms alarms = manager.alarms();
576 if (!alarms.isEmpty() ) {
577 QStringList als;
578 OPimNotifyManager::Alarms::Iterator it = alarms.begin();
579 for ( ; it != alarms.end(); ++it ) {
580 /* only if time is valid */
581 if ( (*it).dateTime().isValid() ) {
582 als << OConversion::dateTimeToString( (*it).dateTime() )
583 + ":" + QString::number( (*it).duration() )
584 + ":" + QString::number( (*it).sound() )
585 + ":";
586 }
587 }
588 // now write the list
589 qWarning("als: %s", als.join("____________").latin1() );
590 str += "Alarms=\""+als.join(";") +"\" ";
591 }
592
593 /*
594 * now the same for reminders but more easy. We just save the uid of the OEvent.
595 */
596 OPimNotifyManager::Reminders reminders = manager.reminders();
597 if (!reminders.isEmpty() ) {
598 OPimNotifyManager::Reminders::Iterator it = reminders.begin();
599 QStringList records;
600 for ( ; it != reminders.end(); ++it ) {
601 records << QString::number( (*it).recordUid() );
602 }
603 str += "Reminders=\""+ records.join(";") +"\" ";
604 }
605 }
606 str += customToXml( ev.toExtraMap() );
607
608
609 return str;
610}
611QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
612 return Qtopia::Record::idsToString( ints );
613}
614
615/* internal class for sorting
616 *
617 * Inspired by todoxmlio.cpp from TT
618 */
619
620struct OTodoXMLContainer {
621 OTodo todo;
622};
623
624namespace {
625 inline QString string( const OTodo& todo) {
626 return todo.summary().isEmpty() ?
627 todo.description().left(20 ) :
628 todo.summary();
629 }
630 inline int completed( const OTodo& todo1, const OTodo& todo2) {
631 int ret = 0;
632 if ( todo1.isCompleted() ) ret++;
633 if ( todo2.isCompleted() ) ret--;
634 return ret;
635 }
636 inline int priority( const OTodo& t1, const OTodo& t2) {
637 return ( t1.priority() - t2.priority() );
638 }
639 inline int description( const OTodo& t1, const OTodo& t2) {
640 return QString::compare( string(t1), string(t2) );
641 }
642 inline int deadline( const OTodo& t1, const OTodo& t2) {
643 int ret = 0;
644 if ( t1.hasDueDate() &&
645 t2.hasDueDate() )
646 ret = t2.dueDate().daysTo( t1.dueDate() );
647 else if ( t1.hasDueDate() )
648 ret = -1;
649 else if ( t2.hasDueDate() )
650 ret = 1;
651 else
652 ret = 0;
653
654 return ret;
655 }
656
657};
658
659/*
660 * Returns:
661 * 0 if item1 == item2
662 *
663 * non-zero if item1 != item2
664 *
665 * This function returns int rather than bool so that reimplementations
666 * can return one of three values and use it to sort by:
667 *
668 * 0 if item1 == item2
669 *
670 * > 0 (positive integer) if item1 > item2
671 *
672 * < 0 (negative integer) if item1 < item2
673 *
674 */
675class OTodoXMLVector : public QVector<OTodoXMLContainer> {
676public:
677 OTodoXMLVector(int size, bool asc, int sort)
678 : QVector<OTodoXMLContainer>( size )
679 {
680 setAutoDelete( true );
681 m_asc = asc;
682 m_sort = sort;
683 }
684 /* return the summary/description */
685 QString string( const OTodo& todo) {
686 return todo.summary().isEmpty() ?
687 todo.description().left(20 ) :
688 todo.summary();
689 }
690 /**
691 * we take the sortorder( switch on it )
692 *
693 */
694 int compareItems( Item d1, Item d2 ) {
695 bool seComp, sePrio, seDesc, seDeadline;
696 seComp = sePrio = seDeadline = seDesc = false;
697 int ret =0;
698 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
699 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
700
701 /* same item */
702 if ( con1->todo.uid() == con2->todo.uid() )
703 return 0;
704
705 switch ( m_sort ) {
706 /* completed */
707 case 0: {
708 ret = completed( con1->todo, con2->todo );
709 seComp = TRUE;
710 break;
711 }
712 /* priority */
713 case 1: {
714 ret = priority( con1->todo, con2->todo );
715 sePrio = TRUE;
716 break;
717 }
718 /* description */
719 case 2: {
720 ret = description( con1->todo, con2->todo );
721 seDesc = TRUE;
722 break;
723 }
724 /* deadline */
725 case 3: {
726 ret = deadline( con1->todo, con2->todo );
727 seDeadline = TRUE;
728 break;
729 }
730 default:
731 ret = 0;
732 break;
733 };
734 /*
735 * FIXME do better sorting if the first sort criteria
736 * ret equals 0 start with complete and so on...
737 */
738
739 /* twist it we're not ascending*/
740 if (!m_asc)
741 ret = ret * -1;
742
743 if ( ret )
744 return ret;
745
746 // default did not gave difference let's try it other way around
747 /*
748 * General try if already checked if not test
749 * and return
750 * 1.Completed
751 * 2.Priority
752 * 3.Description
753 * 4.DueDate
754 */
755 if (!seComp ) {
756 if ( (ret = completed( con1->todo, con2->todo ) ) ) {
757 if (!m_asc ) ret *= -1;
758 return ret;
759 }
760 }
761 if (!sePrio ) {
762 if ( (ret = priority( con1->todo, con2->todo ) ) ) {
763 if (!m_asc ) ret *= -1;
764 return ret;
765 }
766 }
767 if (!seDesc ) {
768 if ( (ret = description(con1->todo, con2->todo ) ) ) {
769 if (!m_asc) ret *= -1;
770 return ret;
771 }
772 }
773 if (!seDeadline) {
774 if ( (ret = deadline( con1->todo, con2->todo ) ) ) {
775 if (!m_asc) ret *= -1;
776 return ret;
777 }
778 }
779
780 return 0;
781 }
782 private:
783 bool m_asc;
784 int m_sort;
785
786};
787
788QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
789 int sortFilter, int cat ) {
790 OTodoXMLVector vector(m_events.count(), asc,sortOrder );
791 QMap<int, OTodo>::Iterator it;
792 int item = 0;
793
794 bool bCat = sortFilter & 1 ? true : false;
795 bool bOnly = sortFilter & 2 ? true : false;
796 bool comp = sortFilter & 4 ? true : false;
797 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
798
799 /* show category */
800 /* -1 == unfiled */
801 if ( bCat && cat == -1 ) {
802 if(!(*it).categories().isEmpty() )
803 continue;
804 }else if ( bCat && cat != 0)
805 if (!(*it).categories().contains( cat ) ) {
806 continue;
807 }
808 /* isOverdue but we should not show overdue - why?*/
809/* if ( (*it).isOverdue() && !bOnly ) {
810 qWarning("item is overdue but !bOnly");
811 continue;
812 }
813*/
814 if ( !(*it).isOverdue() && bOnly ) {
815 continue;
816 }
817
818 if ((*it).isCompleted() && comp ) {
819 continue;
820 }
821
822
823 OTodoXMLContainer* con = new OTodoXMLContainer();
824 con->todo = (*it);
825 vector.insert(item, con );
826 item++;
827 }
828 vector.resize( item );
829 /* sort it now */
830 vector.sort();
831 /* now get the uids */
832 QArray<int> array( vector.count() );
833 for (uint i= 0; i < vector.count(); i++ ) {
834 array[i] = ( vector.at(i) )->todo.uid();
835 }
836 return array;
837};
838void OTodoAccessXML::removeAllCompleted() {
839 QMap<int, OTodo> events = m_events;
840 for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) {
841 if ( (*it).isCompleted() )
842 events.remove( it.key() );
843 }
844 m_events = events;
845}
846QBitArray OTodoAccessXML::supports()const {
847 static QBitArray ar = sup();
848 return ar;
849}
850QBitArray OTodoAccessXML::sup() {
851 QBitArray ar( OTodo::CompletedDate +1 );
852 ar.fill( true );
853 ar[OTodo::CrossReference] = false;
854 ar[OTodo::State ] = false;
855 ar[OTodo::Reminders] = false;
856 ar[OTodo::Notifiers] = false;
857 ar[OTodo::Maintainer] = false;
858
859 return ar;
860}
861QArray<int> OTodoAccessXML::matchRegexp( const QRegExp &r ) const
862{
863 QArray<int> m_currentQuery( m_events.count() );
864 uint arraycounter = 0;
865
866 QMap<int, OTodo>::ConstIterator it;
867 for (it = m_events.begin(); it != m_events.end(); ++it ) {
868 if ( it.data().match( r ) )
869 m_currentQuery[arraycounter++] = it.data().uid();
870
871 }
872 // Shrink to fit..
873 m_currentQuery.resize(arraycounter);
874
875 return m_currentQuery;
876}
diff --git a/libopie/pim/otodoaccessxml.h b/libopie/pim/otodoaccessxml.h
deleted file mode 100644
index e4850a1..0000000
--- a/libopie/pim/otodoaccessxml.h
+++ b/dev/null
@@ -1,60 +0,0 @@
1#ifndef OPIE_TODO_ACCESS_XML_H
2#define OPIE_TODO_ACCESS_XML_H
3
4#include <qasciidict.h>
5#include <qmap.h>
6
7#include "otodoaccessbackend.h"
8
9namespace Opie {
10 class XMLElement;
11};
12
13class OTodoAccessXML : public OTodoAccessBackend {
14public:
15 /**
16 * fileName if Empty we will use the default path
17 */
18 OTodoAccessXML( const QString& appName,
19 const QString& fileName = QString::null );
20 ~OTodoAccessXML();
21
22 bool load();
23 bool reload();
24 bool save();
25
26 QArray<int> allRecords()const;
27 QArray<int> matchRegexp(const QRegExp &r) const;
28 QArray<int> queryByExample( const OTodo&, int querysettings, const QDateTime& d = QDateTime() );
29 OTodo find( int uid )const;
30 void clear();
31 bool add( const OTodo& );
32 bool remove( int uid );
33 void removeAllCompleted();
34 bool replace( const OTodo& );
35
36 /* our functions */
37 QArray<int> effectiveToDos( const QDate& start,
38 const QDate& end,
39 bool includeNoDates );
40 QArray<int> overDue();
41 QArray<int> sorted( bool asc, int sortOrder,
42 int sortFilter, int cat );
43 QBitArray supports()const;
44private:
45 static QBitArray sup();
46 void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& );
47 QString toString( const OTodo& )const;
48 QString toString( const QArray<int>& ints ) const;
49 QMap<int, OTodo> m_events;
50 QString m_file;
51 QString m_app;
52 bool m_opened : 1;
53 bool m_changed : 1;
54 class OTodoAccessXMLPrivate;
55 OTodoAccessXMLPrivate* d;
56 int m_year, m_month, m_day;
57
58};
59
60#endif
diff --git a/libopie/pim/test/converter.cpp b/libopie/pim/test/converter.cpp
deleted file mode 100644
index bfdb605..0000000
--- a/libopie/pim/test/converter.cpp
+++ b/dev/null
@@ -1,107 +0,0 @@
1#include "converter.h"
2
3#include <qdatetime.h>
4#include <qprogressbar.h>
5
6#include <qpe/qpeapplication.h>
7
8#include <opie/ocontactaccess.h>
9#include <opie/ocontactaccessbackend_xml.h>
10#include <opie/ocontactaccessbackend_sql.h>
11
12#include <opie/odatebookaccess.h>
13#include <opie/odatebookaccessbackend_xml.h>
14#include <opie/odatebookaccessbackend_sql.h>
15
16// #define _ADDRESSBOOK_ACCESS
17
18Converter::Converter(){
19}
20
21void Converter::start_conversion(){
22 qWarning("Converting Contacts from XML to SQL..");
23
24 // Creating backends to the requested databases..
25
26#ifdef _ADDRESSBOOK_ACCESS
27 OContactAccessBackend* xmlBackend = new OContactAccessBackend_XML( "Converter",
28 QString::null );
29
30 OContactAccessBackend* sqlBackend = new OContactAccessBackend_SQL( QString::null,
31 QString::null );
32 // Put the created backends into frontends to access them
33 OContactAccess* xmlAccess = new OContactAccess ( "addressbook_xml",
34 QString::null , xmlBackend, true );
35
36 OContactAccess* sqlAccess = new OContactAccess ( "addressbook_sql",
37 QString::null );
38
39#else
40 ODateBookAccessBackend* xmlBackend = new ODateBookAccessBackend_XML( "Converter",
41 QString::null );
42
43 ODateBookAccessBackend* sqlBackend = new ODateBookAccessBackend_SQL( QString::null,
44 QString::null );
45 // Put the created backends into frontends to access them
46 ODateBookAccess* xmlAccess = new ODateBookAccess ( xmlBackend );
47
48 ODateBookAccess* sqlAccess = new ODateBookAccess ( sqlBackend );
49
50 xmlAccess->load();
51
52#endif
53
54 QTime t;
55 t.start();
56
57// Clean the sql-database..
58 sqlAccess->clear();
59
60#ifdef _ADDRESSBOOK_ACCESS
61 // Now trasmit every contact from the xml database to the sql-database
62 OContactAccess::List contactList = xmlAccess->allRecords();
63 m_progressBar->setTotalSteps( contactList.count() );
64 int count = 0;
65 if ( sqlAccess && xmlAccess ){
66 OContactAccess::List::Iterator it;
67 for ( it = contactList.begin(); it != contactList.end(); ++it ){
68 sqlAccess->add( *it );
69 m_progressBar->setProgress( ++count );
70 }
71 }
72#else
73 // Now transmit every contact from the xml database to the sql-database
74 ODateBookAccess::List dateList = xmlAccess->allRecords();
75 m_progressBar->setTotalSteps( dateList.count() );
76 qWarning( "Number of elements to copy: %d", dateList.count() );
77
78 int count = 0;
79 if ( sqlAccess && xmlAccess ){
80 ODateBookAccess::List::Iterator it;
81 for ( it = dateList.begin(); it != dateList.end(); ++it ){
82 sqlAccess->add( *it );
83 m_progressBar->setProgress( ++count );
84 }
85 }
86
87 #endif
88 // Delete the frontends. Backends will be deleted automatically, too !
89 delete sqlAccess;
90
91 qWarning("Conversion is finished and needed %d ms !", t.elapsed());
92
93 delete xmlAccess;
94}
95
96int main( int argc, char** argv ) {
97
98 QPEApplication a( argc, argv );
99
100 Converter dlg;
101
102 a.showMainWidget( &dlg );
103 // dlg. showMaximized ( );
104
105 return a.exec();
106
107}
diff --git a/libopie/pim/test/converter.h b/libopie/pim/test/converter.h
deleted file mode 100755
index 1cc2a7c..0000000
--- a/libopie/pim/test/converter.h
+++ b/dev/null
@@ -1,18 +0,0 @@
1#ifndef _CONVERTER_H_
2#define _CONVERTER_H_
3
4
5#include "converter_base.h"
6
7
8class Converter: public converter_base {
9public:
10 Converter();
11
12 void start_conversion();
13private:
14
15};
16
17
18#endif
diff --git a/libopie/pim/test/converter.pro b/libopie/pim/test/converter.pro
deleted file mode 100644
index bd9c7a3..0000000
--- a/libopie/pim/test/converter.pro
+++ b/dev/null
@@ -1,12 +0,0 @@
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
deleted file mode 100644
index e9bf636..0000000
--- a/libopie/pim/test/converter_base.ui
+++ b/dev/null
@@ -1,238 +0,0 @@
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>273</width>
15 <height>324</height>
16 </rect>
17 </property>
18 <property stdset="1">
19 <name>caption</name>
20 <string>PIM-Database Converter</string>
21 </property>
22 <property>
23 <name>layoutMargin</name>
24 </property>
25 <grid>
26 <property stdset="1">
27 <name>margin</name>
28 <number>4</number>
29 </property>
30 <property stdset="1">
31 <name>spacing</name>
32 <number>6</number>
33 </property>
34 <widget row="0" column="0" >
35 <class>QGroupBox</class>
36 <property stdset="1">
37 <name>name</name>
38 <cstring>GroupBox6</cstring>
39 </property>
40 <property stdset="1">
41 <name>title</name>
42 <string>Converter</string>
43 </property>
44 <property>
45 <name>layoutMargin</name>
46 </property>
47 <property>
48 <name>layoutSpacing</name>
49 </property>
50 <vbox>
51 <property stdset="1">
52 <name>margin</name>
53 <number>4</number>
54 </property>
55 <property stdset="1">
56 <name>spacing</name>
57 <number>4</number>
58 </property>
59 <widget>
60 <class>QGroupBox</class>
61 <property stdset="1">
62 <name>name</name>
63 <cstring>GroupBox1</cstring>
64 </property>
65 <property stdset="1">
66 <name>title</name>
67 <string>Select Database:</string>
68 </property>
69 <grid>
70 <property stdset="1">
71 <name>margin</name>
72 <number>11</number>
73 </property>
74 <property stdset="1">
75 <name>spacing</name>
76 <number>6</number>
77 </property>
78 <widget row="0" column="1" >
79 <class>QComboBox</class>
80 <item>
81 <property>
82 <name>text</name>
83 <string>Addressbook</string>
84 </property>
85 </item>
86 <item>
87 <property>
88 <name>text</name>
89 <string>TodoList</string>
90 </property>
91 </item>
92 <property stdset="1">
93 <name>name</name>
94 <cstring>ComboBox1</cstring>
95 </property>
96 </widget>
97 </grid>
98 </widget>
99 <widget>
100 <class>QGroupBox</class>
101 <property stdset="1">
102 <name>name</name>
103 <cstring>GroupBox2</cstring>
104 </property>
105 <property stdset="1">
106 <name>title</name>
107 <string>Source/Destination:</string>
108 </property>
109 <grid>
110 <property stdset="1">
111 <name>margin</name>
112 <number>11</number>
113 </property>
114 <property stdset="1">
115 <name>spacing</name>
116 <number>6</number>
117 </property>
118 <widget row="1" column="0" >
119 <class>QLabel</class>
120 <property stdset="1">
121 <name>name</name>
122 <cstring>TextLabel3_2</cstring>
123 </property>
124 <property stdset="1">
125 <name>text</name>
126 <string>to</string>
127 </property>
128 </widget>
129 <widget row="1" column="1" >
130 <class>QComboBox</class>
131 <item>
132 <property>
133 <name>text</name>
134 <string>Select</string>
135 </property>
136 </item>
137 <item>
138 <property>
139 <name>text</name>
140 <string>XML</string>
141 </property>
142 </item>
143 <item>
144 <property>
145 <name>text</name>
146 <string>SQL (SQLite)</string>
147 </property>
148 </item>
149 <property stdset="1">
150 <name>name</name>
151 <cstring>ComboBox2_3</cstring>
152 </property>
153 </widget>
154 <widget row="0" column="0" >
155 <class>QLabel</class>
156 <property stdset="1">
157 <name>name</name>
158 <cstring>TextLabel2_2</cstring>
159 </property>
160 <property stdset="1">
161 <name>text</name>
162 <string>Convert from</string>
163 </property>
164 </widget>
165 <widget row="0" column="1" >
166 <class>QComboBox</class>
167 <item>
168 <property>
169 <name>text</name>
170 <string>XML</string>
171 </property>
172 </item>
173 <item>
174 <property>
175 <name>text</name>
176 <string>SQL (SQLite)</string>
177 </property>
178 </item>
179 <property stdset="1">
180 <name>name</name>
181 <cstring>ComboBox2_2_2</cstring>
182 </property>
183 </widget>
184 </grid>
185 </widget>
186 <widget>
187 <class>QGroupBox</class>
188 <property stdset="1">
189 <name>name</name>
190 <cstring>GroupBox4</cstring>
191 </property>
192 <property stdset="1">
193 <name>title</name>
194 <string>Progress:</string>
195 </property>
196 <grid>
197 <property stdset="1">
198 <name>margin</name>
199 <number>11</number>
200 </property>
201 <property stdset="1">
202 <name>spacing</name>
203 <number>6</number>
204 </property>
205 <widget row="0" column="0" >
206 <class>QProgressBar</class>
207 <property stdset="1">
208 <name>name</name>
209 <cstring>m_progressBar</cstring>
210 </property>
211 </widget>
212 </grid>
213 </widget>
214 <widget>
215 <class>QPushButton</class>
216 <property stdset="1">
217 <name>name</name>
218 <cstring>PushButton1</cstring>
219 </property>
220 <property stdset="1">
221 <name>text</name>
222 <string>Go!</string>
223 </property>
224 </widget>
225 </vbox>
226 </widget>
227 </grid>
228</widget>
229<connections>
230 <connection>
231 <sender>PushButton1</sender>
232 <signal>clicked()</signal>
233 <receiver>converter_base</receiver>
234 <slot>start_conversion()</slot>
235 </connection>
236 <slot access="public">start_conversion()</slot>
237</connections>
238</UI>
diff --git a/libopie/pim/test/oevent_test.cpp b/libopie/pim/test/oevent_test.cpp
deleted file mode 100644
index 9f16911..0000000
--- a/libopie/pim/test/oevent_test.cpp
+++ b/dev/null
@@ -1,35 +0,0 @@
1#include <qdatetime.h>
2
3#include "../oevent.h"
4#include "../odatebookaccess.h"
5
6int main(int argc, char* argv ) {
7 ODateBookAccess acc;
8 if(!acc.load() ) qWarning("could not load");
9
10 ODateBookAccess::List::Iterator it;
11 ODateBookAccess::List list = acc.allRecords();
12
13 for( it = list.begin(); it != list.end(); ++it ){
14 OEvent ev = (*it);
15 qWarning("Summary: %s",ev.description().latin1() );
16 qWarning("Start: %s End: %s",ev.startDateTime().toString().latin1(), ev.endDateTime().toString().latin1() );
17 qWarning("All Day: %d Recurrence: %d",ev.isAllDay(), ev.hasRecurrence() );
18 qWarning("UID %d", ev.uid() );
19
20 }
21 QDate date1(2003,02,01 );
22 QDate date2(2003,03,01 );
23
24 OEffectiveEvent::ValueList effList = acc.effectiveEvents( date1,date2 );
25 OEffectiveEvent::ValueList::Iterator effIt;
26
27 for( effIt = effList.begin(); effIt != effList.end(); ++effIt ){
28 OEffectiveEvent ef = (*effIt);
29 qWarning("Summary: %s", ef.description().latin1() );
30 qWarning("Date: %s", ef.date().toString().latin1() );
31 }
32 acc.save();
33
34 return 0;
35}
diff --git a/libopie/pim/test/oevent_test.pro b/libopie/pim/test/oevent_test.pro
deleted file mode 100644
index 3365def..0000000
--- a/libopie/pim/test/oevent_test.pro
+++ b/dev/null
@@ -1,11 +0,0 @@
1 TEMPLATE= app
2 #CONFIG = qt warn_on debug
3 CONFIG = qt warn_on release
4 #HEADERS =
5 SOURCES = oevent_test.cpp
6 INCLUDEPATH+= $(OPIEDIR)/include
7 DEPENDPATH+= $(OPIEDIR)/include
8LIBS += -lqpe -lopie
9 TARGET = oevent_test
10
11include ( $(OPIEDIR)/include.pro ) \ No newline at end of file
diff --git a/libopie/pim/test/test_todo.cpp b/libopie/pim/test/test_todo.cpp
deleted file mode 100644
index 7440503..0000000
--- a/libopie/pim/test/test_todo.cpp
+++ b/dev/null
@@ -1,36 +0,0 @@
1#include <qdatetime.h>
2#include <qmap.h>
3
4#include <opie/otodo.h>
5#include <opie/otodoaccess.h>
6#include <opie/otodoaccessxml.h>
7
8int main(int argc, char* argv[] ) {
9
10 OTodoAccessXML* xml = new OTodoAccessXML("demo");
11 OTodoAccess ac(xml);
12 int elc;
13 QTime timer;
14 qWarning("start loading");
15 timer.start();
16 ac.load();
17 elc = timer.elapsed();
18 qWarning("Elapsed loading %d %d", elc, elc/1000);
19
20 timer.start();
21 OTodoAccess::List lis = ac.allRecords();
22 elc = timer.elapsed();
23 qWarning("Elapsed allRecords %d %d", elc, elc/1000 );
24 OTodoAccess::List::Iterator it;
25 timer.start();
26ac.save();
27/*
28 for( it = lis.begin(); it != lis.end(); ++it ) {
29 qWarning("Desc: " + (*it).summary() );
30 qWarning("UID %d", (*it).uid() );
31 }
32 */
33elc = timer.elapsed();
34
35 qWarning("elapsed iterating %d %d", elc, elc/1000 );
36};
diff --git a/libopie/pim/test/todo_test.pro b/libopie/pim/test/todo_test.pro
deleted file mode 100644
index 3d14dda..0000000
--- a/libopie/pim/test/todo_test.pro
+++ b/dev/null
@@ -1,11 +0,0 @@
1 TEMPLATE= app
2 #CONFIG = qt warn_on debug
3 CONFIG = qt warn_on release
4 #HEADERS =
5 SOURCES = test_todo.cpp
6 INCLUDEPATH+= $(OPIEDIR)/include
7 DEPENDPATH+= $(OPIEDIR)/include
8LIBS += -lqpe -lopie -lopiesql
9 TARGET = todo_test
10
11include ( $(OPIEDIR)/ ) \ No newline at end of file