• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KCalCore Library

  • kcalcore
incidence.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the kcalcore library.
3 
4  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
35 #include "incidence.h"
36 #include "calformat.h"
37 
38 #include <KMimeType>
39 #include <KTemporaryFile>
40 
41 #include <QTextDocument> // for Qt::escape() and Qt::mightBeRichText()
42 
43 using namespace KCalCore;
44 
49 //@cond PRIVATE
50 class KCalCore::Incidence::Private
51 {
52  public:
53  Private()
54  : mRevision( 0 ),
55  mDescriptionIsRich( false ),
56  mSummaryIsRich( false ),
57  mLocationIsRich( false ),
58  mRecurrence( 0 ),
59  mStatus( StatusNone ),
60  mSecrecy( SecrecyPublic ),
61  mPriority( 0 ),
62  mGeoLatitude( INVALID_LATLON ),
63  mGeoLongitude( INVALID_LATLON ),
64  mHasGeo( false ),
65  mLocalOnly( false )
66  {
67  }
68 
69  Private( const Private &p )
70  : mCreated( p.mCreated ),
71  mRevision( p.mRevision ),
72  mDescription( p.mDescription ),
73  mDescriptionIsRich( p.mDescriptionIsRich ),
74  mSummary( p.mSummary ),
75  mSummaryIsRich( p.mSummaryIsRich ),
76  mLocation( p.mLocation ),
77  mLocationIsRich( p.mLocationIsRich ),
78  mCategories( p.mCategories ),
79  mRecurrence ( 0 ),
80  mResources( p.mResources ),
81  mStatus( p.mStatus ),
82  mStatusString( p.mStatusString ),
83  mSecrecy( p.mSecrecy ),
84  mPriority( p.mPriority ),
85  mSchedulingID( p.mSchedulingID ),
86  mRelatedToUid( p.mRelatedToUid ),
87  mGeoLatitude( p.mGeoLatitude ),
88  mGeoLongitude( p.mGeoLongitude ),
89  mHasGeo( p.mHasGeo ),
90  mRecurrenceId( p.mRecurrenceId ),
91  mLocalOnly( false )
92  {
93  }
94 
95  void clear()
96  {
97  mAlarms.clear();
98  mAttachments.clear();
99  delete mRecurrence;
100  mRecurrence = 0;
101  }
102 
103  void init( Incidence *dest, const Incidence &src )
104  {
105  mRevision = src.d->mRevision;
106  mCreated = src.d->mCreated;
107  mDescription = src.d->mDescription;
108  mSummary = src.d->mSummary;
109  mCategories = src.d->mCategories;
110  mRelatedToUid = src.d->mRelatedToUid;
111  mResources = src.d->mResources;
112  mStatusString = src.d->mStatusString;
113  mStatus = src.d->mStatus;
114  mSecrecy = src.d->mSecrecy;
115  mPriority = src.d->mPriority;
116  mLocation = src.d->mLocation;
117  mGeoLatitude = src.d->mGeoLatitude;
118  mGeoLongitude = src.d->mGeoLongitude;
119  mHasGeo = src.d->mHasGeo;
120  mRecurrenceId = src.d->mRecurrenceId;
121  mLocalOnly = src.d->mLocalOnly;
122 
123  // Alarms and Attachments are stored in ListBase<...>, which is a QValueList<...*>.
124  // We need to really duplicate the objects stored therein, otherwise deleting
125  // i will also delete all attachments from this object (setAutoDelete...)
126  foreach ( Alarm::Ptr alarm, src.d->mAlarms ) {
127  Alarm::Ptr b ( new Alarm( *alarm.data() ) );
128  b->setParent( dest );
129  mAlarms.append( b );
130  }
131 
132  foreach ( Attachment::Ptr attachment, src.d->mAttachments ) {
133  Attachment::Ptr a( new Attachment( *attachment ) );
134  mAttachments.append( a );
135  }
136 
137  if ( src.d->mRecurrence ) {
138  mRecurrence = new Recurrence( *( src.d->mRecurrence ) );
139  mRecurrence->addObserver( dest );
140  } else {
141  mRecurrence = 0;
142  }
143  }
144 
145  KDateTime mCreated; // creation datetime
146  int mRevision; // revision number
147 
148  QString mDescription; // description string
149  bool mDescriptionIsRich; // description string is richtext.
150  QString mSummary; // summary string
151  bool mSummaryIsRich; // summary string is richtext.
152  QString mLocation; // location string
153  bool mLocationIsRich; // location string is richtext.
154  QStringList mCategories; // category list
155  mutable Recurrence *mRecurrence; // recurrence
156  Attachment::List mAttachments; // attachments list
157  Alarm::List mAlarms; // alarms list
158  QStringList mResources; // resources list (not calendar resources)
159  Status mStatus; // status
160  QString mStatusString; // status string, for custom status
161  Secrecy mSecrecy; // secrecy
162  int mPriority; // priority: 1 = highest, 2 = less, etc.
163  QString mSchedulingID; // ID for scheduling mails
164 
165  QMap<RelType,QString> mRelatedToUid;// incidence uid this is related to, for each relType
166  float mGeoLatitude; // Specifies latitude in decimal degrees
167  float mGeoLongitude; // Specifies longitude in decimal degrees
168  bool mHasGeo; // if incidence has geo data
169  QHash<Attachment::Ptr,QString> mTempFiles; // Temporary files for writing attachments to.
170  KDateTime mRecurrenceId; // recurrenceId
171  bool mLocalOnly; // allow changes that won't go to the server
172 };
173 //@endcond
174 
175 Incidence::Incidence()
176  : IncidenceBase(), d( new KCalCore::Incidence::Private )
177 {
178  recreate();
179  resetDirtyFields();
180 }
181 
182 Incidence::Incidence( const Incidence &i )
183  : IncidenceBase( i ),
184  Recurrence::RecurrenceObserver(),
185  d( new KCalCore::Incidence::Private( *i.d ) )
186 {
187  d->init( this, i );
188  resetDirtyFields();
189 }
190 
191 Incidence::~Incidence()
192 {
193  // Alarm has a raw incidence pointer, so we must set it to 0
194  // so Alarm doesn't use it after Incidence is destroyed
195  foreach ( Alarm::Ptr alarm, d->mAlarms ) {
196  alarm->setParent( 0 );
197  }
198 
199  delete d->mRecurrence;
200  delete d;
201 }
202 
203 //@cond PRIVATE
204 // A string comparison that considers that null and empty are the same
205 static bool stringCompare( const QString &s1, const QString &s2 )
206 {
207  return ( s1.isEmpty() && s2.isEmpty() ) || ( s1 == s2 );
208 }
209 
210 //@endcond
211 IncidenceBase &Incidence::assign( const IncidenceBase &other )
212 {
213  if ( &other != this ) {
214  d->clear();
215  //TODO: should relations be cleared out, as in destructor???
216  IncidenceBase::assign( other );
217  const Incidence *i = static_cast<const Incidence*>( &other );
218  d->init( this, *i );
219  }
220 
221  return *this;
222 }
223 
224 bool Incidence::equals( const IncidenceBase &incidence ) const
225 {
226  if ( !IncidenceBase::equals( incidence ) ) {
227  return false;
228  }
229 
230  // If they weren't the same type IncidenceBase::equals would had returned false already
231  const Incidence *i2 = static_cast<const Incidence *>( &incidence );
232 
233  if ( alarms().count() != i2->alarms().count() ) {
234  return false;
235  }
236 
237  Alarm::List::ConstIterator a1 = alarms().constBegin();
238  Alarm::List::ConstIterator a1end = alarms().constEnd();
239  Alarm::List::ConstIterator a2 = i2->alarms().constBegin();
240  Alarm::List::ConstIterator a2end = i2->alarms().constEnd();
241  for ( ; a1 != a1end && a2 != a2end; ++a1, ++a2 ) {
242  if ( **a1 == **a2 ) {
243  continue;
244  } else {
245  return false;
246  }
247  }
248 
249  if ( attachments().count() != i2->attachments().count() ) {
250  return false;
251  }
252 
253  Attachment::List::ConstIterator att1 = attachments().constBegin();
254  const Attachment::List::ConstIterator att1end = attachments().constEnd();
255  Attachment::List::ConstIterator att2 = i2->attachments().constBegin();
256  const Attachment::List::ConstIterator att2end = i2->attachments().constEnd();
257  for ( ; att1 != att1end && att2 != att2end; ++att1, ++att2 ) {
258  if ( **att1 == **att2 ) {
259  continue;
260  } else {
261  return false;
262  }
263  }
264 
265  bool recurrenceEqual = ( d->mRecurrence == 0 && i2->d->mRecurrence == 0 );
266  if ( !recurrenceEqual ) {
267  recurrence(); // create if doesn't exist
268  i2->recurrence(); // create if doesn't exist
269  recurrenceEqual = d->mRecurrence != 0 &&
270  i2->d->mRecurrence != 0 &&
271  *d->mRecurrence == *i2->d->mRecurrence;
272  }
273 
274  return
275  recurrenceEqual &&
276  created() == i2->created() &&
277  stringCompare( description(), i2->description() ) &&
278  stringCompare( summary(), i2->summary() ) &&
279  categories() == i2->categories() &&
280  stringCompare( relatedTo(), i2->relatedTo() ) &&
281  resources() == i2->resources() &&
282  d->mStatus == i2->d->mStatus &&
283  ( d->mStatus == StatusNone ||
284  stringCompare( d->mStatusString, i2->d->mStatusString ) ) &&
285  secrecy() == i2->secrecy() &&
286  priority() == i2->priority() &&
287  stringCompare( location(), i2->location() ) &&
288  stringCompare( schedulingID(), i2->schedulingID() );
289 }
290 
291 void Incidence::recreate()
292 {
293  const KDateTime nowUTC = KDateTime::currentUtcDateTime();
294  setCreated( nowUTC );
295 
296  setSchedulingID( QString(), CalFormat::createUniqueId() );
297  setRevision( 0 );
298  setLastModified( nowUTC );
299 }
300 
301 void Incidence::setLastModified( const KDateTime &lm )
302 {
303  if ( !d->mLocalOnly ) {
304  IncidenceBase::setLastModified( lm );
305  }
306 }
307 
308 void Incidence::setReadOnly( bool readOnly )
309 {
310  IncidenceBase::setReadOnly( readOnly );
311  if ( d->mRecurrence ) {
312  d->mRecurrence->setRecurReadOnly( readOnly );
313  }
314 }
315 
316 void Incidence::setLocalOnly( bool localOnly )
317 {
318  if ( mReadOnly ) {
319  return;
320  }
321  d->mLocalOnly = localOnly;
322 }
323 
324 bool Incidence::localOnly() const
325 {
326  return d->mLocalOnly;
327 }
328 
329 void Incidence::setAllDay( bool allDay )
330 {
331  if ( mReadOnly ) {
332  return;
333  }
334  if ( d->mRecurrence ) {
335  d->mRecurrence->setAllDay( allDay );
336  }
337  IncidenceBase::setAllDay( allDay );
338 }
339 
340 void Incidence::setCreated( const KDateTime &created )
341 {
342  if ( mReadOnly || d->mLocalOnly ) {
343  return;
344  }
345 
346  d->mCreated = created.toUtc();
347  setFieldDirty( FieldCreated );
348 
349 // FIXME: Shouldn't we call updated for the creation date, too?
350 // updated();
351 }
352 
353 KDateTime Incidence::created() const
354 {
355  return d->mCreated;
356 }
357 
358 void Incidence::setRevision( int rev )
359 {
360  if ( mReadOnly || d->mLocalOnly ) {
361  return;
362  }
363 
364  update();
365 
366  d->mRevision = rev;
367  setFieldDirty( FieldRevision );
368  updated();
369 }
370 
371 int Incidence::revision() const
372 {
373  return d->mRevision;
374 }
375 
376 void Incidence::setDtStart( const KDateTime &dt )
377 {
378  if ( d->mRecurrence ) {
379  d->mRecurrence->setStartDateTime( dt );
380  d->mRecurrence->setAllDay( allDay() );
381  }
382  IncidenceBase::setDtStart( dt );
383 }
384 
385 void Incidence::shiftTimes( const KDateTime::Spec &oldSpec,
386  const KDateTime::Spec &newSpec )
387 {
388  IncidenceBase::shiftTimes( oldSpec, newSpec );
389  if ( d->mRecurrence ) {
390  d->mRecurrence->shiftTimes( oldSpec, newSpec );
391  }
392  for ( int i = 0, end = d->mAlarms.count(); i < end; ++i ) {
393  d->mAlarms[i]->shiftTimes( oldSpec, newSpec );
394  }
395 }
396 
397 void Incidence::setDescription( const QString &description, bool isRich )
398 {
399  if ( mReadOnly ) {
400  return;
401  }
402  update();
403  d->mDescription = description;
404  d->mDescriptionIsRich = isRich;
405  setFieldDirty( FieldDescription );
406  updated();
407 }
408 
409 void Incidence::setDescription( const QString &description )
410 {
411  setDescription( description, Qt::mightBeRichText( description ) );
412 }
413 
414 QString Incidence::description() const
415 {
416  return d->mDescription;
417 }
418 
419 QString Incidence::richDescription() const
420 {
421  if ( descriptionIsRich() ) {
422  return d->mDescription;
423  } else {
424  return Qt::escape( d->mDescription ).replace( '\n', "<br/>" );
425  }
426 }
427 
428 bool Incidence::descriptionIsRich() const
429 {
430  return d->mDescriptionIsRich;
431 }
432 
433 void Incidence::setSummary( const QString &summary, bool isRich )
434 {
435  if ( mReadOnly ) {
436  return;
437  }
438  update();
439  d->mSummary = summary;
440  d->mSummaryIsRich = isRich;
441  setFieldDirty( FieldSummary );
442  updated();
443 }
444 
445 void Incidence::setSummary( const QString &summary )
446 {
447  setSummary( summary, Qt::mightBeRichText( summary ) );
448 }
449 
450 QString Incidence::summary() const
451 {
452  return d->mSummary;
453 }
454 
455 QString Incidence::richSummary() const
456 {
457  if ( summaryIsRich() ) {
458  return d->mSummary;
459  } else {
460  return Qt::escape( d->mSummary ).replace( '\n', "<br/>" );
461  }
462 }
463 
464 bool Incidence::summaryIsRich() const
465 {
466  return d->mSummaryIsRich;
467 }
468 
469 void Incidence::setCategories( const QStringList &categories )
470 {
471  if ( mReadOnly ) {
472  return;
473  }
474 
475  update();
476  d->mCategories = categories;
477  updated();
478 }
479 
480 void Incidence::setCategories( const QString &catStr )
481 {
482  if ( mReadOnly ) {
483  return;
484  }
485  update();
486  setFieldDirty( FieldCategories );
487 
488  d->mCategories.clear();
489 
490  if ( catStr.isEmpty() ) {
491  updated();
492  return;
493  }
494 
495  d->mCategories = catStr.split( ',' );
496 
497  QStringList::Iterator it;
498  for ( it = d->mCategories.begin();it != d->mCategories.end(); ++it ) {
499  *it = ( *it ).trimmed();
500  }
501 
502  updated();
503 }
504 
505 QStringList Incidence::categories() const
506 {
507  return d->mCategories;
508 }
509 
510 QString Incidence::categoriesStr() const
511 {
512  return d->mCategories.join( "," );
513 }
514 
515 void Incidence::setRelatedTo( const QString &relatedToUid, RelType relType )
516 {
517  // TODO: RFC says that an incidence can have more than one related-to field
518  // even for the same relType.
519 
520  if ( d->mRelatedToUid[relType] != relatedToUid ) {
521  update();
522  d->mRelatedToUid[relType] = relatedToUid;
523  setFieldDirty( FieldRelatedTo );
524  updated();
525  }
526 }
527 
528 QString Incidence::relatedTo( RelType relType ) const
529 {
530  return d->mRelatedToUid.value( relType );
531 }
532 
533 // %%%%%%%%%%%% Recurrence-related methods %%%%%%%%%%%%%%%%%%%%
534 
535 Recurrence *Incidence::recurrence() const
536 {
537  if ( !d->mRecurrence ) {
538  d->mRecurrence = new Recurrence();
539  d->mRecurrence->setStartDateTime( IncidenceBase::dtStart() );
540  d->mRecurrence->setAllDay( allDay() );
541  d->mRecurrence->setRecurReadOnly( mReadOnly );
542  d->mRecurrence->addObserver( const_cast<KCalCore::Incidence*>( this ) );
543  }
544 
545  return d->mRecurrence;
546 }
547 
548 void Incidence::clearRecurrence()
549 {
550  delete d->mRecurrence;
551  d->mRecurrence = 0;
552 }
553 
554 ushort Incidence::recurrenceType() const
555 {
556  if ( d->mRecurrence ) {
557  return d->mRecurrence->recurrenceType();
558  } else {
559  return Recurrence::rNone;
560  }
561 }
562 
563 bool Incidence::recurs() const
564 {
565  if ( d->mRecurrence ) {
566  return d->mRecurrence->recurs();
567  } else {
568  return false;
569  }
570 }
571 
572 bool Incidence::recursOn( const QDate &date,
573  const KDateTime::Spec &timeSpec ) const
574 {
575  return d->mRecurrence && d->mRecurrence->recursOn( date, timeSpec );
576 }
577 
578 bool Incidence::recursAt( const KDateTime &qdt ) const
579 {
580  return d->mRecurrence && d->mRecurrence->recursAt( qdt );
581 }
582 
583 QList<KDateTime> Incidence::startDateTimesForDate( const QDate &date,
584  const KDateTime::Spec &timeSpec ) const
585 {
586  KDateTime start = dtStart();
587  KDateTime end = dateTime( RoleEndRecurrenceBase );
588 
589  QList<KDateTime> result;
590 
591  // TODO_Recurrence: Also work if only due date is given...
592  if ( !start.isValid() && ! end.isValid() ) {
593  return result;
594  }
595 
596  // if the incidence doesn't recur,
597  KDateTime kdate( date, timeSpec );
598  if ( !recurs() ) {
599  if ( !( start > kdate || end < kdate ) ) {
600  result << start;
601  }
602  return result;
603  }
604 
605  int days = start.daysTo( end );
606  // Account for possible recurrences going over midnight, while the original event doesn't
607  QDate tmpday( date.addDays( -days - 1 ) );
608  KDateTime tmp;
609  while ( tmpday <= date ) {
610  if ( recurrence()->recursOn( tmpday, timeSpec ) ) {
611  QList<QTime> times = recurrence()->recurTimesOn( tmpday, timeSpec );
612  foreach ( const QTime &time, times ) {
613  tmp = KDateTime( tmpday, time, start.timeSpec() );
614  if ( endDateForStart( tmp ) >= kdate ) {
615  result << tmp;
616  }
617  }
618  }
619  tmpday = tmpday.addDays( 1 );
620  }
621  return result;
622 }
623 
624 QList<KDateTime> Incidence::startDateTimesForDateTime( const KDateTime &datetime ) const
625 {
626  KDateTime start = dtStart();
627  KDateTime end = dateTime( RoleEndRecurrenceBase );
628 
629  QList<KDateTime> result;
630 
631  // TODO_Recurrence: Also work if only due date is given...
632  if ( !start.isValid() && ! end.isValid() ) {
633  return result;
634  }
635 
636  // if the incidence doesn't recur,
637  if ( !recurs() ) {
638  if ( !( start > datetime || end < datetime ) ) {
639  result << start;
640  }
641  return result;
642  }
643 
644  int days = start.daysTo( end );
645  // Account for possible recurrences going over midnight, while the original event doesn't
646  QDate tmpday( datetime.date().addDays( -days - 1 ) );
647  KDateTime tmp;
648  while ( tmpday <= datetime.date() ) {
649  if ( recurrence()->recursOn( tmpday, datetime.timeSpec() ) ) {
650  // Get the times during the day (in start date's time zone) when recurrences happen
651  QList<QTime> times = recurrence()->recurTimesOn( tmpday, start.timeSpec() );
652  foreach ( const QTime &time, times ) {
653  tmp = KDateTime( tmpday, time, start.timeSpec() );
654  if ( !( tmp > datetime || endDateForStart( tmp ) < datetime ) ) {
655  result << tmp;
656  }
657  }
658  }
659  tmpday = tmpday.addDays( 1 );
660  }
661  return result;
662 }
663 
664 KDateTime Incidence::endDateForStart( const KDateTime &startDt ) const
665 {
666  KDateTime start = dtStart();
667  KDateTime end = dateTime( RoleEndRecurrenceBase );
668  if ( !end.isValid() ) {
669  return start;
670  }
671  if ( !start.isValid() ) {
672  return end;
673  }
674 
675  return startDt.addSecs( start.secsTo( end ) );
676 }
677 
678 void Incidence::addAttachment( const Attachment::Ptr &attachment )
679 {
680  if ( mReadOnly || !attachment ) {
681  return;
682  }
683 
684  Q_ASSERT( !d->mAttachments.contains( attachment ) );
685 
686  update();
687  d->mAttachments.append( attachment );
688  setFieldDirty( FieldAttachment );
689  updated();
690 }
691 
692 void Incidence::deleteAttachment( const Attachment::Ptr &attachment )
693 {
694  int index = d->mAttachments.indexOf( attachment );
695  if ( index > -1 ) {
696  setFieldDirty( FieldAttachment );
697  d->mAttachments.remove( index );
698  }
699 }
700 
701 void Incidence::deleteAttachments( const QString &mime )
702 {
703  Attachment::List result;
704  Attachment::List::Iterator it = d->mAttachments.begin();
705  while ( it != d->mAttachments.end() ) {
706  if ( ( *it )->mimeType() != mime ) {
707  result += *it;
708  }
709  ++it;
710  }
711  d->mAttachments = result;
712  setFieldDirty( FieldAttachment );
713 }
714 
715 Attachment::List Incidence::attachments() const
716 {
717  return d->mAttachments;
718 }
719 
720 Attachment::List Incidence::attachments( const QString &mime ) const
721 {
722  Attachment::List attachments;
723  foreach ( Attachment::Ptr attachment, d->mAttachments ) {
724  if ( attachment->mimeType() == mime ) {
725  attachments.append( attachment );
726  }
727  }
728  return attachments;
729 }
730 
731 void Incidence::clearAttachments()
732 {
733  setFieldDirty( FieldAttachment );
734  d->mAttachments.clear();
735 }
736 
737 QString Incidence::writeAttachmentToTempFile( const Attachment::Ptr &attachment ) const
738 {
739  if ( d->mTempFiles.contains( attachment ) ) {
740  return d->mTempFiles.value( attachment );
741  }
742  KTemporaryFile *file = new KTemporaryFile();
743 
744  QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
745 
746  if ( !patterns.empty() ) {
747  file->setSuffix( QString( patterns.first() ).remove( '*' ) );
748  }
749  file->setAutoRemove( true );
750  file->open();
751  // read-only not to give the idea that it could be written to
752  file->setPermissions( QFile::ReadUser );
753  file->write( QByteArray::fromBase64( attachment->data() ) );
754  d->mTempFiles.insert( attachment, file->fileName() );
755  file->close();
756  return d->mTempFiles.value( attachment );
757 }
758 
759 void Incidence::clearTempFiles()
760 {
761  QHash<Attachment::Ptr,QString>::const_iterator it = d->mTempFiles.constBegin();
762  const QHash<Attachment::Ptr,QString>::const_iterator end = d->mTempFiles.constEnd();
763  for ( ; it != end; ++it ) {
764  QFile::remove( it.value() );
765  }
766  d->mTempFiles.clear();
767 }
768 
769 void Incidence::setResources( const QStringList &resources )
770 {
771  if ( mReadOnly ) {
772  return;
773  }
774 
775  update();
776  d->mResources = resources;
777  setFieldDirty( FieldResources );
778  updated();
779 }
780 
781 QStringList Incidence::resources() const
782 {
783  return d->mResources;
784 }
785 
786 void Incidence::setPriority( int priority )
787 {
788  if ( mReadOnly ) {
789  return;
790  }
791 
792  update();
793  d->mPriority = priority;
794  setFieldDirty( FieldPriority );
795  updated();
796 }
797 
798 int Incidence::priority() const
799 {
800  return d->mPriority;
801 }
802 
803 void Incidence::setStatus( Incidence::Status status )
804 {
805  if ( mReadOnly || status == StatusX ) {
806  return;
807  }
808 
809  update();
810  d->mStatus = status;
811  d->mStatusString.clear();
812  setFieldDirty( FieldStatus );
813  updated();
814 }
815 
816 void Incidence::setCustomStatus( const QString &status )
817 {
818  if ( mReadOnly ) {
819  return;
820  }
821 
822  update();
823  d->mStatus = status.isEmpty() ? StatusNone : StatusX;
824  d->mStatusString = status;
825  setFieldDirty( FieldStatus );
826  updated();
827 }
828 
829 Incidence::Status Incidence::status() const
830 {
831  return d->mStatus;
832 }
833 
834 QString Incidence::customStatus() const
835 {
836  if ( d->mStatus == StatusX ) {
837  return d->mStatusString;
838  } else {
839  return QString();
840  }
841 }
842 
843 void Incidence::setSecrecy( Incidence::Secrecy secrecy )
844 {
845  if ( mReadOnly ) {
846  return;
847  }
848 
849  update();
850  d->mSecrecy = secrecy;
851  setFieldDirty( FieldSecrecy );
852  updated();
853 }
854 
855 Incidence::Secrecy Incidence::secrecy() const
856 {
857  return d->mSecrecy;
858 }
859 
860 Alarm::List Incidence::alarms() const
861 {
862  return d->mAlarms;
863 }
864 
865 Alarm::Ptr Incidence::newAlarm()
866 {
867  Alarm::Ptr alarm( new Alarm( this ) );
868  d->mAlarms.append( alarm );
869  return alarm;
870 }
871 
872 void Incidence::addAlarm( const Alarm::Ptr &alarm )
873 {
874  update();
875  d->mAlarms.append( alarm );
876  setFieldDirty( FieldAlarms );
877  updated();
878 }
879 
880 void Incidence::removeAlarm( const Alarm::Ptr &alarm )
881 {
882  const int index = d->mAlarms.indexOf( alarm );
883  if ( index > -1 ) {
884  update();
885  d->mAlarms.remove( index );
886  setFieldDirty( FieldAlarms );
887  updated();
888  }
889 }
890 
891 void Incidence::clearAlarms()
892 {
893  update();
894  d->mAlarms.clear();
895  setFieldDirty( FieldAlarms );
896  updated();
897 }
898 
899 bool Incidence::hasEnabledAlarms() const
900 {
901  foreach ( Alarm::Ptr alarm, d->mAlarms ) {
902  if ( alarm->enabled() ) {
903  return true;
904  }
905  }
906  return false;
907 }
908 
909 void Incidence::setLocation( const QString &location, bool isRich )
910 {
911  if ( mReadOnly ) {
912  return;
913  }
914 
915  update();
916  d->mLocation = location;
917  d->mLocationIsRich = isRich;
918  setFieldDirty( FieldLocation );
919  updated();
920 }
921 
922 void Incidence::setLocation( const QString &location )
923 {
924  setLocation( location, Qt::mightBeRichText( location ) );
925 }
926 
927 QString Incidence::location() const
928 {
929  return d->mLocation;
930 }
931 
932 QString Incidence::richLocation() const
933 {
934  if ( locationIsRich() ) {
935  return d->mLocation;
936  } else {
937  return Qt::escape( d->mLocation ).replace( '\n', "<br/>" );
938  }
939 }
940 
941 bool Incidence::locationIsRich() const
942 {
943  return d->mLocationIsRich;
944 }
945 
946 void Incidence::setSchedulingID( const QString &sid, const QString &uid )
947 {
948  d->mSchedulingID = sid;
949  if ( !uid.isEmpty() ) {
950  setUid( uid );
951  }
952  setFieldDirty( FieldSchedulingId );
953 }
954 
955 QString Incidence::schedulingID() const
956 {
957  if ( d->mSchedulingID.isNull() ) {
958  // Nothing set, so use the normal uid
959  return uid();
960  }
961  return d->mSchedulingID;
962 }
963 
964 bool Incidence::hasGeo() const
965 {
966  return d->mHasGeo;
967 }
968 
969 void Incidence::setHasGeo( bool hasGeo )
970 {
971  if ( mReadOnly ) {
972  return;
973  }
974 
975  if ( hasGeo == d->mHasGeo ) {
976  return;
977  }
978 
979  update();
980  d->mHasGeo = hasGeo;
981  setFieldDirty( FieldGeoLatitude );
982  setFieldDirty( FieldGeoLongitude );
983  updated();
984 }
985 
986 float Incidence::geoLatitude() const
987 {
988  return d->mGeoLatitude;
989 }
990 
991 void Incidence::setGeoLatitude( float geolatitude )
992 {
993  if ( mReadOnly ) {
994  return;
995  }
996 
997  update();
998  d->mGeoLatitude = geolatitude;
999  setFieldDirty( FieldGeoLatitude );
1000  updated();
1001 }
1002 
1003 float Incidence::geoLongitude() const
1004 {
1005  return d->mGeoLongitude;
1006 }
1007 
1008 void Incidence::setGeoLongitude( float geolongitude )
1009 {
1010  if ( !mReadOnly ) {
1011  update();
1012  d->mGeoLongitude = geolongitude;
1013  setFieldDirty( FieldGeoLongitude );
1014  updated();
1015  }
1016 }
1017 
1018 bool Incidence::hasRecurrenceId() const
1019 {
1020  return d->mRecurrenceId.isValid();
1021 }
1022 
1023 KDateTime Incidence::recurrenceId() const
1024 {
1025  return d->mRecurrenceId;
1026 }
1027 
1028 void Incidence::setRecurrenceId( const KDateTime &recurrenceId )
1029 {
1030  if ( !mReadOnly ) {
1031  update();
1032  d->mRecurrenceId = recurrenceId;
1033  setFieldDirty( FieldRecurrenceId );
1034  updated();
1035  }
1036 }
1037 
1041 void Incidence::recurrenceUpdated( Recurrence *recurrence )
1042 {
1043  if ( recurrence == d->mRecurrence ) {
1044  update();
1045  updated();
1046  }
1047 }
1048 
1049 //@cond PRIVATE
1050 #define ALT_DESC_FIELD "X-ALT-DESC"
1051 #define ALT_DESC_PARAMETERS "FMTTYPE=text/html"
1052 //@endcond
1053 
1054 bool Incidence::hasAltDescription() const
1055 {
1056  const QString value = nonKDECustomProperty( ALT_DESC_FIELD );
1057  const QString parameter = nonKDECustomPropertyParameters( ALT_DESC_FIELD );
1058 
1059  return parameter == ALT_DESC_PARAMETERS && !value.isEmpty();
1060 }
1061 
1062 void Incidence::setAltDescription( const QString &altdescription )
1063 {
1064  if ( altdescription.isEmpty() ) {
1065  removeNonKDECustomProperty( ALT_DESC_FIELD );
1066  } else {
1067  setNonKDECustomProperty( ALT_DESC_FIELD,
1068  altdescription,
1069  ALT_DESC_PARAMETERS );
1070  }
1071 }
1072 
1073 QString Incidence::altDescription() const
1074 {
1075  if ( !hasAltDescription() ) {
1076  return QString();
1077  } else {
1078  return nonKDECustomProperty( ALT_DESC_FIELD );
1079  }
1080 }
1081 
1082 bool Incidence::supportsGroupwareCommunication() const
1083 {
1084  return type() == TypeEvent || type() == TypeTodo;
1085 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:24:51 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KCalCore Library

Skip menu "KCalCore Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepimlibs-4.10.5 API Reference

Skip menu "kdepimlibs-4.10.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal