-rw-r--r-- | libopie/libopie.pro | 2 | ||||
-rw-r--r-- | libopie/pim/obackendfactory.h | 41 | ||||
-rw-r--r-- | libopie/pim/odatebookaccess.cpp | 5 | ||||
-rw-r--r-- | libopie/pim/odatebookaccess.h | 4 | ||||
-rw-r--r-- | libopie/pim/odatebookaccessbackend_xml.cpp | 395 | ||||
-rw-r--r-- | libopie/pim/odatebookaccessbackend_xml.h | 48 | ||||
-rw-r--r-- | libopie/pim/oevent.cpp | 5 | ||||
-rw-r--r-- | libopie/pim/opimnotify.h | 2 | ||||
-rw-r--r-- | libopie/pim/otodoaccessxml.cpp | 2 | ||||
-rw-r--r-- | libopie/pim/test/oevent_test.cpp | 27 | ||||
-rw-r--r-- | libopie2/opiepim/backend/obackendfactory.h | 41 | ||||
-rw-r--r-- | libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp | 395 | ||||
-rw-r--r-- | libopie2/opiepim/backend/odatebookaccessbackend_xml.h | 48 | ||||
-rw-r--r-- | libopie2/opiepim/backend/otodoaccessxml.cpp | 2 | ||||
-rw-r--r-- | libopie2/opiepim/core/odatebookaccess.cpp | 5 | ||||
-rw-r--r-- | libopie2/opiepim/core/odatebookaccess.h | 4 | ||||
-rw-r--r-- | libopie2/opiepim/core/opimnotify.h | 2 | ||||
-rw-r--r-- | libopie2/opiepim/oevent.cpp | 5 |
18 files changed, 995 insertions, 38 deletions
diff --git a/libopie/libopie.pro b/libopie/libopie.pro index 70399ea..391f30e 100644 --- a/libopie/libopie.pro +++ b/libopie/libopie.pro @@ -40,6 +40,7 @@ HEADERS = ofontmenu.h \ pim/otimezone.h \ pim/odatebookaccess.h \ pim/odatebookaccessbackend.h \ + pim/odatebookaccessbackend_xml.h \ orecurrancewidget.h \ oticker.h # pim/otodoaccesssql.h \ @@ -79,6 +80,7 @@ SOURCES = ofontmenu.cc \ pim/otimezone.cpp \ pim/odatebookaccess.cpp \ pim/odatebookaccessbackend.cpp \ + pim/odatebookaccessbackend_xml.cpp \ orecurrancewidget.cpp \ oticker.cpp # pim/otodoaccesssql.cpp \ diff --git a/libopie/pim/obackendfactory.h b/libopie/pim/obackendfactory.h index b796fb8..3a73210 100644 --- a/libopie/pim/obackendfactory.h +++ b/libopie/pim/obackendfactory.h @@ -10,12 +10,22 @@ * either version 2 of the License, or (at your option) any later * version. * ===================================================================== - * ToDo: Use plugins + * ToDo: Use plugins * ===================================================================== * Version: $Id$ * ===================================================================== * History: * $Log$ + * Revision 1.5 2003/02/21 23:31:52 zecke + * Add XML datebookresource + * -clean up todoaccessxml header + * -implement some more stuff in the oeven tester + * -extend DefaultFactory to not crash and to use datebook + * + * -reading of OEvents is working nicely.. saving will be added + * tomorrow + * -fix spelling in ODateBookAcces + * * Revision 1.4 2002/10/14 15:55:18 eilers * Redeactivate SQL.. ;) * @@ -47,6 +57,7 @@ #include "otodoaccessxml.h" #include "ocontactaccessbackend_xml.h" +#include "odatebookaccessbackend_xml.h" #ifdef __USE_SQL #include "otodoaccesssql.h" @@ -64,9 +75,9 @@ class OBackendFactory CONTACT, DATE }; - + static T* Default( const QString backendName, const QString& appName ){ - + // __asm__("int3"); Config config( "pimaccess" ); @@ -78,34 +89,40 @@ class OBackendFactory dict.insert( "todo", new int (TODO) ); dict.insert( "contact", new int (CONTACT) ); + dict.insert( "datebook", new int(DATE) ); qWarning ("TODO is: %d", TODO); qWarning ("CONTACT is: %d", CONTACT); - - switch ( *dict.take( backendName ) ){ + + int *find = dict[ backendName ]; + if (!find ) return 0; + + switch ( *find ){ case TODO: #ifdef __USE_SQL - if ( backend == "sql" ) + if ( backend == "sql" ) return (T*) new OTodoAccessBackendSQL(""); #else - if ( backend == "sql" ) + if ( backend == "sql" ) qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); #endif return (T*) new OTodoAccessXML( appName ); case CONTACT: - if ( backend == "sql" ) + if ( backend == "sql" ) qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); return (T*) new OContactAccessBackend_XML( appName ); case DATE: - qWarning ("OBackendFactory:: DATE-Backend not implemented!"); - return NULL; + if ( backend == "sql" ) + qWarning("OBackendFactory:: sql Backend not implemented! Using XML instead!"); + + return (T*) new ODateBookAccessBackend_XML( appName ); default: return NULL; } - - + + } }; diff --git a/libopie/pim/odatebookaccess.cpp b/libopie/pim/odatebookaccess.cpp index 5f97e7c..08e61ff 100644 --- a/libopie/pim/odatebookaccess.cpp +++ b/libopie/pim/odatebookaccess.cpp @@ -8,6 +8,7 @@ ODateBookAccess::ODateBookAccess( ODateBookAccessBackend* back, enum Access ac ) back = OBackendFactory<ODateBookAccessBackend>::Default("datebook", QString::null ); m_backEnd = back; + setBackEnd( m_backEnd ); } ODateBookAccess::~ODateBookAccess() { } @@ -29,9 +30,9 @@ ODateBookAccess::List ODateBookAccess::nonRepeats()const { List lis( ints, this ); return lis; } -OEffectiveEvent::ValueList ODateBookAccess::effecticeEvents( const QDate& from, const QDate& to ) { +OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDate& from, const QDate& to ) { return m_backEnd->effecticeEvents( from, to ); } -OEffectiveEvent::ValueList ODateBookAccess::effecticeEvents( const QDateTime& start ) { +OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDateTime& start ) { return m_backEnd->effecticeEvents( start ); } diff --git a/libopie/pim/odatebookaccess.h b/libopie/pim/odatebookaccess.h index 3f2c728..7047039 100644 --- a/libopie/pim/odatebookaccess.h +++ b/libopie/pim/odatebookaccess.h @@ -20,8 +20,8 @@ public: /** return non repeating events */ List nonRepeats()const; - OEffectiveEvent::ValueList effecticeEvents( const QDate& from, const QDate& to ); - OEffectiveEvent::ValueList effecticeEvents( const QDateTime& start ); + OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to ); + OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start ); private: ODateBookAccessBackend* m_backEnd; diff --git a/libopie/pim/odatebookaccessbackend_xml.cpp b/libopie/pim/odatebookaccessbackend_xml.cpp new file mode 100644 index 0000000..a4c514b --- a/dev/null +++ b/libopie/pim/odatebookaccessbackend_xml.cpp @@ -0,0 +1,395 @@ +#include <errno.h> +#include <fcntl.h> + +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include <unistd.h> + +#include <qasciidict.h> +#include <qfile.h> + +#include <qtopia/global.h> +#include <qtopia/stringutil.h> + +#include "opimnotifymanager.h" +#include "orecur.h" +#include "otimezone.h" +#include "odatebookaccessbackend_xml.h" + +namespace { + time_t start, end, created, rp_end; + ORecur* rec; + ORecur* recur() { + if (!rec) + rec = new ORecur; + + return rec; + } + int alarmTime; + int snd; + enum Attribute{ + FDescription = 0, + FLocation, + FCategories, + FUid, + FType, + FAlarm, + FSound, + FRType, + FRWeekdays, + FRPosition, + FRFreq, + FRHasEndDate, + FREndDate, + FRStart, + FREnd, + FNote, + FCreated + }; +} + +ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , + const QString& fileName ) + : ODateBookAccessBackend() { + m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; + m_changed = false; +} +ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { +} +bool ODateBookAccessBackend_XML::load() { + return loadFile(); +} +bool ODateBookAccessBackend_XML::reload() { + clear(); + return load(); +} +bool ODateBookAccessBackend_XML::save() { + if (!m_changed) return true; + m_changed = false; + + return true; +} +QArray<int> ODateBookAccessBackend_XML::allRecords()const { + QArray<int> ints( m_raw.count()+ m_rep.count() ); + uint i = 0; + QMap<int, OEvent>::ConstIterator it; + + for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { + ints[i] = it.key(); + i++; + } + for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { + ints[i] = it.key(); + i++; + } + + return ints; +} +QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) { + return QArray<int>(); +} +void ODateBookAccessBackend_XML::clear() { + m_raw.clear(); + m_rep.clear(); +} +OEvent ODateBookAccessBackend_XML::find( int uid ) const{ + if ( m_raw.contains( uid ) ) + return m_raw[uid]; + else + return m_rep[uid]; +} +bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { + m_changed = true; + if (ev.hasRecurrence() ) + m_rep.insert( ev.uid(), ev ); + else + m_raw.insert( ev.uid(), ev ); + + return true; +} +bool ODateBookAccessBackend_XML::remove( int uid ) { + m_changed = true; + m_rep.remove( uid ); + m_rep.remove( uid ); + + return true; +} +bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { + replace( ev.uid() ); + return add( ev ); +} +QArray<int> ODateBookAccessBackend_XML::rawEvents()const { + return allRecords(); +} +QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { + QArray<int> ints( m_rep.count() ); + uint i = 0; + QMap<int, OEvent>::ConstIterator it; + + for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { + ints[i] = it.key(); + i++; + } + + return ints; +} +QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { + QArray<int> ints( m_raw.count() ); + uint i = 0; + QMap<int, OEvent>::ConstIterator it; + + for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { + ints[i] = it.key(); + i++; + } + + return ints; +} +OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { + OEvent::ValueList list; + QMap<int, OEvent>::ConstIterator it; + for (it = m_raw.begin(); it != m_raw.end(); ++it ) + list.append( it.data() ); + + return list; +} +OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { + OEvent::ValueList list; + QMap<int, OEvent>::ConstIterator it; + for (it = m_rep.begin(); it != m_rep.end(); ++it ) + list.append( it.data() ); + + return list; +} +bool ODateBookAccessBackend_XML::loadFile() { + m_changed = false; + + int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); + if ( fd < 0 ) return false; + + struct stat attribute; + if ( ::fstat(fd, &attribute ) == -1 ) { + ::close( fd ); + return false; + } + void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); + if ( map_addr == ( (caddr_t)-1) ) { + ::close( fd ); + return false; + } + + ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); + ::close( fd ); + + QAsciiDict<int> dict(FCreated+1); + dict.setAutoDelete( true ); + dict.insert( "description", new int(FDescription) ); + dict.insert( "location", new int(FLocation) ); + dict.insert( "categories", new int(FCategories) ); + dict.insert( "uid", new int(FUid) ); + dict.insert( "type", new int(FType) ); + dict.insert( "alarm", new int(FAlarm) ); + dict.insert( "sound", new int(FSound) ); + dict.insert( "rtype", new int(FRType) ); + dict.insert( "rweekdays", new int(FRWeekdays) ); + dict.insert( "rposition", new int(FRPosition) ); + dict.insert( "rfreq", new int(FRFreq) ); + dict.insert( "rhasenddate", new int(FRHasEndDate) ); + dict.insert( "enddt", new int(FREndDate) ); + dict.insert( "start", new int(FRStart) ); + dict.insert( "end", new int(FREnd) ); + dict.insert( "note", new int(FNote) ); + dict.insert( "created", new int(FCreated) ); + + char* dt = (char*)map_addr; + int len = attribute.st_size; + int i = 0; + char* point; + const char* collectionString = "<event "; + int strLen = ::strlen(collectionString); + int *find; + while ( dt + 1 != 0 && (( point = ::strstr( dt+i, collectionString ) ) != 0 ) ) { + i = point -dt; + i+= strLen; + + alarmTime = -1; + snd = 0; // silent + + OEvent ev; + rec = 0; + + while ( TRUE ) { + while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) + ++i; + if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) + break; + + + // we have another attribute, read it. + int j = i; + while ( j < len && dt[j] != '=' ) + ++j; + QCString attr( dt+i, j-i+1); + + i = ++j; // skip = + + // find the start of quotes + while ( i < len && dt[i] != '"' ) + ++i; + j = ++i; + + bool haveUtf = FALSE; + bool haveEnt = FALSE; + while ( j < len && dt[j] != '"' ) { + if ( ((unsigned char)dt[j]) > 0x7f ) + haveUtf = TRUE; + if ( dt[j] == '&' ) + haveEnt = TRUE; + ++j; + } + if ( i == j ) { + // empty value + i = j + 1; + continue; + } + + QCString value( dt+i, j-i+1 ); + i = j + 1; + + QString str = (haveUtf ? QString::fromUtf8( value ) + : QString::fromLatin1( value ) ); + if ( haveEnt ) + str = Qtopia::plainString( str ); + + /* + * add key + value + */ + find = dict[attr.data()]; + if (!find) + ev.setCustomField( attr, value ); + else { + setField( ev, *find, value ); + } + } + /* time to finalize */ + finalizeRecord( ev ); + add( ev ); + delete rec; + } + ::munmap(map_addr, attribute.st_size ); + m_changed = false; // changed during add + + return true; +} +void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { + /* AllDay is alway in UTC */ + if ( ev.isAllDay() ) { + OTimeZone utc = OTimeZone::utc(); + ev.setStartDateTime( utc.fromUTCDateTime( start ) ); + ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); + }else { + OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); + ev.setStartDateTime( zone.toDateTime( start ) ); + ev.setEndDateTime ( zone.toDateTime( end ) ); + } + if ( rec && rec->doesRecur() ) { + OTimeZone utc = OTimeZone::utc(); + ORecur recu( *rec ); // call copy c'tor; + recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); + recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); + recu.setStart( ev.startDateTime().date() ); + ev.setRecurrence( recu ); + } + + if (alarmTime != -1 ) { + QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); + OPimAlarm al( snd , dt ); + ev.notifiers().add( al ); + } + if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { + ev.setUid( 1 ); + } + if ( ev.hasRecurrence() ) + m_rep.insert( ev.uid(), ev ); + else + m_raw.insert( ev.uid(), ev ); + +} +void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { +// qWarning(" setting %s", value.latin1() ); + switch( id ) { + case FDescription: + e.setDescription( value ); + break; + case FLocation: + e.setLocation( value ); + break; + case FCategories: + e.setCategories( e.idsFromString( value ) ); + break; + case FUid: + e.setUid( value.toInt() ); + break; + case FType: + if ( value == "AllDay" ) { + e.setAllDay( true ); + e.setTimeZone( "UTC" ); + } + break; + case FAlarm: + alarmTime = value.toInt(); + break; + case FSound: + snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; + break; + // recurrence stuff + case FRType: + if ( value == "Daily" ) + recur()->setType( ORecur::Daily ); + else if ( value == "Weekly" ) + recur()->setType( ORecur::Weekly); + else if ( value == "MonthlyDay" ) + recur()->setType( ORecur::MonthlyDay ); + else if ( value == "MonthlyDate" ) + recur()->setType( ORecur::MonthlyDate ); + else if ( value == "Yearly" ) + recur()->setType( ORecur::Yearly ); + else + recur()->setType( ORecur::NoRepeat ); + break; + case FRWeekdays: + recur()->setDays( value.toInt() ); + break; + case FRPosition: + recur()->setPosition( value.toInt() ); + break; + case FRFreq: + recur()->setFrequency( value.toInt() ); + break; + case FRHasEndDate: + recur()->setHasEndDate( value.toInt() ); + break; + case FREndDate: { + rp_end = (time_t) value.toLong(); + break; + } + case FRStart: { + start = (time_t) value.toLong(); + break; + } + case FREnd: { + end = ( (time_t) value.toLong() ); + break; + } + case FNote: + e.setNote( value ); + break; + case FCreated: + created = value.toInt(); + break; + default: + break; + } +} diff --git a/libopie/pim/odatebookaccessbackend_xml.h b/libopie/pim/odatebookaccessbackend_xml.h new file mode 100644 index 0000000..40f69d8 --- a/dev/null +++ b/libopie/pim/odatebookaccessbackend_xml.h @@ -0,0 +1,48 @@ +#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H +#define OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H + +#include <qmap.h> + +#include "odatebookaccessbackend.h" + +class ODateBookAccessBackend_XML : public ODateBookAccessBackend { +public: + ODateBookAccessBackend_XML( const QString& appName, + const QString& fileName = QString::null); + ~ODateBookAccessBackend_XML(); + + bool load(); + bool reload(); + bool save(); + + QArray<int> allRecords()const; + QArray<int> queryByExample( const OEvent&, int ); + OEvent find( int uid )const; + void clear(); + bool add( const OEvent& ev ); + bool remove( int uid ); + bool replace( const OEvent& ev ); + + QArray<UID> rawEvents()const; + QArray<UID> rawRepeats()const; + QArray<UID> nonRepeats()const; + + OEvent::ValueList directNonRepeats(); + OEvent::ValueList directRawRepeats(); + +private: + bool m_changed :1 ; + bool loadFile(); + inline void finalizeRecord( OEvent& ev ); + inline void setField( OEvent&, int field, const QString& val ); + QString m_name; + QMap<int, OEvent> m_raw; + QMap<int, OEvent> m_rep; + + struct Data; + Data* data; + class Private; + Private *d; +}; + +#endif diff --git a/libopie/pim/oevent.cpp b/libopie/pim/oevent.cpp index aaae3b2..ada596c 100644 --- a/libopie/pim/oevent.cpp +++ b/libopie/pim/oevent.cpp @@ -187,6 +187,11 @@ bool OEvent::isMultipleDay()const { bool OEvent::isAllDay()const { return data->isAllDay; } +void OEvent::setAllDay( bool allDay ) { + changeOrModify(); + data->isAllDay = allDay; + if (allDay ) data->timezone = "UTC"; +} void OEvent::setTimeZone( const QString& tz ) { changeOrModify(); data->timezone = tz; diff --git a/libopie/pim/opimnotify.h b/libopie/pim/opimnotify.h index 3501948..b0de000 100644 --- a/libopie/pim/opimnotify.h +++ b/libopie/pim/opimnotify.h @@ -72,7 +72,7 @@ private: */ class OPimAlarm : public OPimNotify { public: - enum Sound{Loud=0, Silent, Custom }; + enum Sound{Loud=1, Silent=0, Custom=2 }; OPimAlarm( int sound = Silent, const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 ); OPimAlarm( const OPimAlarm& ); ~OPimAlarm(); diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp index c3416cb..22b2469 100644 --- a/libopie/pim/otodoaccessxml.cpp +++ b/libopie/pim/otodoaccessxml.cpp @@ -15,8 +15,6 @@ #include <qpe/stringutil.h> #include <qpe/timeconversion.h> -#include <opie/xmltree.h> - #include "otodoaccessxml.h" OTodoAccessXML::OTodoAccessXML( const QString& appName, diff --git a/libopie/pim/test/oevent_test.cpp b/libopie/pim/test/oevent_test.cpp index 50cc032..6f04995 100644 --- a/libopie/pim/test/oevent_test.cpp +++ b/libopie/pim/test/oevent_test.cpp @@ -1,6 +1,7 @@ #include <qdatetime.h> #include "../oevent.h" +#include "../odatebookaccess.h" int main(int argc, char* argv ) { OEvent ev; @@ -19,5 +20,31 @@ int main(int argc, char* argv ) { qWarning("%s", ev2.startDateTime().toString().latin1() ); qWarning("%s", ev2.startDateTimeInZone().toString().latin1() ); + + ODateBookAccess acc; + if(!acc.load() ) qWarning("could not load"); + + ODateBookAccess::List::Iterator it; + ODateBookAccess::List list = acc.allRecords(); + + for( it = list.begin(); it != list.end(); ++it ){ + OEvent ev = (*it); + qWarning("Summary: %s",ev.description().latin1() ); + qWarning("Start: %s End: %s",ev.startDateTime().toString().latin1(), ev.endDateTime().toString().latin1() ); + qWarning("All Day: %d",ev.isAllDay() ); + + } + QDate date1(2003,02,01 ); + QDate date2(2003,03,01 ); + + OEffectiveEvent::ValueList effList = acc.effectiveEvents( date1,date2 ); + OEffectiveEvent::ValueList::Iterator effIt; + + for( effIt = effList.begin(); effIt != effList.end(); ++effIt ){ + OEffectiveEvent ef = (*effIt); + qWarning("Summary: %s", ef.description().latin1() ); + qWarning("Date: %s", ef.date().toString().latin1() ); + } + return 0; } diff --git a/libopie2/opiepim/backend/obackendfactory.h b/libopie2/opiepim/backend/obackendfactory.h index b796fb8..3a73210 100644 --- a/libopie2/opiepim/backend/obackendfactory.h +++ b/libopie2/opiepim/backend/obackendfactory.h @@ -10,12 +10,22 @@ * either version 2 of the License, or (at your option) any later * version. * ===================================================================== - * ToDo: Use plugins + * ToDo: Use plugins * ===================================================================== * Version: $Id$ * ===================================================================== * History: * $Log$ + * Revision 1.5 2003/02/21 23:31:52 zecke + * Add XML datebookresource + * -clean up todoaccessxml header + * -implement some more stuff in the oeven tester + * -extend DefaultFactory to not crash and to use datebook + * + * -reading of OEvents is working nicely.. saving will be added + * tomorrow + * -fix spelling in ODateBookAcces + * * Revision 1.4 2002/10/14 15:55:18 eilers * Redeactivate SQL.. ;) * @@ -47,6 +57,7 @@ #include "otodoaccessxml.h" #include "ocontactaccessbackend_xml.h" +#include "odatebookaccessbackend_xml.h" #ifdef __USE_SQL #include "otodoaccesssql.h" @@ -64,9 +75,9 @@ class OBackendFactory CONTACT, DATE }; - + static T* Default( const QString backendName, const QString& appName ){ - + // __asm__("int3"); Config config( "pimaccess" ); @@ -78,34 +89,40 @@ class OBackendFactory dict.insert( "todo", new int (TODO) ); dict.insert( "contact", new int (CONTACT) ); + dict.insert( "datebook", new int(DATE) ); qWarning ("TODO is: %d", TODO); qWarning ("CONTACT is: %d", CONTACT); - - switch ( *dict.take( backendName ) ){ + + int *find = dict[ backendName ]; + if (!find ) return 0; + + switch ( *find ){ case TODO: #ifdef __USE_SQL - if ( backend == "sql" ) + if ( backend == "sql" ) return (T*) new OTodoAccessBackendSQL(""); #else - if ( backend == "sql" ) + if ( backend == "sql" ) qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); #endif return (T*) new OTodoAccessXML( appName ); case CONTACT: - if ( backend == "sql" ) + if ( backend == "sql" ) qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); return (T*) new OContactAccessBackend_XML( appName ); case DATE: - qWarning ("OBackendFactory:: DATE-Backend not implemented!"); - return NULL; + if ( backend == "sql" ) + qWarning("OBackendFactory:: sql Backend not implemented! Using XML instead!"); + + return (T*) new ODateBookAccessBackend_XML( appName ); default: return NULL; } - - + + } }; diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp new file mode 100644 index 0000000..a4c514b --- a/dev/null +++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp @@ -0,0 +1,395 @@ +#include <errno.h> +#include <fcntl.h> + +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include <unistd.h> + +#include <qasciidict.h> +#include <qfile.h> + +#include <qtopia/global.h> +#include <qtopia/stringutil.h> + +#include "opimnotifymanager.h" +#include "orecur.h" +#include "otimezone.h" +#include "odatebookaccessbackend_xml.h" + +namespace { + time_t start, end, created, rp_end; + ORecur* rec; + ORecur* recur() { + if (!rec) + rec = new ORecur; + + return rec; + } + int alarmTime; + int snd; + enum Attribute{ + FDescription = 0, + FLocation, + FCategories, + FUid, + FType, + FAlarm, + FSound, + FRType, + FRWeekdays, + FRPosition, + FRFreq, + FRHasEndDate, + FREndDate, + FRStart, + FREnd, + FNote, + FCreated + }; +} + +ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , + const QString& fileName ) + : ODateBookAccessBackend() { + m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; + m_changed = false; +} +ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { +} +bool ODateBookAccessBackend_XML::load() { + return loadFile(); +} +bool ODateBookAccessBackend_XML::reload() { + clear(); + return load(); +} +bool ODateBookAccessBackend_XML::save() { + if (!m_changed) return true; + m_changed = false; + + return true; +} +QArray<int> ODateBookAccessBackend_XML::allRecords()const { + QArray<int> ints( m_raw.count()+ m_rep.count() ); + uint i = 0; + QMap<int, OEvent>::ConstIterator it; + + for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { + ints[i] = it.key(); + i++; + } + for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { + ints[i] = it.key(); + i++; + } + + return ints; +} +QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) { + return QArray<int>(); +} +void ODateBookAccessBackend_XML::clear() { + m_raw.clear(); + m_rep.clear(); +} +OEvent ODateBookAccessBackend_XML::find( int uid ) const{ + if ( m_raw.contains( uid ) ) + return m_raw[uid]; + else + return m_rep[uid]; +} +bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { + m_changed = true; + if (ev.hasRecurrence() ) + m_rep.insert( ev.uid(), ev ); + else + m_raw.insert( ev.uid(), ev ); + + return true; +} +bool ODateBookAccessBackend_XML::remove( int uid ) { + m_changed = true; + m_rep.remove( uid ); + m_rep.remove( uid ); + + return true; +} +bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { + replace( ev.uid() ); + return add( ev ); +} +QArray<int> ODateBookAccessBackend_XML::rawEvents()const { + return allRecords(); +} +QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { + QArray<int> ints( m_rep.count() ); + uint i = 0; + QMap<int, OEvent>::ConstIterator it; + + for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { + ints[i] = it.key(); + i++; + } + + return ints; +} +QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { + QArray<int> ints( m_raw.count() ); + uint i = 0; + QMap<int, OEvent>::ConstIterator it; + + for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { + ints[i] = it.key(); + i++; + } + + return ints; +} +OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { + OEvent::ValueList list; + QMap<int, OEvent>::ConstIterator it; + for (it = m_raw.begin(); it != m_raw.end(); ++it ) + list.append( it.data() ); + + return list; +} +OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { + OEvent::ValueList list; + QMap<int, OEvent>::ConstIterator it; + for (it = m_rep.begin(); it != m_rep.end(); ++it ) + list.append( it.data() ); + + return list; +} +bool ODateBookAccessBackend_XML::loadFile() { + m_changed = false; + + int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); + if ( fd < 0 ) return false; + + struct stat attribute; + if ( ::fstat(fd, &attribute ) == -1 ) { + ::close( fd ); + return false; + } + void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); + if ( map_addr == ( (caddr_t)-1) ) { + ::close( fd ); + return false; + } + + ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); + ::close( fd ); + + QAsciiDict<int> dict(FCreated+1); + dict.setAutoDelete( true ); + dict.insert( "description", new int(FDescription) ); + dict.insert( "location", new int(FLocation) ); + dict.insert( "categories", new int(FCategories) ); + dict.insert( "uid", new int(FUid) ); + dict.insert( "type", new int(FType) ); + dict.insert( "alarm", new int(FAlarm) ); + dict.insert( "sound", new int(FSound) ); + dict.insert( "rtype", new int(FRType) ); + dict.insert( "rweekdays", new int(FRWeekdays) ); + dict.insert( "rposition", new int(FRPosition) ); + dict.insert( "rfreq", new int(FRFreq) ); + dict.insert( "rhasenddate", new int(FRHasEndDate) ); + dict.insert( "enddt", new int(FREndDate) ); + dict.insert( "start", new int(FRStart) ); + dict.insert( "end", new int(FREnd) ); + dict.insert( "note", new int(FNote) ); + dict.insert( "created", new int(FCreated) ); + + char* dt = (char*)map_addr; + int len = attribute.st_size; + int i = 0; + char* point; + const char* collectionString = "<event "; + int strLen = ::strlen(collectionString); + int *find; + while ( dt + 1 != 0 && (( point = ::strstr( dt+i, collectionString ) ) != 0 ) ) { + i = point -dt; + i+= strLen; + + alarmTime = -1; + snd = 0; // silent + + OEvent ev; + rec = 0; + + while ( TRUE ) { + while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) + ++i; + if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) + break; + + + // we have another attribute, read it. + int j = i; + while ( j < len && dt[j] != '=' ) + ++j; + QCString attr( dt+i, j-i+1); + + i = ++j; // skip = + + // find the start of quotes + while ( i < len && dt[i] != '"' ) + ++i; + j = ++i; + + bool haveUtf = FALSE; + bool haveEnt = FALSE; + while ( j < len && dt[j] != '"' ) { + if ( ((unsigned char)dt[j]) > 0x7f ) + haveUtf = TRUE; + if ( dt[j] == '&' ) + haveEnt = TRUE; + ++j; + } + if ( i == j ) { + // empty value + i = j + 1; + continue; + } + + QCString value( dt+i, j-i+1 ); + i = j + 1; + + QString str = (haveUtf ? QString::fromUtf8( value ) + : QString::fromLatin1( value ) ); + if ( haveEnt ) + str = Qtopia::plainString( str ); + + /* + * add key + value + */ + find = dict[attr.data()]; + if (!find) + ev.setCustomField( attr, value ); + else { + setField( ev, *find, value ); + } + } + /* time to finalize */ + finalizeRecord( ev ); + add( ev ); + delete rec; + } + ::munmap(map_addr, attribute.st_size ); + m_changed = false; // changed during add + + return true; +} +void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { + /* AllDay is alway in UTC */ + if ( ev.isAllDay() ) { + OTimeZone utc = OTimeZone::utc(); + ev.setStartDateTime( utc.fromUTCDateTime( start ) ); + ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); + }else { + OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); + ev.setStartDateTime( zone.toDateTime( start ) ); + ev.setEndDateTime ( zone.toDateTime( end ) ); + } + if ( rec && rec->doesRecur() ) { + OTimeZone utc = OTimeZone::utc(); + ORecur recu( *rec ); // call copy c'tor; + recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); + recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); + recu.setStart( ev.startDateTime().date() ); + ev.setRecurrence( recu ); + } + + if (alarmTime != -1 ) { + QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); + OPimAlarm al( snd , dt ); + ev.notifiers().add( al ); + } + if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { + ev.setUid( 1 ); + } + if ( ev.hasRecurrence() ) + m_rep.insert( ev.uid(), ev ); + else + m_raw.insert( ev.uid(), ev ); + +} +void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { +// qWarning(" setting %s", value.latin1() ); + switch( id ) { + case FDescription: + e.setDescription( value ); + break; + case FLocation: + e.setLocation( value ); + break; + case FCategories: + e.setCategories( e.idsFromString( value ) ); + break; + case FUid: + e.setUid( value.toInt() ); + break; + case FType: + if ( value == "AllDay" ) { + e.setAllDay( true ); + e.setTimeZone( "UTC" ); + } + break; + case FAlarm: + alarmTime = value.toInt(); + break; + case FSound: + snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; + break; + // recurrence stuff + case FRType: + if ( value == "Daily" ) + recur()->setType( ORecur::Daily ); + else if ( value == "Weekly" ) + recur()->setType( ORecur::Weekly); + else if ( value == "MonthlyDay" ) + recur()->setType( ORecur::MonthlyDay ); + else if ( value == "MonthlyDate" ) + recur()->setType( ORecur::MonthlyDate ); + else if ( value == "Yearly" ) + recur()->setType( ORecur::Yearly ); + else + recur()->setType( ORecur::NoRepeat ); + break; + case FRWeekdays: + recur()->setDays( value.toInt() ); + break; + case FRPosition: + recur()->setPosition( value.toInt() ); + break; + case FRFreq: + recur()->setFrequency( value.toInt() ); + break; + case FRHasEndDate: + recur()->setHasEndDate( value.toInt() ); + break; + case FREndDate: { + rp_end = (time_t) value.toLong(); + break; + } + case FRStart: { + start = (time_t) value.toLong(); + break; + } + case FREnd: { + end = ( (time_t) value.toLong() ); + break; + } + case FNote: + e.setNote( value ); + break; + case FCreated: + created = value.toInt(); + break; + default: + break; + } +} diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.h b/libopie2/opiepim/backend/odatebookaccessbackend_xml.h new file mode 100644 index 0000000..40f69d8 --- a/dev/null +++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.h @@ -0,0 +1,48 @@ +#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H +#define OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H + +#include <qmap.h> + +#include "odatebookaccessbackend.h" + +class ODateBookAccessBackend_XML : public ODateBookAccessBackend { +public: + ODateBookAccessBackend_XML( const QString& appName, + const QString& fileName = QString::null); + ~ODateBookAccessBackend_XML(); + + bool load(); + bool reload(); + bool save(); + + QArray<int> allRecords()const; + QArray<int> queryByExample( const OEvent&, int ); + OEvent find( int uid )const; + void clear(); + bool add( const OEvent& ev ); + bool remove( int uid ); + bool replace( const OEvent& ev ); + + QArray<UID> rawEvents()const; + QArray<UID> rawRepeats()const; + QArray<UID> nonRepeats()const; + + OEvent::ValueList directNonRepeats(); + OEvent::ValueList directRawRepeats(); + +private: + bool m_changed :1 ; + bool loadFile(); + inline void finalizeRecord( OEvent& ev ); + inline void setField( OEvent&, int field, const QString& val ); + QString m_name; + QMap<int, OEvent> m_raw; + QMap<int, OEvent> m_rep; + + struct Data; + Data* data; + class Private; + Private *d; +}; + +#endif diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp index c3416cb..22b2469 100644 --- a/libopie2/opiepim/backend/otodoaccessxml.cpp +++ b/libopie2/opiepim/backend/otodoaccessxml.cpp @@ -15,8 +15,6 @@ #include <qpe/stringutil.h> #include <qpe/timeconversion.h> -#include <opie/xmltree.h> - #include "otodoaccessxml.h" OTodoAccessXML::OTodoAccessXML( const QString& appName, diff --git a/libopie2/opiepim/core/odatebookaccess.cpp b/libopie2/opiepim/core/odatebookaccess.cpp index 5f97e7c..08e61ff 100644 --- a/libopie2/opiepim/core/odatebookaccess.cpp +++ b/libopie2/opiepim/core/odatebookaccess.cpp @@ -8,6 +8,7 @@ ODateBookAccess::ODateBookAccess( ODateBookAccessBackend* back, enum Access ac ) back = OBackendFactory<ODateBookAccessBackend>::Default("datebook", QString::null ); m_backEnd = back; + setBackEnd( m_backEnd ); } ODateBookAccess::~ODateBookAccess() { } @@ -29,9 +30,9 @@ ODateBookAccess::List ODateBookAccess::nonRepeats()const { List lis( ints, this ); return lis; } -OEffectiveEvent::ValueList ODateBookAccess::effecticeEvents( const QDate& from, const QDate& to ) { +OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDate& from, const QDate& to ) { return m_backEnd->effecticeEvents( from, to ); } -OEffectiveEvent::ValueList ODateBookAccess::effecticeEvents( const QDateTime& start ) { +OEffectiveEvent::ValueList ODateBookAccess::effectiveEvents( const QDateTime& start ) { return m_backEnd->effecticeEvents( start ); } diff --git a/libopie2/opiepim/core/odatebookaccess.h b/libopie2/opiepim/core/odatebookaccess.h index 3f2c728..7047039 100644 --- a/libopie2/opiepim/core/odatebookaccess.h +++ b/libopie2/opiepim/core/odatebookaccess.h @@ -20,8 +20,8 @@ public: /** return non repeating events */ List nonRepeats()const; - OEffectiveEvent::ValueList effecticeEvents( const QDate& from, const QDate& to ); - OEffectiveEvent::ValueList effecticeEvents( const QDateTime& start ); + OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to ); + OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start ); private: ODateBookAccessBackend* m_backEnd; diff --git a/libopie2/opiepim/core/opimnotify.h b/libopie2/opiepim/core/opimnotify.h index 3501948..b0de000 100644 --- a/libopie2/opiepim/core/opimnotify.h +++ b/libopie2/opiepim/core/opimnotify.h @@ -72,7 +72,7 @@ private: */ class OPimAlarm : public OPimNotify { public: - enum Sound{Loud=0, Silent, Custom }; + enum Sound{Loud=1, Silent=0, Custom=2 }; OPimAlarm( int sound = Silent, const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 ); OPimAlarm( const OPimAlarm& ); ~OPimAlarm(); diff --git a/libopie2/opiepim/oevent.cpp b/libopie2/opiepim/oevent.cpp index aaae3b2..ada596c 100644 --- a/libopie2/opiepim/oevent.cpp +++ b/libopie2/opiepim/oevent.cpp @@ -187,6 +187,11 @@ bool OEvent::isMultipleDay()const { bool OEvent::isAllDay()const { return data->isAllDay; } +void OEvent::setAllDay( bool allDay ) { + changeOrModify(); + data->isAllDay = allDay; + if (allDay ) data->timezone = "UTC"; +} void OEvent::setTimeZone( const QString& tz ) { changeOrModify(); data->timezone = tz; |