freebusy.cpp
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 TQDateTime &start, const TQDateTime &end) 00034 { 00035 setDtStart(start); 00036 setDtEnd(end); 00037 } 00038 00039 FreeBusy::FreeBusy( Calendar *calendar, const TQDateTime &start, const TQDateTime &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 TQDate day; 00053 TQDateTime tmpStart; 00054 TQDateTime 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 TQDateTime start( floatingEvent->dtStart().date(), TQTime( 0, 0 ) ); 00072 TQDateTime end( floatingEvent->dtEnd().date(), TQTime( 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 TQDateTime &end ) 00138 { 00139 mDtEnd = end; 00140 return true; 00141 } 00142 00143 TQDateTime 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 TQDateTime &eventStart, const TQDateTime &eventEnd ) { 00154 TQDateTime tmpStart; 00155 TQDateTime 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 TQDateTime &start, const TQDateTime &end) 00201 { 00202 mBusyPeriods.append( Period(start, end) ); 00203 sortList(); 00204 } 00205 00206 void FreeBusy::addPeriod( const TQDateTime &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 TQValueList<Period> periods = freeBusy->busyPeriods(); 00221 TQValueList<Period>::ConstIterator it; 00222 for ( it = periods.begin(); it != periods.end(); ++it ) 00223 addPeriod( (*it).start(), (*it).end() ); 00224 } 00225 00226 bool FreeBusy::operator==( const FreeBusy &freebusy ) const 00227 { 00228 return 00229 static_cast<const IncidenceBase &>( *this ) == static_cast<const IncidenceBase &>( freebusy ) && 00230 dtEnd() == freebusy.dtEnd() && 00231 mCalendar == freebusy.mCalendar && 00232 mBusyPeriods == freebusy.mBusyPeriods; 00233 }