• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

KCal Library

freebusy.cpp

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

KCal Library

Skip menu "KCal Library"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.1
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