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

KCalCore Library

incidencebase.cpp
Go to the documentation of this file.
00001 /*
00002   This file is part of the kcalcore library.
00003 
00004   Copyright (c) 2001,2004 Cornelius Schumacher <schumacher@kde.org>
00005   Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00006   Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00007   Contact: Alvaro Manera <alvaro.manera@nokia.com>
00008 
00009   This library is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Library General Public
00011   License as published by the Free Software Foundation; either
00012   version 2 of the License, or (at your option) any later version.
00013 
00014   This library is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   Library General Public License for more details.
00018 
00019   You should have received a copy of the GNU Library General Public License
00020   along with this library; see the file COPYING.LIB.  If not, write to
00021   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00022   Boston, MA 02110-1301, USA.
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 //@cond PRIVATE
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;     // incidence last modified date
00081     KDateTime mDtStart;          // incidence start time
00082     Person::Ptr mOrganizer;           // incidence person (owner)
00083     QString mUid;                // incidence unique id
00084     Duration mDuration;          // incidence duration
00085     int mUpdateGroupLevel;       // if non-zero, suppresses update() calls
00086     bool mUpdatedPending;        // true if an update has occurred since startUpdates()
00087     bool mAllDay;                // true if the incidence is all-day
00088     bool mHasDuration;           // true if the incidence has a duration
00089     Attendee::List mAttendees;   // list of incidence attendees
00090     QStringList mComments;       // list of incidence comments
00091     QStringList mContacts;       // list of incidence contacts
00092     QList<IncidenceObserver*> mObservers; // list of incidence observers
00093     QSet<Field> mDirtyFields;    // Fields that changed since last time the incidence was created
00094                                  // or since resetDirtyFlags() was called
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 //@endcond
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   // assign is virtual, will call the derived class's
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     // equals is virtual, so here we're calling the derived class method
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   //TODO Does the order of attendees in the list really matter?
00185   //Please delete this comment if you know it's ok, kthx
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     // Don't compare lastModified, otherwise the operator is not
00202     // of much use. We are not comparing for identity, after all.
00203     allDay() == i2.allDay() &&
00204     duration() == i2.duration() &&
00205     hasDuration() == i2.hasDuration();
00206     // no need to compare mObserver
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   // DON'T! updated() because we call this from
00232   // Calendar::updateEvent().
00233 
00234   d->mDirtyFields.insert( FieldLastModified );
00235 
00236   // Convert to UTC and remove milliseconds part.
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   // we don't check for readonly here, because it is
00254   // possible that by setting the organizer we are changing
00255   // the event's readonly status...
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   // split the string into full name plus email.
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 //  if ( mReadOnly ) return;
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   /* If Uid is empty, just use the pointer to Attendee (encoded to
00423    * string) as Uid. Only thing that matters is that the Uid is unique
00424    * insofar IncidenceBase is concerned, and this does that (albeit
00425    * not very nicely). If these are ever saved to disk, should use
00426    * (considerably more expensive) CalFormat::createUniqueId(). As Uid
00427    * is not part of Attendee in iCal std, it's fairly safe bet that
00428    * these will never hit disc though so faster generation speed is
00429    * more important than actually being forever unique.*/
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 void IncidenceBase::setDirtyFields( const QSet<IncidenceBase::Field> &dirtyFields )
00636 {
00637   d->mDirtyFields = dirtyFields;
00638 }
00639 
00640 IncidenceBase::IncidenceObserver::~IncidenceObserver()
00641 {
00642 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 22:16:56 by doxygen 1.8.0 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.3 API Reference

Skip menu "kdepimlibs-4.8.3 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