summaryrefslogtreecommitdiffabout
path: root/libkcal/incidence.cpp
Unidiff
Diffstat (limited to 'libkcal/incidence.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/incidence.cpp594
1 files changed, 594 insertions, 0 deletions
diff --git a/libkcal/incidence.cpp b/libkcal/incidence.cpp
new file mode 100644
index 0000000..d9bda64
--- a/dev/null
+++ b/libkcal/incidence.cpp
@@ -0,0 +1,594 @@
1/*
2 This file is part of libkcal.
3 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21#include <kglobal.h>
22#include <klocale.h>
23#include <kdebug.h>
24
25#include "calformat.h"
26
27#include "incidence.h"
28#include "todo.h"
29
30using namespace KCal;
31
32Incidence::Incidence() :
33 IncidenceBase(),
34 mRelatedTo(0), mSecrecy(SecrecyPublic), mPriority(3)
35{
36 mRecurrence = new Recurrence(this);
37 mCancelled = false;
38 recreate();
39 mHasStartDate = true;
40 mAlarms.setAutoDelete(true);
41 mAttachments.setAutoDelete(true);
42}
43
44Incidence::Incidence( const Incidence &i ) : IncidenceBase( i )
45{
46// TODO: reenable attributes currently commented out.
47 mRevision = i.mRevision;
48 mCreated = i.mCreated;
49 mDescription = i.mDescription;
50 mSummary = i.mSummary;
51 mCategories = i.mCategories;
52// Incidence *mRelatedTo; Incidence *mRelatedTo;
53 mRelatedTo = 0;
54 mRelatedToUid = i.mRelatedToUid;
55// QPtrList<Incidence> mRelations; QPtrList<Incidence> mRelations;
56 mExDates = i.mExDates;
57 mAttachments = i.mAttachments;
58 mResources = i.mResources;
59 mSecrecy = i.mSecrecy;
60 mPriority = i.mPriority;
61 mLocation = i.mLocation;
62 mCancelled = i.mCancelled;
63 mHasStartDate = i.mHasStartDate;
64 QPtrListIterator<Alarm> it( i.mAlarms );
65 const Alarm *a;
66 while( (a = it.current()) ) {
67 Alarm *b = new Alarm( *a );
68 b->setParent( this );
69 mAlarms.append( b );
70
71 ++it;
72 }
73 mAlarms.setAutoDelete(true);
74
75 mRecurrence = new Recurrence( *(i.mRecurrence), this );
76}
77
78Incidence::~Incidence()
79{
80
81 Incidence *ev;
82 QPtrList<Incidence> Relations = relations();
83 for (ev=Relations.first();ev;ev=Relations.next()) {
84 if (ev->relatedTo() == this) ev->setRelatedTo(0);
85 }
86 if (relatedTo()) relatedTo()->removeRelation(this);
87 delete mRecurrence;
88
89}
90
91bool Incidence::cancelled() const
92{
93 return mCancelled;
94}
95void Incidence::setCancelled( bool b )
96{
97 mCancelled = b;
98 updated();
99}
100bool Incidence::hasStartDate() const
101{
102 return mHasStartDate;
103}
104
105void Incidence::setHasStartDate(bool f)
106{
107 if (mReadOnly) return;
108 mHasStartDate = f;
109 updated();
110}
111
112// A string comparison that considers that null and empty are the same
113static bool stringCompare( const QString& s1, const QString& s2 )
114{
115 if ( s1.isEmpty() && s2.isEmpty() )
116 return true;
117 return s1 == s2;
118}
119
120bool KCal::operator==( const Incidence& i1, const Incidence& i2 )
121{
122
123 if( i1.alarms().count() != i2.alarms().count() ) {
124 return false; // no need to check further
125 }
126 if ( i1.alarms().count() > 0 ) {
127 if ( !( *(i1.alarms().first()) == *(i2.alarms().first())) )
128 {
129 qDebug("alarm not equal ");
130 return false;
131 }
132 }
133#if 0
134 QPtrListIterator<Alarm> a1( i1.alarms() );
135 QPtrListIterator<Alarm> a2( i2.alarms() );
136 for( ; a1.current() && a2.current(); ++a1, ++a2 ) {
137 if( *a1.current() == *a2.current() ) {
138 continue;
139 }
140 else {
141 return false;
142 }
143 }
144#endif
145
146 if ( ! operator==( (const IncidenceBase&)i1, (const IncidenceBase&)i2 ) )
147 return false;
148 if ( i1.hasStartDate() == i2.hasStartDate() ) {
149 if ( i1.hasStartDate() ) {
150 if ( i1.dtStart() != i2.dtStart() )
151 return false;
152 }
153 } else {
154 return false;
155 }
156 if (!( *i1.recurrence() == *i2.recurrence()) ) {
157 qDebug("recurrence is NOT equal ");
158 return false;
159 }
160 return
161 // i1.created() == i2.created() &&
162 stringCompare( i1.description(), i2.description() ) &&
163 stringCompare( i1.summary(), i2.summary() ) &&
164 i1.categories() == i2.categories() &&
165 // no need to compare mRelatedTo
166 stringCompare( i1.relatedToUid(), i2.relatedToUid() ) &&
167 // i1.relations() == i2.relations() &&
168 i1.exDates() == i2.exDates() &&
169 i1.attachments() == i2.attachments() &&
170 i1.resources() == i2.resources() &&
171 i1.secrecy() == i2.secrecy() &&
172 i1.priority() == i2.priority() &&
173 stringCompare( i1.location(), i2.location() );
174}
175
176
177void Incidence::recreate()
178{
179 setCreated(QDateTime::currentDateTime());
180
181 setUid(CalFormat::createUniqueId());
182
183 setRevision(0);
184
185 setLastModified(QDateTime::currentDateTime());
186}
187
188void Incidence::setReadOnly( bool readOnly )
189{
190 IncidenceBase::setReadOnly( readOnly );
191 recurrence()->setRecurReadOnly( readOnly);
192}
193
194void Incidence::setCreated(QDateTime created)
195{
196 if (mReadOnly) return;
197 mCreated = getEvenTime(created);
198}
199
200QDateTime Incidence::created() const
201{
202 return mCreated;
203}
204
205void Incidence::setRevision(int rev)
206{
207 if (mReadOnly) return;
208 mRevision = rev;
209
210 updated();
211}
212
213int Incidence::revision() const
214{
215 return mRevision;
216}
217
218void Incidence::setDtStart(const QDateTime &dtStart)
219{
220
221 QDateTime dt = getEvenTime(dtStart);
222 recurrence()->setRecurStart( dt);
223 IncidenceBase::setDtStart( dt );
224}
225
226void Incidence::setDescription(const QString &description)
227{
228 if (mReadOnly) return;
229 mDescription = description;
230 updated();
231}
232
233QString Incidence::description() const
234{
235 return mDescription;
236}
237
238
239void Incidence::setSummary(const QString &summary)
240{
241 if (mReadOnly) return;
242 mSummary = summary;
243 updated();
244}
245
246QString Incidence::summary() const
247{
248 return mSummary;
249}
250
251void Incidence::setCategories(const QStringList &categories)
252{
253 if (mReadOnly) return;
254 mCategories = categories;
255 updated();
256}
257
258// TODO: remove setCategories(QString) function
259void Incidence::setCategories(const QString &catStr)
260{
261 if (mReadOnly) return;
262 mCategories.clear();
263
264 if (catStr.isEmpty()) return;
265
266 mCategories = QStringList::split(",",catStr);
267
268 QStringList::Iterator it;
269 for(it = mCategories.begin();it != mCategories.end(); ++it) {
270 *it = (*it).stripWhiteSpace();
271 }
272
273 updated();
274}
275
276QStringList Incidence::categories() const
277{
278 return mCategories;
279}
280
281QString Incidence::categoriesStr()
282{
283 return mCategories.join(",");
284}
285
286void Incidence::setRelatedToUid(const QString &relatedToUid)
287{
288 if (mReadOnly) return;
289 mRelatedToUid = relatedToUid;
290}
291
292QString Incidence::relatedToUid() const
293{
294 return mRelatedToUid;
295}
296
297void Incidence::setRelatedTo(Incidence *relatedTo)
298{
299 //qDebug("Incidence::setRelatedTo %d ", relatedTo);
300 //qDebug("setRelatedTo(Incidence *relatedTo) %s %s", summary().latin1(), relatedTo->summary().latin1() );
301 if (mReadOnly || mRelatedTo == relatedTo) return;
302 if(mRelatedTo) {
303 // updated();
304 mRelatedTo->removeRelation(this);
305 }
306 mRelatedTo = relatedTo;
307 if (mRelatedTo) mRelatedTo->addRelation(this);
308}
309
310Incidence *Incidence::relatedTo() const
311{
312 return mRelatedTo;
313}
314
315QPtrList<Incidence> Incidence::relations() const
316{
317 return mRelations;
318}
319
320void Incidence::addRelation(Incidence *event)
321{
322 if( mRelations.findRef( event ) == -1 ) {
323 mRelations.append(event);
324 //updated();
325 }
326}
327
328void Incidence::removeRelation(Incidence *event)
329{
330
331 mRelations.removeRef(event);
332
333// if (event->getRelatedTo() == this) event->setRelatedTo(0);
334}
335
336bool Incidence::recursOn(const QDate &qd) const
337{
338 if (recurrence()->recursOnPure(qd) && !isException(qd)) return true;
339 else return false;
340}
341
342void Incidence::setExDates(const DateList &exDates)
343{
344 if (mReadOnly) return;
345 mExDates = exDates;
346
347 recurrence()->setRecurExDatesCount(mExDates.count());
348
349 updated();
350}
351
352void Incidence::addExDate(const QDate &date)
353{
354 if (mReadOnly) return;
355 mExDates.append(date);
356
357 recurrence()->setRecurExDatesCount(mExDates.count());
358
359 updated();
360}
361
362DateList Incidence::exDates() const
363{
364 return mExDates;
365}
366
367bool Incidence::isException(const QDate &date) const
368{
369 DateList::ConstIterator it;
370 for( it = mExDates.begin(); it != mExDates.end(); ++it ) {
371 if ( (*it) == date ) {
372 return true;
373 }
374 }
375
376 return false;
377}
378
379void Incidence::addAttachment(Attachment *attachment)
380{
381 if (mReadOnly || !attachment) return;
382 mAttachments.append(attachment);
383 updated();
384}
385
386void Incidence::deleteAttachment(Attachment *attachment)
387{
388 mAttachments.removeRef(attachment);
389}
390
391void Incidence::deleteAttachments(const QString& mime)
392{
393 Attachment *at = mAttachments.first();
394 while (at) {
395 if (at->mimeType() == mime)
396 mAttachments.remove();
397 else
398 at = mAttachments.next();
399 }
400}
401
402QPtrList<Attachment> Incidence::attachments() const
403{
404 return mAttachments;
405}
406
407QPtrList<Attachment> Incidence::attachments(const QString& mime) const
408{
409 QPtrList<Attachment> attachments;
410 QPtrListIterator<Attachment> it( mAttachments );
411 Attachment *at;
412 while ( (at = it.current()) ) {
413 if (at->mimeType() == mime)
414 attachments.append(at);
415 ++it;
416 }
417
418 return attachments;
419}
420
421void Incidence::setResources(const QStringList &resources)
422{
423 if (mReadOnly) return;
424 mResources = resources;
425 updated();
426}
427
428QStringList Incidence::resources() const
429{
430 return mResources;
431}
432
433
434void Incidence::setPriority(int priority)
435{
436 if (mReadOnly) return;
437 mPriority = priority;
438 updated();
439}
440
441int Incidence::priority() const
442{
443 return mPriority;
444}
445
446void Incidence::setSecrecy(int sec)
447{
448 if (mReadOnly) return;
449 mSecrecy = sec;
450 updated();
451}
452
453int Incidence::secrecy() const
454{
455 return mSecrecy;
456}
457
458QString Incidence::secrecyStr() const
459{
460 return secrecyName(mSecrecy);
461}
462
463QString Incidence::secrecyName(int secrecy)
464{
465 switch (secrecy) {
466 case SecrecyPublic:
467 return i18n("Public");
468 break;
469 case SecrecyPrivate:
470 return i18n("Private");
471 break;
472 case SecrecyConfidential:
473 return i18n("Confidential");
474 break;
475 default:
476 return i18n("Undefined");
477 break;
478 }
479}
480
481QStringList Incidence::secrecyList()
482{
483 QStringList list;
484 list << secrecyName(SecrecyPublic);
485 list << secrecyName(SecrecyPrivate);
486 list << secrecyName(SecrecyConfidential);
487
488 return list;
489}
490
491
492QPtrList<Alarm> Incidence::alarms() const
493{
494 return mAlarms;
495}
496
497Alarm* Incidence::newAlarm()
498{
499 Alarm* alarm = new Alarm(this);
500 mAlarms.append(alarm);
501// updated();
502 return alarm;
503}
504
505void Incidence::addAlarm(Alarm *alarm)
506{
507 mAlarms.append(alarm);
508 updated();
509}
510
511void Incidence::removeAlarm(Alarm *alarm)
512{
513 mAlarms.removeRef(alarm);
514 updated();
515}
516
517void Incidence::clearAlarms()
518{
519 mAlarms.clear();
520 updated();
521}
522
523bool Incidence::isAlarmEnabled() const
524{
525 Alarm* alarm;
526 for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) {
527 if (alarm->enabled())
528 return true;
529 }
530 return false;
531}
532
533Recurrence *Incidence::recurrence() const
534{
535 return mRecurrence;
536}
537
538void Incidence::setLocation(const QString &location)
539{
540 if (mReadOnly) return;
541 mLocation = location;
542 updated();
543}
544
545QString Incidence::location() const
546{
547 return mLocation;
548}
549
550ushort Incidence::doesRecur() const
551{
552 if ( mRecurrence ) return mRecurrence->doesRecur();
553 else return Recurrence::rNone;
554}
555
556QDateTime Incidence::getNextOccurence( const QDateTime& dt, bool* ok ) const
557{
558 QDateTime incidenceStart = dt;
559 *ok = false;
560 if ( doesRecur() ) {
561 bool last;
562 recurrence()->getPreviousDateTime( incidenceStart , &last );
563 int count = 0;
564 if ( !last ) {
565 while ( !last ) {
566 ++count;
567 incidenceStart = recurrence()->getNextDateTime( incidenceStart, &last );
568 if ( recursOn( incidenceStart.date() ) ) {
569 last = true; // exit while llop
570 } else {
571 if ( last ) { // no alarm on last recurrence
572 return QDateTime ();
573 }
574 int year = incidenceStart.date().year();
575 // workaround for bug in recurrence
576 if ( count == 100 || year < 1980 || year > 5000 ) {
577 return QDateTime ();
578 }
579 incidenceStart = incidenceStart.addSecs( 1 );
580 }
581 }
582 } else {
583 return QDateTime ();
584 }
585 } else {
586 if ( hasStartDate () ) {
587 incidenceStart = dtStart();
588
589 }
590 }
591 if ( incidenceStart > dt )
592 *ok = true;
593 return incidenceStart;
594}