00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00035 #include "incidence.h"
00036 #include "calformat.h"
00037
00038 #include <KMimeType>
00039 #include <KTemporaryFile>
00040
00041 #include <QtGui/QTextDocument>
00042
00043 using namespace KCalCore;
00044
00049
00050 class KCalCore::Incidence::Private
00051 {
00052 public:
00053 Private()
00054 : mRevision( 0 ),
00055 mDescriptionIsRich( false ),
00056 mSummaryIsRich( false ),
00057 mLocationIsRich( false ),
00058 mRecurrence( 0 ),
00059 mStatus( StatusNone ),
00060 mSecrecy( SecrecyPublic ),
00061 mPriority( 0 ),
00062 mGeoLatitude( INVALID_LATLON ),
00063 mGeoLongitude( INVALID_LATLON ),
00064 mHasGeo( false ),
00065 mLocalOnly( false )
00066 {
00067 }
00068
00069 Private( const Private &p )
00070 : mCreated( p.mCreated ),
00071 mRevision( p.mRevision ),
00072 mDescription( p.mDescription ),
00073 mDescriptionIsRich( p.mDescriptionIsRich ),
00074 mSummary( p.mSummary ),
00075 mSummaryIsRich( p.mSummaryIsRich ),
00076 mLocation( p.mLocation ),
00077 mLocationIsRich( p.mLocationIsRich ),
00078 mCategories( p.mCategories ),
00079 mRecurrence ( 0 ),
00080 mResources( p.mResources ),
00081 mStatus( p.mStatus ),
00082 mStatusString( p.mStatusString ),
00083 mSecrecy( p.mSecrecy ),
00084 mPriority( p.mPriority ),
00085 mSchedulingID( p.mSchedulingID ),
00086 mRelatedToUid( p.mRelatedToUid ),
00087 mGeoLatitude( p.mGeoLatitude ),
00088 mGeoLongitude( p.mGeoLongitude ),
00089 mHasGeo( p.mHasGeo ),
00090 mRecurrenceId( p.mRecurrenceId ),
00091 mLocalOnly( false )
00092 {
00093 }
00094
00095 void clear()
00096 {
00097 mAlarms.clear();
00098 mAttachments.clear();
00099 delete mRecurrence;
00100 mRecurrence = 0;
00101 }
00102
00103 void init( Incidence *dest, const Incidence &src )
00104 {
00105 mRevision = src.d->mRevision;
00106 mCreated = src.d->mCreated;
00107 mDescription = src.d->mDescription;
00108 mSummary = src.d->mSummary;
00109 mCategories = src.d->mCategories;
00110 mRelatedToUid = src.d->mRelatedToUid;
00111 mResources = src.d->mResources;
00112 mStatusString = src.d->mStatusString;
00113 mStatus = src.d->mStatus;
00114 mSecrecy = src.d->mSecrecy;
00115 mPriority = src.d->mPriority;
00116 mLocation = src.d->mLocation;
00117 mGeoLatitude = src.d->mGeoLatitude;
00118 mGeoLongitude = src.d->mGeoLongitude;
00119 mHasGeo = src.d->mHasGeo;
00120 mRecurrenceId = src.d->mRecurrenceId;
00121 mLocalOnly = src.d->mLocalOnly;
00122
00123
00124
00125
00126 foreach ( Alarm::Ptr alarm, src.d->mAlarms ) {
00127 Alarm::Ptr b ( new Alarm( *alarm.data() ) );
00128 b->setParent( dest );
00129 mAlarms.append( b );
00130 }
00131
00132 foreach ( Attachment::Ptr attachment, src.d->mAttachments ) {
00133 Attachment::Ptr a( new Attachment( *attachment ) );
00134 mAttachments.append( a );
00135 }
00136
00137 if ( src.d->mRecurrence ) {
00138 mRecurrence = new Recurrence( *( src.d->mRecurrence ) );
00139 mRecurrence->addObserver( dest );
00140 } else {
00141 mRecurrence = 0;
00142 }
00143 }
00144
00145 KDateTime mCreated;
00146 int mRevision;
00147
00148 QString mDescription;
00149 bool mDescriptionIsRich;
00150 QString mSummary;
00151 bool mSummaryIsRich;
00152 QString mLocation;
00153 bool mLocationIsRich;
00154 QStringList mCategories;
00155 mutable Recurrence *mRecurrence;
00156 Attachment::List mAttachments;
00157 Alarm::List mAlarms;
00158 QStringList mResources;
00159 Status mStatus;
00160 QString mStatusString;
00161 Secrecy mSecrecy;
00162 int mPriority;
00163 QString mSchedulingID;
00164
00165 QMap<RelType,QString> mRelatedToUid;
00166 float mGeoLatitude;
00167 float mGeoLongitude;
00168 bool mHasGeo;
00169 QHash<Attachment::Ptr,QString> mTempFiles;
00170 KDateTime mRecurrenceId;
00171 bool mLocalOnly;
00172 };
00173
00174
00175 Incidence::Incidence()
00176 : IncidenceBase(), d( new KCalCore::Incidence::Private )
00177 {
00178 recreate();
00179 resetDirtyFields();
00180 }
00181
00182 Incidence::Incidence( const Incidence &i )
00183 : IncidenceBase( i ),
00184 Recurrence::RecurrenceObserver(),
00185 d( new KCalCore::Incidence::Private( *i.d ) )
00186 {
00187 d->init( this, i );
00188 resetDirtyFields();
00189 }
00190
00191 Incidence::~Incidence()
00192 {
00193
00194
00195 foreach ( Alarm::Ptr alarm, d->mAlarms ) {
00196 alarm->setParent( 0 );
00197 }
00198
00199 delete d->mRecurrence;
00200 delete d;
00201 }
00202
00203
00204
00205 static bool stringCompare( const QString &s1, const QString &s2 )
00206 {
00207 return ( s1.isEmpty() && s2.isEmpty() ) || ( s1 == s2 );
00208 }
00209
00210
00211 IncidenceBase &Incidence::assign( const IncidenceBase &other )
00212 {
00213 if ( &other != this ) {
00214 d->clear();
00215
00216 IncidenceBase::assign( other );
00217 const Incidence *i = static_cast<const Incidence*>( &other );
00218 d->init( this, *i );
00219 }
00220
00221 return *this;
00222 }
00223
00224 bool Incidence::equals( const IncidenceBase &incidence ) const
00225 {
00226 if ( !IncidenceBase::equals( incidence ) ) {
00227 return false;
00228 }
00229
00230
00231 const Incidence *i2 = static_cast<const Incidence *>( &incidence );
00232
00233 if ( alarms().count() != i2->alarms().count() ) {
00234 return false;
00235 }
00236
00237 Alarm::List::ConstIterator a1 = alarms().constBegin();
00238 Alarm::List::ConstIterator a1end = alarms().constEnd();
00239 Alarm::List::ConstIterator a2 = i2->alarms().constBegin();
00240 Alarm::List::ConstIterator a2end = i2->alarms().constEnd();
00241 for ( ; a1 != a1end && a2 != a2end; ++a1, ++a2 ) {
00242 if ( **a1 == **a2 ) {
00243 continue;
00244 } else {
00245 return false;
00246 }
00247 }
00248
00249 if ( attachments().count() != i2->attachments().count() ) {
00250 return false;
00251 }
00252
00253 Attachment::List::ConstIterator att1 = attachments().constBegin();
00254 const Attachment::List::ConstIterator att1end = attachments().constEnd();
00255 Attachment::List::ConstIterator att2 = i2->attachments().constBegin();
00256 const Attachment::List::ConstIterator att2end = i2->attachments().constEnd();
00257 for ( ; att1 != att1end && att2 != att2end; ++att1, ++att2 ) {
00258 if ( **att1 == **att2 ) {
00259 continue;
00260 } else {
00261 return false;
00262 }
00263 }
00264
00265 bool recurrenceEqual = ( d->mRecurrence == 0 && i2->d->mRecurrence == 0 );
00266 if ( !recurrenceEqual ) {
00267 recurrence();
00268 i2->recurrence();
00269 recurrenceEqual = d->mRecurrence != 0 &&
00270 i2->d->mRecurrence != 0 &&
00271 *d->mRecurrence == *i2->d->mRecurrence;
00272 }
00273
00274 return
00275 recurrenceEqual &&
00276 created() == i2->created() &&
00277 stringCompare( description(), i2->description() ) &&
00278 stringCompare( summary(), i2->summary() ) &&
00279 categories() == i2->categories() &&
00280 stringCompare( relatedTo(), i2->relatedTo() ) &&
00281 resources() == i2->resources() &&
00282 d->mStatus == i2->d->mStatus &&
00283 ( d->mStatus == StatusNone ||
00284 stringCompare( d->mStatusString, i2->d->mStatusString ) ) &&
00285 secrecy() == i2->secrecy() &&
00286 priority() == i2->priority() &&
00287 stringCompare( location(), i2->location() ) &&
00288 stringCompare( schedulingID(), i2->schedulingID() );
00289 }
00290
00291 void Incidence::recreate()
00292 {
00293 KDateTime nowUTC = KDateTime::currentUtcDateTime();
00294 setCreated( nowUTC );
00295
00296 setSchedulingID( QString(), CalFormat::createUniqueId() );
00297
00298 setRevision( 0 );
00299
00300 setLastModified( nowUTC );
00301 }
00302
00303 void Incidence::setLastModified( const KDateTime &lm )
00304 {
00305 if ( !d->mLocalOnly ) {
00306 IncidenceBase::setLastModified( lm );
00307 }
00308 }
00309
00310 void Incidence::setReadOnly( bool readOnly )
00311 {
00312 IncidenceBase::setReadOnly( readOnly );
00313 if ( d->mRecurrence ) {
00314 d->mRecurrence->setRecurReadOnly( readOnly );
00315 }
00316 }
00317
00318 void Incidence::setLocalOnly( bool localOnly )
00319 {
00320 if ( mReadOnly ) {
00321 return;
00322 }
00323 d->mLocalOnly = localOnly;
00324 }
00325
00326 bool Incidence::localOnly() const
00327 {
00328 return d->mLocalOnly;
00329 }
00330
00331 void Incidence::setAllDay( bool allDay )
00332 {
00333 if ( mReadOnly ) {
00334 return;
00335 }
00336 if ( d->mRecurrence ) {
00337 d->mRecurrence->setAllDay( allDay );
00338 }
00339 IncidenceBase::setAllDay( allDay );
00340 }
00341
00342 void Incidence::setCreated( const KDateTime &created )
00343 {
00344 if ( mReadOnly || d->mLocalOnly ) {
00345 return;
00346 }
00347
00348 d->mCreated = created.toUtc();
00349 setFieldDirty( FieldCreated );
00350
00351
00352
00353 }
00354
00355 KDateTime Incidence::created() const
00356 {
00357 return d->mCreated;
00358 }
00359
00360 void Incidence::setRevision( int rev )
00361 {
00362 if ( mReadOnly || d->mLocalOnly ) {
00363 return;
00364 }
00365
00366 update();
00367
00368 d->mRevision = rev;
00369 setFieldDirty( FieldRevision );
00370 updated();
00371 }
00372
00373 int Incidence::revision() const
00374 {
00375 return d->mRevision;
00376 }
00377
00378 void Incidence::setDtStart( const KDateTime &dt )
00379 {
00380 if ( d->mRecurrence ) {
00381 d->mRecurrence->setStartDateTime( dt );
00382 d->mRecurrence->setAllDay( allDay() );
00383 }
00384 IncidenceBase::setDtStart( dt );
00385 }
00386
00387 void Incidence::shiftTimes( const KDateTime::Spec &oldSpec,
00388 const KDateTime::Spec &newSpec )
00389 {
00390 IncidenceBase::shiftTimes( oldSpec, newSpec );
00391 if ( d->mRecurrence ) {
00392 d->mRecurrence->shiftTimes( oldSpec, newSpec );
00393 }
00394 for ( int i = 0, end = d->mAlarms.count(); i < end; ++i ) {
00395 d->mAlarms[i]->shiftTimes( oldSpec, newSpec );
00396 }
00397 }
00398
00399 void Incidence::setDescription( const QString &description, bool isRich )
00400 {
00401 if ( mReadOnly ) {
00402 return;
00403 }
00404 update();
00405 d->mDescription = description;
00406 d->mDescriptionIsRich = isRich;
00407 setFieldDirty( FieldDescription );
00408 updated();
00409 }
00410
00411 void Incidence::setDescription( const QString &description )
00412 {
00413 setDescription( description, Qt::mightBeRichText( description ) );
00414 }
00415
00416 QString Incidence::description() const
00417 {
00418 return d->mDescription;
00419 }
00420
00421 QString Incidence::richDescription() const
00422 {
00423 if ( descriptionIsRich() ) {
00424 return d->mDescription;
00425 } else {
00426 return Qt::escape( d->mDescription ).replace( '\n', "<br/>" );
00427 }
00428 }
00429
00430 bool Incidence::descriptionIsRich() const
00431 {
00432 return d->mDescriptionIsRich;
00433 }
00434
00435 void Incidence::setSummary( const QString &summary, bool isRich )
00436 {
00437 if ( mReadOnly ) {
00438 return;
00439 }
00440 update();
00441 d->mSummary = summary;
00442 d->mSummaryIsRich = isRich;
00443 setFieldDirty( FieldSummary );
00444 updated();
00445 }
00446
00447 void Incidence::setSummary( const QString &summary )
00448 {
00449 setSummary( summary, Qt::mightBeRichText( summary ) );
00450 }
00451
00452 QString Incidence::summary() const
00453 {
00454 return d->mSummary;
00455 }
00456
00457 QString Incidence::richSummary() const
00458 {
00459 if ( summaryIsRich() ) {
00460 return d->mSummary;
00461 } else {
00462 return Qt::escape( d->mSummary ).replace( '\n', "<br/>" );
00463 }
00464 }
00465
00466 bool Incidence::summaryIsRich() const
00467 {
00468 return d->mSummaryIsRich;
00469 }
00470
00471 void Incidence::setCategories( const QStringList &categories )
00472 {
00473 if ( mReadOnly ) {
00474 return;
00475 }
00476
00477 update();
00478 d->mCategories = categories;
00479 updated();
00480 }
00481
00482 void Incidence::setCategories( const QString &catStr )
00483 {
00484 if ( mReadOnly ) {
00485 return;
00486 }
00487 update();
00488 setFieldDirty( FieldCategories );
00489
00490 d->mCategories.clear();
00491
00492 if ( catStr.isEmpty() ) {
00493 updated();
00494 return;
00495 }
00496
00497 d->mCategories = catStr.split( ',' );
00498
00499 QStringList::Iterator it;
00500 for ( it = d->mCategories.begin();it != d->mCategories.end(); ++it ) {
00501 *it = (*it).trimmed();
00502 }
00503
00504 updated();
00505 }
00506
00507 QStringList Incidence::categories() const
00508 {
00509 return d->mCategories;
00510 }
00511
00512 QString Incidence::categoriesStr() const
00513 {
00514 return d->mCategories.join( "," );
00515 }
00516
00517 void Incidence::setRelatedTo( const QString &relatedToUid, RelType relType )
00518 {
00519
00520
00521
00522 if ( d->mRelatedToUid[relType] != relatedToUid ) {
00523 update();
00524 d->mRelatedToUid[relType] = relatedToUid;
00525 setFieldDirty( FieldRelatedTo );
00526 updated();
00527 }
00528 }
00529
00530 QString Incidence::relatedTo( RelType relType ) const
00531 {
00532 return d->mRelatedToUid.value( relType );
00533 }
00534
00535
00536
00537 Recurrence *Incidence::recurrence() const
00538 {
00539 if ( !d->mRecurrence ) {
00540 d->mRecurrence = new Recurrence();
00541 d->mRecurrence->setStartDateTime( IncidenceBase::dtStart() );
00542 d->mRecurrence->setAllDay( allDay() );
00543 d->mRecurrence->setRecurReadOnly( mReadOnly );
00544 d->mRecurrence->addObserver( const_cast<KCalCore::Incidence*>( this ) );
00545 }
00546
00547 return d->mRecurrence;
00548 }
00549
00550 void Incidence::clearRecurrence()
00551 {
00552 delete d->mRecurrence;
00553 d->mRecurrence = 0;
00554 }
00555
00556 ushort Incidence::recurrenceType() const
00557 {
00558 if ( d->mRecurrence ) {
00559 return d->mRecurrence->recurrenceType();
00560 } else {
00561 return Recurrence::rNone;
00562 }
00563 }
00564
00565 bool Incidence::recurs() const
00566 {
00567 if ( d->mRecurrence ) {
00568 return d->mRecurrence->recurs();
00569 } else {
00570 return false;
00571 }
00572 }
00573
00574 bool Incidence::recursOn( const QDate &date,
00575 const KDateTime::Spec &timeSpec ) const
00576 {
00577 return d->mRecurrence && d->mRecurrence->recursOn( date, timeSpec );
00578 }
00579
00580 bool Incidence::recursAt( const KDateTime &qdt ) const
00581 {
00582 return d->mRecurrence && d->mRecurrence->recursAt( qdt );
00583 }
00584
00585 QList<KDateTime> Incidence::startDateTimesForDate( const QDate &date,
00586 const KDateTime::Spec &timeSpec ) const
00587 {
00588 KDateTime start = dtStart();
00589 KDateTime end = dateTime( RoleEndRecurrenceBase );
00590
00591 QList<KDateTime> result;
00592
00593
00594 if ( !start.isValid() && ! end.isValid() ) {
00595 return result;
00596 }
00597
00598
00599 KDateTime kdate( date, timeSpec );
00600 if ( !recurs() ) {
00601 if ( !( start > kdate || end < kdate ) ) {
00602 result << start;
00603 }
00604 return result;
00605 }
00606
00607 int days = start.daysTo( end );
00608
00609 QDate tmpday( date.addDays( -days - 1 ) );
00610 KDateTime tmp;
00611 while ( tmpday <= date ) {
00612 if ( recurrence()->recursOn( tmpday, timeSpec ) ) {
00613 QList<QTime> times = recurrence()->recurTimesOn( tmpday, timeSpec );
00614 foreach ( const QTime &time, times ) {
00615 tmp = KDateTime( tmpday, time, start.timeSpec() );
00616 if ( endDateForStart( tmp ) >= kdate ) {
00617 result << tmp;
00618 }
00619 }
00620 }
00621 tmpday = tmpday.addDays( 1 );
00622 }
00623 return result;
00624 }
00625
00626 QList<KDateTime> Incidence::startDateTimesForDateTime( const KDateTime &datetime ) const
00627 {
00628 KDateTime start = dtStart();
00629 KDateTime end = dateTime( RoleEndRecurrenceBase );
00630
00631 QList<KDateTime> result;
00632
00633
00634 if ( !start.isValid() && ! end.isValid() ) {
00635 return result;
00636 }
00637
00638
00639 if ( !recurs() ) {
00640 if ( !( start > datetime || end < datetime ) ) {
00641 result << start;
00642 }
00643 return result;
00644 }
00645
00646 int days = start.daysTo( end );
00647
00648 QDate tmpday( datetime.date().addDays( -days - 1 ) );
00649 KDateTime tmp;
00650 while ( tmpday <= datetime.date() ) {
00651 if ( recurrence()->recursOn( tmpday, datetime.timeSpec() ) ) {
00652
00653 QList<QTime> times = recurrence()->recurTimesOn( tmpday, start.timeSpec() );
00654 foreach ( const QTime &time, times ) {
00655 tmp = KDateTime( tmpday, time, start.timeSpec() );
00656 if ( !( tmp > datetime || endDateForStart( tmp ) < datetime ) ) {
00657 result << tmp;
00658 }
00659 }
00660 }
00661 tmpday = tmpday.addDays( 1 );
00662 }
00663 return result;
00664 }
00665
00666 KDateTime Incidence::endDateForStart( const KDateTime &startDt ) const
00667 {
00668 KDateTime start = dtStart();
00669 KDateTime end = dateTime( RoleEndRecurrenceBase );
00670 if ( !end.isValid() ) {
00671 return start;
00672 }
00673 if ( !start.isValid() ) {
00674 return end;
00675 }
00676
00677 return startDt.addSecs( start.secsTo( end ) );
00678 }
00679
00680 void Incidence::addAttachment( const Attachment::Ptr &attachment )
00681 {
00682 if ( mReadOnly || !attachment ) {
00683 return;
00684 }
00685
00686 Q_ASSERT( !d->mAttachments.contains( attachment ) );
00687
00688 update();
00689 d->mAttachments.append( attachment );
00690 setFieldDirty( FieldAttachment );
00691 updated();
00692 }
00693
00694 void Incidence::deleteAttachment( const Attachment::Ptr &attachment )
00695 {
00696 int index = d->mAttachments.indexOf( attachment );
00697 if ( index > -1 ) {
00698 setFieldDirty( FieldAttachment );
00699 d->mAttachments.remove( index );
00700 }
00701 }
00702
00703 void Incidence::deleteAttachments( const QString &mime )
00704 {
00705 Attachment::List result;
00706 Attachment::List::Iterator it = d->mAttachments.begin();
00707 while ( it != d->mAttachments.end() ) {
00708 if ( (*it)->mimeType() != mime ) {
00709 result += *it;
00710 }
00711 ++it;
00712 }
00713 d->mAttachments = result;
00714 setFieldDirty( FieldAttachment );
00715 }
00716
00717 Attachment::List Incidence::attachments() const
00718 {
00719 return d->mAttachments;
00720 }
00721
00722 Attachment::List Incidence::attachments( const QString &mime ) const
00723 {
00724 Attachment::List attachments;
00725 foreach ( Attachment::Ptr attachment, d->mAttachments ) {
00726 if ( attachment->mimeType() == mime ) {
00727 attachments.append( attachment );
00728 }
00729 }
00730 return attachments;
00731 }
00732
00733 void Incidence::clearAttachments()
00734 {
00735 setFieldDirty( FieldAttachment );
00736 d->mAttachments.clear();
00737 }
00738
00739 QString Incidence::writeAttachmentToTempFile( const Attachment::Ptr &attachment ) const
00740 {
00741 if ( d->mTempFiles.contains( attachment ) ) {
00742 return d->mTempFiles.value( attachment );
00743 }
00744 KTemporaryFile *file = new KTemporaryFile();
00745
00746 QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
00747
00748 if ( !patterns.empty() ) {
00749 file->setSuffix( QString( patterns.first() ).remove( '*' ) );
00750 }
00751 file->setAutoRemove( true );
00752 file->open();
00753
00754 file->setPermissions( QFile::ReadUser );
00755 file->write( QByteArray::fromBase64( attachment->data() ) );
00756 d->mTempFiles.insert( attachment, file->fileName() );
00757 file->close();
00758 return d->mTempFiles.value( attachment );
00759 }
00760
00761 void Incidence::clearTempFiles()
00762 {
00763 QHash<Attachment::Ptr,QString>::const_iterator it = d->mTempFiles.constBegin();
00764 const QHash<Attachment::Ptr,QString>::const_iterator end = d->mTempFiles.constEnd();
00765 for ( ; it != end; ++it ) {
00766 QFile::remove( it.value() );
00767 }
00768 d->mTempFiles.clear();
00769 }
00770
00771 void Incidence::setResources( const QStringList &resources )
00772 {
00773 if ( mReadOnly ) {
00774 return;
00775 }
00776
00777 update();
00778 d->mResources = resources;
00779 setFieldDirty( FieldResources );
00780 updated();
00781 }
00782
00783 QStringList Incidence::resources() const
00784 {
00785 return d->mResources;
00786 }
00787
00788 void Incidence::setPriority( int priority )
00789 {
00790 if ( mReadOnly ) {
00791 return;
00792 }
00793
00794 update();
00795 d->mPriority = priority;
00796 setFieldDirty( FieldPriority );
00797 updated();
00798 }
00799
00800 int Incidence::priority() const
00801 {
00802 return d->mPriority;
00803 }
00804
00805 void Incidence::setStatus( Incidence::Status status )
00806 {
00807 if ( mReadOnly || status == StatusX ) {
00808 return;
00809 }
00810
00811 update();
00812 d->mStatus = status;
00813 d->mStatusString.clear();
00814 setFieldDirty( FieldStatus );
00815 updated();
00816 }
00817
00818 void Incidence::setCustomStatus( const QString &status )
00819 {
00820 if ( mReadOnly ) {
00821 return;
00822 }
00823
00824 update();
00825 d->mStatus = status.isEmpty() ? StatusNone : StatusX;
00826 d->mStatusString = status;
00827 setFieldDirty( FieldStatus );
00828 updated();
00829 }
00830
00831 Incidence::Status Incidence::status() const
00832 {
00833 return d->mStatus;
00834 }
00835
00836 QString Incidence::customStatus() const
00837 {
00838 if ( d->mStatus == StatusX ) {
00839 return d->mStatusString;
00840 } else {
00841 return QString();
00842 }
00843 }
00844
00845 void Incidence::setSecrecy( Incidence::Secrecy secrecy )
00846 {
00847 if ( mReadOnly ) {
00848 return;
00849 }
00850
00851 update();
00852 d->mSecrecy = secrecy;
00853 setFieldDirty( FieldSecrecy );
00854 updated();
00855 }
00856
00857 Incidence::Secrecy Incidence::secrecy() const
00858 {
00859 return d->mSecrecy;
00860 }
00861
00862 Alarm::List Incidence::alarms() const
00863 {
00864 return d->mAlarms;
00865 }
00866
00867 Alarm::Ptr Incidence::newAlarm()
00868 {
00869 Alarm::Ptr alarm( new Alarm( this ) );
00870 d->mAlarms.append( alarm );
00871 return alarm;
00872 }
00873
00874 void Incidence::addAlarm( const Alarm::Ptr &alarm )
00875 {
00876 update();
00877 d->mAlarms.append( alarm );
00878 setFieldDirty( FieldAlarms );
00879 updated();
00880 }
00881
00882 void Incidence::removeAlarm( const Alarm::Ptr &alarm )
00883 {
00884 const int index = d->mAlarms.indexOf( alarm );
00885 if ( index > -1 ) {
00886 update();
00887 d->mAlarms.remove( index );
00888 setFieldDirty( FieldAlarms );
00889 updated();
00890 }
00891 }
00892
00893 void Incidence::clearAlarms()
00894 {
00895 update();
00896 d->mAlarms.clear();
00897 setFieldDirty( FieldAlarms );
00898 updated();
00899 }
00900
00901 bool Incidence::hasEnabledAlarms() const
00902 {
00903 foreach ( Alarm::Ptr alarm, d->mAlarms ) {
00904 if ( alarm->enabled() ) {
00905 return true;
00906 }
00907 }
00908 return false;
00909 }
00910
00911 void Incidence::setLocation( const QString &location, bool isRich )
00912 {
00913 if ( mReadOnly ) {
00914 return;
00915 }
00916
00917 update();
00918 d->mLocation = location;
00919 d->mLocationIsRich = isRich;
00920 setFieldDirty( FieldLocation );
00921 updated();
00922 }
00923
00924 void Incidence::setLocation( const QString &location )
00925 {
00926 setLocation( location, Qt::mightBeRichText( location ) );
00927 }
00928
00929 QString Incidence::location() const
00930 {
00931 return d->mLocation;
00932 }
00933
00934 QString Incidence::richLocation() const
00935 {
00936 if ( locationIsRich() ) {
00937 return d->mLocation;
00938 } else {
00939 return Qt::escape( d->mLocation ).replace( '\n', "<br/>" );
00940 }
00941 }
00942
00943 bool Incidence::locationIsRich() const
00944 {
00945 return d->mLocationIsRich;
00946 }
00947
00948 void Incidence::setSchedulingID( const QString &sid, const QString &uid )
00949 {
00950 d->mSchedulingID = sid;
00951 if ( !uid.isEmpty() ) {
00952 setUid( uid );
00953 }
00954 setFieldDirty( FieldSchedulingId );
00955 }
00956
00957 QString Incidence::schedulingID() const
00958 {
00959 if ( d->mSchedulingID.isNull() ) {
00960
00961 return uid();
00962 }
00963 return d->mSchedulingID;
00964 }
00965
00966 bool Incidence::hasGeo() const
00967 {
00968 return d->mHasGeo;
00969 }
00970
00971 void Incidence::setHasGeo( bool hasGeo )
00972 {
00973 if ( mReadOnly ) {
00974 return;
00975 }
00976
00977 if ( hasGeo == d->mHasGeo ) {
00978 return;
00979 }
00980
00981 update();
00982 d->mHasGeo = hasGeo;
00983 setFieldDirty( FieldGeoLatitude );
00984 setFieldDirty( FieldGeoLongitude );
00985 updated();
00986 }
00987
00988 float Incidence::geoLatitude() const
00989 {
00990 return d->mGeoLatitude;
00991 }
00992
00993 void Incidence::setGeoLatitude( float geolatitude )
00994 {
00995 if ( mReadOnly ) {
00996 return;
00997 }
00998
00999 update();
01000 d->mGeoLatitude = geolatitude;
01001 setFieldDirty( FieldGeoLatitude );
01002 updated();
01003 }
01004
01005 float Incidence::geoLongitude() const
01006 {
01007 return d->mGeoLongitude;
01008 }
01009
01010 void Incidence::setGeoLongitude( float geolongitude )
01011 {
01012 if ( !mReadOnly ) {
01013 update();
01014 d->mGeoLongitude = geolongitude;
01015 setFieldDirty( FieldGeoLongitude );
01016 updated();
01017 }
01018 }
01019
01020 bool Incidence::hasRecurrenceId() const
01021 {
01022 return d->mRecurrenceId.isValid();
01023 }
01024
01025 KDateTime Incidence::recurrenceId() const
01026 {
01027 return d->mRecurrenceId;
01028 }
01029
01030 void Incidence::setRecurrenceId( const KDateTime &recurrenceId )
01031 {
01032 if ( !mReadOnly ) {
01033 update();
01034 d->mRecurrenceId = recurrenceId;
01035 setFieldDirty( FieldRecurrenceId );
01036 updated();
01037 }
01038 }
01039
01043 void Incidence::recurrenceUpdated( Recurrence *recurrence )
01044 {
01045 if ( recurrence == d->mRecurrence ) {
01046 update();
01047 updated();
01048 }
01049 }
01050
01051
01052 #define ALT_DESC_FIELD "X-ALT-DESC"
01053 #define ALT_DESC_PARAMETERS "FMTTYPE=text/html"
01054
01055
01056 bool Incidence::hasAltDescription() const
01057 {
01058 const QString value = nonKDECustomProperty( ALT_DESC_FIELD );
01059 const QString parameter = nonKDECustomPropertyParameters( ALT_DESC_FIELD );
01060
01061 return parameter == ALT_DESC_PARAMETERS && !value.isEmpty();
01062 }
01063
01064 void Incidence::setAltDescription( const QString &altdescription )
01065 {
01066 if ( altdescription.isEmpty() ) {
01067 removeNonKDECustomProperty( ALT_DESC_FIELD );
01068 } else {
01069 setNonKDECustomProperty( ALT_DESC_FIELD,
01070 altdescription,
01071 ALT_DESC_PARAMETERS );
01072 }
01073 }
01074
01075 QString Incidence::altDescription() const
01076 {
01077 if ( !hasAltDescription() ) {
01078 return QString();
01079 } else {
01080 return nonKDECustomProperty( ALT_DESC_FIELD );
01081 }
01082 }