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
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 05:05:29 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 05:05:29 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.