KCal Library
todo.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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 : mDtDue( other.mDtDue ),
00057 mDtRecurrence( other.mDtRecurrence ),
00058 mCompleted( other.mCompleted ),
00059 mPercentComplete( other.mPercentComplete ),
00060 mHasDueDate( other.mHasDueDate ),
00061 mHasStartDate( other.mHasStartDate ),
00062 mHasCompletedDate( other.mHasCompletedDate )
00063 {}
00064
00065 KDateTime mDtDue;
00066
00067 KDateTime mDtRecurrence;
00068 KDateTime mCompleted;
00069 int mPercentComplete;
00070 bool mHasDueDate;
00071 bool mHasStartDate;
00072 bool mHasCompletedDate;
00073
00077 bool recurTodo( Todo *todo );
00078 };
00079
00080
00081 Todo::Todo()
00082 : d( new KCal::Todo::Private )
00083 {
00084 }
00085
00086 Todo::Todo( const Todo &other )
00087 : Incidence( other ), d( new KCal::Todo::Private( *other.d ) )
00088 {
00089 }
00090
00091 Todo::~Todo()
00092 {
00093 delete d;
00094 }
00095
00096 Todo *Todo::clone()
00097 {
00098 return new Todo( *this );
00099 }
00100
00101 bool Todo::operator==( const Todo &t2 ) const
00102 {
00103 return
00104 static_cast<const Incidence &>( *this ) == static_cast<const Incidence &>( t2 ) &&
00105 dtDue() == t2.dtDue() &&
00106 hasDueDate() == t2.hasDueDate() &&
00107 hasStartDate() == t2.hasStartDate() &&
00108 completed() == t2.completed() &&
00109 hasCompletedDate() == t2.hasCompletedDate() &&
00110 percentComplete() == t2.percentComplete();
00111 }
00112
00113 QByteArray Todo::type() const
00114 {
00115 return "Todo";
00116 }
00117
00118 void Todo::setDtDue( const KDateTime &dtDue, bool first )
00119 {
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 if ( recurs() && !first ) {
00130 d->mDtRecurrence = dtDue;
00131 } else {
00132 d->mDtDue = dtDue;
00133
00134 recurrence()->setStartDateTime( dtDue );
00135 recurrence()->setAllDay( allDay() );
00136 }
00137
00138 if ( recurs() && dtDue < recurrence()->startDateTime() ) {
00139 setDtStart( dtDue );
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 updated();
00149 }
00150
00151 KDateTime Todo::dtDue( bool first ) const
00152 {
00153 if ( recurs() && !first && d->mDtRecurrence.isValid() ) {
00154 return d->mDtRecurrence;
00155 }
00156
00157 return d->mDtDue;
00158 }
00159
00160 QString Todo::dtDueTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const
00161 {
00162 if ( spec.isValid() ) {
00163
00164 QString timeZone;
00165 if ( spec.timeZone() != KSystemTimeZones::local() ) {
00166 timeZone = ' ' + spec.timeZone().name();
00167 }
00168
00169 return KGlobal::locale()->formatTime( dtDue( !recurs() ).toTimeSpec( spec ).time(), shortfmt )
00170 + timeZone;
00171 } else {
00172 return KGlobal::locale()->formatTime( dtDue( !recurs() ).time(), shortfmt );
00173 }
00174 }
00175
00176 QString Todo::dtDueDateStr( bool shortfmt, const KDateTime::Spec &spec ) const
00177 {
00178 if ( spec.isValid() ) {
00179
00180 QString timeZone;
00181 if ( spec.timeZone() != KSystemTimeZones::local() ) {
00182 timeZone = ' ' + spec.timeZone().name();
00183 }
00184
00185 return KGlobal::locale()->formatDate(
00186 dtDue( !recurs() ).toTimeSpec( spec ).date(),
00187 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) )
00188 + timeZone;
00189 } else {
00190 return KGlobal::locale()->formatDate(
00191 dtDue( !recurs() ).date(),
00192 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00193 }
00194 }
00195
00196 QString Todo::dtDueStr( bool shortfmt, const KDateTime::Spec &spec ) const
00197 {
00198 if ( spec.isValid() ) {
00199
00200 QString timeZone;
00201 if ( spec.timeZone() != KSystemTimeZones::local() ) {
00202 timeZone = ' ' + spec.timeZone().name();
00203 }
00204
00205 return KGlobal::locale()->formatDateTime(
00206 dtDue( !recurs() ).toTimeSpec( spec ).dateTime(),
00207 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) )
00208 + timeZone;
00209 } else {
00210 return KGlobal::locale()->formatDateTime(
00211 dtDue( !recurs() ).dateTime(),
00212 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00213 }
00214 }
00215
00216 bool Todo::hasDueDate() const
00217 {
00218 return d->mHasDueDate;
00219 }
00220
00221 void Todo::setHasDueDate( bool f )
00222 {
00223 if ( mReadOnly ) {
00224 return;
00225 }
00226 d->mHasDueDate = f;
00227 updated();
00228 }
00229
00230 bool Todo::hasStartDate() const
00231 {
00232 return d->mHasStartDate;
00233 }
00234
00235 void Todo::setHasStartDate( bool f )
00236 {
00237 if ( mReadOnly ) {
00238 return;
00239 }
00240
00241 if ( recurs() && !f ) {
00242 if ( !comments().filter( "NoStartDate" ).count() ) {
00243 addComment( "NoStartDate" );
00244 }
00245 } else {
00246 QString s( "NoStartDate" );
00247 removeComment( s );
00248 }
00249 d->mHasStartDate = f;
00250 updated();
00251 }
00252
00253 KDateTime Todo::dtStart() const
00254 {
00255 return dtStart( false );
00256 }
00257
00258 KDateTime Todo::dtStart( bool first ) const
00259 {
00260 if ( recurs() && !first ) {
00261 return d->mDtRecurrence.addDays( dtDue( first ).daysTo( IncidenceBase::dtStart() ) );
00262 } else {
00263 return IncidenceBase::dtStart();
00264 }
00265 }
00266
00267 void Todo::setDtStart( const KDateTime &dtStart )
00268 {
00269
00270 if ( recurs() ) {
00271 recurrence()->setStartDateTime( d->mDtDue );
00272 recurrence()->setAllDay( allDay() );
00273 }
00274 IncidenceBase::setDtStart( dtStart );
00275 }
00276
00277 QString Todo::dtStartTimeStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const
00278 {
00279 if ( spec.isValid() ) {
00280
00281 QString timeZone;
00282 if ( spec.timeZone() != KSystemTimeZones::local() ) {
00283 timeZone = ' ' + spec.timeZone().name();
00284 }
00285
00286 return KGlobal::locale()->formatTime( dtStart( first ).toTimeSpec( spec ).time(), shortfmt )
00287 + timeZone;
00288 } else {
00289 return KGlobal::locale()->formatTime( dtStart( first ).time(), shortfmt );
00290 }
00291 }
00292
00293 QString Todo::dtStartTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const
00294 {
00295 return Incidence::dtStartTimeStr( shortfmt, spec );
00296 }
00297
00298 QString Todo::dtStartDateStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const
00299 {
00300 if ( spec.isValid() ) {
00301
00302 QString timeZone;
00303 if ( spec.timeZone() != KSystemTimeZones::local() ) {
00304 timeZone = ' ' + spec.timeZone().name();
00305 }
00306
00307 return
00308 KGlobal::locale()->formatDate( dtStart( first ).toTimeSpec( spec ).date(),
00309 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) )
00310 + timeZone;
00311 } else {
00312 return
00313 KGlobal::locale()->formatDate( dtStart( first ).date(),
00314 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00315 }
00316 }
00317
00318 QString Todo::dtStartDateStr( bool shortfmt, const KDateTime::Spec &spec ) const
00319 {
00320 return Incidence::dtStartDateStr( shortfmt, spec );
00321 }
00322
00323 QString Todo::dtStartStr( 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()->formatDateTime( dtStart( first ).toTimeSpec( spec ).dateTime(),
00334 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) )
00335 + timeZone;
00336 } else {
00337 return
00338 KGlobal::locale()->formatDateTime( dtStart( first ).dateTime(),
00339 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00340 }
00341 }
00342
00343 QString Todo::dtStartStr( bool shortfmt, const KDateTime::Spec &spec ) const
00344 {
00345 return Incidence::dtStartStr( shortfmt, spec );
00346 }
00347
00348 bool Todo::isCompleted() const
00349 {
00350 if ( d->mPercentComplete == 100 ) {
00351 return true;
00352 } else {
00353 return false;
00354 }
00355 }
00356
00357 void Todo::setCompleted( bool completed )
00358 {
00359 if ( completed ) {
00360 d->mPercentComplete = 100;
00361 } else {
00362 d->mPercentComplete = 0;
00363 d->mHasCompletedDate = false;
00364 d->mCompleted = KDateTime();
00365 }
00366 updated();
00367 }
00368
00369 KDateTime Todo::completed() const
00370 {
00371 if ( hasCompletedDate() ) {
00372 return d->mCompleted;
00373 } else {
00374 return KDateTime();
00375 }
00376 }
00377
00378 QString Todo::completedStr( bool shortfmt ) const
00379 {
00380 return
00381 KGlobal::locale()->formatDateTime( d->mCompleted.dateTime(),
00382 ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) );
00383 }
00384
00385 void Todo::setCompleted( const KDateTime &completed )
00386 {
00387 if ( !d->recurTodo( this ) ) {
00388 d->mHasCompletedDate = true;
00389 d->mPercentComplete = 100;
00390 d->mCompleted = completed.toUtc();
00391 }
00392 updated();
00393 }
00394
00395 bool Todo::hasCompletedDate() const
00396 {
00397 return d->mHasCompletedDate;
00398 }
00399
00400 int Todo::percentComplete() const
00401 {
00402 return d->mPercentComplete;
00403 }
00404
00405 void Todo::setPercentComplete( int percent )
00406 {
00407
00408 d->mPercentComplete = percent;
00409 if ( percent != 100 ) {
00410 d->mHasCompletedDate = false;
00411 }
00412 updated();
00413 }
00414
00415 void Todo::shiftTimes( const KDateTime::Spec &oldSpec,
00416 const KDateTime::Spec &newSpec )
00417 {
00418 Incidence::shiftTimes( oldSpec, newSpec );
00419 d->mDtDue = d->mDtDue.toTimeSpec( oldSpec );
00420 d->mDtDue.setTimeSpec( newSpec );
00421 if ( recurs() ) {
00422 d->mDtRecurrence = d->mDtRecurrence.toTimeSpec( oldSpec );
00423 d->mDtRecurrence.setTimeSpec( newSpec );
00424 }
00425 if ( d->mHasCompletedDate ) {
00426 d->mCompleted = d->mCompleted.toTimeSpec( oldSpec );
00427 d->mCompleted.setTimeSpec( newSpec );
00428 }
00429 }
00430
00431 void Todo::setDtRecurrence( const KDateTime &dt )
00432 {
00433 d->mDtRecurrence = dt;
00434 }
00435
00436 KDateTime Todo::dtRecurrence() const
00437 {
00438 return d->mDtRecurrence.isValid() ? d->mDtRecurrence : d->mDtDue;
00439 }
00440
00441 bool Todo::recursOn( const QDate &date, const KDateTime::Spec &timeSpec ) const
00442 {
00443 QDate today = QDate::currentDate();
00444 return
00445 Incidence::recursOn( date, timeSpec ) &&
00446 !( date < today && d->mDtRecurrence.date() < today &&
00447 d->mDtRecurrence > recurrence()->startDateTime() );
00448 }
00449
00450 bool Todo::isOverdue() const
00451 {
00452 bool inPast = allDay() ?
00453 dtDue().date() < QDate::currentDate() :
00454 dtDue() < KDateTime::currentUtcDateTime();
00455 return inPast && !isCompleted();
00456 }
00457
00458 KDateTime Todo::endDateRecurrenceBase() const
00459 {
00460 return dtDue();
00461 }
00462
00463
00464 bool Todo::Private::recurTodo( Todo *todo )
00465 {
00466 if ( todo->recurs() ) {
00467 Recurrence *r = todo->recurrence();
00468 KDateTime endDateTime = r->endDateTime();
00469 KDateTime nextDate = r->getNextDateTime( todo->dtDue() );
00470
00471 if ( ( r->duration() == -1 ||
00472 ( nextDate.isValid() && endDateTime.isValid() &&
00473 nextDate <= endDateTime ) ) ) {
00474
00475 while ( !todo->recursAt( nextDate ) ||
00476 nextDate <= KDateTime::currentUtcDateTime() ) {
00477
00478 if ( !nextDate.isValid() || nextDate > endDateTime ) {
00479 return false;
00480 }
00481
00482 nextDate = r->getNextDateTime( nextDate );
00483 }
00484
00485 todo->setDtDue( nextDate );
00486 todo->setCompleted( false );
00487 todo->setRevision( todo->revision() + 1 );
00488
00489 return true;
00490 }
00491 }
00492
00493 return false;
00494 }
00495