karm

task.cpp

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