• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

KCal Library

todo.cpp

Go to the documentation of this file.
00001 /*
00002   This file is part of the kcal library.
00003 
00004   Copyright (c) 2001-2003 Cornelius Schumacher <schumacher@kde.org>
00005 
00006   This library is free software; you can redistribute it and/or
00007   modify it under the terms of the GNU Library General Public
00008   License as published by the Free Software Foundation; either
00009   version 2 of the License, or (at your option) any later version.
00010 
00011   This library is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   Library General Public License for more details.
00015 
00016   You should have received a copy of the GNU Library General Public License
00017   along with this library; see the file COPYING.LIB.  If not, write to
00018   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019   Boston, MA 02110-1301, USA.
00020 */
00032 #include "todo.h"
00033 
00034 #include <kglobal.h>
00035 #include <klocale.h>
00036 #include <kdebug.h>
00037 #include <ksystemtimezone.h>
00038 
00039 using namespace KCal;
00040 
00045 //@cond PRIVATE
00046 class KCal::Todo::Private
00047 {
00048   public:
00049     Private()
00050       : mPercentComplete( 0 ),
00051         mHasDueDate( false ),
00052         mHasStartDate( false ),
00053         mHasCompletedDate( false )
00054     {}
00055     Private( const KCal::Todo::Private &other )
00056     { init( other ); }
00057 
00058     void init( const KCal::Todo::Private &other );
00059 
00060     KDateTime mDtDue;        // to-do due date (if there is one)
00061                              // ALSO the first occurrence of a recurring to-do
00062     KDateTime mDtRecurrence; // next occurrence (for recurring to-dos)
00063     KDateTime mCompleted;    // to-do completion date (if it has been completed)
00064     int mPercentComplete;    // to-do percent complete [0,100]
00065     bool mHasDueDate;        // true if the to-do has a due date
00066     bool mHasStartDate;      // true if the to-do has a starting date
00067     bool mHasCompletedDate;  // true if the to-do has a completion date
00068 
00072     bool recurTodo( Todo *todo );
00073 };
00074 
00075 void KCal::Todo::Private::init( const KCal::Todo::Private &other )
00076 {
00077   mDtDue = other.mDtDue;
00078   mDtRecurrence = other.mDtRecurrence;
00079   mCompleted = other.mCompleted;
00080   mPercentComplete = other.mPercentComplete;
00081   mHasDueDate = other.mHasDueDate;
00082   mHasStartDate = other.mHasStartDate;
00083   mHasCompletedDate = other.mHasCompletedDate;
00084 }
00085 
00086 //@endcond
00087 
00088 Todo::Todo()
00089   : d( new KCal::Todo::Private )
00090 {
00091 }
00092 
00093 Todo::Todo( const Todo &other )
00094   : Incidence( other ),
00095     d( new KCal::Todo::Private( *other.d ) )
00096 {
00097 }
00098 
00099 Todo::~Todo()
00100 {
00101   delete d;
00102 }
00103 
00104 Todo *Todo::clone()
00105 {
00106   return new Todo( *this );
00107 }
00108 
00109 Todo &Todo::operator=( const Todo &other )
00110 {
00111   Incidence::operator=( other );
00112   d->init( *other.d );
00113   return *this;
00114 }
00115 
00116 bool Todo::operator==( const Todo &todo ) const
00117 {
00118   return
00119     static_cast<const Incidence &>( *this ) == static_cast<const Incidence &>( todo ) &&
00120     dtDue() == todo.dtDue() &&
00121     hasDueDate() == todo.hasDueDate() &&
00122     hasStartDate() == todo.hasStartDate() &&
00123     completed() == todo.completed() &&
00124     hasCompletedDate() == todo.hasCompletedDate() &&
00125     percentComplete() == todo.percentComplete();
00126 }
00127 
00128 QByteArray Todo::type() const
00129 {
00130   return "Todo";
00131 }
00132 
00133 void Todo::setDtDue( const KDateTime &dtDue, bool first )
00134 {
00135   //int diffsecs = d->mDtDue.secsTo(dtDue);
00136 
00137   /*if (mReadOnly) return;
00138   const Alarm::List& alarms = alarms();
00139   for (Alarm *alarm = alarms.first(); alarm; alarm = alarms.next()) {
00140     if (alarm->enabled()) {
00141       alarm->setTime(alarm->time().addSecs(diffsecs));
00142     }
00143   }*/
00144   if ( recurs() && !first ) {
00145     d->mDtRecurrence = dtDue;
00146   } else {
00147     d->mDtDue = dtDue;
00148     // TODO: This doesn't seem right...
00149     recurrence()->setStartDateTime( dtDue );
00150     recurrence()->setAllDay( allDay() );
00151   }
00152 
00153   if ( recurs() && dtDue < recurrence()->startDateTime() ) {
00154     setDtStart( dtDue );
00155   }
00156 
00157   //kDebug() << "setDtDue says date is" << d->mDtDue.toString();
00158 
00159   /*const Alarm::List& alarms = alarms();
00160   for (Alarm *alarm = alarms.first(); alarm; alarm = alarms.next())
00161     alarm->setAlarmStart(d->mDtDue);*/
00162 
00163   updated();
00164 }
00165 
00166 KDateTime Todo::dtDue( bool first ) const
00167 {
00168   if ( !hasDueDate() ) {
00169     return KDateTime();
00170   }
00171   if ( recurs() && !first && d->mDtRecurrence.isValid() ) {
00172     return d->mDtRecurrence;
00173   }
00174 
00175   return d->mDtDue;
00176 }
00177 
00178 QString Todo::dtDueTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const
00179 {
00180   if ( spec.isValid() ) {
00181 
00182     QString timeZone;
00183     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00184       timeZone = ' ' + spec.timeZone().name();
00185     }
00186 
00187     return KGlobal::locale()->formatTime( dtDue( !recurs() ).toTimeSpec( spec ).time(), shortfmt )
00188       + timeZone;
00189   } else {
00190     return KGlobal::locale()->formatTime( dtDue( !recurs() ).time(), shortfmt );
00191   }
00192 }
00193 
00194 QString Todo::dtDueDateStr( bool shortfmt, const KDateTime::Spec &spec ) const
00195 {
00196   if ( spec.isValid() ) {
00197 
00198     QString timeZone;
00199     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00200       timeZone = ' ' + spec.timeZone().name();
00201     }
00202 
00203     return KGlobal::locale()->formatDate(
00204       dtDue( !recurs() ).toTimeSpec( spec ).date(),
00205       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) )
00206       + timeZone;
00207   } else {
00208     return KGlobal::locale()->formatDate(
00209       dtDue( !recurs() ).date(),
00210       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00211   }
00212 }
00213 
00214 QString Todo::dtDueStr( bool shortfmt, const KDateTime::Spec &spec ) const
00215 {
00216   if ( allDay() ) {
00217     return dtDueDateStr( shortfmt, spec );
00218   }
00219 
00220   if ( spec.isValid() ) {
00221 
00222     QString timeZone;
00223     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00224       timeZone = ' ' + spec.timeZone().name();
00225     }
00226 
00227     return KGlobal::locale()->formatDateTime(
00228       dtDue( !recurs() ).toTimeSpec( spec ).dateTime(),
00229       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) )
00230       + timeZone;
00231   } else {
00232     return  KGlobal::locale()->formatDateTime(
00233       dtDue( !recurs() ).dateTime(),
00234       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00235   }
00236 }
00237 
00238 bool Todo::hasDueDate() const
00239 {
00240   return d->mHasDueDate;
00241 }
00242 
00243 void Todo::setHasDueDate( bool f )
00244 {
00245   if ( mReadOnly ) {
00246     return;
00247   }
00248   d->mHasDueDate = f;
00249   updated();
00250 }
00251 
00252 bool Todo::hasStartDate() const
00253 {
00254   return d->mHasStartDate;
00255 }
00256 
00257 void Todo::setHasStartDate( bool f )
00258 {
00259   if ( mReadOnly ) {
00260     return;
00261   }
00262 
00263   if ( recurs() && !f ) {
00264     if ( !comments().filter( "NoStartDate" ).count() ) {
00265       addComment( "NoStartDate" ); //TODO: --> custom flag?
00266     }
00267   } else {
00268     QString s( "NoStartDate" );
00269     removeComment( s );
00270   }
00271   d->mHasStartDate = f;
00272   updated();
00273 }
00274 
00275 KDateTime Todo::dtStart() const
00276 {
00277   return dtStart( false );
00278 }
00279 
00280 KDateTime Todo::dtStart( bool first ) const
00281 {
00282   if ( !hasStartDate() ) {
00283     return KDateTime();
00284   }
00285   if ( recurs() && !first ) {
00286     return d->mDtRecurrence.addDays( dtDue( first ).daysTo( IncidenceBase::dtStart() ) );
00287   } else {
00288     return IncidenceBase::dtStart();
00289   }
00290 }
00291 
00292 void Todo::setDtStart( const KDateTime &dtStart )
00293 {
00294   // TODO: This doesn't seem right (rfc 2445/6 says, recurrence is calculated from the dtstart...)
00295   if ( recurs() ) {
00296     recurrence()->setStartDateTime( d->mDtDue );
00297     recurrence()->setAllDay( allDay() );
00298   }
00299   IncidenceBase::setDtStart( dtStart );
00300 }
00301 
00302 QString Todo::dtStartTimeStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const
00303 {
00304   if ( spec.isValid() ) {
00305 
00306     QString timeZone;
00307     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00308       timeZone = ' ' + spec.timeZone().name();
00309     }
00310 
00311     return KGlobal::locale()->formatTime( dtStart( first ).toTimeSpec( spec ).time(), shortfmt )
00312       + timeZone;
00313   } else {
00314     return KGlobal::locale()->formatTime( dtStart( first ).time(), shortfmt );
00315   }
00316 }
00317 
00318 QString Todo::dtStartTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const
00319 {
00320   return Incidence::dtStartTimeStr( shortfmt, spec );
00321 }
00322 
00323 QString Todo::dtStartDateStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const
00324 {
00325   if ( spec.isValid() ) {
00326 
00327     QString timeZone;
00328     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00329       timeZone = ' ' + spec.timeZone().name();
00330     }
00331 
00332     return
00333       KGlobal::locale()->formatDate( dtStart( first ).toTimeSpec( spec ).date(),
00334                                    ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) )
00335       + timeZone;
00336   } else {
00337     return
00338       KGlobal::locale()->formatDate( dtStart( first ).date(),
00339                                    ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00340   }
00341 }
00342 
00343 QString Todo::dtStartDateStr( bool shortfmt, const KDateTime::Spec &spec ) const
00344 {
00345   return Incidence::dtStartDateStr( shortfmt, spec );
00346 }
00347 
00348 QString Todo::dtStartStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const
00349 {
00350   if ( allDay() ) {
00351     return dtStartDateStr( shortfmt, spec );
00352   }
00353 
00354   if ( spec.isValid() ) {
00355 
00356     QString timeZone;
00357     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00358       timeZone = ' ' + spec.timeZone().name();
00359     }
00360 
00361     return
00362       KGlobal::locale()->formatDateTime( dtStart( first ).toTimeSpec( spec ).dateTime(),
00363                                        ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) )
00364       + timeZone;
00365   } else {
00366     return
00367       KGlobal::locale()->formatDateTime( dtStart( first ).dateTime(),
00368                                        ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00369   }
00370 }
00371 
00372 QString Todo::dtStartStr( bool shortfmt, const KDateTime::Spec &spec ) const
00373 {
00374   return Incidence::dtStartStr( shortfmt, spec );
00375 }
00376 
00377 bool Todo::isCompleted() const
00378 {
00379   if ( d->mPercentComplete == 100 ) {
00380     return true;
00381   } else {
00382     return false;
00383   }
00384 }
00385 
00386 void Todo::setCompleted( bool completed )
00387 {
00388   if ( completed ) {
00389     d->mPercentComplete = 100;
00390   } else {
00391     d->mPercentComplete = 0;
00392     d->mHasCompletedDate = false;
00393     d->mCompleted = KDateTime();
00394   }
00395   updated();
00396 }
00397 
00398 KDateTime Todo::completed() const
00399 {
00400   if ( hasCompletedDate() ) {
00401     return d->mCompleted;
00402   } else {
00403     return KDateTime();
00404   }
00405 }
00406 
00407 QString Todo::completedStr( bool shortfmt ) const
00408 {
00409   return
00410     KGlobal::locale()->formatDateTime( d->mCompleted.dateTime(),
00411                                        ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00412 }
00413 
00414 void Todo::setCompleted( const KDateTime &completed )
00415 {
00416   if ( !d->recurTodo( this ) ) {
00417     d->mHasCompletedDate = true;
00418     d->mPercentComplete = 100;
00419     d->mCompleted = completed.toUtc();
00420   }
00421   updated();
00422 }
00423 
00424 bool Todo::hasCompletedDate() const
00425 {
00426   return d->mHasCompletedDate;
00427 }
00428 
00429 int Todo::percentComplete() const
00430 {
00431   return d->mPercentComplete;
00432 }
00433 
00434 void Todo::setPercentComplete( int percent )
00435 {
00436   //TODO: (?) assert percent between 0 and 100, inclusive
00437   d->mPercentComplete = percent;
00438   if ( percent != 100 ) {
00439     d->mHasCompletedDate = false;
00440   }
00441   updated();
00442 }
00443 
00444 void Todo::shiftTimes( const KDateTime::Spec &oldSpec,
00445                        const KDateTime::Spec &newSpec )
00446 {
00447   Incidence::shiftTimes( oldSpec, newSpec );
00448   d->mDtDue = d->mDtDue.toTimeSpec( oldSpec );
00449   d->mDtDue.setTimeSpec( newSpec );
00450   if ( recurs() ) {
00451     d->mDtRecurrence = d->mDtRecurrence.toTimeSpec( oldSpec );
00452     d->mDtRecurrence.setTimeSpec( newSpec );
00453   }
00454   if ( d->mHasCompletedDate ) {
00455     d->mCompleted = d->mCompleted.toTimeSpec( oldSpec );
00456     d->mCompleted.setTimeSpec( newSpec );
00457   }
00458 }
00459 
00460 void Todo::setDtRecurrence( const KDateTime &dt )
00461 {
00462   d->mDtRecurrence = dt;
00463 }
00464 
00465 KDateTime Todo::dtRecurrence() const
00466 {
00467   return d->mDtRecurrence.isValid() ? d->mDtRecurrence : d->mDtDue;
00468 }
00469 
00470 bool Todo::recursOn( const QDate &date, const KDateTime::Spec &timeSpec ) const
00471 {
00472   QDate today = QDate::currentDate();
00473   return
00474     Incidence::recursOn( date, timeSpec ) &&
00475     !( date < today && d->mDtRecurrence.date() < today &&
00476        d->mDtRecurrence > recurrence()->startDateTime() );
00477 }
00478 
00479 bool Todo::isOverdue() const
00480 {
00481   if ( !dtDue().isValid() ) {
00482     return false; // if it's never due, it can't be overdue
00483   }
00484 
00485   bool inPast = allDay() ?
00486                 dtDue().date() < QDate::currentDate() :
00487                 dtDue() < KDateTime::currentUtcDateTime();
00488   return inPast && !isCompleted();
00489 }
00490 
00491 KDateTime Todo::endDateRecurrenceBase() const
00492 {
00493   return dtDue();
00494 }
00495 
00496 //@cond PRIVATE
00497 bool Todo::Private::recurTodo( Todo *todo )
00498 {
00499   if ( todo->recurs() ) {
00500     Recurrence *r = todo->recurrence();
00501     KDateTime endDateTime = r->endDateTime();
00502     KDateTime nextDate = r->getNextDateTime( todo->dtDue() );
00503 
00504     if ( ( r->duration() == -1 ||
00505            ( nextDate.isValid() && endDateTime.isValid() &&
00506              nextDate <= endDateTime ) ) ) {
00507 
00508       while ( !todo->recursAt( nextDate ) ||
00509               nextDate <= KDateTime::currentUtcDateTime() ) {
00510 
00511         if ( !nextDate.isValid() || nextDate > endDateTime ) {
00512           return false;
00513         }
00514 
00515         nextDate = r->getNextDateTime( nextDate );
00516       }
00517 
00518       todo->setDtDue( nextDate );
00519       todo->setCompleted( false );
00520       todo->setRevision( todo->revision() + 1 );
00521 
00522       return true;
00523     }
00524   }
00525 
00526   return false;
00527 }
00528 //@endcond

KCal Library

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal