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