00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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;
00063 FreeBusyPeriod::List mBusyPeriods;
00064
00065
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
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
00113 Event::List::ConstIterator it;
00114 for ( it = eventList.constBegin(); it != eventList.constEnd(); ++it ) {
00115 Event *event = *it;
00116
00117
00118 if ( event->transparency() == Event::Transparent ) {
00119 continue;
00120 }
00121
00122
00123
00124
00125
00126 Event *allDayEvent = 0;
00127 if ( event->allDay() ) {
00128
00129 kDebug() << "All-day event";
00130 allDayEvent = new Event( *event );
00131
00132
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
00143 event = allDayEvent;
00144 }
00145
00146
00147
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
00157
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
00181 addLocalPeriod( q, event->dtStart(), event->dtEnd() );
00182
00183
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
00223
00224
00225
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 ) {
00318 p.shiftTimes( oldSpec, newSpec );
00319 }
00320 }
00321 }
00322
00323 FreeBusy &FreeBusy::operator=( const FreeBusy &other )
00324 {
00325
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
00344 bool FreeBusy::Private::addLocalPeriod( FreeBusy *fb,
00345 const KDateTime &eventStart,
00346 const KDateTime &eventEnd )
00347 {
00348 KDateTime tmpStart;
00349 KDateTime tmpEnd;
00350
00351
00352
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