/* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher Copyright (C) 2004 Reinhold Kainhofer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "freebusy.h" using namespace KCal; FreeBusy::FreeBusy() { } FreeBusy::FreeBusy(const TQDateTime &start, const TQDateTime &end) { setDtStart(start); setDtEnd(end); } FreeBusy::FreeBusy( Calendar *calendar, const TQDateTime &start, const TQDateTime &end ) { kdDebug(5800) << "FreeBusy::FreeBusy" << endl; mCalendar = calendar; setDtStart(start); setDtEnd(end); // Get all the events in the calendar Event::List eventList = mCalendar->rawEvents( start.date(), end.date() ); int extraDays, i, x, duration; duration = start.daysTo(end); TQDate day; TQDateTime tmpStart; TQDateTime tmpEnd; // Loops through every event in the calendar Event::List::ConstIterator it; for( it = eventList.begin(); it != eventList.end(); ++it ) { Event *event = *it; // The code below can not handle floating events. Fixing this resulted // in a lot of duplicated code. Instead, make a copy of the event and // set the period to the full day(s). This trick works for recurring, // multiday, and single day floating events. Event *floatingEvent = 0; if ( event->doesFloat() ) { // Floating event. Do the hack kdDebug(5800) << "Floating event\n"; floatingEvent = new Event( *event ); // Set the start and end times to be on midnight TQDateTime start( floatingEvent->dtStart().date(), TQTime( 0, 0 ) ); TQDateTime end( floatingEvent->dtEnd().date(), TQTime( 23, 59, 59, 999 ) ); floatingEvent->setFloats( false ); floatingEvent->setDtStart( start ); floatingEvent->setDtEnd( end ); kdDebug(5800) << "Use: " << start.toString() << " to " << end.toString() << endl; // Finally, use this event for the setting below event = floatingEvent; } // This whole for loop is for recurring events, it loops through // each of the days of the freebusy request // First check if this is transparent. If it is, it shouldn't be in the // freebusy list if ( event->transparency() == Event::Transparent ) // Transparent continue; for( i = 0; i <= duration; ++i ) { day=(start.addDays(i).date()); tmpStart.setDate(day); tmpEnd.setDate(day); if( event->doesRecur() ) { if ( event->isMultiDay() ) { // FIXME: This doesn't work for sub-daily recurrences or recurrences with // a different time than the original event. extraDays = event->dtStart().date().daysTo(event->dtEnd().date()); for ( x = 0; x <= extraDays; ++x ) { if ( event->recursOn(day.addDays(-x))) { tmpStart.setDate(day.addDays(-x)); tmpStart.setTime(event->dtStart().time()); tmpEnd=tmpStart.addSecs( (event->duration()) ); addLocalPeriod( tmpStart, tmpEnd ); break; } } } else { if (event->recursOn(day)) { tmpStart.setTime(event->dtStart().time()); tmpEnd.setTime(event->dtEnd().time()); addLocalPeriod (tmpStart, tmpEnd); } } } } // Non-recurring events addLocalPeriod(event->dtStart(), event->dtEnd()); // Clean up delete floatingEvent; } sortList(); } FreeBusy::~FreeBusy() { } bool FreeBusy::setDtEnd( const TQDateTime &end ) { mDtEnd = end; return true; } TQDateTime FreeBusy::dtEnd() const { return mDtEnd; } PeriodList FreeBusy::busyPeriods() const { return mBusyPeriods; } bool FreeBusy::addLocalPeriod(const TQDateTime &eventStart, const TQDateTime &eventEnd ) { TQDateTime tmpStart; TQDateTime tmpEnd; //Check to see if the start *or* end of the event is //between the start and end of the freebusy dates. if ( !( ( ( dtStart().secsTo(eventStart) >= 0 ) && ( eventStart.secsTo(dtEnd()) >= 0 ) ) || ( ( dtStart().secsTo(eventEnd) >= 0 ) && ( eventEnd.secsTo(dtEnd()) >= 0 ) ) ) ) return false; if ( eventStart.secsTo( dtStart() ) >= 0 ) { tmpStart = dtStart(); } else { tmpStart = eventStart; } if ( eventEnd.secsTo( dtEnd() ) <= 0 ) { tmpEnd = dtEnd(); } else { tmpEnd = eventEnd; } Period p(tmpStart, tmpEnd); mBusyPeriods.append( p ); return true; } FreeBusy::FreeBusy( PeriodList busyPeriods) { mBusyPeriods = busyPeriods; } void FreeBusy::sortList() { qHeapSort( mBusyPeriods ); return; } void FreeBusy::addPeriods(const PeriodList &list ) { mBusyPeriods += list; sortList(); } void FreeBusy::addPeriod(const TQDateTime &start, const TQDateTime &end) { mBusyPeriods.append( Period(start, end) ); sortList(); } void FreeBusy::addPeriod( const TQDateTime &start, const Duration &dur ) { mBusyPeriods.append( Period(start, dur) ); sortList(); } void FreeBusy::merge( FreeBusy *freeBusy ) { if ( freeBusy->dtStart() < dtStart() ) setDtStart( freeBusy->dtStart() ); if ( freeBusy->dtEnd() > dtEnd() ) setDtEnd( freeBusy->dtEnd() ); TQValueList periods = freeBusy->busyPeriods(); TQValueList::ConstIterator it; for ( it = periods.begin(); it != periods.end(); ++it ) addPeriod( (*it).start(), (*it).end() ); } bool FreeBusy::operator==( const FreeBusy &freebusy ) const { return static_cast( *this ) == static_cast( freebusy ) && dtEnd() == freebusy.dtEnd() && mCalendar == freebusy.mCalendar && mBusyPeriods == freebusy.mBusyPeriods; }