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

KCalCore Library

  • kcalcore
incidencebase.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the kcalcore library.
3 
4  Copyright (c) 2001,2004 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6  Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
7  Contact: Alvaro Manera <alvaro.manera@nokia.com>
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Library General Public
11  License as published by the Free Software Foundation; either
12  version 2 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Library General Public License for more details.
18 
19  You should have received a copy of the GNU Library General Public License
20  along with this library; see the file COPYING.LIB. If not, write to
21  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  Boston, MA 02110-1301, USA.
23 */
37 #include "incidencebase.h"
38 #include "calformat.h"
39 #include "visitor.h"
40 
41 #include <QDebug>
42 
43 #include <KUrl>
44 
45 #include <QtCore/QStringList>
46 
47 using namespace KCalCore;
48 
53 //@cond PRIVATE
54 class KCalCore::IncidenceBase::Private
55 {
56  public:
57  Private()
58  : mOrganizer( new Person() ),
59  mUpdateGroupLevel( 0 ),
60  mUpdatedPending( false ),
61  mAllDay( true ),
62  mHasDuration( false )
63  {}
64 
65  Private( const Private &other )
66  : mUpdateGroupLevel( 0 ),
67  mUpdatedPending( false ),
68  mAllDay( true ),
69  mHasDuration( false )
70  {
71  init( other );
72  }
73 
74  ~Private()
75  {
76  }
77 
78  void init( const Private &other );
79 
80  KDateTime mLastModified; // incidence last modified date
81  KDateTime mDtStart; // incidence start time
82  Person::Ptr mOrganizer; // incidence person (owner)
83  QString mUid; // incidence unique id
84  Duration mDuration; // incidence duration
85  int mUpdateGroupLevel; // if non-zero, suppresses update() calls
86  bool mUpdatedPending; // true if an update has occurred since startUpdates()
87  bool mAllDay; // true if the incidence is all-day
88  bool mHasDuration; // true if the incidence has a duration
89  Attendee::List mAttendees; // list of incidence attendees
90  QStringList mComments; // list of incidence comments
91  QStringList mContacts; // list of incidence contacts
92  QList<IncidenceObserver*> mObservers; // list of incidence observers
93  QSet<Field> mDirtyFields; // Fields that changed since last time the incidence was created
94  // or since resetDirtyFlags() was called
95 };
96 
97 void IncidenceBase::Private::init( const Private &other )
98 {
99  mLastModified = other.mLastModified;
100  mDtStart = other.mDtStart;
101  mOrganizer = other.mOrganizer;
102  mUid = other.mUid;
103  mDuration = other.mDuration;
104  mAllDay = other.mAllDay;
105  mHasDuration = other.mHasDuration;
106 
107  mComments = other.mComments;
108  mContacts = other.mContacts;
109 
110  mAttendees.clear();
111  Attendee::List::ConstIterator it;
112  for ( it = other.mAttendees.constBegin(); it != other.mAttendees.constEnd(); ++it ) {
113  mAttendees.append( Attendee::Ptr( new Attendee( *( *it ) ) ) );
114  }
115 }
116 //@endcond
117 
118 IncidenceBase::IncidenceBase()
119  : d( new KCalCore::IncidenceBase::Private )
120 {
121  mReadOnly = false;
122  setUid( CalFormat::createUniqueId() );
123 }
124 
125 IncidenceBase::IncidenceBase( const IncidenceBase &i )
126  : CustomProperties( i ),
127  d( new KCalCore::IncidenceBase::Private( *i.d ) )
128 {
129  mReadOnly = i.mReadOnly;
130 }
131 
132 IncidenceBase::~IncidenceBase()
133 {
134  delete d;
135 }
136 
137 IncidenceBase &IncidenceBase::operator=( const IncidenceBase &other )
138 {
139  Q_ASSERT( type() == other.type() );
140 
141  startUpdates();
142 
143  // assign is virtual, will call the derived class's
144  IncidenceBase &ret = assign( other );
145  endUpdates();
146  return ret;
147 }
148 
149 IncidenceBase &IncidenceBase::assign( const IncidenceBase &other )
150 {
151  CustomProperties::operator=( other );
152  d->init( *other.d );
153  mReadOnly = other.mReadOnly;
154  d->mDirtyFields.clear();
155  d->mDirtyFields.insert( FieldUnknown );
156  return *this;
157 }
158 
159 bool IncidenceBase::operator==( const IncidenceBase &i2 ) const
160 {
161  if ( i2.type() != type() ) {
162  return false;
163  } else {
164  // equals is virtual, so here we're calling the derived class method
165  return equals( i2 );
166  }
167 }
168 
169 bool IncidenceBase::operator!=( const IncidenceBase &i2 ) const
170 {
171  return !operator==( i2 );
172 }
173 
174 bool IncidenceBase::equals( const IncidenceBase &i2 ) const
175 {
176  if ( attendees().count() != i2.attendees().count() ) {
177  return false;
178  }
179 
180  Attendee::List al1 = attendees();
181  Attendee::List al2 = i2.attendees();
182  Attendee::List::ConstIterator a1 = al1.constBegin();
183  Attendee::List::ConstIterator a2 = al2.constBegin();
184  //TODO Does the order of attendees in the list really matter?
185  //Please delete this comment if you know it's ok, kthx
186  for ( ; a1 != al1.constEnd() && a2 != al2.constEnd(); ++a1, ++a2 ) {
187  if ( !( **a1 == **a2 ) ) {
188  return false;
189  }
190  }
191 
192  if ( !CustomProperties::operator==( i2 ) ) {
193  return false;
194  }
195 
196  return
197  ( ( dtStart() == i2.dtStart() ) ||
198  ( !dtStart().isValid() && !i2.dtStart().isValid() ) ) &&
199  *( organizer().data() ) == *( i2.organizer().data() ) &&
200  uid() == i2.uid() &&
201  // Don't compare lastModified, otherwise the operator is not
202  // of much use. We are not comparing for identity, after all.
203  allDay() == i2.allDay() &&
204  duration() == i2.duration() &&
205  hasDuration() == i2.hasDuration();
206  // no need to compare mObserver
207 }
208 
209 bool IncidenceBase::accept( Visitor &v, IncidenceBase::Ptr incidence )
210 {
211  Q_UNUSED( v );
212  Q_UNUSED( incidence );
213  return false;
214 }
215 
216 void IncidenceBase::setUid( const QString &uid )
217 {
218  update();
219  d->mUid = uid;
220  d->mDirtyFields.insert( FieldUid );
221  updated();
222 }
223 
224 QString IncidenceBase::uid() const
225 {
226  return d->mUid;
227 }
228 
229 void IncidenceBase::setLastModified( const KDateTime &lm )
230 {
231  // DON'T! updated() because we call this from
232  // Calendar::updateEvent().
233 
234  d->mDirtyFields.insert( FieldLastModified );
235 
236  // Convert to UTC and remove milliseconds part.
237  KDateTime current = lm.toUtc();
238  QTime t = current.time();
239  t.setHMS( t.hour(), t.minute(), t.second(), 0 );
240  current.setTime( t );
241 
242  d->mLastModified = current;
243 }
244 
245 KDateTime IncidenceBase::lastModified() const
246 {
247  return d->mLastModified;
248 }
249 
250 void IncidenceBase::setOrganizer( const Person::Ptr &o )
251 {
252  update();
253  // we don't check for readonly here, because it is
254  // possible that by setting the organizer we are changing
255  // the event's readonly status...
256  d->mOrganizer = o;
257 
258  d->mDirtyFields.insert( FieldOrganizer );
259 
260  updated();
261 }
262 
263 void IncidenceBase::setOrganizer( const QString &o )
264 {
265  QString mail( o );
266  if ( mail.startsWith( QLatin1String( "MAILTO:" ), Qt::CaseInsensitive ) ) {
267  mail = mail.remove( 0, 7 );
268  }
269 
270  // split the string into full name plus email.
271  const Person::Ptr organizer = Person::fromFullName( mail );
272  setOrganizer( organizer );
273 }
274 
275 Person::Ptr IncidenceBase::organizer() const
276 {
277  return d->mOrganizer;
278 }
279 
280 void IncidenceBase::setReadOnly( bool readOnly )
281 {
282  mReadOnly = readOnly;
283 }
284 
285 bool IncidenceBase::isReadOnly() const
286 {
287  return mReadOnly;
288 }
289 
290 void IncidenceBase::setDtStart( const KDateTime &dtStart )
291 {
292 // if ( mReadOnly ) return;
293  update();
294  d->mDtStart = dtStart;
295  d->mAllDay = dtStart.isDateOnly();
296  d->mDirtyFields.insert( FieldDtStart );
297  updated();
298 }
299 
300 KDateTime IncidenceBase::dtStart() const
301 {
302  return d->mDtStart;
303 }
304 
305 bool IncidenceBase::allDay() const
306 {
307  return d->mAllDay;
308 }
309 
310 void IncidenceBase::setAllDay( bool f )
311 {
312  if ( mReadOnly || f == d->mAllDay ) {
313  return;
314  }
315  update();
316  d->mAllDay = f;
317  if ( d->mDtStart.isValid() ) {
318  d->mDirtyFields.insert( FieldDtStart );
319  }
320  updated();
321 }
322 
323 void IncidenceBase::shiftTimes( const KDateTime::Spec &oldSpec,
324  const KDateTime::Spec &newSpec )
325 {
326  update();
327  d->mDtStart = d->mDtStart.toTimeSpec( oldSpec );
328  d->mDtStart.setTimeSpec( newSpec );
329  d->mDirtyFields.insert( FieldDtStart );
330  d->mDirtyFields.insert( FieldDtEnd );
331  updated();
332 }
333 
334 void IncidenceBase::addComment( const QString &comment )
335 {
336  d->mComments += comment;
337 }
338 
339 bool IncidenceBase::removeComment( const QString &comment )
340 {
341  bool found = false;
342  QStringList::Iterator i;
343 
344  for ( i = d->mComments.begin(); !found && i != d->mComments.end(); ++i ) {
345  if ( ( *i ) == comment ) {
346  found = true;
347  d->mComments.erase( i );
348  }
349  }
350 
351  if ( found ) {
352  d->mDirtyFields.insert( FieldComment );
353  }
354 
355  return found;
356 }
357 
358 void IncidenceBase::clearComments()
359 {
360  d->mDirtyFields.insert( FieldComment );
361  d->mComments.clear();
362 }
363 
364 QStringList IncidenceBase::comments() const
365 {
366  return d->mComments;
367 }
368 
369 void IncidenceBase::addContact( const QString &contact )
370 {
371  if ( !contact.isEmpty() ) {
372  d->mContacts += contact;
373  d->mDirtyFields.insert( FieldContact );
374  }
375 }
376 
377 bool IncidenceBase::removeContact( const QString &contact )
378 {
379  bool found = false;
380  QStringList::Iterator i;
381 
382  for ( i = d->mContacts.begin(); !found && i != d->mContacts.end(); ++i ) {
383  if ( ( *i ) == contact ) {
384  found = true;
385  d->mContacts.erase( i );
386  }
387  }
388 
389  if ( found ) {
390  d->mDirtyFields.insert( FieldContact );
391  }
392 
393  return found;
394 }
395 
396 void IncidenceBase::clearContacts()
397 {
398  d->mDirtyFields.insert( FieldContact );
399  d->mContacts.clear();
400 }
401 
402 QStringList IncidenceBase::contacts() const
403 {
404  return d->mContacts;
405 }
406 
407 void IncidenceBase::addAttendee( const Attendee::Ptr &a, bool doupdate )
408 {
409  if ( !a || mReadOnly ) {
410  return;
411  }
412 
413  Q_ASSERT( !d->mAttendees.contains( a ) );
414 
415  if ( doupdate ) {
416  update();
417  }
418  if ( a->name().left( 7 ).toUpper() == "MAILTO:" ) {
419  a->setName( a->name().remove( 0, 7 ) );
420  }
421 
422  /* If Uid is empty, just use the pointer to Attendee (encoded to
423  * string) as Uid. Only thing that matters is that the Uid is unique
424  * insofar IncidenceBase is concerned, and this does that (albeit
425  * not very nicely). If these are ever saved to disk, should use
426  * (considerably more expensive) CalFormat::createUniqueId(). As Uid
427  * is not part of Attendee in iCal std, it's fairly safe bet that
428  * these will never hit disc though so faster generation speed is
429  * more important than actually being forever unique.*/
430  if ( a->uid().isEmpty() ) {
431  a->setUid( QString::number( (qlonglong)a.data() ) );
432  }
433 
434  d->mAttendees.append( a );
435  if ( doupdate ) {
436  d->mDirtyFields.insert( FieldAttendees );
437  updated();
438  }
439 }
440 
441 void IncidenceBase::deleteAttendee( const Attendee::Ptr &a, bool doupdate )
442 {
443  if ( !a || mReadOnly ) {
444  return;
445  }
446 
447  int index = d->mAttendees.indexOf( a );
448  if ( index >= 0 ) {
449  if ( doupdate ) {
450  update();
451  }
452 
453  d->mAttendees.remove( index );
454 
455  if ( doupdate ) {
456  d->mDirtyFields.insert( FieldAttendees );
457  updated();
458  }
459  }
460 }
461 
462 Attendee::List IncidenceBase::attendees() const
463 {
464  return d->mAttendees;
465 }
466 
467 int IncidenceBase::attendeeCount() const
468 {
469  return d->mAttendees.count();
470 }
471 
472 void IncidenceBase::clearAttendees()
473 {
474  if ( mReadOnly ) {
475  return;
476  }
477  d->mDirtyFields.insert( FieldAttendees );
478  d->mAttendees.clear();
479 }
480 
481 Attendee::Ptr IncidenceBase::attendeeByMail( const QString &email ) const
482 {
483  Attendee::List::ConstIterator it;
484  for ( it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it ) {
485  if ( ( *it )->email() == email ) {
486  return *it;
487  }
488  }
489 
490  return Attendee::Ptr();
491 }
492 
493 Attendee::Ptr IncidenceBase::attendeeByMails( const QStringList &emails,
494  const QString &email ) const
495 {
496  QStringList mails = emails;
497  if ( !email.isEmpty() ) {
498  mails.append( email );
499  }
500 
501  Attendee::List::ConstIterator itA;
502  for ( itA = d->mAttendees.constBegin(); itA != d->mAttendees.constEnd(); ++itA ) {
503  for ( QStringList::const_iterator it = mails.constBegin(); it != mails.constEnd(); ++it ) {
504  if ( ( *itA )->email() == ( *it ) ) {
505  return *itA;
506  }
507  }
508  }
509 
510  return Attendee::Ptr();
511 }
512 
513 Attendee::Ptr IncidenceBase::attendeeByUid( const QString &uid ) const
514 {
515  Attendee::List::ConstIterator it;
516  for ( it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it ) {
517  if ( ( *it )->uid() == uid ) {
518  return *it;
519  }
520  }
521 
522  return Attendee::Ptr();
523 }
524 
525 void IncidenceBase::setDuration( const Duration &duration )
526 {
527  update();
528  d->mDuration = duration;
529  setHasDuration( true );
530  d->mDirtyFields.insert( FieldDuration );
531  updated();
532 }
533 
534 Duration IncidenceBase::duration() const
535 {
536  return d->mDuration;
537 }
538 
539 void IncidenceBase::setHasDuration( bool hasDuration )
540 {
541  d->mHasDuration = hasDuration;
542 }
543 
544 bool IncidenceBase::hasDuration() const
545 {
546  return d->mHasDuration;
547 }
548 
549 void IncidenceBase::registerObserver( IncidenceBase::IncidenceObserver *observer )
550 {
551  if ( observer && !d->mObservers.contains( observer ) ) {
552  d->mObservers.append( observer );
553  }
554 }
555 
556 void IncidenceBase::unRegisterObserver( IncidenceBase::IncidenceObserver *observer )
557 {
558  d->mObservers.removeAll( observer );
559 }
560 
561 void IncidenceBase::update()
562 {
563  if ( !d->mUpdateGroupLevel ) {
564  d->mUpdatedPending = true;
565  KDateTime rid = recurrenceId();
566  foreach ( IncidenceObserver *o, d->mObservers ) {
567  o->incidenceUpdate( uid(), rid );
568  }
569  }
570 }
571 
572 void IncidenceBase::updated()
573 {
574  if ( d->mUpdateGroupLevel ) {
575  d->mUpdatedPending = true;
576  } else {
577  KDateTime rid = recurrenceId();
578  foreach ( IncidenceObserver *o, d->mObservers ) {
579  o->incidenceUpdated( uid(), rid );
580  }
581  }
582 }
583 
584 void IncidenceBase::startUpdates()
585 {
586  update();
587  ++d->mUpdateGroupLevel;
588 }
589 
590 void IncidenceBase::endUpdates()
591 {
592  if ( d->mUpdateGroupLevel > 0 ) {
593  if ( --d->mUpdateGroupLevel == 0 && d->mUpdatedPending ) {
594  d->mUpdatedPending = false;
595  updated();
596  }
597  }
598 }
599 
600 void IncidenceBase::customPropertyUpdate()
601 {
602  update();
603 }
604 
605 void IncidenceBase::customPropertyUpdated()
606 {
607  updated();
608 }
609 
610 KDateTime IncidenceBase::recurrenceId() const
611 {
612  return KDateTime();
613 }
614 
615 void IncidenceBase::resetDirtyFields()
616 {
617  d->mDirtyFields.clear();
618 }
619 
620 QSet<IncidenceBase::Field> IncidenceBase::dirtyFields() const
621 {
622  return d->mDirtyFields;
623 }
624 
625 void IncidenceBase::setFieldDirty( IncidenceBase::Field field )
626 {
627  d->mDirtyFields.insert( field );
628 }
629 
630 KUrl IncidenceBase::uri() const
631 {
632  return KUrl( QString( "urn:x-ical:" ) + uid() );
633 }
634 
635 void IncidenceBase::setDirtyFields( const QSet<IncidenceBase::Field> &dirtyFields )
636 {
637  d->mDirtyFields = dirtyFields;
638 }
639 
640 IncidenceBase::IncidenceObserver::~IncidenceObserver()
641 {
642 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:24:52 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