libkcal

todo.cpp
00001 /*
00002     This file is part of libkcal.
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 */
00021 
00022 #include <kglobal.h>
00023 #include <klocale.h>
00024 #include <kdebug.h>
00025 
00026 #include "todo.h"
00027 
00028 using namespace KCal;
00029 
00030 Todo::Todo()
00031 {
00032   mHasDueDate = false;
00033   mHasStartDate = false;
00034 
00035   mHasCompletedDate = false;
00036   mPercentComplete = 0;
00037 }
00038 
00039 Todo::Todo(const Todo &t) : Incidence(t)
00040 {
00041   mDtDue = t.mDtDue;
00042   mHasDueDate = t.mHasDueDate;
00043   mHasStartDate = t.mHasStartDate;
00044   mCompleted = t.mCompleted;
00045   mHasCompletedDate = t.mHasCompletedDate;
00046   mPercentComplete = t.mPercentComplete;
00047   mDtRecurrence = t.mDtRecurrence;
00048 }
00049 
00050 Todo::~Todo()
00051 {
00052 }
00053 
00054 Todo *Todo::clone()
00055 {
00056   return new Todo( *this );
00057 }
00058 
00059 
00060 Todo& Todo::operator=( const Todo &t )
00061 {
00062   Incidence::operator=( t );
00063   mDtDue = t.mDtDue;
00064   mHasDueDate = t.mHasDueDate;
00065   mHasStartDate = t.mHasStartDate;
00066   mCompleted = t.mCompleted;
00067   mHasCompletedDate = t.mHasCompletedDate;
00068   mPercentComplete = t.mPercentComplete;
00069   mDtRecurrence = t.mDtRecurrence;
00070   return *this;
00071 }
00072 
00073 bool Todo::operator==( const Todo& t2 ) const
00074 {
00075     return
00076         static_cast<const Incidence&>(*this) == static_cast<const Incidence&>(t2) &&
00077         dtDue() == t2.dtDue() &&
00078         hasDueDate() == t2.hasDueDate() &&
00079         hasStartDate() == t2.hasStartDate() &&
00080         completed() == t2.completed() &&
00081         hasCompletedDate() == t2.hasCompletedDate() &&
00082         percentComplete() == t2.percentComplete();
00083 }
00084 
00085 void Todo::setDtDue(const TQDateTime &dtDue, bool first )
00086 {
00087   //int diffsecs = mDtDue.secsTo(dtDue);
00088 
00089   /*if (mReadOnly) return;
00090   const Alarm::List& alarms = alarms();
00091   for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) {
00092     if (alarm->enabled()) {
00093       alarm->setTime(alarm->time().addSecs(diffsecs));
00094     }
00095   }*/
00096   if( doesRecur() && !first ) {
00097     mDtRecurrence = dtDue;
00098   } else {
00099     mDtDue = dtDue;
00100     // TODO: This doesn't seem right...
00101     recurrence()->setStartDateTime( dtDue );
00102     recurrence()->setFloats( doesFloat() );
00103   }
00104 
00105   if ( doesRecur() && dtDue < recurrence()->startDateTime() )
00106     setDtStart( dtDue );
00107 
00108   //kdDebug(5800) << "setDtDue says date is " << mDtDue.toString() << endl;
00109 
00110   /*const Alarm::List& alarms = alarms();
00111   for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next())
00112     alarm->setAlarmStart(mDtDue);*/
00113 
00114   updated();
00115 }
00116 
00117 TQDateTime Todo::dtDue( bool first ) const
00118 {
00119   if ( doesRecur() && !first && mDtRecurrence.isValid() ) {
00120     return mDtRecurrence;
00121   } else if ( hasDueDate() ) {
00122     return mDtDue;
00123   } else {
00124     return TQDateTime();
00125   }
00126 }
00127 
00128 TQString Todo::dtDueTimeStr() const
00129 {
00130   return KGlobal::locale()->formatTime( dtDue(!doesRecur()).time() );
00131 }
00132 
00133 TQString Todo::dtDueDateStr(bool shortfmt) const
00134 {
00135   return KGlobal::locale()->formatDate(dtDue( !doesRecur() ).date(),shortfmt);
00136 }
00137 
00138 // TODO: Add shortfmt param!!!
00139 TQString Todo::dtDueStr() const
00140 {
00141   return KGlobal::locale()->formatDateTime( dtDue( !doesRecur() ) );
00142 }
00143 
00144 bool Todo::hasDueDate() const
00145 {
00146   return mHasDueDate;
00147 }
00148 
00149 void Todo::setHasDueDate(bool f)
00150 {
00151   if (mReadOnly) return;
00152   mHasDueDate = f;
00153   updated();
00154 }
00155 
00156 
00157 bool Todo::hasStartDate() const
00158 {
00159   return mHasStartDate;
00160 }
00161 
00162 void Todo::setHasStartDate(bool f)
00163 {
00164   if (mReadOnly) return;
00165 
00166   if ( doesRecur() && !f ) {
00167     if ( !comments().grep("NoStartDate").count() )
00168       addComment("NoStartDate"); //TODO: --> custom flag?
00169   } else {
00170     TQString s("NoStartDate");
00171     removeComment(s);
00172   }
00173   mHasStartDate = f;
00174   updated();
00175 }
00176 
00177 TQDateTime Todo::dtStart( bool first ) const
00178 {
00179   if ( doesRecur() && !first ) {
00180     TQDateTime dt = mDtRecurrence.addDays( dtDue( true ).daysTo( IncidenceBase::dtStart() ) );
00181 
00182     // We want the dtStart's time, not dtDue's
00183     dt.setTime( IncidenceBase::dtStart().time() );
00184     return dt;
00185   } else if ( hasStartDate() ) {
00186     return IncidenceBase::dtStart();
00187   } else {
00188     return TQDateTime();
00189   }
00190 }
00191 
00192 void Todo::setDtStart( const TQDateTime &dtStart )
00193 {
00194   // TODO: This doesn't seem right (rfc 2445/6 says, recurrence is calculated from the dtstart...)
00195   if ( doesRecur() ) {
00196     recurrence()->setStartDateTime( mDtDue );
00197     recurrence()->setFloats( doesFloat() );
00198   }
00199   IncidenceBase::setDtStart( dtStart );
00200 }
00201 
00202 TQString Todo::dtStartTimeStr( bool first ) const
00203 {
00204   return KGlobal::locale()->formatTime(dtStart(first).time());
00205 }
00206 
00207 TQString Todo::dtStartDateStr(bool shortfmt, bool first) const
00208 {
00209   return KGlobal::locale()->formatDate(dtStart(first).date(),shortfmt);
00210 }
00211 
00212 TQString Todo::dtStartStr(bool first) const
00213 {
00214   return KGlobal::locale()->formatDateTime(dtStart(first));
00215 }
00216 
00217 bool Todo::isCompleted() const
00218 {
00219   if (mPercentComplete == 100) return true;
00220   else return false;
00221 }
00222 
00223 void Todo::setCompleted(bool completed)
00224 {
00225   if (completed)
00226     mPercentComplete = 100;
00227   else {
00228     mPercentComplete = 0;
00229     mHasCompletedDate = false;
00230     mCompleted = TQDateTime();
00231   }
00232   updated();
00233 }
00234 
00235 TQDateTime Todo::completed() const
00236 {
00237   if ( hasCompletedDate() )
00238     return mCompleted;
00239   else
00240     return TQDateTime();
00241 }
00242 
00243 TQString Todo::completedStr() const
00244 {
00245   return KGlobal::locale()->formatDateTime(mCompleted);
00246 }
00247 
00248 void Todo::setCompleted(const TQDateTime &completed)
00249 {
00250   if( !recurTodo() ) {
00251     mHasCompletedDate = true;
00252     mPercentComplete = 100;
00253     mCompleted = completed;
00254   }
00255   updated();
00256 }
00257 
00258 bool Todo::hasCompletedDate() const
00259 {
00260   return mHasCompletedDate;
00261 }
00262 
00263 int Todo::percentComplete() const
00264 {
00265   return mPercentComplete;
00266 }
00267 
00268 void Todo::setPercentComplete( int v )
00269 {
00270   mPercentComplete = v;
00271   if ( v != 100 ) {
00272     mHasCompletedDate = false;
00273     mCompleted = TQDateTime();
00274   }
00275 
00276   updated();
00277 }
00278 
00279 void Todo::setDtRecurrence( const TQDateTime &dt )
00280 {
00281   mDtRecurrence = dt;
00282 }
00283 
00284 TQDateTime Todo::dtRecurrence() const
00285 {
00286   return mDtRecurrence.isValid() ? mDtRecurrence : mDtDue;
00287 }
00288 
00289 bool Todo::recursOn( const TQDate &date ) const
00290 {
00291   TQDate today = TQDate::currentDate();
00292   return ( Incidence::recursOn(date) &&
00293            !( date < today && mDtRecurrence.date() < today &&
00294               mDtRecurrence > recurrence()->startDateTime() ) );
00295 }
00296 
00297 bool Todo::recurTodo()
00298 {
00299   if ( doesRecur() ) {
00300     Recurrence *r = recurrence();
00301     TQDateTime endDateTime = r->endDateTime();
00302     TQDateTime nextDate = r->getNextDateTime( dtDue() );
00303 
00304     if ( ( r->duration() == -1 || ( nextDate.isValid() && endDateTime.isValid()
00305            && nextDate <= endDateTime ) ) ) {
00306 
00307       while ( !recursAt( nextDate ) || nextDate <= TQDateTime::currentDateTime() ) {
00308 
00309         if ( !nextDate.isValid() ||
00310              ( nextDate > endDateTime && r->duration() != -1 ) ) {
00311           return false;
00312         }
00313 
00314         nextDate = r->getNextDateTime( nextDate );
00315       }
00316 
00317       setDtDue( nextDate );
00318       setCompleted( false );
00319       setRevision( revision() + 1 );
00320 
00321       return true;
00322     }
00323   }
00324 
00325   return false;
00326 }
00327 
00328 bool Todo::isOverdue() const
00329 {
00330   bool inPast = doesFloat() ? dtDue().date() < TQDate::currentDate()
00331                             : dtDue() < TQDateTime::currentDateTime();
00332   return ( inPast && !isCompleted() );
00333 }