-rw-r--r-- | libopie/pim/odatebookaccessbackend_xml.cpp | 184 | ||||
-rw-r--r-- | libopie/pim/oevent.cpp | 64 | ||||
-rw-r--r-- | libopie/pim/oevent.h | 10 | ||||
-rw-r--r-- | libopie/pim/orecur.cpp | 66 | ||||
-rw-r--r-- | libopie/pim/orecur.h | 4 | ||||
-rw-r--r-- | libopie/pim/test/oevent_test.cpp | 10 | ||||
-rw-r--r-- | libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp | 184 | ||||
-rw-r--r-- | libopie2/opiepim/core/orecur.cpp | 66 | ||||
-rw-r--r-- | libopie2/opiepim/core/orecur.h | 4 | ||||
-rw-r--r-- | libopie2/opiepim/oevent.cpp | 64 | ||||
-rw-r--r-- | libopie2/opiepim/oevent.h | 10 |
11 files changed, 631 insertions, 35 deletions
diff --git a/libopie/pim/odatebookaccessbackend_xml.cpp b/libopie/pim/odatebookaccessbackend_xml.cpp index a4c514b..5239d84 100644 --- a/libopie/pim/odatebookaccessbackend_xml.cpp +++ b/libopie/pim/odatebookaccessbackend_xml.cpp | |||
@@ -3,2 +3,5 @@ | |||
3 | 3 | ||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | |||
4 | #include <sys/types.h> | 7 | #include <sys/types.h> |
@@ -14,2 +17,3 @@ | |||
14 | #include <qtopia/stringutil.h> | 17 | #include <qtopia/stringutil.h> |
18 | #include <qtopia/timeconversion.h> | ||
15 | 19 | ||
@@ -32,7 +36,7 @@ namespace { | |||
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, |
@@ -48,4 +52,85 @@ namespace { | |||
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 | } |
@@ -68,5 +153,50 @@ bool ODateBookAccessBackend_XML::reload() { | |||
68 | bool ODateBookAccessBackend_XML::save() { | 153 | bool 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; |
@@ -185,3 +315,3 @@ bool ODateBookAccessBackend_XML::loadFile() { | |||
185 | 315 | ||
186 | QAsciiDict<int> dict(FCreated+1); | 316 | QAsciiDict<int> dict(FExceptions+1); |
187 | dict.setAutoDelete( true ); | 317 | dict.setAutoDelete( true ); |
@@ -204,2 +334,6 @@ bool ODateBookAccessBackend_XML::loadFile() { | |||
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 | ||
@@ -291,6 +425,11 @@ void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { | |||
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 | } |
@@ -391,2 +530,25 @@ void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& val | |||
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: |
diff --git a/libopie/pim/oevent.cpp b/libopie/pim/oevent.cpp index ada596c..c3eeee2 100644 --- a/libopie/pim/oevent.cpp +++ b/libopie/pim/oevent.cpp | |||
@@ -44,2 +44,3 @@ struct OEvent::Data : public QShared { | |||
44 | Data() : QShared() { | 44 | Data() : QShared() { |
45 | child = 0; | ||
45 | recur = 0; | 46 | recur = 0; |
@@ -47,2 +48,3 @@ struct OEvent::Data : public QShared { | |||
47 | isAllDay = false; | 48 | isAllDay = false; |
49 | parent = 0; | ||
48 | } | 50 | } |
@@ -62,2 +64,4 @@ struct OEvent::Data : public QShared { | |||
62 | QString timezone; | 64 | QString timezone; |
65 | QArray<int>* child; | ||
66 | int parent; | ||
63 | }; | 67 | }; |
@@ -104,3 +108,3 @@ QString OEvent::location()const { | |||
104 | } | 108 | } |
105 | OPimNotifyManager &OEvent::notifiers() { | 109 | OPimNotifyManager &OEvent::notifiers()const { |
106 | // I hope we can skip the changeOrModify here | 110 | // I hope we can skip the changeOrModify here |
@@ -114,3 +118,9 @@ OPimNotifyManager &OEvent::notifiers() { | |||
114 | bool OEvent::hasNotifiers()const { | 118 | bool 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 | } |
@@ -199,2 +209,3 @@ void OEvent::setTimeZone( const QString& tz ) { | |||
199 | QString OEvent::timeZone()const { | 209 | QString OEvent::timeZone()const { |
210 | if (data->isAllDay ) return QString::fromLatin1("UTC"); | ||
200 | return data->timezone; | 211 | return data->timezone; |
@@ -241,2 +252,7 @@ void OEvent::changeOrModify() { | |||
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 | ||
@@ -258,4 +274,46 @@ QMap<QString, QString> OEvent::toExtraMap()const { | |||
258 | } | 274 | } |
275 | int OEvent::parent()const { | ||
276 | return data->parent; | ||
277 | } | ||
278 | void OEvent::setParent( int uid ) { | ||
279 | changeOrModify(); | ||
280 | data->parent = uid; | ||
281 | } | ||
282 | QArray<int> OEvent::children() const{ | ||
283 | if (!data->child) return QArray<int>(); | ||
284 | else | ||
285 | return data->child->copy(); | ||
286 | } | ||
287 | void 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 | } | ||
294 | void 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 | } | ||
305 | void 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 | } | ||
261 | struct OEffectiveEvent::Data : public QShared { | 319 | struct OEffectiveEvent::Data : public QShared { |
diff --git a/libopie/pim/oevent.h b/libopie/pim/oevent.h index c718e2e..585515c 100644 --- a/libopie/pim/oevent.h +++ b/libopie/pim/oevent.h | |||
@@ -63,3 +63,3 @@ public: | |||
63 | bool hasNotifiers()const; | 63 | bool hasNotifiers()const; |
64 | OPimNotifyManager ¬ifiers(); | 64 | OPimNotifyManager ¬ifiers()const; |
65 | 65 | ||
@@ -101,3 +101,11 @@ public: | |||
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 | ||
diff --git a/libopie/pim/orecur.cpp b/libopie/pim/orecur.cpp index e6a4787..e3b45b4 100644 --- a/libopie/pim/orecur.cpp +++ b/libopie/pim/orecur.cpp | |||
@@ -1 +1,3 @@ | |||
1 | #include <time.h> | ||
2 | |||
1 | #include <qshared.h> | 3 | #include <qshared.h> |
@@ -4,2 +6,3 @@ | |||
4 | 6 | ||
7 | #include "otimezone.h" | ||
5 | #include "orecur.h" | 8 | #include "orecur.h" |
@@ -83,2 +86,10 @@ bool ORecur::doesRecur( const QDate& date ) { | |||
83 | bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { | 86 | bool 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 | } | ||
94 | bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) { | ||
84 | 95 | ||
@@ -97,3 +108,3 @@ bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { | |||
97 | 108 | ||
98 | if (start() >= from) { | 109 | if (start() >= from ) { |
99 | next = start(); | 110 | next = start(); |
@@ -445,2 +456,55 @@ void ORecur::checkOrModify() { | |||
445 | } | 456 | } |
457 | QString 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/libopie/pim/orecur.h b/libopie/pim/orecur.h index 1e0014b..b214b3f 100644 --- a/libopie/pim/orecur.h +++ b/libopie/pim/orecur.h | |||
@@ -75,3 +75,7 @@ public: | |||
75 | void setService( const QString& ser ); | 75 | void setService( const QString& ser ); |
76 | |||
77 | /* almost internal */ | ||
78 | QString toString()const; | ||
76 | private: | 79 | private: |
80 | bool p_nextOccurrence( const QDate& from, QDate& next ); | ||
77 | void deref(); | 81 | void deref(); |
diff --git a/libopie/pim/test/oevent_test.cpp b/libopie/pim/test/oevent_test.cpp index 6f04995..247b83b 100644 --- a/libopie/pim/test/oevent_test.cpp +++ b/libopie/pim/test/oevent_test.cpp | |||
@@ -7,8 +7,8 @@ int main(int argc, char* argv ) { | |||
7 | OEvent ev; | 7 | OEvent ev; |
8 | ev.setUid( 20 ); | 8 | // ev.setUid( 20 ); |
9 | 9 | ||
10 | ev.setDescription( "Foo" ); | 10 | ev.setDescription( "Foo Descsfewrf" ); |
11 | 11 | ||
12 | OEvent ev2 = ev; | 12 | OEvent ev2 = ev; |
13 | ev2.setDescription("Foo2"); | 13 | ev2.setDescription("Foo3"); |
14 | qWarning("%s", ev2.description().latin1() ); | 14 | qWarning("%s", ev2.description().latin1() ); |
@@ -22,2 +22,3 @@ int main(int argc, char* argv ) { | |||
22 | qWarning("%s", ev2.startDateTimeInZone().toString().latin1() ); | 22 | qWarning("%s", ev2.startDateTimeInZone().toString().latin1() ); |
23 | qWarning("%d %d", ev.isAllDay(), ev2.isAllDay() ); | ||
23 | 24 | ||
@@ -47,2 +48,5 @@ int main(int argc, char* argv ) { | |||
47 | } | 48 | } |
49 | ev.setUid( 1 ); | ||
50 | acc.add( ev ); | ||
51 | acc.save(); | ||
48 | 52 | ||
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 | |||
@@ -3,2 +3,5 @@ | |||
3 | 3 | ||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | |||
4 | #include <sys/types.h> | 7 | #include <sys/types.h> |
@@ -14,2 +17,3 @@ | |||
14 | #include <qtopia/stringutil.h> | 17 | #include <qtopia/stringutil.h> |
18 | #include <qtopia/timeconversion.h> | ||
15 | 19 | ||
@@ -32,7 +36,7 @@ namespace { | |||
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, |
@@ -48,4 +52,85 @@ namespace { | |||
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 | } |
@@ -68,5 +153,50 @@ bool ODateBookAccessBackend_XML::reload() { | |||
68 | bool ODateBookAccessBackend_XML::save() { | 153 | bool 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; |
@@ -185,3 +315,3 @@ bool ODateBookAccessBackend_XML::loadFile() { | |||
185 | 315 | ||
186 | QAsciiDict<int> dict(FCreated+1); | 316 | QAsciiDict<int> dict(FExceptions+1); |
187 | dict.setAutoDelete( true ); | 317 | dict.setAutoDelete( true ); |
@@ -204,2 +334,6 @@ bool ODateBookAccessBackend_XML::loadFile() { | |||
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 | ||
@@ -291,6 +425,11 @@ void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { | |||
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 | } |
@@ -391,2 +530,25 @@ void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& val | |||
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: |
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 +1,3 @@ | |||
1 | #include <time.h> | ||
2 | |||
1 | #include <qshared.h> | 3 | #include <qshared.h> |
@@ -4,2 +6,3 @@ | |||
4 | 6 | ||
7 | #include "otimezone.h" | ||
5 | #include "orecur.h" | 8 | #include "orecur.h" |
@@ -83,2 +86,10 @@ bool ORecur::doesRecur( const QDate& date ) { | |||
83 | bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { | 86 | bool 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 | } | ||
94 | bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) { | ||
84 | 95 | ||
@@ -97,3 +108,3 @@ bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { | |||
97 | 108 | ||
98 | if (start() >= from) { | 109 | if (start() >= from ) { |
99 | next = start(); | 110 | next = start(); |
@@ -445,2 +456,55 @@ void ORecur::checkOrModify() { | |||
445 | } | 456 | } |
457 | QString 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 | |||
@@ -75,3 +75,7 @@ public: | |||
75 | void setService( const QString& ser ); | 75 | void setService( const QString& ser ); |
76 | |||
77 | /* almost internal */ | ||
78 | QString toString()const; | ||
76 | private: | 79 | private: |
80 | bool p_nextOccurrence( const QDate& from, QDate& next ); | ||
77 | void deref(); | 81 | void deref(); |
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 | |||
@@ -44,2 +44,3 @@ struct OEvent::Data : public QShared { | |||
44 | Data() : QShared() { | 44 | Data() : QShared() { |
45 | child = 0; | ||
45 | recur = 0; | 46 | recur = 0; |
@@ -47,2 +48,3 @@ struct OEvent::Data : public QShared { | |||
47 | isAllDay = false; | 48 | isAllDay = false; |
49 | parent = 0; | ||
48 | } | 50 | } |
@@ -62,2 +64,4 @@ struct OEvent::Data : public QShared { | |||
62 | QString timezone; | 64 | QString timezone; |
65 | QArray<int>* child; | ||
66 | int parent; | ||
63 | }; | 67 | }; |
@@ -104,3 +108,3 @@ QString OEvent::location()const { | |||
104 | } | 108 | } |
105 | OPimNotifyManager &OEvent::notifiers() { | 109 | OPimNotifyManager &OEvent::notifiers()const { |
106 | // I hope we can skip the changeOrModify here | 110 | // I hope we can skip the changeOrModify here |
@@ -114,3 +118,9 @@ OPimNotifyManager &OEvent::notifiers() { | |||
114 | bool OEvent::hasNotifiers()const { | 118 | bool 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 | } |
@@ -199,2 +209,3 @@ void OEvent::setTimeZone( const QString& tz ) { | |||
199 | QString OEvent::timeZone()const { | 209 | QString OEvent::timeZone()const { |
210 | if (data->isAllDay ) return QString::fromLatin1("UTC"); | ||
200 | return data->timezone; | 211 | return data->timezone; |
@@ -241,2 +252,7 @@ void OEvent::changeOrModify() { | |||
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 | ||
@@ -258,4 +274,46 @@ QMap<QString, QString> OEvent::toExtraMap()const { | |||
258 | } | 274 | } |
275 | int OEvent::parent()const { | ||
276 | return data->parent; | ||
277 | } | ||
278 | void OEvent::setParent( int uid ) { | ||
279 | changeOrModify(); | ||
280 | data->parent = uid; | ||
281 | } | ||
282 | QArray<int> OEvent::children() const{ | ||
283 | if (!data->child) return QArray<int>(); | ||
284 | else | ||
285 | return data->child->copy(); | ||
286 | } | ||
287 | void 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 | } | ||
294 | void 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 | } | ||
305 | void 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 | } | ||
261 | struct OEffectiveEvent::Data : public QShared { | 319 | struct OEffectiveEvent::Data : public QShared { |
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 | |||
@@ -63,3 +63,3 @@ public: | |||
63 | bool hasNotifiers()const; | 63 | bool hasNotifiers()const; |
64 | OPimNotifyManager ¬ifiers(); | 64 | OPimNotifyManager ¬ifiers()const; |
65 | 65 | ||
@@ -101,3 +101,11 @@ public: | |||
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 | ||