• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • 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   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 // FIXME: Shouldn't we call updated for the creation date, too?
00352 //  updated();
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   // TODO: RFC says that an incidence can have more than one related-to field
00520   // even for the same relType.
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 // %%%%%%%%%%%%  Recurrence-related methods %%%%%%%%%%%%%%%%%%%%
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   // TODO_Recurrence: Also work if only due date is given...
00594   if ( !start.isValid() && ! end.isValid() ) {
00595     return result;
00596   }
00597 
00598   // if the incidence doesn't recur,
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   // Account for possible recurrences going over midnight, while the original event doesn't
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   // TODO_Recurrence: Also work if only due date is given...
00634   if ( !start.isValid() && ! end.isValid() ) {
00635     return result;
00636   }
00637 
00638   // if the incidence doesn't recur,
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   // Account for possible recurrences going over midnight, while the original event doesn't
00648   QDate tmpday( datetime.date().addDays( -days - 1 ) );
00649   KDateTime tmp;
00650   while ( tmpday <= datetime.date() ) {
00651     if ( recurrence()->recursOn( tmpday, datetime.timeSpec() ) ) {
00652       // Get the times during the day (in start date's time zone) when recurrences happen
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   // read-only not to give the idea that it could be written to
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     // Nothing set, so use the normal uid
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 //@cond PRIVATE
01052 #define ALT_DESC_FIELD "X-ALT-DESC"
01053 #define ALT_DESC_PARAMETERS "FMTTYPE=text/html"
01054 //@endcond
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 }

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • 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
Generated for KDE-PIM Libraries by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal