• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KCalCore Library

  • kcalcore
freebusy.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the kcalcore library.
3 
4  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
33 #include "freebusy.h"
34 #include "visitor.h"
35 
36 #include "icalformat.h"
37 
38 #include <KDebug>
39 
40 using namespace KCalCore;
41 
42 //@cond PRIVATE
43 class KCalCore::FreeBusy::Private
44 {
45  private:
46  FreeBusy *q;
47  public:
48  Private( FreeBusy *qq ) : q( qq )
49  {}
50 
51  Private( const KCalCore::FreeBusy::Private &other, FreeBusy *qq ) : q( qq )
52  {
53  init( other );
54  }
55 
56  Private( const FreeBusyPeriod::List &busyPeriods, FreeBusy *qq )
57  : q( qq ), mBusyPeriods( busyPeriods )
58  {}
59 
60  void init( const KCalCore::FreeBusy::Private &other );
61  void init( const Event::List &events, const KDateTime &start, const KDateTime &end );
62 
63  KDateTime mDtEnd; // end datetime
64  FreeBusyPeriod::List mBusyPeriods; // list of periods
65 
66  // This is used for creating a freebusy object for the current user
67  bool addLocalPeriod( FreeBusy *fb, const KDateTime &start, const KDateTime &end );
68 };
69 
70 void KCalCore::FreeBusy::Private::init( const KCalCore::FreeBusy::Private &other )
71 {
72  mDtEnd = other.mDtEnd;
73  mBusyPeriods = other.mBusyPeriods;
74 }
75 //@endcond
76 
77 FreeBusy::FreeBusy()
78  : d( new KCalCore::FreeBusy::Private( this ) )
79 {
80 }
81 
82 FreeBusy::FreeBusy( const FreeBusy &other )
83  : IncidenceBase( other ),
84  d( new KCalCore::FreeBusy::Private( *other.d, this ) )
85 {
86 }
87 
88 FreeBusy::FreeBusy( const KDateTime &start, const KDateTime &end )
89  : d( new KCalCore::FreeBusy::Private( this ) )
90 {
91  setDtStart( start );
92  setDtEnd( end );
93 }
94 
95 FreeBusy::FreeBusy( const Event::List &events, const KDateTime &start, const KDateTime &end )
96  : d( new KCalCore::FreeBusy::Private( this ) )
97 {
98  setDtStart( start );
99  setDtEnd( end );
100 
101  d->init( events, start, end );
102 }
103 
104 //@cond PRIVATE
105 void FreeBusy::Private::init( const Event::List &eventList,
106  const KDateTime &start, const KDateTime &end )
107 {
108  int extraDays, i, x, duration;
109  duration = start.daysTo( end );
110  QDate day;
111  KDateTime tmpStart;
112  KDateTime tmpEnd;
113 
114  // Loops through every event in the calendar
115  Event::List::ConstIterator it;
116  for ( it = eventList.constBegin(); it != eventList.constEnd(); ++it ) {
117  Event::Ptr event = *it;
118 
119  // If this event is transparent it shouldn't be in the freebusy list.
120  if ( event->transparency() == Event::Transparent ) {
121  continue;
122  }
123 
124  // The code below can not handle all-day events. Fixing this resulted
125  // in a lot of duplicated code. Instead, make a copy of the event and
126  // set the period to the full day(s). This trick works for recurring,
127  // multiday, and single day all-day events.
128  Event::Ptr allDayEvent;
129  if ( event->allDay() ) {
130  // addDay event. Do the hack
131  kDebug() << "All-day event";
132  allDayEvent = Event::Ptr( new Event( *event ) );
133 
134  // Set the start and end times to be on midnight
135  KDateTime st = allDayEvent->dtStart();
136  st.setTime( QTime( 0, 0 ) );
137  KDateTime nd = allDayEvent->dtEnd();
138  nd.setTime( QTime( 23, 59, 59, 999 ) );
139  allDayEvent->setAllDay( false );
140  allDayEvent->setDtStart( st );
141  allDayEvent->setDtEnd( nd );
142 
143  kDebug() << "Use:" << st.toString() << "to" << nd.toString();
144  // Finally, use this event for the setting below
145  event = allDayEvent;
146  }
147 
148  // This whole for loop is for recurring events, it loops through
149  // each of the days of the freebusy request
150 
151  for ( i = 0; i <= duration; ++i ) {
152  day = start.addDays( i ).date();
153  tmpStart.setDate( day );
154  tmpEnd.setDate( day );
155 
156  if ( event->recurs() ) {
157  if ( event->isMultiDay() ) {
158  // FIXME: This doesn't work for sub-daily recurrences or recurrences with
159  // a different time than the original event.
160  extraDays = event->dtStart().daysTo( event->dtEnd() );
161  for ( x = 0; x <= extraDays; ++x ) {
162  if ( event->recursOn( day.addDays( -x ), start.timeSpec() ) ) {
163  tmpStart.setDate( day.addDays( -x ) );
164  tmpStart.setTime( event->dtStart().time() );
165  tmpEnd = event->duration().end( tmpStart );
166 
167  addLocalPeriod( q, tmpStart, tmpEnd );
168  break;
169  }
170  }
171  } else {
172  if ( event->recursOn( day, start.timeSpec() ) ) {
173  tmpStart.setTime( event->dtStart().time() );
174  tmpEnd.setTime( event->dtEnd().time() );
175 
176  addLocalPeriod ( q, tmpStart, tmpEnd );
177  }
178  }
179  }
180 
181  }
182  // Non-recurring events
183  addLocalPeriod( q, event->dtStart(), event->dtEnd() );
184  }
185 
186  q->sortList();
187 }
188 //@endcond
189 
190 FreeBusy::FreeBusy( const Period::List &busyPeriods )
191  : d( new KCalCore::FreeBusy::Private( this ) )
192 {
193  addPeriods( busyPeriods );
194 }
195 
196 FreeBusy::FreeBusy( const FreeBusyPeriod::List &busyPeriods )
197  : d( new KCalCore::FreeBusy::Private( busyPeriods, this ) )
198 {
199 }
200 
201 FreeBusy::~FreeBusy()
202 {
203  delete d;
204 }
205 
206 IncidenceBase::IncidenceType FreeBusy::type() const
207 {
208  return TypeFreeBusy;
209 }
210 
211 QByteArray FreeBusy::typeStr() const
212 {
213  return "FreeBusy";
214 }
215 
216 void FreeBusy::setDtStart( const KDateTime &start )
217 {
218  IncidenceBase::setDtStart( start.toUtc() );
219  updated();
220 }
221 
222 void FreeBusy::setDtEnd( const KDateTime &end )
223 {
224  d->mDtEnd = end;
225 }
226 
227 KDateTime FreeBusy::dtEnd() const
228 {
229  return d->mDtEnd;
230 }
231 
232 Period::List FreeBusy::busyPeriods() const
233 {
234  Period::List res;
235 
236  foreach ( const FreeBusyPeriod &p, d->mBusyPeriods ) {
237  res << p;
238  }
239 
240  return res;
241 }
242 
243 FreeBusyPeriod::List FreeBusy::fullBusyPeriods() const
244 {
245  return d->mBusyPeriods;
246 }
247 
248 void FreeBusy::sortList()
249 {
250  qSort( d->mBusyPeriods );
251  return;
252 }
253 
254 void FreeBusy::addPeriods( const Period::List &list )
255 {
256  foreach ( const Period &p, list ) {
257  d->mBusyPeriods << FreeBusyPeriod( p );
258  }
259  sortList();
260 }
261 
262 void FreeBusy::addPeriods( const FreeBusyPeriod::List &list )
263 {
264  d->mBusyPeriods += list;
265  sortList();
266 }
267 
268 void FreeBusy::addPeriod( const KDateTime &start, const KDateTime &end )
269 {
270  d->mBusyPeriods.append( FreeBusyPeriod( start, end ) );
271  sortList();
272 }
273 
274 void FreeBusy::addPeriod( const KDateTime &start, const Duration &duration )
275 {
276  d->mBusyPeriods.append( FreeBusyPeriod( start, duration ) );
277  sortList();
278 }
279 
280 void FreeBusy::merge( FreeBusy::Ptr freeBusy )
281 {
282  if ( freeBusy->dtStart() < dtStart() ) {
283  setDtStart( freeBusy->dtStart() );
284  }
285 
286  if ( freeBusy->dtEnd() > dtEnd() ) {
287  setDtEnd( freeBusy->dtEnd() );
288  }
289 
290  Period::List periods = freeBusy->busyPeriods();
291  Period::List::ConstIterator it;
292  for ( it = periods.constBegin(); it != periods.constEnd(); ++it ) {
293  d->mBusyPeriods.append( FreeBusyPeriod( ( *it ).start(), ( *it ).end() ) );
294  }
295  sortList();
296 }
297 
298 void FreeBusy::shiftTimes( const KDateTime::Spec &oldSpec,
299  const KDateTime::Spec &newSpec )
300 {
301  if ( oldSpec.isValid() && newSpec.isValid() && oldSpec != newSpec ) {
302  IncidenceBase::shiftTimes( oldSpec, newSpec );
303  d->mDtEnd = d->mDtEnd.toTimeSpec( oldSpec );
304  d->mDtEnd.setTimeSpec( newSpec );
305  foreach ( FreeBusyPeriod p, d->mBusyPeriods ) { //krazy:exclude=foreach
306  p.shiftTimes( oldSpec, newSpec );
307  }
308  }
309 }
310 
311 IncidenceBase &FreeBusy::assign( const IncidenceBase &other )
312 {
313  if ( &other != this ) {
314  IncidenceBase::assign( other );
315  const FreeBusy *f = static_cast<const FreeBusy*>( &other );
316  d->init( *( f->d ) );
317  }
318  return *this;
319 }
320 
321 bool FreeBusy::equals( const IncidenceBase &freeBusy ) const
322 {
323  if ( !IncidenceBase::equals( freeBusy ) ) {
324  return false;
325  } else {
326  // If they weren't the same type IncidenceBase::equals would had returned false already
327  const FreeBusy *fb = static_cast<const FreeBusy*>( &freeBusy );
328  return
329  dtEnd() == fb->dtEnd() &&
330  d->mBusyPeriods == fb->d->mBusyPeriods;
331  }
332 }
333 
334 bool FreeBusy::accept( Visitor &v, IncidenceBase::Ptr incidence )
335 {
336  return v.visit( incidence.staticCast<FreeBusy>() );
337 }
338 
339 KDateTime FreeBusy::dateTime( DateTimeRole role ) const
340 {
341  Q_UNUSED( role );
342  // No roles affecting freeBusy yet
343  return KDateTime();
344 }
345 
346 void FreeBusy::setDateTime( const KDateTime &dateTime, DateTimeRole role )
347 {
348  Q_UNUSED( dateTime );
349  Q_UNUSED( role );
350 }
351 
352 void FreeBusy::virtual_hook( int id, void *data )
353 {
354  Q_UNUSED( id );
355  Q_UNUSED( data );
356  Q_ASSERT( false );
357 }
358 
359 //@cond PRIVATE
360 bool FreeBusy::Private::addLocalPeriod( FreeBusy *fb,
361  const KDateTime &eventStart,
362  const KDateTime &eventEnd )
363 {
364  KDateTime tmpStart;
365  KDateTime tmpEnd;
366 
367  //Check to see if the start *or* end of the event is
368  //between the start and end of the freebusy dates.
369  KDateTime start = fb->dtStart();
370  if ( !( ( ( start.secsTo( eventStart ) >= 0 ) &&
371  ( eventStart.secsTo( mDtEnd ) >= 0 ) ) ||
372  ( ( start.secsTo( eventEnd ) >= 0 ) &&
373  ( eventEnd.secsTo( mDtEnd ) >= 0 ) ) ) ) {
374  return false;
375  }
376 
377  if ( eventStart.secsTo( start ) >= 0 ) {
378  tmpStart = start;
379  } else {
380  tmpStart = eventStart;
381  }
382 
383  if ( eventEnd.secsTo( mDtEnd ) <= 0 ) {
384  tmpEnd = mDtEnd;
385  } else {
386  tmpEnd = eventEnd;
387  }
388 
389  FreeBusyPeriod p( tmpStart, tmpEnd );
390  mBusyPeriods.append( p );
391 
392  return true;
393 }
394 //@endcond
395 
396 QLatin1String FreeBusy::mimeType() const
397 {
398  return FreeBusy::freeBusyMimeType();
399 }
400 
401 QLatin1String KCalCore::FreeBusy::freeBusyMimeType()
402 {
403  return QLatin1String( "application/x-vnd.akonadi.calendar.freebusy" );
404 }
405 
406 QDataStream &KCalCore::operator<<( QDataStream &stream, const KCalCore::FreeBusy::Ptr &freebusy )
407 {
408  KCalCore::ICalFormat format;
409  QString data = format.createScheduleMessage( freebusy, iTIPPublish );
410  return stream << data;
411 }
412 
413 QDataStream &KCalCore::operator>>( QDataStream &stream, KCalCore::FreeBusy::Ptr &freebusy )
414 {
415  QString freeBusyVCal;
416  stream >> freeBusyVCal;
417 
418  KCalCore::ICalFormat format;
419  freebusy = format.parseFreeBusy( freeBusyVCal );
420 
421  if ( !freebusy ) {
422  kDebug() << "Error parsing free/busy";
423  kDebug() << freeBusyVCal;
424  }
425 
426  return stream;
427 }
428 
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:24:51 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KCalCore Library

Skip menu "KCalCore Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepimlibs-4.10.5 API Reference

Skip menu "kdepimlibs-4.10.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal