• Skip to content
  • Skip to link menu
KDE 4.3 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 #include "incidenceformatter.h"
00034 
00035 #include <kglobal.h>
00036 #include <klocale.h>
00037 #include <kdebug.h>
00038 #include <ksystemtimezone.h>
00039 
00040 using namespace KCal;
00041 
00046 //@cond PRIVATE
00047 class KCal::Todo::Private
00048 {
00049   public:
00050     Private()
00051       : mPercentComplete( 0 ),
00052         mHasDueDate( false ),
00053         mHasStartDate( false ),
00054         mHasCompletedDate( false )
00055     {}
00056     Private( const KCal::Todo::Private &other )
00057     { init( other ); }
00058 
00059     void init( const KCal::Todo::Private &other );
00060 
00061     KDateTime mDtDue;        // to-do due date (if there is one)
00062                              // ALSO the first occurrence of a recurring to-do
00063     KDateTime mDtRecurrence; // next occurrence (for recurring to-dos)
00064     KDateTime mCompleted;    // to-do completion date (if it has been completed)
00065     int mPercentComplete;    // to-do percent complete [0,100]
00066     bool mHasDueDate;        // true if the to-do has a due date
00067     bool mHasStartDate;      // true if the to-do has a starting date
00068     bool mHasCompletedDate;  // true if the to-do has a completion date
00069 
00073     bool recurTodo( Todo *todo );
00074 };
00075 
00076 void KCal::Todo::Private::init( const KCal::Todo::Private &other )
00077 {
00078   mDtDue = other.mDtDue;
00079   mDtRecurrence = other.mDtRecurrence;
00080   mCompleted = other.mCompleted;
00081   mPercentComplete = other.mPercentComplete;
00082   mHasDueDate = other.mHasDueDate;
00083   mHasStartDate = other.mHasStartDate;
00084   mHasCompletedDate = other.mHasCompletedDate;
00085 }
00086 
00087 //@endcond
00088 
00089 Todo::Todo()
00090   : d( new KCal::Todo::Private )
00091 {
00092 }
00093 
00094 Todo::Todo( const Todo &other )
00095   : Incidence( other ),
00096     d( new KCal::Todo::Private( *other.d ) )
00097 {
00098 }
00099 
00100 Todo::~Todo()
00101 {
00102   delete d;
00103 }
00104 
00105 Todo *Todo::clone()
00106 {
00107   return new Todo( *this );
00108 }
00109 
00110 Todo &Todo::operator=( const Todo &other )
00111 {
00112   // check for self assignment
00113   if ( &other == this ) {
00114     return *this;
00115   }
00116 
00117   Incidence::operator=( other );
00118   d->init( *other.d );
00119   return *this;
00120 }
00121 
00122 bool Todo::operator==( const Todo &todo ) const
00123 {
00124   return
00125     Incidence::operator==( todo ) &&
00126     dtDue() == todo.dtDue() &&
00127     hasDueDate() == todo.hasDueDate() &&
00128     hasStartDate() == todo.hasStartDate() &&
00129     completed() == todo.completed() &&
00130     hasCompletedDate() == todo.hasCompletedDate() &&
00131     percentComplete() == todo.percentComplete();
00132 }
00133 
00134 QByteArray Todo::type() const
00135 {
00136   return "Todo";
00137 }
00138 
00139 void Todo::setDtDue( const KDateTime &dtDue, bool first )
00140 {
00141   //int diffsecs = d->mDtDue.secsTo(dtDue);
00142 
00143   /*if (mReadOnly) return;
00144   const Alarm::List& alarms = alarms();
00145   for (Alarm *alarm = alarms.first(); alarm; alarm = alarms.next()) {
00146     if (alarm->enabled()) {
00147       alarm->setTime(alarm->time().addSecs(diffsecs));
00148     }
00149   }*/
00150   if ( recurs() && !first ) {
00151     d->mDtRecurrence = dtDue;
00152   } else {
00153     d->mDtDue = dtDue;
00154     // TODO: This doesn't seem right...
00155     recurrence()->setStartDateTime( dtDue );
00156     recurrence()->setAllDay( allDay() );
00157   }
00158 
00159   if ( recurs() && dtDue < recurrence()->startDateTime() ) {
00160     setDtStart( dtDue );
00161   }
00162 
00163   /*const Alarm::List& alarms = alarms();
00164   for (Alarm *alarm = alarms.first(); alarm; alarm = alarms.next())
00165     alarm->setAlarmStart(d->mDtDue);*/
00166 
00167   updated();
00168 }
00169 
00170 KDateTime Todo::dtDue( bool first ) const
00171 {
00172   if ( !hasDueDate() ) {
00173     return KDateTime();
00174   }
00175   if ( recurs() && !first && d->mDtRecurrence.isValid() ) {
00176     return d->mDtRecurrence;
00177   }
00178 
00179   return d->mDtDue;
00180 }
00181 
00182 QString Todo::dtDueTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const
00183 {
00184   if ( spec.isValid() ) {
00185 
00186     QString timeZone;
00187     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00188       timeZone = ' ' + spec.timeZone().name();
00189     }
00190 
00191     return KGlobal::locale()->formatTime(
00192       dtDue( !recurs() ).toTimeSpec( spec ).time(), !shortfmt ) + timeZone;
00193   } else {
00194     return KGlobal::locale()->formatTime(
00195       dtDue( !recurs() ).time(), !shortfmt );
00196   }
00197 }
00198 
00199 QString Todo::dtDueDateStr( bool shortfmt, const KDateTime::Spec &spec ) const
00200 {
00201   if ( spec.isValid() ) {
00202 
00203     QString timeZone;
00204     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00205       timeZone = ' ' + spec.timeZone().name();
00206     }
00207 
00208     return KGlobal::locale()->formatDate(
00209       dtDue( !recurs() ).toTimeSpec( spec ).date(),
00210       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone;
00211   } else {
00212     return KGlobal::locale()->formatDate(
00213       dtDue( !recurs() ).date(),
00214       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00215   }
00216 }
00217 
00218 QString Todo::dtDueStr( bool shortfmt, const KDateTime::Spec &spec ) const
00219 {
00220   if ( allDay() ) {
00221     return IncidenceFormatter::dateToString( dtDue(), shortfmt, spec );
00222   }
00223 
00224   if ( spec.isValid() ) {
00225 
00226     QString timeZone;
00227     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00228       timeZone = ' ' + spec.timeZone().name();
00229     }
00230 
00231     return KGlobal::locale()->formatDateTime(
00232       dtDue( !recurs() ).toTimeSpec( spec ).dateTime(),
00233       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone;
00234   } else {
00235     return  KGlobal::locale()->formatDateTime(
00236       dtDue( !recurs() ).dateTime(),
00237       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00238   }
00239 }
00240 
00241 bool Todo::hasDueDate() const
00242 {
00243   return d->mHasDueDate;
00244 }
00245 
00246 void Todo::setHasDueDate( bool f )
00247 {
00248   if ( mReadOnly ) {
00249     return;
00250   }
00251   d->mHasDueDate = f;
00252   updated();
00253 }
00254 
00255 bool Todo::hasStartDate() const
00256 {
00257   return d->mHasStartDate;
00258 }
00259 
00260 void Todo::setHasStartDate( bool f )
00261 {
00262   if ( mReadOnly ) {
00263     return;
00264   }
00265 
00266   if ( recurs() && !f ) {
00267     if ( !comments().filter( "NoStartDate" ).count() ) {
00268       addComment( "NoStartDate" ); //TODO: --> custom flag?
00269     }
00270   } else {
00271     QString s( "NoStartDate" );
00272     removeComment( s );
00273   }
00274   d->mHasStartDate = f;
00275   updated();
00276 }
00277 
00278 KDateTime Todo::dtStart() const
00279 {
00280   return dtStart( false );
00281 }
00282 
00283 KDateTime Todo::dtStart( bool first ) const
00284 {
00285   if ( !hasStartDate() ) {
00286     return KDateTime();
00287   }
00288   if ( recurs() && !first ) {
00289     return d->mDtRecurrence.addDays( dtDue( true ).daysTo( IncidenceBase::dtStart() ) );
00290   } else {
00291     return IncidenceBase::dtStart();
00292   }
00293 }
00294 
00295 void Todo::setDtStart( const KDateTime &dtStart )
00296 {
00297   // TODO: This doesn't seem right (rfc 2445/6 says, recurrence is calculated from the dtstart...)
00298   if ( recurs() ) {
00299     recurrence()->setStartDateTime( d->mDtDue );
00300     recurrence()->setAllDay( allDay() );
00301   }
00302   IncidenceBase::setDtStart( dtStart );
00303 }
00304 
00305 QString Todo::dtStartTimeStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const
00306 {
00307   if ( spec.isValid() ) {
00308 
00309     QString timeZone;
00310     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00311       timeZone = ' ' + spec.timeZone().name();
00312     }
00313 
00314     return KGlobal::locale()->formatTime(
00315       dtStart( first ).toTimeSpec( spec ).time(), !shortfmt ) + timeZone;
00316   } else {
00317     return KGlobal::locale()->formatTime(
00318       dtStart( first ).time(), !shortfmt );
00319   }
00320 }
00321 
00322 QString Todo::dtStartTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const
00323 {
00324   return IncidenceFormatter::timeToString( dtStart(), shortfmt, spec );
00325 }
00326 
00327 QString Todo::dtStartDateStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const
00328 {
00329   if ( spec.isValid() ) {
00330 
00331     QString timeZone;
00332     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00333       timeZone = ' ' + spec.timeZone().name();
00334     }
00335 
00336     return KGlobal::locale()->formatDate(
00337       dtStart( first ).toTimeSpec( spec ).date(),
00338       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone;
00339   } else {
00340     return KGlobal::locale()->formatDate(
00341       dtStart( first ).date(),
00342       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00343   }
00344 }
00345 
00346 QString Todo::dtStartDateStr( bool shortfmt, const KDateTime::Spec &spec ) const
00347 {
00348   return IncidenceFormatter::dateToString( dtStart(), shortfmt, spec );
00349 }
00350 
00351 QString Todo::dtStartStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const
00352 {
00353   if ( allDay() ) {
00354     return IncidenceFormatter::dateToString( dtStart(), shortfmt, spec );
00355   }
00356 
00357   if ( spec.isValid() ) {
00358 
00359     QString timeZone;
00360     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00361       timeZone = ' ' + spec.timeZone().name();
00362     }
00363 
00364     return KGlobal::locale()->formatDateTime(
00365       dtStart( first ).toTimeSpec( spec ).dateTime(),
00366       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone;
00367   } else {
00368     return KGlobal::locale()->formatDateTime(
00369       dtStart( first ).dateTime(),
00370       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00371   }
00372 }
00373 
00374 QString Todo::dtStartStr( bool shortfmt, const KDateTime::Spec &spec ) const
00375 {
00376   if ( allDay() ) {
00377     return IncidenceFormatter::dateToString( dtStart(), shortfmt, spec );
00378   }
00379 
00380   if ( spec.isValid() ) {
00381 
00382     QString timeZone;
00383     if ( spec.timeZone() != KSystemTimeZones::local() ) {
00384       timeZone = ' ' + spec.timeZone().name();
00385     }
00386 
00387     return KGlobal::locale()->formatDateTime(
00388       dtStart().toTimeSpec( spec ).dateTime(),
00389       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone;
00390   } else {
00391     return KGlobal::locale()->formatDateTime(
00392       dtStart().dateTime(),
00393       ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00394   }
00395 }
00396 
00397 bool Todo::isCompleted() const
00398 {
00399   if ( d->mPercentComplete == 100 ) {
00400     return true;
00401   } else {
00402     return false;
00403   }
00404 }
00405 
00406 void Todo::setCompleted( bool completed )
00407 {
00408   if ( completed ) {
00409     d->mPercentComplete = 100;
00410   } else {
00411     d->mPercentComplete = 0;
00412     d->mHasCompletedDate = false;
00413     d->mCompleted = KDateTime();
00414   }
00415   updated();
00416 }
00417 
00418 KDateTime Todo::completed() const
00419 {
00420   if ( hasCompletedDate() ) {
00421     return d->mCompleted;
00422   } else {
00423     return KDateTime();
00424   }
00425 }
00426 
00427 QString Todo::completedStr( bool shortfmt ) const
00428 {
00429   return
00430     KGlobal::locale()->formatDateTime( d->mCompleted.dateTime(),
00431                                        ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00432 }
00433 
00434 void Todo::setCompleted( const KDateTime &completed )
00435 {
00436   if ( !d->recurTodo( this ) ) {
00437     d->mHasCompletedDate = true;
00438     d->mPercentComplete = 100;
00439     d->mCompleted = completed.toUtc();
00440   }
00441   updated();
00442 }
00443 
00444 bool Todo::hasCompletedDate() const
00445 {
00446   return d->mHasCompletedDate;
00447 }
00448 
00449 int Todo::percentComplete() const
00450 {
00451   return d->mPercentComplete;
00452 }
00453 
00454 void Todo::setPercentComplete( int percent )
00455 {
00456   //TODO: (?) assert percent between 0 and 100, inclusive
00457   d->mPercentComplete = percent;
00458   if ( percent != 100 ) {
00459     d->mHasCompletedDate = false;
00460   }
00461   updated();
00462 }
00463 
00464 void Todo::shiftTimes( const KDateTime::Spec &oldSpec,
00465                        const KDateTime::Spec &newSpec )
00466 {
00467   Incidence::shiftTimes( oldSpec, newSpec );
00468   d->mDtDue = d->mDtDue.toTimeSpec( oldSpec );
00469   d->mDtDue.setTimeSpec( newSpec );
00470   if ( recurs() ) {
00471     d->mDtRecurrence = d->mDtRecurrence.toTimeSpec( oldSpec );
00472     d->mDtRecurrence.setTimeSpec( newSpec );
00473   }
00474   if ( d->mHasCompletedDate ) {
00475     d->mCompleted = d->mCompleted.toTimeSpec( oldSpec );
00476     d->mCompleted.setTimeSpec( newSpec );
00477   }
00478 }
00479 
00480 void Todo::setDtRecurrence( const KDateTime &dt )
00481 {
00482   d->mDtRecurrence = dt;
00483 }
00484 
00485 KDateTime Todo::dtRecurrence() const
00486 {
00487   return d->mDtRecurrence.isValid() ? d->mDtRecurrence : d->mDtDue;
00488 }
00489 
00490 bool Todo::recursOn( const QDate &date, const KDateTime::Spec &timeSpec ) const
00491 {
00492   QDate today = QDate::currentDate();
00493   return
00494     Incidence::recursOn( date, timeSpec ) &&
00495     !( date < today && d->mDtRecurrence.date() < today &&
00496        d->mDtRecurrence > recurrence()->startDateTime() );
00497 }
00498 
00499 bool Todo::isOverdue() const
00500 {
00501   if ( !dtDue().isValid() ) {
00502     return false; // if it's never due, it can't be overdue
00503   }
00504 
00505   bool inPast = allDay() ?
00506                 dtDue().date() < QDate::currentDate() :
00507                 dtDue() < KDateTime::currentUtcDateTime();
00508   return inPast && !isCompleted();
00509 }
00510 
00511 KDateTime Todo::endDateRecurrenceBase() const
00512 {
00513   return dtDue();
00514 }
00515 
00516 //@cond PRIVATE
00517 bool Todo::Private::recurTodo( Todo *todo )
00518 {
00519   if ( todo->recurs() ) {
00520     Recurrence *r = todo->recurrence();
00521     KDateTime endDateTime = r->endDateTime();
00522     KDateTime nextDate = r->getNextDateTime( todo->dtDue() );
00523 
00524     if ( ( r->duration() == -1 ||
00525            ( nextDate.isValid() && endDateTime.isValid() &&
00526              nextDate <= endDateTime ) ) ) {
00527 
00528       while ( !todo->recursAt( nextDate ) ||
00529               nextDate <= KDateTime::currentUtcDateTime() ) {
00530 
00531         if ( !nextDate.isValid() ||
00532              ( nextDate > endDateTime && r->duration() != -1 ) ) {
00533 
00534           return false;
00535         }
00536 
00537         nextDate = r->getNextDateTime( nextDate );
00538       }
00539 
00540       todo->setDtDue( nextDate );
00541       todo->setCompleted( false );
00542       todo->setRevision( todo->revision() + 1 );
00543 
00544       return true;
00545     }
00546   }
00547 
00548   return false;
00549 }
00550 //@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
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.1
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