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

KCalCore Library

freebusy.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) 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 */
00033 #include "freebusy.h"
00034 #include "visitor.h"
00035 
00036 #include "icalformat.h"
00037 
00038 #include <KDebug>
00039 
00040 using namespace KCalCore;
00041 
00042 //@cond PRIVATE
00043 class KCalCore::FreeBusy::Private
00044 {
00045   private:
00046   FreeBusy *q;
00047   public:
00048     Private( FreeBusy *qq ) : q( qq )
00049     {}
00050 
00051     Private( const KCalCore::FreeBusy::Private &other, FreeBusy *qq ) : q( qq )
00052     {
00053       init( other );
00054     }
00055 
00056     Private( const FreeBusyPeriod::List &busyPeriods, FreeBusy *qq )
00057       : q( qq ), mBusyPeriods( busyPeriods )
00058     {}
00059 
00060     void init( const KCalCore::FreeBusy::Private &other );
00061     void init( const Event::List &events, const KDateTime &start, const KDateTime &end );
00062 
00063     KDateTime mDtEnd;                  // end datetime
00064     FreeBusyPeriod::List mBusyPeriods; // list of periods
00065 
00066     // This is used for creating a freebusy object for the current user
00067     bool addLocalPeriod( FreeBusy *fb, const KDateTime &start, const KDateTime &end );
00068 };
00069 
00070 void KCalCore::FreeBusy::Private::init( const KCalCore::FreeBusy::Private &other )
00071 {
00072   mDtEnd = other.mDtEnd;
00073   mBusyPeriods = other.mBusyPeriods;
00074 }
00075 //@endcond
00076 
00077 FreeBusy::FreeBusy()
00078   : d( new KCalCore::FreeBusy::Private( this ) )
00079 {
00080 }
00081 
00082 FreeBusy::FreeBusy( const FreeBusy &other )
00083   : IncidenceBase( other ),
00084     d( new KCalCore::FreeBusy::Private( *other.d, this ) )
00085 {
00086 }
00087 
00088 FreeBusy::FreeBusy( const KDateTime &start, const KDateTime &end )
00089   : d( new KCalCore::FreeBusy::Private( this ) )
00090 {
00091   setDtStart( start );
00092   setDtEnd( end );
00093 }
00094 
00095 FreeBusy::FreeBusy( const Event::List &events, const KDateTime &start, const KDateTime &end )
00096   : d( new KCalCore::FreeBusy::Private( this ) )
00097 {
00098   setDtStart( start );
00099   setDtEnd( end );
00100 
00101   d->init( events, start, end );
00102 }
00103 
00104 //@cond PRIVATE
00105 void FreeBusy::Private::init( const Event::List &eventList,
00106                               const KDateTime &start, const KDateTime &end )
00107 {
00108   int extraDays, i, x, duration;
00109   duration = start.daysTo( end );
00110   QDate day;
00111   KDateTime tmpStart;
00112   KDateTime tmpEnd;
00113 
00114   // Loops through every event in the calendar
00115   Event::List::ConstIterator it;
00116   for ( it = eventList.constBegin(); it != eventList.constEnd(); ++it ) {
00117     Event::Ptr event = *it;
00118 
00119     // If this event is transparent it shouldn't be in the freebusy list.
00120     if ( event->transparency() == Event::Transparent ) {
00121       continue;
00122     }
00123 
00124     // The code below can not handle all-day events. Fixing this resulted
00125     // in a lot of duplicated code. Instead, make a copy of the event and
00126     // set the period to the full day(s). This trick works for recurring,
00127     // multiday, and single day all-day events.
00128     Event::Ptr allDayEvent;
00129     if ( event->allDay() ) {
00130       // addDay event. Do the hack
00131       kDebug() << "All-day event";
00132       allDayEvent = Event::Ptr( new Event( *event ) );
00133 
00134       // Set the start and end times to be on midnight
00135       KDateTime st = allDayEvent->dtStart();
00136       st.setTime( QTime( 0, 0 ) );
00137       KDateTime nd = allDayEvent->dtEnd();
00138       nd.setTime( QTime( 23, 59, 59, 999 ) );
00139       allDayEvent->setAllDay( false );
00140       allDayEvent->setDtStart( st );
00141       allDayEvent->setDtEnd( nd );
00142 
00143       kDebug() << "Use:" << st.toString() << "to" << nd.toString();
00144       // Finally, use this event for the setting below
00145       event = allDayEvent;
00146     }
00147 
00148     // This whole for loop is for recurring events, it loops through
00149     // each of the days of the freebusy request
00150 
00151     for ( i = 0; i <= duration; ++i ) {
00152       day = start.addDays(i).date();
00153       tmpStart.setDate( day );
00154       tmpEnd.setDate( day );
00155 
00156       if ( event->recurs() ) {
00157         if ( event->isMultiDay() ) {
00158   // FIXME: This doesn't work for sub-daily recurrences or recurrences with
00159   //        a different time than the original event.
00160           extraDays = event->dtStart().daysTo( event->dtEnd() );
00161           for ( x = 0; x <= extraDays; ++x ) {
00162             if ( event->recursOn( day.addDays(-x), start.timeSpec() ) ) {
00163               tmpStart.setDate( day.addDays(-x) );
00164               tmpStart.setTime( event->dtStart().time() );
00165               tmpEnd = event->duration().end( tmpStart );
00166 
00167               addLocalPeriod( q, tmpStart, tmpEnd );
00168               break;
00169             }
00170           }
00171         } else {
00172           if ( event->recursOn( day, start.timeSpec() ) ) {
00173             tmpStart.setTime( event->dtStart().time() );
00174             tmpEnd.setTime( event->dtEnd().time() );
00175 
00176             addLocalPeriod ( q, tmpStart, tmpEnd );
00177           }
00178         }
00179       }
00180 
00181     }
00182     // Non-recurring events
00183     addLocalPeriod( q, event->dtStart(), event->dtEnd() );
00184   }
00185 
00186   q->sortList();
00187 }
00188 //@endcond
00189 
00190 FreeBusy::FreeBusy( const Period::List &busyPeriods )
00191   : d( new KCalCore::FreeBusy::Private( this ) )
00192 {
00193   addPeriods(busyPeriods);
00194 }
00195 
00196 FreeBusy::FreeBusy( const FreeBusyPeriod::List &busyPeriods )
00197   : d( new KCalCore::FreeBusy::Private( busyPeriods, this ) )
00198 {
00199 }
00200 
00201 FreeBusy::~FreeBusy()
00202 {
00203   delete d;
00204 }
00205 
00206 IncidenceBase::IncidenceType FreeBusy::type() const
00207 {
00208   return TypeFreeBusy;
00209 }
00210 
00211 QByteArray FreeBusy::typeStr() const
00212 {
00213   return "FreeBusy";
00214 }
00215 
00216 void FreeBusy::setDtStart( const KDateTime &start )
00217 {
00218   IncidenceBase::setDtStart( start.toUtc() );
00219   updated();
00220 }
00221 
00222 void FreeBusy::setDtEnd( const KDateTime &end )
00223 {
00224   d->mDtEnd = end;
00225 }
00226 
00227 KDateTime FreeBusy::dtEnd() const
00228 {
00229   return d->mDtEnd;
00230 }
00231 
00232 Period::List FreeBusy::busyPeriods() const
00233 {
00234   Period::List res;
00235 
00236   foreach ( const FreeBusyPeriod &p, d->mBusyPeriods ) {
00237     res << p;
00238   }
00239 
00240   return res;
00241 }
00242 
00243 FreeBusyPeriod::List FreeBusy::fullBusyPeriods() const
00244 {
00245   return d->mBusyPeriods;
00246 }
00247 
00248 void FreeBusy::sortList()
00249 {
00250   qSort( d->mBusyPeriods );
00251   return;
00252 }
00253 
00254 void FreeBusy::addPeriods( const Period::List &list )
00255 {
00256   foreach ( const Period &p, list ) {
00257     d->mBusyPeriods << FreeBusyPeriod( p );
00258   }
00259   sortList();
00260 }
00261 
00262 void FreeBusy::addPeriods( const FreeBusyPeriod::List &list )
00263 {
00264   d->mBusyPeriods += list;
00265   sortList();
00266 }
00267 
00268 void FreeBusy::addPeriod( const KDateTime &start, const KDateTime &end )
00269 {
00270   d->mBusyPeriods.append( FreeBusyPeriod( start, end ) );
00271   sortList();
00272 }
00273 
00274 void FreeBusy::addPeriod( const KDateTime &start, const Duration &duration )
00275 {
00276   d->mBusyPeriods.append( FreeBusyPeriod( start, duration ) );
00277   sortList();
00278 }
00279 
00280 void FreeBusy::merge( FreeBusy::Ptr freeBusy )
00281 {
00282   if ( freeBusy->dtStart() < dtStart() ) {
00283     setDtStart( freeBusy->dtStart() );
00284   }
00285 
00286   if ( freeBusy->dtEnd() > dtEnd() ) {
00287     setDtEnd( freeBusy->dtEnd() );
00288   }
00289 
00290   Period::List periods = freeBusy->busyPeriods();
00291   Period::List::ConstIterator it;
00292   for ( it = periods.constBegin(); it != periods.constEnd(); ++it ) {
00293     d->mBusyPeriods.append( FreeBusyPeriod( (*it).start(), (*it).end() ) );
00294   }
00295   sortList();
00296 }
00297 
00298 void FreeBusy::shiftTimes( const KDateTime::Spec &oldSpec,
00299                            const KDateTime::Spec &newSpec )
00300 {
00301   if ( oldSpec.isValid() && newSpec.isValid() && oldSpec != newSpec ) {
00302     IncidenceBase::shiftTimes( oldSpec, newSpec );
00303     d->mDtEnd = d->mDtEnd.toTimeSpec( oldSpec );
00304     d->mDtEnd.setTimeSpec( newSpec );
00305     foreach ( FreeBusyPeriod p, d->mBusyPeriods ) { //krazy:exclude=foreach
00306       p.shiftTimes( oldSpec, newSpec );
00307     }
00308   }
00309 }
00310 
00311 IncidenceBase &FreeBusy::assign( const IncidenceBase &other )
00312 {
00313   if ( &other != this ) {
00314     IncidenceBase::assign( other );
00315     const FreeBusy *f = static_cast<const FreeBusy*>( &other );
00316     d->init( *( f->d ) );
00317   }
00318   return *this;
00319 }
00320 
00321 bool FreeBusy::equals( const IncidenceBase &freeBusy ) const
00322 {
00323   if ( !IncidenceBase::equals( freeBusy ) ) {
00324     return false;
00325   } else {
00326     // If they weren't the same type IncidenceBase::equals would had returned false already
00327     const FreeBusy *fb = static_cast<const FreeBusy*>( &freeBusy );
00328     return
00329       dtEnd() == fb->dtEnd() &&
00330       d->mBusyPeriods == fb->d->mBusyPeriods;
00331   }
00332 }
00333 
00334 bool FreeBusy::accept( Visitor &v, IncidenceBase::Ptr incidence )
00335 {
00336   return v.visit( incidence.staticCast<FreeBusy>() );
00337 }
00338 
00339 KDateTime FreeBusy::dateTime( DateTimeRole role ) const
00340 {
00341   Q_UNUSED( role );
00342   // No roles affecting freeBusy yet
00343   return KDateTime();
00344 }
00345 
00346 void FreeBusy::setDateTime( const KDateTime &dateTime, DateTimeRole role )
00347 {
00348   Q_UNUSED( dateTime );
00349   Q_UNUSED( role );
00350 }
00351 
00352 void FreeBusy::virtual_hook( int id, void *data )
00353 {
00354   Q_UNUSED( id );
00355   Q_UNUSED( data );
00356   Q_ASSERT( false );
00357 }
00358 
00359 //@cond PRIVATE
00360 bool FreeBusy::Private::addLocalPeriod( FreeBusy *fb,
00361                                         const KDateTime &eventStart,
00362                                         const KDateTime &eventEnd )
00363 {
00364   KDateTime tmpStart;
00365   KDateTime tmpEnd;
00366 
00367   //Check to see if the start *or* end of the event is
00368   //between the start and end of the freebusy dates.
00369   KDateTime start = fb->dtStart();
00370   if ( !( ( ( start.secsTo( eventStart ) >= 0 ) &&
00371             ( eventStart.secsTo( mDtEnd ) >= 0 ) ) ||
00372           ( ( start.secsTo( eventEnd ) >= 0 ) &&
00373             ( eventEnd.secsTo( mDtEnd ) >= 0 ) ) ) ) {
00374     return false;
00375   }
00376 
00377   if ( eventStart.secsTo( start ) >= 0 ) {
00378     tmpStart = start;
00379   } else {
00380     tmpStart = eventStart;
00381   }
00382 
00383   if ( eventEnd.secsTo( mDtEnd ) <= 0 ) {
00384     tmpEnd = mDtEnd;
00385   } else {
00386     tmpEnd = eventEnd;
00387   }
00388 
00389   FreeBusyPeriod p( tmpStart, tmpEnd );
00390   mBusyPeriods.append( p );
00391 
00392   return true;
00393 }
00394 //@endcond
00395 
00396 QLatin1String FreeBusy::mimeType() const
00397 {
00398   return FreeBusy::freeBusyMimeType();
00399 }
00400 
00401 QLatin1String KCalCore::FreeBusy::freeBusyMimeType()
00402 {
00403   return QLatin1String( "application/x-vnd.akonadi.calendar.freebusy" );
00404 }
00405 
00406 QDataStream &KCalCore::operator<<( QDataStream &stream, const KCalCore::FreeBusy::Ptr &freebusy )
00407 {
00408   KCalCore::ICalFormat format;
00409   QString data = format.createScheduleMessage( freebusy, iTIPPublish );
00410   return stream << data;
00411 }
00412 
00413 QDataStream &KCalCore::operator>>( QDataStream &stream, KCalCore::FreeBusy::Ptr &freebusy )
00414 {
00415   QString freeBusyVCal;
00416   stream >> freeBusyVCal;
00417 
00418   KCalCore::ICalFormat format;
00419   freebusy = format.parseFreeBusy( freeBusyVCal );
00420 
00421   if ( !freebusy ) {
00422     kDebug() << "Error parsing free/busy";
00423     kDebug() << freeBusyVCal;
00424   }
00425 
00426   return stream;
00427 }
00428 
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 7 2012 23:54:01 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