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

KCalCore Library

incidence.cpp
Go to the documentation of this file.
00001 /*
00002   This file is part of the kcalcore library.
00003 
00004   Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
00005   Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00006 
00007   This library is free software; you can redistribute it and/or
00008   modify it under the terms of the GNU Library General Public
00009   License as published by the Free Software Foundation; either
00010   version 2 of the License, or (at your option) any later version.
00011 
00012   This library is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   Library General Public License for more details.
00016 
00017   You should have received a copy of the GNU Library General Public License
00018   along with this library; see the file COPYING.LIB.  If not, write to
00019   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020   Boston, MA 02110-1301, USA.
00021 */
00035 #include "incidence.h"
00036 #include "calformat.h"
00037 
00038 #include <KMimeType>
00039 #include <KTemporaryFile>
00040 
00041 #include <QtGui/QTextDocument> // for Qt::escape() and Qt::mightBeRichText()
00042 
00043 using namespace KCalCore;
00044 
00049 //@cond PRIVATE
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       // Alarms and Attachments are stored in ListBase<...>, which is a QValueList<...*>.
00124       // We need to really duplicate the objects stored therein, otherwise deleting
00125       // i will also delete all attachments from this object (setAutoDelete...)
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;                 // creation datetime
00146     int mRevision;                      // revision number
00147 
00148     QString mDescription;               // description string
00149     bool mDescriptionIsRich;            // description string is richtext.
00150     QString mSummary;                   // summary string
00151     bool mSummaryIsRich;                // summary string is richtext.
00152     QString mLocation;                  // location string
00153     bool mLocationIsRich;               // location string is richtext.
00154     QStringList mCategories;            // category list
00155     mutable Recurrence *mRecurrence;    // recurrence
00156     Attachment::List mAttachments;      // attachments list
00157     Alarm::List mAlarms;                // alarms list
00158     QStringList mResources;             // resources list (not calendar resources)
00159     Status mStatus;                     // status
00160     QString mStatusString;              // status string, for custom status
00161     Secrecy mSecrecy;                   // secrecy
00162     int mPriority;                      // priority: 1 = highest, 2 = less, etc.
00163     QString mSchedulingID;              // ID for scheduling mails
00164 
00165     QMap<RelType,QString> mRelatedToUid;// incidence uid this is related to, for each relType
00166     float mGeoLatitude;                 // Specifies latitude in decimal degrees
00167     float mGeoLongitude;                // Specifies longitude in decimal degrees
00168     bool mHasGeo;                       // if incidence has geo data
00169     QHash<Attachment::Ptr,QString> mTempFiles; // Temporary files for writing attachments to.
00170     KDateTime mRecurrenceId;            // recurrenceId
00171     bool mLocalOnly;                    // allow changes that won't go to the server
00172 };
00173 //@endcond
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   // Alarm has a raw incidence pointer, so we must set it to 0
00194   // so Alarm doesn't use it after Incidence is destroyed
00195   foreach ( Alarm::Ptr alarm, d->mAlarms ) {
00196     alarm->setParent( 0 );
00197   }
00198 
00199   delete d->mRecurrence;
00200   delete d;
00201 }
00202 
00203 //@cond PRIVATE
00204 // A string comparison that considers that null and empty are the same
00205 static bool stringCompare( const QString &s1, const QString &s2 )
00206 {
00207   return ( s1.isEmpty() && s2.isEmpty() ) || ( s1 == s2 );
00208 }
00209 
00210 //@endcond
00211 IncidenceBase &Incidence::assign( const IncidenceBase &other )
00212 {
00213   if ( &other != this ) {
00214     d->clear();
00215     //TODO: should relations be cleared out, as in destructor???
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   // If they weren't the same type IncidenceBase::equals would had returned false already
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(); // create if doesn't exist
00268     i2->recurrence(); // create if doesn't exist
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   const KDateTime nowUTC = KDateTime::currentUtcDateTime();
00294   setCreated( nowUTC );
00295 
00296   setSchedulingID( QString(), CalFormat::createUniqueId() );
00297   setRevision( 0 );
00298   setLastModified( nowUTC );
00299 }
00300 
00301 void Incidence::setLastModified( const KDateTime &lm )
00302 {
00303   if ( !d->mLocalOnly ) {
00304     IncidenceBase::setLastModified( lm );
00305   }
00306 }
00307 
00308 void Incidence::setReadOnly( bool readOnly )
00309 {
00310   IncidenceBase::setReadOnly( readOnly );
00311   if ( d->mRecurrence ) {
00312     d->mRecurrence->setRecurReadOnly( readOnly );
00313   }
00314 }
00315 
00316 void Incidence::setLocalOnly( bool localOnly )
00317 {
00318     if ( mReadOnly ) {
00319       return;
00320     }
00321     d->mLocalOnly = localOnly;
00322 }
00323 
00324 bool Incidence::localOnly() const
00325 {
00326   return d->mLocalOnly;
00327 }
00328 
00329 void Incidence::setAllDay( bool allDay )
00330 {
00331   if ( mReadOnly ) {
00332     return;
00333   }
00334   if ( d->mRecurrence ) {
00335     d->mRecurrence->setAllDay( allDay );
00336   }
00337   IncidenceBase::setAllDay( allDay );
00338 }
00339 
00340 void Incidence::setCreated( const KDateTime &created )
00341 {
00342   if ( mReadOnly || d->mLocalOnly ) {
00343     return;
00344   }
00345 
00346   d->mCreated = created.toUtc();
00347   setFieldDirty( FieldCreated );
00348 
00349 // FIXME: Shouldn't we call updated for the creation date, too?
00350 //  updated();
00351 }
00352 
00353 KDateTime Incidence::created() const
00354 {
00355   return d->mCreated;
00356 }
00357 
00358 void Incidence::setRevision( int rev )
00359 {
00360   if ( mReadOnly || d->mLocalOnly ) {
00361     return;
00362   }
00363 
00364   update();
00365 
00366   d->mRevision = rev;
00367   setFieldDirty( FieldRevision );
00368   updated();
00369 }
00370 
00371 int Incidence::revision() const
00372 {
00373   return d->mRevision;
00374 }
00375 
00376 void Incidence::setDtStart( const KDateTime &dt )
00377 {
00378   if ( d->mRecurrence ) {
00379     d->mRecurrence->setStartDateTime( dt );
00380     d->mRecurrence->setAllDay( allDay() );
00381   }
00382   IncidenceBase::setDtStart( dt );
00383 }
00384 
00385 void Incidence::shiftTimes( const KDateTime::Spec &oldSpec,
00386                             const KDateTime::Spec &newSpec )
00387 {
00388   IncidenceBase::shiftTimes( oldSpec, newSpec );
00389   if ( d->mRecurrence ) {
00390     d->mRecurrence->shiftTimes( oldSpec, newSpec );
00391   }
00392   for ( int i = 0, end = d->mAlarms.count();  i < end;  ++i ) {
00393     d->mAlarms[i]->shiftTimes( oldSpec, newSpec );
00394   }
00395 }
00396 
00397 void Incidence::setDescription( const QString &description, bool isRich )
00398 {
00399   if ( mReadOnly ) {
00400     return;
00401   }
00402   update();
00403   d->mDescription = description;
00404   d->mDescriptionIsRich = isRich;
00405   setFieldDirty( FieldDescription );
00406   updated();
00407 }
00408 
00409 void Incidence::setDescription( const QString &description )
00410 {
00411   setDescription( description, Qt::mightBeRichText( description ) );
00412 }
00413 
00414 QString Incidence::description() const
00415 {
00416   return d->mDescription;
00417 }
00418 
00419 QString Incidence::richDescription() const
00420 {
00421   if ( descriptionIsRich() ) {
00422     return d->mDescription;
00423   } else {
00424     return Qt::escape( d->mDescription ).replace( '\n', "<br/>" );
00425   }
00426 }
00427 
00428 bool Incidence::descriptionIsRich() const
00429 {
00430   return d->mDescriptionIsRich;
00431 }
00432 
00433 void Incidence::setSummary( const QString &summary, bool isRich )
00434 {
00435   if ( mReadOnly ) {
00436     return;
00437   }
00438   update();
00439   d->mSummary = summary;
00440   d->mSummaryIsRich = isRich;
00441   setFieldDirty( FieldSummary );
00442   updated();
00443 }
00444 
00445 void Incidence::setSummary( const QString &summary )
00446 {
00447   setSummary( summary, Qt::mightBeRichText( summary ) );
00448 }
00449 
00450 QString Incidence::summary() const
00451 {
00452   return d->mSummary;
00453 }
00454 
00455 QString Incidence::richSummary() const
00456 {
00457   if ( summaryIsRich() ) {
00458     return d->mSummary;
00459   } else {
00460     return Qt::escape( d->mSummary ).replace( '\n', "<br/>" );
00461   }
00462 }
00463 
00464 bool Incidence::summaryIsRich() const
00465 {
00466   return d->mSummaryIsRich;
00467 }
00468 
00469 void Incidence::setCategories( const QStringList &categories )
00470 {
00471   if ( mReadOnly ) {
00472     return;
00473   }
00474 
00475   update();
00476   d->mCategories = categories;
00477   updated();
00478 }
00479 
00480 void Incidence::setCategories( const QString &catStr )
00481 {
00482   if ( mReadOnly ) {
00483     return;
00484   }
00485   update();
00486   setFieldDirty( FieldCategories );
00487 
00488   d->mCategories.clear();
00489 
00490   if ( catStr.isEmpty() ) {
00491     updated();
00492     return;
00493   }
00494 
00495   d->mCategories = catStr.split( ',' );
00496 
00497   QStringList::Iterator it;
00498   for ( it = d->mCategories.begin();it != d->mCategories.end(); ++it ) {
00499     *it = (*it).trimmed();
00500   }
00501 
00502   updated();
00503 }
00504 
00505 QStringList Incidence::categories() const
00506 {
00507   return d->mCategories;
00508 }
00509 
00510 QString Incidence::categoriesStr() const
00511 {
00512   return d->mCategories.join( "," );
00513 }
00514 
00515 void Incidence::setRelatedTo( const QString &relatedToUid, RelType relType )
00516 {
00517   // TODO: RFC says that an incidence can have more than one related-to field
00518   // even for the same relType.
00519 
00520   if ( d->mRelatedToUid[relType] != relatedToUid ) {
00521     update();
00522     d->mRelatedToUid[relType] = relatedToUid;
00523     setFieldDirty( FieldRelatedTo );
00524     updated();
00525   }
00526 }
00527 
00528 QString Incidence::relatedTo( RelType relType ) const
00529 {
00530   return d->mRelatedToUid.value( relType );
00531 }
00532 
00533 // %%%%%%%%%%%%  Recurrence-related methods %%%%%%%%%%%%%%%%%%%%
00534 
00535 Recurrence *Incidence::recurrence() const
00536 {
00537   if ( !d->mRecurrence ) {
00538     d->mRecurrence = new Recurrence();
00539     d->mRecurrence->setStartDateTime( IncidenceBase::dtStart() );
00540     d->mRecurrence->setAllDay( allDay() );
00541     d->mRecurrence->setRecurReadOnly( mReadOnly );
00542     d->mRecurrence->addObserver( const_cast<KCalCore::Incidence*>( this ) );
00543   }
00544 
00545   return d->mRecurrence;
00546 }
00547 
00548 void Incidence::clearRecurrence()
00549 {
00550   delete d->mRecurrence;
00551   d->mRecurrence = 0;
00552 }
00553 
00554 ushort Incidence::recurrenceType() const
00555 {
00556   if ( d->mRecurrence ) {
00557     return d->mRecurrence->recurrenceType();
00558   } else {
00559     return Recurrence::rNone;
00560   }
00561 }
00562 
00563 bool Incidence::recurs() const
00564 {
00565   if ( d->mRecurrence ) {
00566     return d->mRecurrence->recurs();
00567   } else {
00568     return false;
00569   }
00570 }
00571 
00572 bool Incidence::recursOn( const QDate &date,
00573                           const KDateTime::Spec &timeSpec ) const
00574 {
00575   return d->mRecurrence && d->mRecurrence->recursOn( date, timeSpec );
00576 }
00577 
00578 bool Incidence::recursAt( const KDateTime &qdt ) const
00579 {
00580   return d->mRecurrence && d->mRecurrence->recursAt( qdt );
00581 }
00582 
00583 QList<KDateTime> Incidence::startDateTimesForDate( const QDate &date,
00584                                                    const KDateTime::Spec &timeSpec ) const
00585 {
00586   KDateTime start = dtStart();
00587   KDateTime end = dateTime( RoleEndRecurrenceBase );
00588 
00589   QList<KDateTime> result;
00590 
00591   // TODO_Recurrence: Also work if only due date is given...
00592   if ( !start.isValid() && ! end.isValid() ) {
00593     return result;
00594   }
00595 
00596   // if the incidence doesn't recur,
00597   KDateTime kdate( date, timeSpec );
00598   if ( !recurs() ) {
00599     if ( !( start > kdate || end < kdate ) ) {
00600       result << start;
00601     }
00602     return result;
00603   }
00604 
00605   int days = start.daysTo( end );
00606   // Account for possible recurrences going over midnight, while the original event doesn't
00607   QDate tmpday( date.addDays( -days - 1 ) );
00608   KDateTime tmp;
00609   while ( tmpday <= date ) {
00610     if ( recurrence()->recursOn( tmpday, timeSpec ) ) {
00611       QList<QTime> times = recurrence()->recurTimesOn( tmpday, timeSpec );
00612       foreach ( const QTime &time, times ) {
00613         tmp = KDateTime( tmpday, time, start.timeSpec() );
00614         if ( endDateForStart( tmp ) >= kdate ) {
00615           result << tmp;
00616         }
00617       }
00618     }
00619     tmpday = tmpday.addDays( 1 );
00620   }
00621   return result;
00622 }
00623 
00624 QList<KDateTime> Incidence::startDateTimesForDateTime( const KDateTime &datetime ) const
00625 {
00626   KDateTime start = dtStart();
00627   KDateTime end = dateTime( RoleEndRecurrenceBase );
00628 
00629   QList<KDateTime> result;
00630 
00631   // TODO_Recurrence: Also work if only due date is given...
00632   if ( !start.isValid() && ! end.isValid() ) {
00633     return result;
00634   }
00635 
00636   // if the incidence doesn't recur,
00637   if ( !recurs() ) {
00638     if ( !( start > datetime || end < datetime ) ) {
00639       result << start;
00640     }
00641     return result;
00642   }
00643 
00644   int days = start.daysTo( end );
00645   // Account for possible recurrences going over midnight, while the original event doesn't
00646   QDate tmpday( datetime.date().addDays( -days - 1 ) );
00647   KDateTime tmp;
00648   while ( tmpday <= datetime.date() ) {
00649     if ( recurrence()->recursOn( tmpday, datetime.timeSpec() ) ) {
00650       // Get the times during the day (in start date's time zone) when recurrences happen
00651       QList<QTime> times = recurrence()->recurTimesOn( tmpday, start.timeSpec() );
00652       foreach ( const QTime &time, times ) {
00653         tmp = KDateTime( tmpday, time, start.timeSpec() );
00654         if ( !( tmp > datetime || endDateForStart( tmp ) < datetime ) ) {
00655           result << tmp;
00656         }
00657       }
00658     }
00659     tmpday = tmpday.addDays( 1 );
00660   }
00661   return result;
00662 }
00663 
00664 KDateTime Incidence::endDateForStart( const KDateTime &startDt ) const
00665 {
00666   KDateTime start = dtStart();
00667   KDateTime end = dateTime( RoleEndRecurrenceBase );
00668   if ( !end.isValid() ) {
00669     return start;
00670   }
00671   if ( !start.isValid() ) {
00672     return end;
00673   }
00674 
00675   return startDt.addSecs( start.secsTo( end ) );
00676 }
00677 
00678 void Incidence::addAttachment( const Attachment::Ptr &attachment )
00679 {
00680   if ( mReadOnly || !attachment ) {
00681     return;
00682   }
00683 
00684   Q_ASSERT( !d->mAttachments.contains( attachment ) );
00685 
00686   update();
00687   d->mAttachments.append( attachment );
00688   setFieldDirty( FieldAttachment );
00689   updated();
00690 }
00691 
00692 void Incidence::deleteAttachment( const Attachment::Ptr &attachment )
00693 {
00694   int index = d->mAttachments.indexOf( attachment );
00695   if ( index > -1 ) {
00696     setFieldDirty( FieldAttachment );
00697     d->mAttachments.remove( index );
00698   }
00699 }
00700 
00701 void Incidence::deleteAttachments( const QString &mime )
00702 {
00703   Attachment::List result;
00704   Attachment::List::Iterator it = d->mAttachments.begin();
00705   while ( it != d->mAttachments.end() ) {
00706     if ( (*it)->mimeType() != mime ) {
00707       result += *it;
00708     }
00709     ++it;
00710   }
00711   d->mAttachments = result;
00712   setFieldDirty( FieldAttachment );
00713 }
00714 
00715 Attachment::List Incidence::attachments() const
00716 {
00717   return d->mAttachments;
00718 }
00719 
00720 Attachment::List Incidence::attachments( const QString &mime ) const
00721 {
00722   Attachment::List attachments;
00723   foreach ( Attachment::Ptr attachment, d->mAttachments ) {
00724     if ( attachment->mimeType() == mime ) {
00725       attachments.append( attachment );
00726     }
00727   }
00728   return attachments;
00729 }
00730 
00731 void Incidence::clearAttachments()
00732 {
00733   setFieldDirty( FieldAttachment );
00734   d->mAttachments.clear();
00735 }
00736 
00737 QString Incidence::writeAttachmentToTempFile( const Attachment::Ptr &attachment ) const
00738 {
00739   if ( d->mTempFiles.contains( attachment ) ) {
00740     return d->mTempFiles.value( attachment );
00741   }
00742   KTemporaryFile *file = new KTemporaryFile();
00743 
00744   QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
00745 
00746   if ( !patterns.empty() ) {
00747     file->setSuffix( QString( patterns.first() ).remove( '*' ) );
00748   }
00749   file->setAutoRemove( true );
00750   file->open();
00751   // read-only not to give the idea that it could be written to
00752   file->setPermissions( QFile::ReadUser );
00753   file->write( QByteArray::fromBase64( attachment->data() ) );
00754   d->mTempFiles.insert( attachment, file->fileName() );
00755   file->close();
00756   return d->mTempFiles.value( attachment );
00757 }
00758 
00759 void Incidence::clearTempFiles()
00760 {
00761   QHash<Attachment::Ptr,QString>::const_iterator it = d->mTempFiles.constBegin();
00762   const QHash<Attachment::Ptr,QString>::const_iterator end = d->mTempFiles.constEnd();
00763   for ( ; it != end; ++it ) {
00764     QFile::remove( it.value() );
00765   }
00766   d->mTempFiles.clear();
00767 }
00768 
00769 void Incidence::setResources( const QStringList &resources )
00770 {
00771   if ( mReadOnly ) {
00772     return;
00773   }
00774 
00775   update();
00776   d->mResources = resources;
00777   setFieldDirty( FieldResources );
00778   updated();
00779 }
00780 
00781 QStringList Incidence::resources() const
00782 {
00783   return d->mResources;
00784 }
00785 
00786 void Incidence::setPriority( int priority )
00787 {
00788   if ( mReadOnly ) {
00789     return;
00790   }
00791 
00792   update();
00793   d->mPriority = priority;
00794   setFieldDirty( FieldPriority );
00795   updated();
00796 }
00797 
00798 int Incidence::priority() const
00799 {
00800   return d->mPriority;
00801 }
00802 
00803 void Incidence::setStatus( Incidence::Status status )
00804 {
00805   if ( mReadOnly || status == StatusX ) {
00806     return;
00807   }
00808 
00809   update();
00810   d->mStatus = status;
00811   d->mStatusString.clear();
00812   setFieldDirty( FieldStatus );
00813   updated();
00814 }
00815 
00816 void Incidence::setCustomStatus( const QString &status )
00817 {
00818   if ( mReadOnly ) {
00819     return;
00820   }
00821 
00822   update();
00823   d->mStatus = status.isEmpty() ? StatusNone : StatusX;
00824   d->mStatusString = status;
00825   setFieldDirty( FieldStatus );
00826   updated();
00827 }
00828 
00829 Incidence::Status Incidence::status() const
00830 {
00831   return d->mStatus;
00832 }
00833 
00834 QString Incidence::customStatus() const
00835 {
00836   if ( d->mStatus == StatusX ) {
00837     return d->mStatusString;
00838   } else {
00839     return QString();
00840   }
00841 }
00842 
00843 void Incidence::setSecrecy( Incidence::Secrecy secrecy )
00844 {
00845   if ( mReadOnly ) {
00846     return;
00847   }
00848 
00849   update();
00850   d->mSecrecy = secrecy;
00851   setFieldDirty( FieldSecrecy );
00852   updated();
00853 }
00854 
00855 Incidence::Secrecy Incidence::secrecy() const
00856 {
00857   return d->mSecrecy;
00858 }
00859 
00860 Alarm::List Incidence::alarms() const
00861 {
00862   return d->mAlarms;
00863 }
00864 
00865 Alarm::Ptr Incidence::newAlarm()
00866 {
00867   Alarm::Ptr alarm( new Alarm( this ) );
00868   d->mAlarms.append( alarm );
00869   return alarm;
00870 }
00871 
00872 void Incidence::addAlarm( const Alarm::Ptr &alarm )
00873 {
00874   update();
00875   d->mAlarms.append( alarm );
00876   setFieldDirty( FieldAlarms );
00877   updated();
00878 }
00879 
00880 void Incidence::removeAlarm( const Alarm::Ptr &alarm )
00881 {
00882   const int index = d->mAlarms.indexOf( alarm );
00883   if ( index > -1 ) {
00884     update();
00885     d->mAlarms.remove( index );
00886     setFieldDirty( FieldAlarms );
00887     updated();
00888   }
00889 }
00890 
00891 void Incidence::clearAlarms()
00892 {
00893   update();
00894   d->mAlarms.clear();
00895   setFieldDirty( FieldAlarms );
00896   updated();
00897 }
00898 
00899 bool Incidence::hasEnabledAlarms() const
00900 {
00901   foreach ( Alarm::Ptr alarm, d->mAlarms ) {
00902     if ( alarm->enabled() ) {
00903       return true;
00904     }
00905   }
00906   return false;
00907 }
00908 
00909 void Incidence::setLocation( const QString &location, bool isRich )
00910 {
00911   if ( mReadOnly ) {
00912     return;
00913   }
00914 
00915   update();
00916   d->mLocation = location;
00917   d->mLocationIsRich = isRich;
00918   setFieldDirty( FieldLocation );
00919   updated();
00920 }
00921 
00922 void Incidence::setLocation( const QString &location )
00923 {
00924   setLocation( location, Qt::mightBeRichText( location ) );
00925 }
00926 
00927 QString Incidence::location() const
00928 {
00929   return d->mLocation;
00930 }
00931 
00932 QString Incidence::richLocation() const
00933 {
00934   if ( locationIsRich() ) {
00935     return d->mLocation;
00936   } else {
00937     return Qt::escape( d->mLocation ).replace( '\n', "<br/>" );
00938   }
00939 }
00940 
00941 bool Incidence::locationIsRich() const
00942 {
00943   return d->mLocationIsRich;
00944 }
00945 
00946 void Incidence::setSchedulingID( const QString &sid, const QString &uid )
00947 {
00948   d->mSchedulingID = sid;
00949   if ( !uid.isEmpty() ) {
00950     setUid( uid );
00951   }
00952   setFieldDirty( FieldSchedulingId );
00953 }
00954 
00955 QString Incidence::schedulingID() const
00956 {
00957   if ( d->mSchedulingID.isNull() ) {
00958     // Nothing set, so use the normal uid
00959     return uid();
00960   }
00961   return d->mSchedulingID;
00962 }
00963 
00964 bool Incidence::hasGeo() const
00965 {
00966   return d->mHasGeo;
00967 }
00968 
00969 void Incidence::setHasGeo( bool hasGeo )
00970 {
00971   if ( mReadOnly ) {
00972     return;
00973   }
00974 
00975   if ( hasGeo == d->mHasGeo ) {
00976     return;
00977   }
00978 
00979   update();
00980   d->mHasGeo = hasGeo;
00981   setFieldDirty( FieldGeoLatitude );
00982   setFieldDirty( FieldGeoLongitude );
00983   updated();
00984 }
00985 
00986 float Incidence::geoLatitude() const
00987 {
00988   return d->mGeoLatitude;
00989 }
00990 
00991 void Incidence::setGeoLatitude( float geolatitude )
00992 {
00993   if ( mReadOnly ) {
00994     return;
00995   }
00996 
00997   update();
00998   d->mGeoLatitude = geolatitude;
00999   setFieldDirty( FieldGeoLatitude );
01000   updated();
01001 }
01002 
01003 float Incidence::geoLongitude() const
01004 {
01005   return d->mGeoLongitude;
01006 }
01007 
01008 void Incidence::setGeoLongitude( float geolongitude )
01009 {
01010   if ( !mReadOnly ) {
01011     update();
01012     d->mGeoLongitude = geolongitude;
01013     setFieldDirty( FieldGeoLongitude );
01014     updated();
01015   }
01016 }
01017 
01018 bool Incidence::hasRecurrenceId() const
01019 {
01020   return d->mRecurrenceId.isValid();
01021 }
01022 
01023 KDateTime Incidence::recurrenceId() const
01024 {
01025   return d->mRecurrenceId;
01026 }
01027 
01028 void Incidence::setRecurrenceId( const KDateTime &recurrenceId )
01029 {
01030   if ( !mReadOnly ) {
01031     update();
01032     d->mRecurrenceId = recurrenceId;
01033     setFieldDirty( FieldRecurrenceId );
01034     updated();
01035   }
01036 }
01037 
01041 void Incidence::recurrenceUpdated( Recurrence *recurrence )
01042 {
01043   if ( recurrence == d->mRecurrence ) {
01044     update();
01045     updated();
01046   }
01047 }
01048 
01049 //@cond PRIVATE
01050 #define ALT_DESC_FIELD "X-ALT-DESC"
01051 #define ALT_DESC_PARAMETERS "FMTTYPE=text/html"
01052 //@endcond
01053 
01054 bool Incidence::hasAltDescription() const
01055 {
01056   const QString value = nonKDECustomProperty( ALT_DESC_FIELD );
01057   const QString parameter = nonKDECustomPropertyParameters( ALT_DESC_FIELD );
01058 
01059   return parameter == ALT_DESC_PARAMETERS && !value.isEmpty();
01060 }
01061 
01062 void Incidence::setAltDescription( const QString &altdescription )
01063 {
01064   if ( altdescription.isEmpty() ) {
01065     removeNonKDECustomProperty( ALT_DESC_FIELD );
01066   } else {
01067     setNonKDECustomProperty( ALT_DESC_FIELD,
01068                              altdescription,
01069                              ALT_DESC_PARAMETERS );
01070   }
01071 }
01072 
01073 QString Incidence::altDescription() const
01074 {
01075   if ( !hasAltDescription() ) {
01076       return QString();
01077   } else {
01078     return nonKDECustomProperty( ALT_DESC_FIELD );
01079   }
01080 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:07:48 by doxygen 1.7.5 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.8.5 API Reference

Skip menu "kdepimlibs-4.8.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • 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