KCalCore Library
incidencebase.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00037 #include "incidencebase.h"
00038 #include "calformat.h"
00039 #include "visitor.h"
00040
00041 #include <QDebug>
00042
00043 #include <KUrl>
00044
00045 #include <QtCore/QStringList>
00046
00047 using namespace KCalCore;
00048
00053
00054 class KCalCore::IncidenceBase::Private
00055 {
00056 public:
00057 Private()
00058 : mOrganizer( new Person() ),
00059 mUpdateGroupLevel( 0 ),
00060 mUpdatedPending( false ),
00061 mAllDay( true ),
00062 mHasDuration( false )
00063 {}
00064
00065 Private( const Private &other )
00066 : mUpdateGroupLevel( 0 ),
00067 mUpdatedPending( false ),
00068 mAllDay( true ),
00069 mHasDuration( false )
00070 {
00071 init( other );
00072 }
00073
00074 ~Private()
00075 {
00076 }
00077
00078 void init( const Private &other );
00079
00080 KDateTime mLastModified;
00081 KDateTime mDtStart;
00082 Person::Ptr mOrganizer;
00083 QString mUid;
00084 Duration mDuration;
00085 int mUpdateGroupLevel;
00086 bool mUpdatedPending;
00087 bool mAllDay;
00088 bool mHasDuration;
00089 Attendee::List mAttendees;
00090 QStringList mComments;
00091 QStringList mContacts;
00092 QList<IncidenceObserver*> mObservers;
00093 QSet<Field> mDirtyFields;
00094
00095 };
00096
00097 void IncidenceBase::Private::init( const Private &other )
00098 {
00099 mLastModified = other.mLastModified;
00100 mDtStart = other.mDtStart;
00101 mOrganizer = other.mOrganizer;
00102 mUid = other.mUid;
00103 mDuration = other.mDuration;
00104 mAllDay = other.mAllDay;
00105 mHasDuration = other.mHasDuration;
00106
00107 mComments = other.mComments;
00108 mContacts = other.mContacts;
00109
00110 mAttendees.clear();
00111 Attendee::List::ConstIterator it;
00112 for ( it = other.mAttendees.constBegin(); it != other.mAttendees.constEnd(); ++it ) {
00113 mAttendees.append( Attendee::Ptr( new Attendee( *(*it) ) ) );
00114 }
00115 }
00116
00117
00118 IncidenceBase::IncidenceBase()
00119 : d( new KCalCore::IncidenceBase::Private )
00120 {
00121 mReadOnly = false;
00122 setUid( CalFormat::createUniqueId() );
00123 }
00124
00125 IncidenceBase::IncidenceBase( const IncidenceBase &i )
00126 : CustomProperties( i ),
00127 d( new KCalCore::IncidenceBase::Private( *i.d ) )
00128 {
00129 mReadOnly = i.mReadOnly;
00130 }
00131
00132 IncidenceBase::~IncidenceBase()
00133 {
00134 delete d;
00135 }
00136
00137 IncidenceBase &IncidenceBase::operator=( const IncidenceBase &other )
00138 {
00139 Q_ASSERT( type() == other.type() );
00140
00141 startUpdates();
00142
00143
00144 IncidenceBase &ret = assign( other );
00145 endUpdates();
00146 return ret;
00147 }
00148
00149 IncidenceBase &IncidenceBase::assign( const IncidenceBase &other )
00150 {
00151 CustomProperties::operator=( other );
00152 d->init( *other.d );
00153 mReadOnly = other.mReadOnly;
00154 d->mDirtyFields.clear();
00155 d->mDirtyFields.insert( FieldUnknown );
00156 return *this;
00157 }
00158
00159 bool IncidenceBase::operator==( const IncidenceBase &i2 ) const
00160 {
00161 if ( i2.type() != type() ) {
00162 return false;
00163 } else {
00164
00165 return equals( i2 );
00166 }
00167 }
00168
00169 bool IncidenceBase::operator!=( const IncidenceBase &i2 ) const
00170 {
00171 return !operator==( i2 );
00172 }
00173
00174 bool IncidenceBase::equals( const IncidenceBase &i2 ) const
00175 {
00176 if ( attendees().count() != i2.attendees().count() ) {
00177 return false;
00178 }
00179
00180 Attendee::List al1 = attendees();
00181 Attendee::List al2 = i2.attendees();
00182 Attendee::List::ConstIterator a1 = al1.constBegin();
00183 Attendee::List::ConstIterator a2 = al2.constBegin();
00184
00185
00186 for ( ; a1 != al1.constEnd() && a2 != al2.constEnd(); ++a1, ++a2 ) {
00187 if ( !( **a1 == **a2 ) ) {
00188 return false;
00189 }
00190 }
00191
00192 if ( !CustomProperties::operator==( i2 ) ) {
00193 return false;
00194 }
00195
00196 return
00197 ( ( dtStart() == i2.dtStart() ) ||
00198 ( !dtStart().isValid() && !i2.dtStart().isValid() ) ) &&
00199 *( organizer().data() ) == *( i2.organizer().data() ) &&
00200 uid() == i2.uid() &&
00201
00202
00203 allDay() == i2.allDay() &&
00204 duration() == i2.duration() &&
00205 hasDuration() == i2.hasDuration();
00206
00207 }
00208
00209 bool IncidenceBase::accept( Visitor &v, IncidenceBase::Ptr incidence )
00210 {
00211 Q_UNUSED( v );
00212 Q_UNUSED( incidence );
00213 return false;
00214 }
00215
00216 void IncidenceBase::setUid( const QString &uid )
00217 {
00218 update();
00219 d->mUid = uid;
00220 d->mDirtyFields.insert( FieldUid );
00221 updated();
00222 }
00223
00224 QString IncidenceBase::uid() const
00225 {
00226 return d->mUid;
00227 }
00228
00229 void IncidenceBase::setLastModified( const KDateTime &lm )
00230 {
00231
00232
00233
00234 d->mDirtyFields.insert( FieldLastModified );
00235
00236
00237 KDateTime current = lm.toUtc();
00238 QTime t = current.time();
00239 t.setHMS( t.hour(), t.minute(), t.second(), 0 );
00240 current.setTime( t );
00241
00242 d->mLastModified = current;
00243 }
00244
00245 KDateTime IncidenceBase::lastModified() const
00246 {
00247 return d->mLastModified;
00248 }
00249
00250 void IncidenceBase::setOrganizer( const Person::Ptr &o )
00251 {
00252 update();
00253
00254
00255
00256 d->mOrganizer = o;
00257
00258 d->mDirtyFields.insert( FieldOrganizer );
00259
00260 updated();
00261 }
00262
00263 void IncidenceBase::setOrganizer( const QString &o )
00264 {
00265 QString mail( o );
00266 if ( mail.startsWith( QLatin1String( "MAILTO:" ), Qt::CaseInsensitive ) ) {
00267 mail = mail.remove( 0, 7 );
00268 }
00269
00270
00271 const Person::Ptr organizer = Person::fromFullName( mail );
00272 setOrganizer( organizer );
00273 }
00274
00275 Person::Ptr IncidenceBase::organizer() const
00276 {
00277 return d->mOrganizer;
00278 }
00279
00280 void IncidenceBase::setReadOnly( bool readOnly )
00281 {
00282 mReadOnly = readOnly;
00283 }
00284
00285 bool IncidenceBase::isReadOnly() const
00286 {
00287 return mReadOnly;
00288 }
00289
00290 void IncidenceBase::setDtStart( const KDateTime &dtStart )
00291 {
00292
00293 update();
00294 d->mDtStart = dtStart;
00295 d->mAllDay = dtStart.isDateOnly();
00296 d->mDirtyFields.insert( FieldDtStart );
00297 updated();
00298 }
00299
00300 KDateTime IncidenceBase::dtStart() const
00301 {
00302 return d->mDtStart;
00303 }
00304
00305 bool IncidenceBase::allDay() const
00306 {
00307 return d->mAllDay;
00308 }
00309
00310 void IncidenceBase::setAllDay( bool f )
00311 {
00312 if ( mReadOnly || f == d->mAllDay ) {
00313 return;
00314 }
00315 update();
00316 d->mAllDay = f;
00317 if ( d->mDtStart.isValid() ) {
00318 d->mDirtyFields.insert( FieldDtStart );
00319 }
00320 updated();
00321 }
00322
00323 void IncidenceBase::shiftTimes( const KDateTime::Spec &oldSpec,
00324 const KDateTime::Spec &newSpec )
00325 {
00326 update();
00327 d->mDtStart = d->mDtStart.toTimeSpec( oldSpec );
00328 d->mDtStart.setTimeSpec( newSpec );
00329 d->mDirtyFields.insert( FieldDtStart );
00330 d->mDirtyFields.insert( FieldDtEnd );
00331 updated();
00332 }
00333
00334 void IncidenceBase::addComment( const QString &comment )
00335 {
00336 d->mComments += comment;
00337 }
00338
00339 bool IncidenceBase::removeComment( const QString &comment )
00340 {
00341 bool found = false;
00342 QStringList::Iterator i;
00343
00344 for ( i = d->mComments.begin(); !found && i != d->mComments.end(); ++i ) {
00345 if ( (*i) == comment ) {
00346 found = true;
00347 d->mComments.erase( i );
00348 }
00349 }
00350
00351 if ( found ) {
00352 d->mDirtyFields.insert( FieldComment );
00353 }
00354
00355 return found;
00356 }
00357
00358 void IncidenceBase::clearComments()
00359 {
00360 d->mDirtyFields.insert( FieldComment );
00361 d->mComments.clear();
00362 }
00363
00364 QStringList IncidenceBase::comments() const
00365 {
00366 return d->mComments;
00367 }
00368
00369 void IncidenceBase::addContact( const QString &contact )
00370 {
00371 if ( !contact.isEmpty() ) {
00372 d->mContacts += contact;
00373 d->mDirtyFields.insert( FieldContact );
00374 }
00375 }
00376
00377 bool IncidenceBase::removeContact( const QString &contact )
00378 {
00379 bool found = false;
00380 QStringList::Iterator i;
00381
00382 for ( i = d->mContacts.begin(); !found && i != d->mContacts.end(); ++i ) {
00383 if ( (*i) == contact ) {
00384 found = true;
00385 d->mContacts.erase( i );
00386 }
00387 }
00388
00389 if ( found ) {
00390 d->mDirtyFields.insert( FieldContact );
00391 }
00392
00393 return found;
00394 }
00395
00396 void IncidenceBase::clearContacts()
00397 {
00398 d->mDirtyFields.insert( FieldContact );
00399 d->mContacts.clear();
00400 }
00401
00402 QStringList IncidenceBase::contacts() const
00403 {
00404 return d->mContacts;
00405 }
00406
00407 void IncidenceBase::addAttendee( const Attendee::Ptr &a, bool doupdate )
00408 {
00409 if ( !a || mReadOnly ) {
00410 return;
00411 }
00412
00413 Q_ASSERT( !d->mAttendees.contains( a ) );
00414
00415 if ( doupdate ) {
00416 update();
00417 }
00418 if ( a->name().left(7).toUpper() == "MAILTO:" ) {
00419 a->setName( a->name().remove( 0, 7 ) );
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 if ( a->uid().isEmpty() ) {
00431 a->setUid( QString::number( (qlonglong)a.data() ) );
00432 }
00433
00434 d->mAttendees.append( a );
00435 if ( doupdate ) {
00436 d->mDirtyFields.insert( FieldAttendees );
00437 updated();
00438 }
00439 }
00440
00441 void IncidenceBase::deleteAttendee( const Attendee::Ptr &a, bool doupdate )
00442 {
00443 if ( !a || mReadOnly ) {
00444 return;
00445 }
00446
00447 int index = d->mAttendees.indexOf( a );
00448 if ( index >= 0 ) {
00449 if ( doupdate ) {
00450 update();
00451 }
00452
00453 d->mAttendees.remove( index );
00454
00455 if ( doupdate ) {
00456 d->mDirtyFields.insert( FieldAttendees );
00457 updated();
00458 }
00459 }
00460 }
00461
00462 Attendee::List IncidenceBase::attendees() const
00463 {
00464 return d->mAttendees;
00465 }
00466
00467 int IncidenceBase::attendeeCount() const
00468 {
00469 return d->mAttendees.count();
00470 }
00471
00472 void IncidenceBase::clearAttendees()
00473 {
00474 if ( mReadOnly ) {
00475 return;
00476 }
00477 d->mDirtyFields.insert( FieldAttendees );
00478 d->mAttendees.clear();
00479 }
00480
00481 Attendee::Ptr IncidenceBase::attendeeByMail( const QString &email ) const
00482 {
00483 Attendee::List::ConstIterator it;
00484 for ( it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it ) {
00485 if ( (*it)->email() == email ) {
00486 return *it;
00487 }
00488 }
00489
00490 return Attendee::Ptr();
00491 }
00492
00493 Attendee::Ptr IncidenceBase::attendeeByMails( const QStringList &emails,
00494 const QString &email ) const
00495 {
00496 QStringList mails = emails;
00497 if ( !email.isEmpty() ) {
00498 mails.append( email );
00499 }
00500
00501 Attendee::List::ConstIterator itA;
00502 for ( itA = d->mAttendees.constBegin(); itA != d->mAttendees.constEnd(); ++itA ) {
00503 for ( QStringList::const_iterator it = mails.constBegin(); it != mails.constEnd(); ++it ) {
00504 if ( (*itA)->email() == (*it) ) {
00505 return *itA;
00506 }
00507 }
00508 }
00509
00510 return Attendee::Ptr();
00511 }
00512
00513 Attendee::Ptr IncidenceBase::attendeeByUid( const QString &uid ) const
00514 {
00515 Attendee::List::ConstIterator it;
00516 for ( it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it ) {
00517 if ( (*it)->uid() == uid ) {
00518 return *it;
00519 }
00520 }
00521
00522 return Attendee::Ptr();
00523 }
00524
00525 void IncidenceBase::setDuration( const Duration &duration )
00526 {
00527 update();
00528 d->mDuration = duration;
00529 setHasDuration( true );
00530 d->mDirtyFields.insert( FieldDuration );
00531 updated();
00532 }
00533
00534 Duration IncidenceBase::duration() const
00535 {
00536 return d->mDuration;
00537 }
00538
00539 void IncidenceBase::setHasDuration( bool hasDuration )
00540 {
00541 d->mHasDuration = hasDuration;
00542 }
00543
00544 bool IncidenceBase::hasDuration() const
00545 {
00546 return d->mHasDuration;
00547 }
00548
00549 void IncidenceBase::registerObserver( IncidenceBase::IncidenceObserver *observer )
00550 {
00551 if ( observer && !d->mObservers.contains( observer ) ) {
00552 d->mObservers.append( observer );
00553 }
00554 }
00555
00556 void IncidenceBase::unRegisterObserver( IncidenceBase::IncidenceObserver *observer )
00557 {
00558 d->mObservers.removeAll( observer );
00559 }
00560
00561 void IncidenceBase::update()
00562 {
00563 if ( !d->mUpdateGroupLevel ) {
00564 d->mUpdatedPending = true;
00565 KDateTime rid = recurrenceId();
00566 foreach ( IncidenceObserver *o, d->mObservers ) {
00567 o->incidenceUpdate( uid(), rid );
00568 }
00569 }
00570 }
00571
00572 void IncidenceBase::updated()
00573 {
00574 if ( d->mUpdateGroupLevel ) {
00575 d->mUpdatedPending = true;
00576 } else {
00577 KDateTime rid = recurrenceId();
00578 foreach ( IncidenceObserver *o, d->mObservers ) {
00579 o->incidenceUpdated( uid(), rid );
00580 }
00581 }
00582 }
00583
00584 void IncidenceBase::startUpdates()
00585 {
00586 update();
00587 ++d->mUpdateGroupLevel;
00588 }
00589
00590 void IncidenceBase::endUpdates()
00591 {
00592 if ( d->mUpdateGroupLevel > 0 ) {
00593 if ( --d->mUpdateGroupLevel == 0 && d->mUpdatedPending ) {
00594 d->mUpdatedPending = false;
00595 updated();
00596 }
00597 }
00598 }
00599
00600 void IncidenceBase::customPropertyUpdate()
00601 {
00602 update();
00603 }
00604
00605 void IncidenceBase::customPropertyUpdated()
00606 {
00607 updated();
00608 }
00609
00610 KDateTime IncidenceBase::recurrenceId() const
00611 {
00612 return KDateTime();
00613 }
00614
00615 void IncidenceBase::resetDirtyFields()
00616 {
00617 d->mDirtyFields.clear();
00618 }
00619
00620 QSet<IncidenceBase::Field> IncidenceBase::dirtyFields() const
00621 {
00622 return d->mDirtyFields;
00623 }
00624
00625 void IncidenceBase::setFieldDirty( IncidenceBase::Field field )
00626 {
00627 d->mDirtyFields.insert( field );
00628 }
00629
00630 KUrl IncidenceBase::uri() const
00631 {
00632 return KUrl( QString( "urn:x-ical:" ) + uid() );
00633 }
00634
00635 IncidenceBase::IncidenceObserver::~IncidenceObserver()
00636 {
00637 }