summaryrefslogtreecommitdiff
path: root/libopie2
authorzecke <zecke>2003-02-22 16:11:16 (UTC)
committer zecke <zecke>2003-02-22 16:11:16 (UTC)
commit397a7b1635488deda02b36df70692e27f59bb3e0 (patch) (unidiff)
tree1232b1b7e8ac84c5d48df79b635ba61acbdf0f62 /libopie2
parente7981098a5c373748d98158e8a6c59750bb0d7dc (diff)
downloadopie-397a7b1635488deda02b36df70692e27f59bb3e0.zip
opie-397a7b1635488deda02b36df70692e27f59bb3e0.tar.gz
opie-397a7b1635488deda02b36df70692e27f59bb3e0.tar.bz2
Implement saving of events
Implement the ExceptionList Add Children and parent to OEvent Make ORecur honor exceptions Extend the test app to add and save
Diffstat (limited to 'libopie2') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp184
-rw-r--r--libopie2/opiepim/core/orecur.cpp66
-rw-r--r--libopie2/opiepim/core/orecur.h4
-rw-r--r--libopie2/opiepim/oevent.cpp64
-rw-r--r--libopie2/opiepim/oevent.h10
5 files changed, 312 insertions, 16 deletions
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
index a4c514b..5239d84 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
@@ -1,6 +1,9 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <stdio.h>
5#include <stdlib.h>
6
4#include <sys/types.h> 7#include <sys/types.h>
5#include <sys/mman.h> 8#include <sys/mman.h>
6#include <sys/stat.h> 9#include <sys/stat.h>
@@ -12,6 +15,7 @@
12 15
13#include <qtopia/global.h> 16#include <qtopia/global.h>
14#include <qtopia/stringutil.h> 17#include <qtopia/stringutil.h>
18#include <qtopia/timeconversion.h>
15 19
16#include "opimnotifymanager.h" 20#include "opimnotifymanager.h"
17#include "orecur.h" 21#include "orecur.h"
@@ -30,11 +34,11 @@ namespace {
30 int alarmTime; 34 int alarmTime;
31 int snd; 35 int snd;
32 enum Attribute{ 36 enum Attribute{
33 FDescription = 0, 37 FDescription = 0,
34 FLocation, 38 FLocation,
35 FCategories, 39 FCategories,
36 FUid, 40 FUid,
37 FType, 41 FType,
38 FAlarm, 42 FAlarm,
39 FSound, 43 FSound,
40 FRType, 44 FRType,
@@ -46,8 +50,89 @@ namespace {
46 FRStart, 50 FRStart,
47 FREnd, 51 FREnd,
48 FNote, 52 FNote,
49 FCreated 53 FCreated,
54 FTimeZone,
55 FRecParent,
56 FRecChildren,
57 FExceptions
50 }; 58 };
59 inline void save( const OEvent& ev, QString& buf ) {
60 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
61 if (!ev.location().isEmpty() )
62 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
63
64 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
65 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
66
67 if (ev.isAllDay() )
68 buf += " type=\"AllDay\"";
69
70 if (ev.hasNotifiers() ) {
71 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
72 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
73 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
74 if ( alarm.sound() == OPimAlarm::Loud )
75 buf += "loud";
76 else
77 buf += "silent";
78 buf += "\"";
79 }
80 if ( ev.hasRecurrence() ) {
81 buf += ev.recurrence().toString();
82 }
83
84 /*
85 * fscking timezones :) well, we'll first convert
86 * the QDateTime to a QDateTime in UTC time
87 * and then we'll create a nice time_t
88 */
89 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
90 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
91 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
92 if (!ev.note().isEmpty() ) {
93 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
94 }
95
96 buf += " timezone=\"";
97 if ( ev.timeZone().isEmpty() )
98 buf += "None";
99 else
100 buf += ev.timeZone();
101
102 if (ev.parent() != 0 ) {
103 buf += " recparent=\""+QString::number(ev.parent() )+"\"";
104 }
105
106 if (ev.children().count() != 0 ) {
107 QArray<int> children = ev.children();
108 buf += " recchildren=\"";
109 for ( uint i = 0; i < children.count(); i++ ) {
110 if ( i != 0 ) buf += " ";
111 buf += QString::number( children[i] );
112 }
113 buf+= "\"";
114 }
115
116 // skip custom writing
117 }
118
119 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
120 QMap<int, OEvent>::ConstIterator it;
121 QString buf;
122 QCString str;
123 int total_written;
124 for ( it = list.begin(); it != list.end(); ++it ) {
125 buf = "<event";
126 save( it.data(), buf );
127 buf += " />\n";
128 str = buf.utf8();
129
130 total_written = file.writeBlock(str.data(), str.length() );
131 if ( total_written != int(str.length() ) )
132 return false;
133 }
134 return true;
135 }
51} 136}
52 137
53ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , 138ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
@@ -66,9 +151,54 @@ bool ODateBookAccessBackend_XML::reload() {
66 return load(); 151 return load();
67} 152}
68bool ODateBookAccessBackend_XML::save() { 153bool ODateBookAccessBackend_XML::save() {
69 if (!m_changed) return true; 154 qWarning("going to save now");
70 m_changed = false; 155// if (!m_changed) return true;
156
157 int total_written;
158 QString strFileNew = m_name + ".new";
159
160 QFile f( strFileNew );
161 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
162
163 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
164 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
165 buf += "<events>\n";
166 QCString str = buf.utf8();
167 total_written = f.writeBlock( str.data(), str.length() );
168 if ( total_written != int(str.length() ) ) {
169 f.close();
170 QFile::remove( strFileNew );
171 return false;
172 }
71 173
174 if (!forAll( m_raw, f ) ) {
175 f.close();
176 QFile::remove( strFileNew );
177 return false;
178 }
179 if (!forAll( m_rep, f ) ) {
180 f.close();
181 QFile::remove( strFileNew );
182 return false;
183 }
184
185 buf = "</events>\n</DATEBOOK>\n";
186 str = buf.utf8();
187 total_written = f.writeBlock( str.data(), str.length() );
188 if ( total_written != int(str.length() ) ) {
189 f.close();
190 QFile::remove( strFileNew );
191 return false;
192 }
193 f.close();
194
195 exit(0);
196 if ( ::rename( strFileNew, m_name ) < 0 ) {
197 QFile::remove( strFileNew );
198 return false;
199 }
200
201 m_changed = false;
72 return true; 202 return true;
73} 203}
74QArray<int> ODateBookAccessBackend_XML::allRecords()const { 204QArray<int> ODateBookAccessBackend_XML::allRecords()const {
@@ -183,7 +313,7 @@ bool ODateBookAccessBackend_XML::loadFile() {
183 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); 313 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
184 ::close( fd ); 314 ::close( fd );
185 315
186 QAsciiDict<int> dict(FCreated+1); 316 QAsciiDict<int> dict(FExceptions+1);
187 dict.setAutoDelete( true ); 317 dict.setAutoDelete( true );
188 dict.insert( "description", new int(FDescription) ); 318 dict.insert( "description", new int(FDescription) );
189 dict.insert( "location", new int(FLocation) ); 319 dict.insert( "location", new int(FLocation) );
@@ -202,6 +332,10 @@ bool ODateBookAccessBackend_XML::loadFile() {
202 dict.insert( "end", new int(FREnd) ); 332 dict.insert( "end", new int(FREnd) );
203 dict.insert( "note", new int(FNote) ); 333 dict.insert( "note", new int(FNote) );
204 dict.insert( "created", new int(FCreated) ); 334 dict.insert( "created", new int(FCreated) );
335 dict.insert( "recparent", new int(FRecParent) );
336 dict.insert( "recchildren", new int(FRecChildren) );
337 dict.insert( "exceptions", new int(FExceptions) );
338 dict.insert( "timezone", new int(FTimeZone) );
205 339
206 char* dt = (char*)map_addr; 340 char* dt = (char*)map_addr;
207 int len = attribute.st_size; 341 int len = attribute.st_size;
@@ -289,10 +423,15 @@ void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
289 OTimeZone utc = OTimeZone::utc(); 423 OTimeZone utc = OTimeZone::utc();
290 ev.setStartDateTime( utc.fromUTCDateTime( start ) ); 424 ev.setStartDateTime( utc.fromUTCDateTime( start ) );
291 ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); 425 ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
426 ev.setTimeZone( "UTC"); // make sure it is really utc
292 }else { 427 }else {
428 /* to current date time */
293 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 429 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
294 ev.setStartDateTime( zone.toDateTime( start ) ); 430 QDateTime date = zone.toDateTime( start );
295 ev.setEndDateTime ( zone.toDateTime( end ) ); 431 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
432
433 date = zone.toDateTime( end );
434 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
296 } 435 }
297 if ( rec && rec->doesRecur() ) { 436 if ( rec && rec->doesRecur() ) {
298 OTimeZone utc = OTimeZone::utc(); 437 OTimeZone utc = OTimeZone::utc();
@@ -389,6 +528,29 @@ void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& val
389 case FCreated: 528 case FCreated:
390 created = value.toInt(); 529 created = value.toInt();
391 break; 530 break;
531 case FRecParent:
532 e.setParent( value.toInt() );
533 break;
534 case FRecChildren:{
535 QStringList list = QStringList::split(' ', value );
536 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
537 e.addChild( (*it).toInt() );
538 }
539 }
540 break;
541 case FExceptions:{
542 QStringList list = QStringList::split(' ', value );
543 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
544 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
545 qWarning("adding exception %s", date.toString().latin1() );
546 recur()->exceptions().append( date );
547 }
548 }
549 break;
550 case FTimeZone:
551 if ( value != "None" )
552 e.setTimeZone( value );
553 break;
392 default: 554 default:
393 break; 555 break;
394 } 556 }
diff --git a/libopie2/opiepim/core/orecur.cpp b/libopie2/opiepim/core/orecur.cpp
index e6a4787..e3b45b4 100644
--- a/libopie2/opiepim/core/orecur.cpp
+++ b/libopie2/opiepim/core/orecur.cpp
@@ -1,7 +1,10 @@
1#include <time.h>
2
1#include <qshared.h> 3#include <qshared.h>
2 4
3#include <qtopia/timeconversion.h> 5#include <qtopia/timeconversion.h>
4 6
7#include "otimezone.h"
5#include "orecur.h" 8#include "orecur.h"
6 9
7struct ORecur::Data : public QShared { 10struct ORecur::Data : public QShared {
@@ -81,6 +84,14 @@ bool ORecur::doesRecur( const QDate& date ) {
81// GPL from Datebookdb.cpp 84// GPL from Datebookdb.cpp
82// FIXME exception list! 85// FIXME exception list!
83bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { 86bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
87 bool stillLooking;
88 stillLooking = p_nextOccurrence( from, next );
89 while ( stillLooking && data->list.contains(next) )
90 stillLooking = p_nextOccurrence( next.addDays(1), next );
91
92 return stillLooking;
93}
94bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
84 95
85 // easy checks, first are we too far in the future or too far in the past? 96 // easy checks, first are we too far in the future or too far in the past?
86 QDate tmpDate; 97 QDate tmpDate;
@@ -95,7 +106,7 @@ bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
95 if (hasEndDate() && endDate() < from) 106 if (hasEndDate() && endDate() < from)
96 return FALSE; 107 return FALSE;
97 108
98 if (start() >= from) { 109 if (start() >= from ) {
99 next = start(); 110 next = start();
100 return TRUE; 111 return TRUE;
101 } 112 }
@@ -443,4 +454,57 @@ void ORecur::checkOrModify() {
443 data = d2; 454 data = d2;
444 } 455 }
445} 456}
457QString ORecur::toString()const {
458 QString buf;
459
460 buf += " rtype=\"";
461 switch ( data->type ) {
462 case ORecur::Daily:
463 buf += "Daily";
464 break;
465 case ORecur::Weekly:
466 buf += "Weekly";
467 break;
468 case ORecur::MonthlyDay:
469 buf += "MonthlyDay";
470 break;
471 case ORecur::MonthlyDate:
472 buf += "MonthlyDate";
473 break;
474 case ORecur::Yearly:
475 buf += "Yearly";
476 break;
477 default:
478 buf += "NoRepeat";
479 break;
480 }
481 buf += "\"";
482 if (data->days > 0 )
483 buf += " rweekdays=\"" + QString::number( static_cast<int>( data->days ) ) + "\"";
484 if ( data->pos != 0 )
485 buf += " rposition=\"" + QString::number(data->pos ) + "\"";
486
487 buf += " rfreq=\"" + QString::number( data->freq ) + "\"";
488 buf += " rhasenddate=\"" + QString::number( static_cast<int>( data->hasEnd ) ) + "\"";
489 if ( data->hasEnd )
490 buf += " enddt=\""
491 + QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) )
492 + "\"";
493 buf += " created=\"" + QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) + "\"";
494
495 if ( data->list.isEmpty() ) return buf;
496 // save exceptions list here!!
497 ExceptionList::ConstIterator it;
498 ExceptionList list = data->list;
499 buf += " exceptions=\"";
500 QDate date;
501 for ( it = list.begin(); it != list.end(); ++it ) {
502 date = (*it);
503 if ( it != list.begin() ) buf += " ";
504
505 buf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() );
506 }
507 buf += "\"";
446 508
509 return buf;
510}
diff --git a/libopie2/opiepim/core/orecur.h b/libopie2/opiepim/core/orecur.h
index 1e0014b..b214b3f 100644
--- a/libopie2/opiepim/core/orecur.h
+++ b/libopie2/opiepim/core/orecur.h
@@ -73,7 +73,11 @@ public:
73 void setRepitition(int ); 73 void setRepitition(int );
74 74
75 void setService( const QString& ser ); 75 void setService( const QString& ser );
76
77 /* almost internal */
78 QString toString()const;
76private: 79private:
80 bool p_nextOccurrence( const QDate& from, QDate& next );
77 void deref(); 81 void deref();
78 inline void checkOrModify(); 82 inline void checkOrModify();
79 83
diff --git a/libopie2/opiepim/oevent.cpp b/libopie2/opiepim/oevent.cpp
index ada596c..c3eeee2 100644
--- a/libopie2/opiepim/oevent.cpp
+++ b/libopie2/opiepim/oevent.cpp
@@ -42,9 +42,11 @@ int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) {
42 42
43struct OEvent::Data : public QShared { 43struct OEvent::Data : public QShared {
44 Data() : QShared() { 44 Data() : QShared() {
45 child = 0;
45 recur = 0; 46 recur = 0;
46 manager = 0; 47 manager = 0;
47 isAllDay = false; 48 isAllDay = false;
49 parent = 0;
48 } 50 }
49 ~Data() { 51 ~Data() {
50 delete manager; 52 delete manager;
@@ -60,6 +62,8 @@ struct OEvent::Data : public QShared {
60 QDateTime end; 62 QDateTime end;
61 bool isAllDay : 1; 63 bool isAllDay : 1;
62 QString timezone; 64 QString timezone;
65 QArray<int>* child;
66 int parent;
63}; 67};
64 68
65OEvent::OEvent( int uid ) 69OEvent::OEvent( int uid )
@@ -102,7 +106,7 @@ void OEvent::setLocation( const QString& loc ) {
102QString OEvent::location()const { 106QString OEvent::location()const {
103 return data->location; 107 return data->location;
104} 108}
105OPimNotifyManager &OEvent::notifiers() { 109OPimNotifyManager &OEvent::notifiers()const {
106 // I hope we can skip the changeOrModify here 110 // I hope we can skip the changeOrModify here
107 // the notifier should take care of it 111 // the notifier should take care of it
108 // and OPimNotify is shared too 112 // and OPimNotify is shared too
@@ -112,7 +116,13 @@ OPimNotifyManager &OEvent::notifiers() {
112 return *data->manager; 116 return *data->manager;
113} 117}
114bool OEvent::hasNotifiers()const { 118bool OEvent::hasNotifiers()const {
115 return ( data->manager); 119 if (!data->manager )
120 return false;
121 if (data->manager->reminders().isEmpty() &&
122 data->manager->alarms().isEmpty() )
123 return false;
124
125 return true;
116} 126}
117ORecur OEvent::recurrence()const { 127ORecur OEvent::recurrence()const {
118 if (!data->recur) 128 if (!data->recur)
@@ -197,6 +207,7 @@ void OEvent::setTimeZone( const QString& tz ) {
197 data->timezone = tz; 207 data->timezone = tz;
198} 208}
199QString OEvent::timeZone()const { 209QString OEvent::timeZone()const {
210 if (data->isAllDay ) return QString::fromLatin1("UTC");
200 return data->timezone; 211 return data->timezone;
201} 212}
202bool OEvent::match( const QRegExp& )const { 213bool OEvent::match( const QRegExp& )const {
@@ -239,6 +250,11 @@ void OEvent::changeOrModify() {
239 d2->end = data->end; 250 d2->end = data->end;
240 d2->isAllDay = data->isAllDay; 251 d2->isAllDay = data->isAllDay;
241 d2->timezone = data->timezone; 252 d2->timezone = data->timezone;
253 d2->parent = data->parent;
254 d2->child = data->child;
255
256 if (d2->child )
257 d2->child->detach();
242 258
243 data = d2; 259 data = d2;
244 } 260 }
@@ -256,8 +272,50 @@ QMap<int, QString> OEvent::toMap()const {
256QMap<QString, QString> OEvent::toExtraMap()const { 272QMap<QString, QString> OEvent::toExtraMap()const {
257 return QMap<QString, QString>(); 273 return QMap<QString, QString>();
258} 274}
275int OEvent::parent()const {
276 return data->parent;
277}
278void OEvent::setParent( int uid ) {
279 changeOrModify();
280 data->parent = uid;
281}
282QArray<int> OEvent::children() const{
283 if (!data->child) return QArray<int>();
284 else
285 return data->child->copy();
286}
287void OEvent::setChildren( const QArray<int>& arr ) {
288 changeOrModify();
289 if (data->child) delete data->child;
259 290
260 291 data->child = new QArray<int>( arr );
292 data->child->detach();
293}
294void OEvent::addChild( int uid ) {
295 changeOrModify();
296 if (!data->child ) {
297 data->child = new QArray<int>(1);
298 (*data->child)[0] = uid;
299 }else{
300 int count = data->child->count();
301 data->child->resize( count + 1 );
302 (*data->child)[count] = uid;
303 }
304}
305void OEvent::removeChild( int uid ) {
306 if (!data->child || !data->child->contains( uid ) ) return;
307 changeOrModify();
308 QArray<int> newAr( data->child->count() - 1 );
309 int j = 0;
310 uint count = data->child->count();
311 for ( uint i = 0; i < count; i++ ) {
312 if ( (*data->child)[i] != uid ) {
313 newAr[j] = (*data->child)[i];
314 j++;
315 }
316 }
317 (*data->child) = newAr;
318}
261struct OEffectiveEvent::Data : public QShared { 319struct OEffectiveEvent::Data : public QShared {
262 Data() : QShared() { 320 Data() : QShared() {
263 } 321 }
diff --git a/libopie2/opiepim/oevent.h b/libopie2/opiepim/oevent.h
index c718e2e..585515c 100644
--- a/libopie2/opiepim/oevent.h
+++ b/libopie2/opiepim/oevent.h
@@ -61,7 +61,7 @@ public:
61 void setLocation( const QString& loc ); 61 void setLocation( const QString& loc );
62 62
63 bool hasNotifiers()const; 63 bool hasNotifiers()const;
64 OPimNotifyManager &notifiers(); 64 OPimNotifyManager &notifiers()const;
65 65
66 ORecur recurrence()const; 66 ORecur recurrence()const;
67 void setRecurrence( const ORecur& ); 67 void setRecurrence( const ORecur& );
@@ -99,7 +99,15 @@ public:
99 99
100 bool match( const QRegExp& )const; 100 bool match( const QRegExp& )const;
101 101
102 /** For exception to recurrence here is a list of children... */
103 QArray<int> children()const;
104 void setChildren( const QArray<int>& );
105 void addChild( int uid );
106 void removeChild( int uid );
102 107
108 /** return the parent OEvent */
109 int parent()const;
110 void setParent( int uid );
103 111
104 112
105 /* needed reimp */ 113 /* needed reimp */