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 "tdeapplication.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 TDEIconLoader 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, TDEIcon::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"