libkcal

freebusy.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of libkcal.
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 */
00022 
00023 #include <kdebug.h>
00024 
00025 #include "freebusy.h"
00026 
00027 using namespace KCal;
00028 
00029 FreeBusy::FreeBusy()
00030 {
00031 }
00032 
00033 FreeBusy::FreeBusy(const QDateTime &start, const QDateTime &end)
00034 {
00035   setDtStart(start);
00036   setDtEnd(end);
00037 }
00038 
00039 FreeBusy::FreeBusy( Calendar *calendar, const QDateTime &start, const QDateTime &end )
00040 {
00041   kdDebug(5800) << "FreeBusy::FreeBusy" << endl;
00042   mCalendar = calendar;
00043 
00044   setDtStart(start);
00045   setDtEnd(end);
00046 
00047   // Get all the events in the calendar
00048   Event::List eventList = mCalendar->rawEvents( start.date(), end.date() );
00049 
00050   int extraDays, i, x, duration;
00051   duration = start.daysTo(end);
00052   QDate day;
00053   QDateTime tmpStart;
00054   QDateTime tmpEnd;
00055   // Loops through every event in the calendar
00056   Event::List::ConstIterator it;
00057   for( it = eventList.begin(); it != eventList.end(); ++it ) {
00058     Event *event = *it;
00059 
00060     // The code below can not handle floating events. Fixing this resulted
00061     // in a lot of duplicated code. Instead, make a copy of the event and
00062     // set the period to the full day(s). This trick works for recurring,
00063     // multiday, and single day floating events.
00064     Event *floatingEvent = 0;
00065     if ( event->doesFloat() ) {
00066       // Floating event. Do the hack
00067       kdDebug(5800) << "Floating event\n";
00068       floatingEvent = new Event( *event );
00069 
00070       // Set the start and end times to be on midnight
00071       QDateTime start( floatingEvent->dtStart().date(), QTime( 0, 0 ) );
00072       QDateTime end( floatingEvent->dtEnd().date(), QTime( 23, 59, 59, 999 ) );
00073       floatingEvent->setFloats( false );
00074       floatingEvent->setDtStart( start );
00075       floatingEvent->setDtEnd( end );
00076 
00077       kdDebug(5800) << "Use: " << start.toString() << " to " << end.toString()
00078                     << endl;
00079       // Finally, use this event for the setting below
00080       event = floatingEvent;
00081     }
00082 
00083     // This whole for loop is for recurring events, it loops through
00084     // each of the days of the freebusy request
00085 
00086     // First check if this is transparent. If it is, it shouldn't be in the
00087     // freebusy list
00088     if ( event->transparency() == Event::Transparent )
00089       // Transparent
00090       continue;
00091 
00092     for( i = 0; i <= duration; ++i ) {
00093       day=(start.addDays(i).date());
00094       tmpStart.setDate(day);
00095       tmpEnd.setDate(day);
00096 
00097       if( event->doesRecur() ) {
00098         if ( event->isMultiDay() ) {
00099 // FIXME: This doesn't work for sub-daily recurrences or recurrences with
00100 //        a different time than the original event.
00101           extraDays = event->dtStart().date().daysTo(event->dtEnd().date());
00102           for ( x = 0; x <= extraDays; ++x ) {
00103             if ( event->recursOn(day.addDays(-x))) {
00104               tmpStart.setDate(day.addDays(-x));
00105               tmpStart.setTime(event->dtStart().time());
00106               tmpEnd=tmpStart.addSecs( (event->duration()) );
00107 
00108               addLocalPeriod( tmpStart, tmpEnd );
00109               break;
00110             }
00111           }
00112         } else {
00113           if (event->recursOn(day)) {
00114             tmpStart.setTime(event->dtStart().time());
00115             tmpEnd.setTime(event->dtEnd().time());
00116 
00117             addLocalPeriod (tmpStart, tmpEnd);
00118           }
00119         }
00120       }
00121 
00122     }
00123     // Non-recurring events
00124     addLocalPeriod(event->dtStart(), event->dtEnd());
00125 
00126     // Clean up
00127     delete floatingEvent;
00128   }
00129 
00130   sortList();
00131 }
00132 
00133 FreeBusy::~FreeBusy()
00134 {
00135 }
00136 
00137 bool FreeBusy::setDtEnd( const QDateTime &end )
00138 {
00139   mDtEnd = end;
00140   return true;
00141 }
00142 
00143 QDateTime FreeBusy::dtEnd() const
00144 {
00145   return mDtEnd;
00146 }
00147 
00148 PeriodList FreeBusy::busyPeriods() const
00149 {
00150   return mBusyPeriods;
00151 }
00152 
00153 bool FreeBusy::addLocalPeriod(const QDateTime &eventStart, const QDateTime &eventEnd ) {
00154   QDateTime tmpStart;
00155   QDateTime tmpEnd;
00156 
00157   //Check to see if the start *or* end of the event is
00158   //between the start and end of the freebusy dates.
00159   if ( !( ( ( dtStart().secsTo(eventStart) >= 0 ) &&
00160             ( eventStart.secsTo(dtEnd()) >= 0 ) )
00161        || ( ( dtStart().secsTo(eventEnd) >= 0 ) &&
00162             ( eventEnd.secsTo(dtEnd()) >= 0 ) ) ) )
00163     return false;
00164 
00165   if ( eventStart.secsTo( dtStart() ) >= 0 ) {
00166     tmpStart = dtStart();
00167   } else {
00168     tmpStart = eventStart;
00169   }
00170 
00171   if ( eventEnd.secsTo( dtEnd() ) <= 0 ) {
00172     tmpEnd = dtEnd();
00173   } else {
00174     tmpEnd = eventEnd;
00175   }
00176 
00177   Period p(tmpStart, tmpEnd);
00178   mBusyPeriods.append( p );
00179 
00180   return true;
00181 }
00182 
00183 FreeBusy::FreeBusy( PeriodList busyPeriods)
00184 {
00185   mBusyPeriods = busyPeriods;
00186 }
00187 
00188 void FreeBusy::sortList()
00189 {
00190   qHeapSort( mBusyPeriods );
00191   return;
00192 }
00193 
00194 void FreeBusy::addPeriods(const PeriodList &list )
00195 {
00196   mBusyPeriods += list;
00197   sortList();
00198 }
00199 
00200 void FreeBusy::addPeriod(const QDateTime &start, const QDateTime &end)
00201 {
00202   mBusyPeriods.append( Period(start, end) );
00203   sortList();
00204 }
00205 
00206 void FreeBusy::addPeriod( const QDateTime &start, const Duration &dur )
00207 {
00208   mBusyPeriods.append( Period(start, dur) );
00209   sortList();
00210 }
00211 
00212 void FreeBusy::merge( FreeBusy *freeBusy )
00213 {
00214   if ( freeBusy->dtStart() < dtStart() )
00215     setDtStart( freeBusy->dtStart() );
00216 
00217   if ( freeBusy->dtEnd() > dtEnd() )
00218     setDtEnd( freeBusy->dtEnd() );
00219 
00220   QValueList<Period> periods = freeBusy->busyPeriods();
00221   QValueList<Period>::ConstIterator it;
00222   for ( it = periods.begin(); it != periods.end(); ++it )
00223     addPeriod( (*it).start(), (*it).end() );
00224 }