karm

task.cpp
00001 #include <tqcstring.h>
00002 #include <tqdatetime.h>
00003 #include <tqstring.h>
00004 #include <tqtimer.h>
00005 
00006 #include <kiconloader.h>
00007 
00008 #include "kapplication.h"       // kapp
00009 #include "kdebug.h"
00010 
00011 #include "event.h"
00012 
00013 #include "karmutility.h"
00014 #include "task.h"
00015 #include "taskview.h"
00016 #include "preferences.h"
00017 
00018 
00019 const int gSecondsPerMinute = 60;
00020 
00021 
00022 TQPtrVector<TQPixmap> *Task::icons = 0;
00023 
00024 Task::Task( const TQString& taskName, long minutes, long sessionTime,
00025             DesktopList desktops, TaskView *parent)
00026   : TQObject(), TQListViewItem(parent)
00027 { 
00028   init(taskName, minutes, sessionTime, desktops, 0);
00029 }
00030 
00031 Task::Task( const TQString& taskName, long minutes, long sessionTime,
00032             DesktopList desktops, Task *parent)
00033   : TQObject(), TQListViewItem(parent)
00034 {
00035   init(taskName, minutes, sessionTime, desktops, 0);
00036 }
00037 
00038 Task::Task( KCal::Todo* todo, TaskView* parent )
00039   : TQObject(), TQListViewItem( parent )
00040 {
00041   long minutes = 0;
00042   TQString name;
00043   long sessionTime = 0;
00044   int percent_complete = 0;
00045   DesktopList desktops;
00046 
00047   parseIncidence(todo, minutes, sessionTime, name, desktops, percent_complete);
00048   init(name, minutes, sessionTime, desktops, percent_complete);
00049 }
00050 
00051 void Task::init( const TQString& taskName, long minutes, long sessionTime,
00052                  DesktopList desktops, int percent_complete)
00053 {
00054   // If our parent is the taskview then connect our totalTimesChanged
00055   // signal to its receiver
00056   if ( ! parent() )
00057     connect( this, TQT_SIGNAL( totalTimesChanged ( long, long ) ),
00058              listView(), TQT_SLOT( taskTotalTimesChanged( long, long) ));
00059 
00060   connect( this, TQT_SIGNAL( deletingTask( Task* ) ),
00061            listView(), TQT_SLOT( deletingTask( Task* ) ));
00062 
00063   if (icons == 0) {
00064     icons = new TQPtrVector<TQPixmap>(8);
00065     KIconLoader kil("karm"); // always load icons from the KArm application
00066     for (int i=0; i<8; i++)
00067     {
00068       TQPixmap *icon = new TQPixmap();
00069       TQString name;
00070       name.sprintf("watch-%d.xpm",i);
00071       *icon = kil.loadIcon( name, KIcon::User );
00072       icons->insert(i,icon);
00073     }
00074   }
00075 
00076   _removing = false;
00077   _name = taskName.stripWhiteSpace();
00078   _lastStart = TQDateTime::currentDateTime();
00079   _totalTime = _time = minutes;
00080   _totalSessionTime = _sessionTime = sessionTime;
00081   _timer = new TQTimer(this);
00082   _desktops = desktops;
00083   connect(_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(updateActiveIcon()));
00084   setPixmap(1, UserIcon(TQString::fromLatin1("empty-watch.xpm")));
00085   _currentPic = 0;
00086   _percentcomplete = percent_complete;
00087 
00088   update();
00089   changeParentTotalTimes( _sessionTime, _time);
00090 }
00091 
00092 Task::~Task() {
00093   emit deletingTask(this);
00094   delete _timer;
00095 }
00096 
00097 void Task::setRunning( bool on, KarmStorage* storage, TQDateTime whenStarted, TQDateTime whenStopped  )
00098 // Sets a task running or stopped. If the task is to be stopped, whenStarted is not evaluated.
00099 // on=true if the task shall be started on=false if the task shall be stopped
00100 // This is the back-end, the front-end is StartTimerFor()
00101 {
00102   kdDebug(5970) << "Entering Task::setRunning " << "on=" << on << "whenStarted=" << whenStarted << " whenStopped=" << whenStopped << endl;
00103   if ( on ) 
00104   {
00105     if (!_timer->isActive()) 
00106     {
00107       _timer->start(1000);
00108       storage->startTimer(this);
00109       _currentPic=7;
00110       _lastStart = whenStarted;
00111       updateActiveIcon();
00112     }
00113   }
00114   else 
00115   {
00116     if (_timer->isActive()) 
00117     {
00118       _timer->stop();
00119       if ( ! _removing ) 
00120       {
00121         storage->stopTimer(this, whenStopped);
00122         setPixmap(1, UserIcon(TQString::fromLatin1("empty-watch.xpm")));
00123       }
00124     }
00125   }
00126 }
00127 
00128 void Task::setUid(TQString uid) {
00129   _uid = uid;
00130 }
00131 
00132 bool Task::isRunning() const
00133 {
00134   return _timer->isActive();
00135 }
00136 
00137 void Task::setName( const TQString& name, KarmStorage* storage )
00138 {
00139   kdDebug(5970) << "Task:setName: " << name << endl;
00140 
00141   TQString oldname = _name;
00142   if ( oldname != name ) {
00143     _name = name;
00144     storage->setName(this, oldname);
00145     update();
00146   }
00147 }
00148 
00149 void Task::setPercentComplete(const int percent, KarmStorage *storage)
00150 {
00151   kdDebug(5970) << "Task::setPercentComplete(" << percent << ", storage): "
00152     << _uid << endl;
00153 
00154   if (!percent)
00155     _percentcomplete = 0;
00156   else if (percent > 100)
00157     _percentcomplete = 100;
00158   else if (percent < 0)
00159     _percentcomplete = 0;
00160   else
00161     _percentcomplete = percent;
00162 
00163   if (isRunning() && _percentcomplete==100) taskView()->stopTimerFor(this);
00164 
00165   setPixmapProgress();
00166 
00167   // When parent marked as complete, mark all children as complete as well.
00168   // Complete tasks are not displayed in the task view, so if a parent is
00169   // marked as complete and some of the children are not, then we get an error
00170   // message.  KArm actually keep chugging along in this case and displays the
00171   // child tasks just fine, so an alternative solution is to remove that error
00172   // message (from KarmStorage::load).  But I think it makes more sense that
00173   // if you mark a parent task as complete, then all children should be
00174   // complete as well.
00175   //
00176   // This behavior is consistent with KOrganizer (as of 2003-09-24).
00177   if (_percentcomplete == 100)
00178   {
00179     for (Task* child= this->firstChild(); child; child = child->nextSibling())
00180       child->setPercentComplete(_percentcomplete, storage);
00181   }
00182 }
00183 
00184 void Task::setPixmapProgress()
00185 {
00186   TQPixmap icon ;
00187   if (_percentcomplete >= 100)
00188     icon = UserIcon("task-complete.xpm");
00189   else
00190     icon = UserIcon("task-incomplete.xpm");
00191   setPixmap(0, icon);
00192 }
00193 
00194 bool Task::isComplete() { return _percentcomplete == 100; }
00195 
00196 void Task::removeFromView()
00197 {
00198   while ( Task* child = firstChild() )
00199     child->removeFromView();
00200   delete this;
00201 }
00202 
00203 void Task::setDesktopList ( DesktopList desktopList )
00204 {
00205   _desktops = desktopList;
00206 }
00207 
00208 void Task::changeTime( long minutes, KarmStorage* storage )
00209 {
00210   changeTimes( minutes, minutes, storage); 
00211 }
00212 
00213 void Task::changeTimes( long minutesSession, long minutes, KarmStorage* storage)
00214 {
00215   if( minutesSession != 0 || minutes != 0) 
00216   {
00217     _sessionTime += minutesSession;
00218     _time += minutes;
00219     if ( storage ) storage->changeTime(this, minutes * gSecondsPerMinute);
00220     changeTotalTimes( minutesSession, minutes );
00221   }
00222 }
00223 
00224 void Task::changeTotalTimes( long minutesSession, long minutes )
00225 {
00226   kdDebug(5970)
00227     << "Task::changeTotalTimes(" << minutesSession << ", "
00228     << minutes << ") for " << name() << endl;
00229 
00230   _totalSessionTime += minutesSession;
00231   _totalTime += minutes;
00232   update();
00233   changeParentTotalTimes( minutesSession, minutes );
00234 }
00235 
00236 void Task::resetTimes()
00237 {
00238   _totalSessionTime -= _sessionTime;
00239   _totalTime -= _time;
00240   changeParentTotalTimes( -_sessionTime, -_time);
00241   _sessionTime = 0;
00242   _time = 0;
00243   update();
00244 }
00245 
00246 void Task::changeParentTotalTimes( long minutesSession, long minutes )
00247 {
00248   //kdDebug(5970)
00249   //  << "Task::changeParentTotalTimes(" << minutesSession << ", "
00250   //  << minutes << ") for " << name() << endl;
00251 
00252   if ( isRoot() )
00253     emit totalTimesChanged( minutesSession, minutes );
00254   else
00255     parent()->changeTotalTimes( minutesSession, minutes );
00256 }
00257 
00258 bool Task::remove( TQPtrList<Task>& activeTasks, KarmStorage* storage)
00259 {
00260   kdDebug(5970) << "Task::remove: " << _name << endl;
00261 
00262   bool ok = true;
00263 
00264   _removing = true;
00265   storage->removeTask(this);
00266   if( isRunning() ) setRunning( false, storage );
00267 
00268   for (Task* child = this->firstChild(); child; child = child->nextSibling())
00269   {
00270     if (child->isRunning())
00271       child->setRunning(false, storage);
00272     child->remove(activeTasks, storage);
00273   }
00274 
00275   changeParentTotalTimes( -_sessionTime, -_time);
00276 
00277   _removing = false;
00278 
00279   return ok;
00280 }
00281 
00282 void Task::updateActiveIcon()
00283 {
00284   _currentPic = (_currentPic+1) % 8;
00285   setPixmap(1, *(*icons)[_currentPic]);
00286 }
00287 
00288 TQString Task::fullName() const
00289 {
00290   if (isRoot())
00291     return name();
00292   else
00293     return parent()->fullName() + TQString::fromLatin1("/") + name();
00294 }
00295 
00296 KCal::Todo* Task::asTodo(KCal::Todo* todo) const
00297 {
00298 
00299   Q_ASSERT( todo != NULL );
00300 
00301   kdDebug(5970) << "Task::asTodo: name() = '" << name() << "'" << endl;
00302   todo->setSummary( name() );
00303 
00304   // Note: if the date start is empty, the KOrganizer GUI will have the
00305   // checkbox blank, but will prefill the todo's starting datetime to the
00306   // time the file is opened.
00307   // todo->setDtStart( current );
00308 
00309   todo->setCustomProperty( kapp->instanceName(),
00310       TQCString( "totalTaskTime" ), TQString::number( _time ) );
00311   todo->setCustomProperty( kapp->instanceName(),
00312       TQCString( "totalSessionTime" ), TQString::number( _sessionTime) );
00313 
00314   if (getDesktopStr().isEmpty())
00315     todo->removeCustomProperty(kapp->instanceName(), TQCString("desktopList"));
00316   else
00317     todo->setCustomProperty( kapp->instanceName(),
00318         TQCString( "desktopList" ), getDesktopStr() );
00319 
00320   todo->setOrganizer( Preferences::instance()->userRealName() );
00321 
00322   todo->setPercentComplete(_percentcomplete);
00323 
00324   return todo;
00325 }
00326 
00327 bool Task::parseIncidence( KCal::Incidence* incident, long& minutes,
00328     long& sessionMinutes, TQString& name, DesktopList& desktops,
00329     int& percent_complete )
00330 {
00331   bool ok;
00332 
00333   name = incident->summary();
00334   _uid = incident->uid();
00335 
00336   _comment = incident->description();
00337 
00338   ok = false;
00339   minutes = incident->customProperty( kapp->instanceName(),
00340       TQCString( "totalTaskTime" )).toInt( &ok );
00341   if ( !ok )
00342     minutes = 0;
00343 
00344   ok = false;
00345   sessionMinutes = incident->customProperty( kapp->instanceName(),
00346       TQCString( "totalSessionTime" )).toInt( &ok );
00347   if ( !ok )
00348     sessionMinutes = 0;
00349 
00350   TQString desktopList = incident->customProperty( kapp->instanceName(),
00351       TQCString( "desktopList" ) );
00352   TQStringList desktopStrList = TQStringList::split( TQString::fromLatin1(","),
00353       desktopList );
00354   desktops.clear();
00355 
00356   for ( TQStringList::iterator iter = desktopStrList.begin();
00357         iter != desktopStrList.end();
00358         ++iter ) {
00359     int desktopInt = (*iter).toInt( &ok );
00360     if ( ok ) {
00361       desktops.push_back( desktopInt );
00362     }
00363   }
00364 
00365   percent_complete = static_cast<KCal::Todo*>(incident)->percentComplete();
00366 
00367   //kdDebug(5970) << "Task::parseIncidence: "
00368   //  << name << ", Minutes: " << minutes
00369   //  <<  ", desktop: " << desktopList << endl;
00370 
00371   return true;
00372 }
00373 
00374 TQString Task::getDesktopStr() const
00375 {
00376   if ( _desktops.empty() )
00377     return TQString();
00378 
00379   TQString desktopstr;
00380   for ( DesktopList::const_iterator iter = _desktops.begin();
00381         iter != _desktops.end();
00382         ++iter ) {
00383     desktopstr += TQString::number( *iter ) + TQString::fromLatin1( "," );
00384   }
00385   desktopstr.remove( desktopstr.length() - 1, 1 );
00386   return desktopstr;
00387 }
00388 
00389 void Task::cut()
00390 {
00391   //kdDebug(5970) << "Task::cut - " << name() << endl;
00392   changeParentTotalTimes( -_totalSessionTime, -_totalTime);
00393   if ( ! parent())
00394     listView()->takeItem(this);
00395   else
00396     parent()->takeItem(this);
00397 }
00398 
00399 void Task::move(Task* destination)
00400 {
00401   cut();
00402   paste(destination);
00403 }
00404 
00405 void Task::paste(Task* destination)
00406 {
00407   destination->insertItem(this);
00408   changeParentTotalTimes( _totalSessionTime, _totalTime);
00409 }
00410 
00411 void Task::update()
00412 {
00413   setText(0, _name);
00414   setText(1, formatTime(_sessionTime));
00415   setText(2, formatTime(_time));
00416   setText(3, formatTime(_totalSessionTime));
00417   setText(4, formatTime(_totalTime));
00418 }
00419 
00420 void Task::addComment( TQString comment, KarmStorage* storage )
00421 {
00422   _comment = _comment + TQString::fromLatin1("\n") + comment;
00423   storage->addComment(this, comment);
00424 }
00425 
00426 TQString Task::comment() const
00427 {
00428   return _comment;
00429 }
00430 
00431 int Task::compare ( TQListViewItem * i, int col, bool ascending ) const
00432 {
00433   long thistime = 0;
00434   long thattime = 0;
00435   Task *task = static_cast<Task*>(i);
00436 
00437   switch ( col )
00438   {
00439     case 1: 
00440       thistime = _sessionTime;
00441       thattime = task->sessionTime();
00442       break;
00443     case 2:
00444       thistime = _time;
00445       thattime = task->time();
00446       break;
00447     case 3:
00448       thistime = _totalSessionTime;
00449       thattime = task->totalSessionTime();
00450       break;
00451     case 4:
00452       thistime = _totalTime;
00453       thattime = task->totalTime();
00454       break;
00455     default:
00456       return key(col, ascending).localeAwareCompare( i->key(col, ascending) );
00457   }
00458 
00459   if ( thistime < thattime ) return -1;
00460   if ( thistime > thattime ) return 1;
00461   return 0;
00462 
00463 }
00464 
00465 #include "task.moc"