karm

task.cpp
1 #include <tqcstring.h>
2 #include <tqdatetime.h>
3 #include <tqstring.h>
4 #include <tqtimer.h>
5 
6 #include <kiconloader.h>
7 
8 #include "tdeapplication.h" // kapp
9 #include "kdebug.h"
10 
11 #include "event.h"
12 
13 #include "karmutility.h"
14 #include "task.h"
15 #include "taskview.h"
16 #include "preferences.h"
17 
18 
19 const int gSecondsPerMinute = 60;
20 
21 
22 TQPtrVector<TQPixmap> *Task::icons = 0;
23 
24 Task::Task( const TQString& taskName, long minutes, long sessionTime,
25  DesktopList desktops, TaskView *parent)
26  : TQObject(), TQListViewItem(parent)
27 {
28  init(taskName, minutes, sessionTime, desktops, 0);
29 }
30 
31 Task::Task( const TQString& taskName, long minutes, long sessionTime,
32  DesktopList desktops, Task *parent)
33  : TQObject(), TQListViewItem(parent)
34 {
35  init(taskName, minutes, sessionTime, desktops, 0);
36 }
37 
38 Task::Task( KCal::Todo* todo, TaskView* parent )
39  : TQObject(), TQListViewItem( parent )
40 {
41  long minutes = 0;
42  TQString name;
43  long sessionTime = 0;
44  int percent_complete = 0;
45  DesktopList desktops;
46 
47  parseIncidence(todo, minutes, sessionTime, name, desktops, percent_complete);
48  init(name, minutes, sessionTime, desktops, percent_complete);
49 }
50 
51 void Task::init( const TQString& taskName, long minutes, long sessionTime,
52  DesktopList desktops, int percent_complete)
53 {
54  // If our parent is the taskview then connect our totalTimesChanged
55  // signal to its receiver
56  if ( ! parent() )
57  connect( this, TQ_SIGNAL( totalTimesChanged ( long, long ) ),
58  listView(), TQ_SLOT( taskTotalTimesChanged( long, long) ));
59 
60  connect( this, TQ_SIGNAL( deletingTask( Task* ) ),
61  listView(), TQ_SLOT( deletingTask( Task* ) ));
62 
63  if (icons == 0) {
64  icons = new TQPtrVector<TQPixmap>(8);
65  TDEIconLoader kil("karm"); // always load icons from the KArm application
66  for (int i=0; i<8; i++)
67  {
68  TQPixmap *icon = new TQPixmap();
69  TQString name;
70  name.sprintf("watch-%d.xpm",i);
71  *icon = kil.loadIcon( name, TDEIcon::User );
72  icons->insert(i,icon);
73  }
74  }
75 
76  _removing = false;
77  _name = taskName.stripWhiteSpace();
78  _lastStart = TQDateTime::currentDateTime();
79  _totalTime = _time = minutes;
80  _totalSessionTime = _sessionTime = sessionTime;
81  _timer = new TQTimer(this);
82  _desktops = desktops;
83  connect(_timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(updateActiveIcon()));
84  setPixmap(1, UserIcon(TQString::fromLatin1("empty-watch.xpm")));
85  _currentPic = 0;
86  _percentcomplete = percent_complete;
87 
88  update();
89  changeParentTotalTimes( _sessionTime, _time);
90 }
91 
92 Task::~Task() {
93  emit deletingTask(this);
94  delete _timer;
95 }
96 
97 void Task::setRunning( bool on, KarmStorage* storage, TQDateTime whenStarted, TQDateTime whenStopped )
98 // Sets a task running or stopped. If the task is to be stopped, whenStarted is not evaluated.
99 // on=true if the task shall be started on=false if the task shall be stopped
100 // This is the back-end, the front-end is StartTimerFor()
101 {
102  kdDebug(5970) << "Entering Task::setRunning " << "on=" << on << "whenStarted=" << whenStarted << " whenStopped=" << whenStopped << endl;
103  if ( on )
104  {
105  if (!_timer->isActive())
106  {
107  _timer->start(1000);
108  storage->startTimer(this);
109  _currentPic=7;
110  _lastStart = whenStarted;
112  }
113  }
114  else
115  {
116  if (_timer->isActive())
117  {
118  _timer->stop();
119  if ( ! _removing )
120  {
121  storage->stopTimer(this, whenStopped);
122  setPixmap(1, UserIcon(TQString::fromLatin1("empty-watch.xpm")));
123  }
124  }
125  }
126 }
127 
128 void Task::setUid(TQString uid) {
129  _uid = uid;
130 }
131 
132 bool Task::isRunning() const
133 {
134  return _timer->isActive();
135 }
136 
137 void Task::setName( const TQString& name, KarmStorage* storage )
138 {
139  kdDebug(5970) << "Task:setName: " << name << endl;
140 
141  TQString oldname = _name;
142  if ( oldname != name ) {
143  _name = name;
144  storage->setName(this, oldname);
145  update();
146  }
147 }
148 
149 void Task::setPercentComplete(const int percent, KarmStorage *storage)
150 {
151  kdDebug(5970) << "Task::setPercentComplete(" << percent << ", storage): "
152  << _uid << endl;
153 
154  if (!percent)
155  _percentcomplete = 0;
156  else if (percent > 100)
157  _percentcomplete = 100;
158  else if (percent < 0)
159  _percentcomplete = 0;
160  else
161  _percentcomplete = percent;
162 
163  if (isRunning() && _percentcomplete==100) taskView()->stopTimerFor(this);
164 
166 
167  // When parent marked as complete, mark all children as complete as well.
168  // Complete tasks are not displayed in the task view, so if a parent is
169  // marked as complete and some of the children are not, then we get an error
170  // message. KArm actually keep chugging along in this case and displays the
171  // child tasks just fine, so an alternative solution is to remove that error
172  // message (from KarmStorage::load). But I think it makes more sense that
173  // if you mark a parent task as complete, then all children should be
174  // complete as well.
175  //
176  // This behavior is consistent with KOrganizer (as of 2003-09-24).
177  if (_percentcomplete == 100)
178  {
179  for (Task* child= this->firstChild(); child; child = child->nextSibling())
180  child->setPercentComplete(_percentcomplete, storage);
181  }
182 }
183 
185 {
186  TQPixmap icon ;
187  if (_percentcomplete >= 100)
188  icon = UserIcon("task-complete.xpm");
189  else
190  icon = UserIcon("task-incomplete.xpm");
191  setPixmap(0, icon);
192 }
193 
194 bool Task::isComplete() { return _percentcomplete == 100; }
195 
197 {
198  while ( Task* child = firstChild() )
199  child->removeFromView();
200  delete this;
201 }
202 
203 void Task::setDesktopList ( DesktopList desktopList )
204 {
205  _desktops = desktopList;
206 }
207 
208 void Task::changeTime( long minutes, KarmStorage* storage )
209 {
210  changeTimes( minutes, minutes, storage);
211 }
212 
213 void Task::changeTimes( long minutesSession, long minutes, KarmStorage* storage)
214 {
215  if( minutesSession != 0 || minutes != 0)
216  {
217  _sessionTime += minutesSession;
218  _time += minutes;
219  if ( storage ) storage->changeTime(this, minutes * gSecondsPerMinute);
220  changeTotalTimes( minutesSession, minutes );
221  }
222 }
223 
224 void Task::changeTotalTimes( long minutesSession, long minutes )
225 {
226  kdDebug(5970)
227  << "Task::changeTotalTimes(" << minutesSession << ", "
228  << minutes << ") for " << name() << endl;
229 
230  _totalSessionTime += minutesSession;
231  _totalTime += minutes;
232  update();
233  changeParentTotalTimes( minutesSession, minutes );
234 }
235 
237 {
238  _totalSessionTime -= _sessionTime;
239  _totalTime -= _time;
240  changeParentTotalTimes( -_sessionTime, -_time);
241  _sessionTime = 0;
242  _time = 0;
243  update();
244 }
245 
246 void Task::changeParentTotalTimes( long minutesSession, long minutes )
247 {
248  //kdDebug(5970)
249  // << "Task::changeParentTotalTimes(" << minutesSession << ", "
250  // << minutes << ") for " << name() << endl;
251 
252  if ( isRoot() )
253  emit totalTimesChanged( minutesSession, minutes );
254  else
255  parent()->changeTotalTimes( minutesSession, minutes );
256 }
257 
258 bool Task::remove( TQPtrList<Task>& activeTasks, KarmStorage* storage)
259 {
260  kdDebug(5970) << "Task::remove: " << _name << endl;
261 
262  bool ok = true;
263 
264  _removing = true;
265  storage->removeTask(this);
266  if( isRunning() ) setRunning( false, storage );
267 
268  for (Task* child = this->firstChild(); child; child = child->nextSibling())
269  {
270  if (child->isRunning())
271  child->setRunning(false, storage);
272  child->remove(activeTasks, storage);
273  }
274 
275  changeParentTotalTimes( -_sessionTime, -_time);
276 
277  _removing = false;
278 
279  return ok;
280 }
281 
283 {
284  _currentPic = (_currentPic+1) % 8;
285  setPixmap(1, *(*icons)[_currentPic]);
286 }
287 
288 TQString Task::fullName() const
289 {
290  if (isRoot())
291  return name();
292  else
293  return parent()->fullName() + TQString::fromLatin1("/") + name();
294 }
295 
296 KCal::Todo* Task::asTodo(KCal::Todo* todo) const
297 {
298 
299  Q_ASSERT( todo != NULL );
300 
301  kdDebug(5970) << "Task::asTodo: name() = '" << name() << "'" << endl;
302  todo->setSummary( name() );
303 
304  // Note: if the date start is empty, the KOrganizer GUI will have the
305  // checkbox blank, but will prefill the todo's starting datetime to the
306  // time the file is opened.
307  // todo->setDtStart( current );
308 
309  todo->setCustomProperty( kapp->instanceName(),
310  TQCString( "totalTaskTime" ), TQString::number( _time ) );
311  todo->setCustomProperty( kapp->instanceName(),
312  TQCString( "totalSessionTime" ), TQString::number( _sessionTime) );
313 
314  if (getDesktopStr().isEmpty())
315  todo->removeCustomProperty(kapp->instanceName(), TQCString("desktopList"));
316  else
317  todo->setCustomProperty( kapp->instanceName(),
318  TQCString( "desktopList" ), getDesktopStr() );
319 
320  todo->setOrganizer( Preferences::instance()->userRealName() );
321 
322  todo->setPercentComplete(_percentcomplete);
323 
324  return todo;
325 }
326 
327 bool Task::parseIncidence( KCal::Incidence* incident, long& minutes,
328  long& sessionMinutes, TQString& name, DesktopList& desktops,
329  int& percent_complete )
330 {
331  bool ok;
332 
333  name = incident->summary();
334  _uid = incident->uid();
335 
336  _comment = incident->description();
337 
338  ok = false;
339  minutes = incident->customProperty( kapp->instanceName(),
340  TQCString( "totalTaskTime" )).toInt( &ok );
341  if ( !ok )
342  minutes = 0;
343 
344  ok = false;
345  sessionMinutes = incident->customProperty( kapp->instanceName(),
346  TQCString( "totalSessionTime" )).toInt( &ok );
347  if ( !ok )
348  sessionMinutes = 0;
349 
350  TQString desktopList = incident->customProperty( kapp->instanceName(),
351  TQCString( "desktopList" ) );
352  TQStringList desktopStrList = TQStringList::split( TQString::fromLatin1(","),
353  desktopList );
354  desktops.clear();
355 
356  for ( TQStringList::iterator iter = desktopStrList.begin();
357  iter != desktopStrList.end();
358  ++iter ) {
359  int desktopInt = (*iter).toInt( &ok );
360  if ( ok ) {
361  desktops.push_back( desktopInt );
362  }
363  }
364 
365  percent_complete = static_cast<KCal::Todo*>(incident)->percentComplete();
366 
367  //kdDebug(5970) << "Task::parseIncidence: "
368  // << name << ", Minutes: " << minutes
369  // << ", desktop: " << desktopList << endl;
370 
371  return true;
372 }
373 
374 TQString Task::getDesktopStr() const
375 {
376  if ( _desktops.empty() )
377  return TQString();
378 
379  TQString desktopstr;
380  for ( DesktopList::const_iterator iter = _desktops.begin();
381  iter != _desktops.end();
382  ++iter ) {
383  desktopstr += TQString::number( *iter ) + TQString::fromLatin1( "," );
384  }
385  desktopstr.remove( desktopstr.length() - 1, 1 );
386  return desktopstr;
387 }
388 
389 void Task::cut()
390 {
391  //kdDebug(5970) << "Task::cut - " << name() << endl;
392  changeParentTotalTimes( -_totalSessionTime, -_totalTime);
393  if ( ! parent())
394  listView()->takeItem(this);
395  else
396  parent()->takeItem(this);
397 }
398 
399 void Task::move(Task* destination)
400 {
401  cut();
402  paste(destination);
403 }
404 
405 void Task::paste(Task* destination)
406 {
407  destination->insertItem(this);
408  changeParentTotalTimes( _totalSessionTime, _totalTime);
409 }
410 
412 {
413  setText(0, _name);
414  setText(1, formatTime(_sessionTime));
415  setText(2, formatTime(_time));
416  setText(3, formatTime(_totalSessionTime));
417  setText(4, formatTime(_totalTime));
418 }
419 
420 void Task::addComment( TQString comment, KarmStorage* storage )
421 {
422  _comment = _comment + TQString::fromLatin1("\n") + comment;
423  storage->addComment(this, comment);
424 }
425 
426 TQString Task::comment() const
427 {
428  return _comment;
429 }
430 
431 int Task::compare ( TQListViewItem * i, int col, bool ascending ) const
432 {
433  long thistime = 0;
434  long thattime = 0;
435  Task *task = static_cast<Task*>(i);
436 
437  switch ( col )
438  {
439  case 1:
440  thistime = _sessionTime;
441  thattime = task->sessionTime();
442  break;
443  case 2:
444  thistime = _time;
445  thattime = task->time();
446  break;
447  case 3:
448  thistime = _totalSessionTime;
449  thattime = task->totalSessionTime();
450  break;
451  case 4:
452  thistime = _totalTime;
453  thattime = task->totalTime();
454  break;
455  default:
456  return key(col, ascending).localeAwareCompare( i->key(col, ascending) );
457  }
458 
459  if ( thistime < thattime ) return -1;
460  if ( thistime > thattime ) return 1;
461  return 0;
462 
463 }
464 
465 #include "task.moc"
Singleton to store/retrieve KArm data to/from persistent storage.
Definition: karmstorage.h:68
void setName(const Task *task, const TQString &oldname)
Log a change to a task name.
Definition: karmstorage.h:219
bool removeTask(Task *task)
Remove this task from iCalendar file.
void startTimer(const Task *task)
Log the event that a timer has started for a task.
Definition: karmstorage.h:230
void stopTimer(const Task *task, TQDateTime when=TQDateTime::currentDateTime())
Log the event that the timer has stopped for this task.
void changeTime(const Task *task, const long deltaSeconds)
Log the change in a task's time.
void addComment(const Task *task, const TQString &comment)
Log a new comment for this task.
Container and interface for the tasks.
Definition: taskview.h:43
A class representing a task.
Definition: task.h:42
void addComment(TQString comment, KarmStorage *storage)
Add a comment to this task.
Definition: task.cpp:420
void changeTimes(long minutesSession, long minutes, KarmStorage *storage=0)
Add minutes to time and session time, and write to storage.
Definition: task.cpp:213
void resetTimes()
Reset all times to 0.
Definition: task.cpp:236
void setRunning(bool on, KarmStorage *storage, TQDateTime whenStarted=TQDateTime::currentDateTime(), TQDateTime whenStopped=TQDateTime::currentDateTime())
starts or stops a task
Definition: task.cpp:97
bool isComplete()
Return true if task is complete (percent complete equals 100).
Definition: task.cpp:194
void changeTime(long minutes, KarmStorage *storage)
Change task time.
Definition: task.cpp:208
void update()
Update the display of the task (all columns) in the UI.
Definition: task.cpp:411
void removeFromView()
Remove current task and all it's children from the view.
Definition: task.cpp:196
TQString name() const
returns the name of this task.
Definition: task.h:162
Task * firstChild() const
return parent Task or null in case of TaskView.
Definition: task.h:60
KCal::Todo * asTodo(KCal::Todo *calendar) const
Load the todo passed in with this tasks info.
Definition: task.cpp:296
void updateActiveIcon()
animate the active icon
Definition: task.cpp:282
void setName(const TQString &name, KarmStorage *storage)
sets the name of the task
Definition: task.cpp:137
TQString fullName() const
Returns that task name, prefixed by parent tree up to root.
Definition: task.cpp:288
void setPixmapProgress()
Sets an appropriate icon for this task based on its level of completion.
Definition: task.cpp:184
bool isRoot() const
tells you whether this task is the root of the task tree
Definition: task.h:209
void changeTotalTimes(long minutesSession, long minutes)
adds minutes to total and session time
Definition: task.cpp:224
TQString uid() const
Return unique iCalendar Todo ID for this task.
Definition: task.h:70
void setPercentComplete(const int percent, KarmStorage *storage)
Update percent complete for this task.
Definition: task.cpp:149
TaskView * taskView() const
Return task view for this task.
Definition: task.h:65
int compare(TQListViewItem *i, int col, bool ascending) const
Sort times numerically, not alphabetically.
Definition: task.cpp:431
void move(Task *destination)
cut Task out of parent Task or the TaskView and into the destination Task
Definition: task.cpp:399
void paste(Task *destination)
insert Task into the destination Task
Definition: task.cpp:405
bool isRunning() const
return the state of a task - if it's running or not
Definition: task.cpp:132
void cut()
cut Task out of parent Task or the TaskView
Definition: task.cpp:389
bool remove(TQPtrList< Task > &activeTasks, KarmStorage *storage)
remove Task with all it's children
Definition: task.cpp:258
TQString comment() const
Retrieve the entire comment for the task.
Definition: task.cpp:426
void deletingTask(Task *thisTask)
signal that we're about to delete a task
void setUid(const TQString uid)
Set unique id for the task.
Definition: task.cpp:128