karm

taskview.cpp
1 #include <tqclipboard.h>
2 #include <tqfile.h>
3 #include <tqlayout.h>
4 #include <tqlistbox.h>
5 #include <tqlistview.h>
6 #include <tqptrlist.h>
7 #include <tqptrstack.h>
8 #include <tqstring.h>
9 #include <tqtextstream.h>
10 #include <tqtimer.h>
11 #include <tqxml.h>
12 
13 #include "tdeapplication.h" // kapp
14 #include <tdeconfig.h>
15 #include <kdebug.h>
16 #include <tdefiledialog.h>
17 #include <tdelocale.h> // i18n
18 #include <tdemessagebox.h>
19 #include <kurlrequester.h>
20 
21 #include "csvexportdialog.h"
22 #include "desktoptracker.h"
23 #include "edittaskdialog.h"
24 #include "idletimedetector.h"
25 #include "karmstorage.h"
26 #include "plannerparser.h"
27 #include "preferences.h"
28 #include "printdialog.h"
29 #include "reportcriteria.h"
30 #include "task.h"
31 #include "taskview.h"
32 #include "timekard.h"
33 #include "taskviewwhatsthis.h"
34 
35 #define T_LINESIZE 1023
36 #define HIDDEN_COLUMN -10
37 
38 class DesktopTracker;
39 
40 TaskView::TaskView(TQWidget *parent, const char *name, const TQString &icsfile ):TDEListView(parent,name)
41 {
42  _preferences = Preferences::instance( icsfile );
43  _storage = KarmStorage::instance();
44 
45  connect( this, TQ_SIGNAL( expanded( TQListViewItem * ) ),
46  this, TQ_SLOT( itemStateChanged( TQListViewItem * ) ) );
47  connect( this, TQ_SIGNAL( collapsed( TQListViewItem * ) ),
48  this, TQ_SLOT( itemStateChanged( TQListViewItem * ) ) );
49 
50  // setup default values
51  previousColumnWidths[0] = previousColumnWidths[1]
52  = previousColumnWidths[2] = previousColumnWidths[3] = HIDDEN_COLUMN;
53 
54  addColumn( i18n("Task Name") );
55  addColumn( i18n("Session Time") );
56  addColumn( i18n("Time") );
57  addColumn( i18n("Total Session Time") );
58  addColumn( i18n("Total Time") );
59  setColumnAlignment( 1, TQt::AlignRight );
60  setColumnAlignment( 2, TQt::AlignRight );
61  setColumnAlignment( 3, TQt::AlignRight );
62  setColumnAlignment( 4, TQt::AlignRight );
63  adaptColumns();
64  setAllColumnsShowFocus( true );
65 
66  // set up the minuteTimer
67  _minuteTimer = new TQTimer(this);
68  connect( _minuteTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( minuteUpdate() ));
69  _minuteTimer->start(1000 * secsPerMinute);
70 
71  // React when user changes iCalFile
72  connect(_preferences, TQ_SIGNAL(iCalFile(TQString)),
73  this, TQ_SLOT(iCalFileChanged(TQString)));
74 
75  // resize columns when config is changed
76  connect(_preferences, TQ_SIGNAL( setupChanged() ), this,TQ_SLOT( adaptColumns() ));
77 
78  _minuteTimer->start(1000 * secsPerMinute);
79 
80  // Set up the idle detection.
81  _idleTimeDetector = new IdleTimeDetector( _preferences->idlenessTimeout() );
82  connect( _idleTimeDetector, TQ_SIGNAL( extractTime(int) ),
83  this, TQ_SLOT( extractTime(int) ));
84  connect( _idleTimeDetector, TQ_SIGNAL( stopAllTimersAt(TQDateTime) ),
85  this, TQ_SLOT( stopAllTimersAt(TQDateTime) ));
86  connect( _preferences, TQ_SIGNAL( idlenessTimeout(int) ),
87  _idleTimeDetector, TQ_SLOT( setMaxIdle(int) ));
88  connect( _preferences, TQ_SIGNAL( detectIdleness(bool) ),
89  _idleTimeDetector, TQ_SLOT( toggleOverAllIdleDetection(bool) ));
90  if (!_idleTimeDetector->isIdleDetectionPossible())
91  _preferences->disableIdleDetection();
92 
93  // Setup auto save timer
94  _autoSaveTimer = new TQTimer(this);
95  connect( _preferences, TQ_SIGNAL( autoSave(bool) ),
96  this, TQ_SLOT( autoSaveChanged(bool) ));
97  connect( _preferences, TQ_SIGNAL( autoSavePeriod(int) ),
98  this, TQ_SLOT( autoSavePeriodChanged(int) ));
99  connect( _autoSaveTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( save() ));
100 
101  // Setup manual save timer (to save changes a little while after they happen)
102  _manualSaveTimer = new TQTimer(this);
103  connect( _manualSaveTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( save() ));
104 
105  // Connect desktop tracker events to task starting/stopping
106  _desktopTracker = new DesktopTracker();
107  connect( _desktopTracker, TQ_SIGNAL( reachedtActiveDesktop( Task* ) ),
108  this, TQ_SLOT( startTimerFor(Task*) ));
109  connect( _desktopTracker, TQ_SIGNAL( leftActiveDesktop( Task* ) ),
110  this, TQ_SLOT( stopTimerFor(Task*) ));
111  new TaskViewWhatsThis( this );
112 }
113 
115 {
116  return _storage;
117 }
118 
119 void TaskView::contentsMousePressEvent ( TQMouseEvent * e )
120 {
121  kdDebug(5970) << "entering contentsMousePressEvent" << endl;
122  TDEListView::contentsMousePressEvent(e);
123  Task* task = current_item();
124  // This checks that there has been a click onto an item,
125  // not into an empty part of the TDEListView.
126  if ( task != 0 && // zero can happen if there is no task
127  e->pos().y() >= current_item()->itemPos() &&
128  e->pos().y() < current_item()->itemPos()+current_item()->height() )
129  {
130  // see if the click was on the completed icon
131  int leftborder = treeStepSize() * ( task->depth() + ( rootIsDecorated() ? 1 : 0)) + itemMargin();
132  if ((leftborder < e->x()) && (e->x() < 19 + leftborder ))
133  {
134  if ( e->button() == TQt::LeftButton )
135  if ( task->isComplete() ) task->setPercentComplete( 0, _storage );
136  else task->setPercentComplete( 100, _storage );
137  }
138  emit updateButtons();
139  }
140 }
141 
142 void TaskView::contentsMouseDoubleClickEvent ( TQMouseEvent * e )
143 // if the user double-clicks onto a tasks, he says "I am now working exclusively
144 // on that task". That means, on a doubleclick, we check if it occurs on an item
145 // not in the blank space, if yes, stop all other tasks and start the new timer.
146 {
147  kdDebug(5970) << "entering contentsMouseDoubleClickEvent" << endl;
148  TDEListView::contentsMouseDoubleClickEvent(e);
149 
150  Task *task = current_item();
151 
152  if ( task != 0 ) // current_item() exists
153  {
154  if ( e->pos().y() >= task->itemPos() && // doubleclick was onto current_item()
155  e->pos().y() < task->itemPos()+task->height() )
156  {
157  if ( activeTasks.findRef(task) == -1 ) // task is active
158  {
159  stopAllTimers();
161  }
162  else stopCurrentTimer();
163  }
164  }
165 }
166 
167 TaskView::~TaskView()
168 {
169  _preferences->save();
170 }
171 
173 {
174  return static_cast<Task*>(firstChild());
175 }
176 
178 {
179  return static_cast<Task*>(currentItem());
180 }
181 
183 {
184  return static_cast<Task*>(itemAtIndex(i));
185 }
186 
187 void TaskView::load( TQString fileName )
188 {
189  // if the program is used as an embedded plugin for konqueror, there may be a need
190  // to load from a file without touching the preferences.
191  _isloading = true;
192  TQString err = _storage->load(this, _preferences, fileName);
193 
194  if (!err.isEmpty())
195  {
196  KMessageBox::error(this, err);
197  _isloading = false;
198  return;
199  }
200 
201  // Register tasks with desktop tracker
202  int i = 0;
203  for ( Task* t = item_at_index(i); t; t = item_at_index(++i) )
204  _desktopTracker->registerForDesktops( t, t->getDesktops() );
205 
206  restoreItemState( first_child() );
207 
208  setSelected(first_child(), true);
209  setCurrentItem(first_child());
210  if ( _desktopTracker->startTracking() != TQString() )
211  KMessageBox::error( 0, i18n("You are on a too high logical desktop, desktop tracking will not work") );
212  _isloading = false;
213  refresh();
214 }
215 
216 void TaskView::restoreItemState( TQListViewItem *item )
217 {
218  while( item )
219  {
220  Task *t = (Task *)item;
221  t->setOpen( _preferences->readBoolEntry( t->uid() ) );
222  if( item->childCount() > 0 ) restoreItemState( item->firstChild() );
223  item = item->nextSibling();
224  }
225 }
226 
227 void TaskView::itemStateChanged( TQListViewItem *item )
228 {
229  if ( !item || _isloading ) return;
230  Task *t = (Task *)item;
231  kdDebug(5970) << "TaskView::itemStateChanged()"
232  << " uid=" << t->uid() << " state=" << t->isOpen()
233  << endl;
234  if( _preferences ) _preferences->writeEntry( t->uid(), t->isOpen() );
235 }
236 
237 void TaskView::closeStorage() { _storage->closeStorage( this ); }
238 
239 void TaskView::iCalFileModified(ResourceCalendar *rc)
240 {
241  kdDebug(5970) << "entering iCalFileModified" << endl;
242  kdDebug(5970) << rc->infoText() << endl;
243  rc->dump();
244  _storage->buildTaskView(rc,this);
245  kdDebug(5970) << "exiting iCalFileModified" << endl;
246 }
247 
249 {
250  kdDebug(5970) << "entering TaskView::refresh()" << endl;
251  this->setRootIsDecorated(true);
252  int i = 0;
253  for ( Task* t = item_at_index(i); t; t = item_at_index(++i) )
254  {
255  t->setPixmapProgress();
256  }
257 
258  // remove root decoration if there is no more children.
259  bool anyChilds = false;
260  for(Task* child = first_child();
261  child;
262  child = child->nextSibling()) {
263  if (child->childCount() != 0) {
264  anyChilds = true;
265  break;
266  }
267  }
268  if (!anyChilds) {
269  setRootIsDecorated(false);
270  }
271  emit updateButtons();
272  kdDebug(5970) << "exiting TaskView::refresh()" << endl;
273 }
274 
276 {
277  kdDebug(5970) << "TaskView::loadFromFlatFile()" << endl;
278 
279  //KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this);
280 
281  TQString fileName(KFileDialog::getOpenFileName(TQString(), TQString(),
282  0));
283  if (!fileName.isEmpty()) {
284  TQString err = _storage->loadFromFlatFile(this, fileName);
285  if (!err.isEmpty())
286  {
287  KMessageBox::error(this, err);
288  return;
289  }
290  // Register tasks with desktop tracker
291  int task_idx = 0;
292  Task* task = item_at_index(task_idx++);
293  while (task)
294  {
295  // item_at_index returns 0 where no more items.
296  _desktopTracker->registerForDesktops( task, task->getDesktops() );
297  task = item_at_index(task_idx++);
298  }
299 
300  setSelected(first_child(), true);
301  setCurrentItem(first_child());
302 
303  if ( _desktopTracker->startTracking() != TQString() )
304  KMessageBox::error(0, i18n("You are on a too high logical desktop, desktop tracking will not work") );
305  }
306 }
307 
308 TQString TaskView::importPlanner(TQString fileName)
309 {
310  kdDebug(5970) << "entering importPlanner" << endl;
311  PlannerParser* handler=new PlannerParser(this);
312  if (fileName.isEmpty()) fileName=KFileDialog::getOpenFileName(TQString(), TQString(), 0);
313  TQFile xmlFile( fileName );
314  TQXmlInputSource source( xmlFile );
315  TQXmlSimpleReader reader;
316  reader.setContentHandler( handler );
317  reader.parse( source );
318  refresh();
319  return "";
320 }
321 
322 TQString TaskView::report( const ReportCriteria& rc )
323 {
324  return _storage->report( this, rc );
325 }
326 
328 {
329  kdDebug(5970) << "TaskView::exportcsvFile()" << endl;
330 
331  CSVExportDialog dialog( ReportCriteria::CSVTotalsExport, this );
332  if ( current_item() && current_item()->isRoot() )
333  dialog.enableTasksToExportQuestion();
334  dialog.urlExportTo->KURLRequester::setMode(KFile::File);
335  if ( dialog.exec() ) {
336  TQString err = _storage->report( this, dialog.reportCriteria() );
337  if ( !err.isEmpty() ) KMessageBox::error( this, i18n(err.ascii()) );
338  }
339 }
340 
342 {
343  kdDebug(5970) << "TaskView::exportcsvHistory()" << endl;
344  TQString err;
345 
346  CSVExportDialog dialog( ReportCriteria::CSVHistoryExport, this );
347  if ( current_item() && current_item()->isRoot() )
348  dialog.enableTasksToExportQuestion();
349  dialog.urlExportTo->KURLRequester::setMode(KFile::File);
350  if ( dialog.exec() ) {
351  err = _storage->report( this, dialog.reportCriteria() );
352  }
353  return err;
354 }
355 
357 {
358  kdDebug(5970) << "Entering TaskView::scheduleSave" << endl;
359  // save changes a little while after they happen
360  _manualSaveTimer->start( 10, true /*single-shot*/ );
361 }
362 
363 Preferences* TaskView::preferences() { return _preferences; }
364 
365 TQString TaskView::save()
366 // This saves the tasks. If they do not yet have an endDate, their startDate is also not saved.
367 {
368  kdDebug(5970) << "Entering TaskView::save" << endl;
369  TQString err = _storage->save(this);
370  emit(setStatusBar(err));
371  return err;
372 }
373 
375 {
377 }
378 
380 {
381  long n = 0;
382  for (Task* t = item_at_index(n); t; t=item_at_index(++n));
383  return n;
384 }
385 
386 void TaskView::startTimerFor(Task* task, TQDateTime startTime )
387 {
388  kdDebug(5970) << "Entering TaskView::startTimerFor" << endl;
389  if (save()==TQString())
390  {
391  if (task != 0 && activeTasks.findRef(task) == -1)
392  {
393  _idleTimeDetector->startIdleDetection();
394  if (!task->isComplete())
395  {
396  task->setRunning(true, _storage, startTime);
397  activeTasks.append(task);
398  emit updateButtons();
399  if ( activeTasks.count() == 1 )
400  emit timersActive();
401  emit tasksChanged( activeTasks);
402  }
403  }
404  }
405  else KMessageBox::error(0,i18n("Saving is impossible, so timing is useless. \nSaving problems may result from a full harddisk, a directory name instead of a file name, or stale locks. Check that your harddisk has enough space, that your calendar file exists and is a file and remove stale locks, typically from ~/.trinity/share/apps/tdeabc/lock."));
406 }
407 
409 {
410  activeTasks.clear();
411 }
412 
414 {
415  kdDebug(5970) << "Entering TaskView::stopAllTimers()" << endl;
416  for ( unsigned int i = 0; i < activeTasks.count(); i++ )
417  activeTasks.at(i)->setRunning(false, _storage);
418 
419  _idleTimeDetector->stopIdleDetection();
420  activeTasks.clear();
421  emit updateButtons();
422  emit timersInactive();
423  emit tasksChanged( activeTasks );
424 }
425 
426 void TaskView::stopAllTimersAt(TQDateTime qdt)
427 // stops all timers for the time qdt. This makes sense, if the idletimedetector detected
428 // the last work has been done 50 minutes ago.
429 {
430  kdDebug(5970) << "Entering TaskView::stopAllTimersAt " << qdt << endl;
431  for ( unsigned int i = 0; i < activeTasks.count(); i++ )
432  {
433  activeTasks.at(i)->setRunning(false, _storage, qdt, qdt);
434  kdDebug() << activeTasks.at(i)->name() << endl;
435  }
436 
437  _idleTimeDetector->stopIdleDetection();
438  activeTasks.clear();
439  emit updateButtons();
440  emit timersInactive();
441  emit tasksChanged( activeTasks );
442 }
443 
445 {
446  TQListViewItemIterator item( first_child());
447  for ( ; item.current(); ++item ) {
448  Task * task = (Task *) item.current();
449  task->startNewSession();
450  }
451 }
452 
454 {
455  TQListViewItemIterator item( first_child());
456  for ( ; item.current(); ++item ) {
457  Task * task = (Task *) item.current();
458  task->resetTimes();
459  }
460 }
461 
462 void TaskView::stopTimerFor(Task* task)
463 {
464  kdDebug(5970) << "Entering stopTimerFor. task = " << task->name() << endl;
465  if ( task != 0 && activeTasks.findRef(task) != -1 ) {
466  activeTasks.removeRef(task);
467  task->setRunning(false, _storage);
468  if ( activeTasks.count() == 0 ) {
469  _idleTimeDetector->stopIdleDetection();
470  emit timersInactive();
471  }
472  emit updateButtons();
473  }
474  emit tasksChanged( activeTasks);
475 }
476 
478 {
479  stopTimerFor( current_item());
480 }
481 
482 void TaskView::minuteUpdate()
483 {
484  addTimeToActiveTasks(1, false);
485 }
486 
487 void TaskView::addTimeToActiveTasks(int minutes, bool save_data)
488 {
489  for( unsigned int i = 0; i < activeTasks.count(); i++ )
490  activeTasks.at(i)->changeTime(minutes, ( save_data ? _storage : 0 ) );
491 }
492 
494 {
495  newTask(i18n("New Task"), 0);
496 }
497 
498 void TaskView::newTask(TQString caption, Task *parent)
499 {
500  EditTaskDialog *dialog = new EditTaskDialog(caption, false);
501  long total, totalDiff, session, sessionDiff;
502  DesktopList desktopList;
503 
504  int result = dialog->exec();
505  if ( result == TQDialog::Accepted ) {
506  TQString taskName = i18n( "Unnamed Task" );
507  if ( !dialog->taskName().isEmpty()) taskName = dialog->taskName();
508 
509  total = totalDiff = session = sessionDiff = 0;
510  dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList );
511 
512  // If all available desktops are checked, disable auto tracking,
513  // since it makes no sense to track for every desktop.
514  if ( desktopList.size() == ( unsigned int ) _desktopTracker->desktopCount() )
515  desktopList.clear();
516 
517  TQString uid = addTask( taskName, total, session, desktopList, parent );
518  if ( uid.isNull() )
519  {
520  KMessageBox::error( 0, i18n(
521  "Error storing new task. Your changes were not saved. Make sure you can edit your iCalendar file. Also quit all applications using this file and remove any lock file related to its name from ~/.trinity/share/apps/tdeabc/lock/ " ) );
522  }
523 
524  delete dialog;
525  }
526 }
527 
529 ( const TQString& taskname, long total, long session,
530  const DesktopList& desktops, Task* parent )
531 {
532  Task *task;
533  kdDebug(5970) << "TaskView::addTask: taskname = " << taskname << endl;
534 
535  if ( parent ) task = new Task( taskname, total, session, desktops, parent );
536  else task = new Task( taskname, total, session, desktops, this );
537 
538  task->setUid( _storage->addTask( task, parent ) );
539  TQString taskuid=task->uid();
540  if ( ! taskuid.isNull() )
541  {
542  _desktopTracker->registerForDesktops( task, desktops );
543  setCurrentItem( task );
544  setSelected( task, true );
545  task->setPixmapProgress();
546  save();
547  }
548  else
549  {
550  delete task;
551  }
552  return taskuid;
553 }
554 
556 {
557  Task* task = current_item();
558  if(!task)
559  return;
560  newTask(i18n("New Sub Task"), task);
561  task->setOpen(true);
562  refresh();
563 }
564 
565 void TaskView::editTask()
566 {
567  Task *task = current_item();
568  if (!task)
569  return;
570 
571  DesktopList desktopList = task->getDesktops();
572  EditTaskDialog *dialog = new EditTaskDialog(i18n("Edit Task"), true, &desktopList);
573  dialog->setTask( task->name(),
574  task->time(),
575  task->sessionTime() );
576  int result = dialog->exec();
577  if (result == TQDialog::Accepted) {
578  TQString taskName = i18n("Unnamed Task");
579  if (!dialog->taskName().isEmpty()) {
580  taskName = dialog->taskName();
581  }
582  // setName only does something if the new name is different
583  task->setName(taskName, _storage);
584 
585  // update session time as well if the time was changed
586  long total, session, totalDiff, sessionDiff;
587  total = totalDiff = session = sessionDiff = 0;
588  DesktopList desktopList;
589  dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
590 
591  if( totalDiff != 0 || sessionDiff != 0)
592  task->changeTimes( sessionDiff, totalDiff, _storage );
593 
594  // If all available desktops are checked, disable auto tracking,
595  // since it makes no sense to track for every desktop.
596  if (desktopList.size() == (unsigned int)_desktopTracker->desktopCount())
597  desktopList.clear();
598 
599  task->setDesktopList(desktopList);
600 
601  _desktopTracker->registerForDesktops( task, desktopList );
602 
603  emit updateButtons();
604  }
605  delete dialog;
606 }
607 
608 //void TaskView::addCommentToTask()
609 //{
610 // Task *task = current_item();
611 // if (!task)
612 // return;
613 
614 // bool ok;
615 // TQString comment = KLineEditDlg::getText(i18n("Comment"),
616 // i18n("Log comment for task '%1':").arg(task->name()),
617 // TQString(), &ok, this);
618 // if ( ok )
619 // task->addComment( comment, _storage );
620 //}
621 
622 void TaskView::reinstateTask(int completion)
623 {
624  Task* task = current_item();
625  if (task == 0) {
626  KMessageBox::information(0,i18n("No task selected."));
627  return;
628  }
629 
630  if (completion<0) completion=0;
631  if (completion<100)
632  {
633  task->setPercentComplete(completion, _storage);
634  task->setPixmapProgress();
635  save();
636  emit updateButtons();
637  }
638 }
639 
640 void TaskView::deleteTask(bool markingascomplete)
641 {
642  Task *task = current_item();
643  if (task == 0) {
644  KMessageBox::information(0,i18n("No task selected."));
645  return;
646  }
647 
648  int response = KMessageBox::Continue;
649  if (!markingascomplete && _preferences->promptDelete()) {
650  if (task->childCount() == 0) {
651  response = KMessageBox::warningContinueCancel( 0,
652  i18n( "Are you sure you want to delete "
653  "the task named\n\"%1\" and its entire history?")
654  .arg(task->name()),
655  i18n( "Deleting Task"), KStdGuiItem::del());
656  }
657  else {
658  response = KMessageBox::warningContinueCancel( 0,
659  i18n( "Are you sure you want to delete the task named"
660  "\n\"%1\" and its entire history?\n"
661  "NOTE: all its subtasks and their history will also "
662  "be deleted.").arg(task->name()),
663  i18n( "Deleting Task"), KStdGuiItem::del());
664  }
665  }
666 
667  if (response == KMessageBox::Continue)
668  {
669  if (markingascomplete)
670  {
671  task->setPercentComplete(100, _storage);
672  task->setPixmapProgress();
673  save();
674  emit updateButtons();
675 
676  // Have to remove after saving, as the save routine only affects tasks
677  // that are in the view. Otherwise, the new percent complete does not
678  // get saved. (No longer remove when marked as complete.)
679  //task->removeFromView();
680 
681  }
682  else
683  {
684  TQString uid=task->uid();
685  task->remove(activeTasks, _storage);
686  task->removeFromView();
687  if( _preferences ) _preferences->deleteEntry( uid ); // forget if the item was expanded or collapsed
688  save();
689  }
690 
691  // remove root decoration if there is no more children.
692  refresh();
693 
694  // Stop idle detection if no more counters are running
695  if (activeTasks.count() == 0) {
696  _idleTimeDetector->stopIdleDetection();
697  emit timersInactive();
698  }
699 
700  emit tasksChanged( activeTasks );
701  }
702 }
703 
704 void TaskView::extractTime(int minutes)
705 // This procedure subtracts ''minutes'' from the active task's time in the memory.
706 // It is called by the idletimedetector class.
707 // When the desktop has been idle for the past 20 minutes, the past 20 minutes have
708 // already been added to the task's time in order for the time to be displayed correctly.
709 // That is why idletimedetector needs to subtract this time first.
710 {
711  kdDebug(5970) << "Entering extractTime" << endl;
712  addTimeToActiveTasks(-minutes,false); // subtract minutes, but do not store it
713 }
714 
715 void TaskView::autoSaveChanged(bool on)
716 {
717  if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute);
718  else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop();
719 }
720 
721 void TaskView::autoSavePeriodChanged(int /*minutes*/)
722 {
723  autoSaveChanged(_preferences->autoSave());
724 }
725 
726 void TaskView::adaptColumns()
727 {
728  // to hide a column X we set it's width to 0
729  // at that moment we'll remember the original column within
730  // previousColumnWidths[X]
731  //
732  // When unhiding a previously hidden column
733  // (previousColumnWidths[X] != HIDDEN_COLUMN !)
734  // we restore it's width from the saved value and set
735  // previousColumnWidths[X] to HIDDEN_COLUMN
736 
737  for( int x=1; x <= 4; x++) {
738  // the column was invisible before and were switching it on now
739  if( _preferences->displayColumn(x-1)
740  && previousColumnWidths[x-1] != HIDDEN_COLUMN )
741  {
742  setColumnWidth( x, previousColumnWidths[x-1] );
743  previousColumnWidths[x-1] = HIDDEN_COLUMN;
744  setColumnWidthMode( x, TQListView::Maximum );
745  }
746  // the column was visible before and were switching it off now
747  else
748  if( ! _preferences->displayColumn(x-1)
749  && previousColumnWidths[x-1] == HIDDEN_COLUMN )
750  {
751  setColumnWidthMode( x, TQListView::Manual ); // we don't want update()
752  // to resize/unhide the col
753  previousColumnWidths[x-1] = columnWidth( x );
754  setColumnWidth( x, 0 );
755  }
756  }
757 }
758 
759 void TaskView::deletingTask(Task* deletedTask)
760 {
761  DesktopList desktopList;
762 
763  _desktopTracker->registerForDesktops( deletedTask, desktopList );
764  activeTasks.removeRef( deletedTask );
765 
766  emit tasksChanged( activeTasks);
767 }
768 
769 void TaskView::iCalFileChanged(TQString file)
770 // User might have picked a new file in the preferences dialog.
771 // This is not iCalFileModified.
772 {
773  kdDebug(5970) << "TaskView:iCalFileChanged: " << file << endl;
774  if (_storage->icalfile() != file)
775  {
776  stopAllTimers();
777  _storage->save(this);
778  load();
779  }
780 }
781 
782 TQValueList<HistoryEvent> TaskView::getHistory(const TQDate& from,
783  const TQDate& to) const
784 {
785  return _storage->getHistory(from, to);
786 }
787 
788 void TaskView::markTaskAsComplete()
789 {
790  if (current_item())
791  kdDebug(5970) << "TaskView::markTaskAsComplete: "
792  << current_item()->uid() << endl;
793  else
794  kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
795 
796  bool markingascomplete = true;
797  deleteTask(markingascomplete);
798 }
799 
800 void TaskView::markTaskAsIncomplete()
801 {
802  if (current_item())
803  kdDebug(5970) << "TaskView::markTaskAsComplete: "
804  << current_item()->uid() << endl;
805  else
806  kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
807 
808  reinstateTask(50); // if it has been reopened, assume half-done
809 }
810 
811 
813 {
814  TimeKard t;
815  if (current_item() && current_item()->isRoot())
816  {
817  int response = KMessageBox::questionYesNo( 0,
818  i18n("Copy totals for just this task and its subtasks, or copy totals for all tasks?"),
819  i18n("Copy Totals to Clipboard"),
820  i18n("Copy This Task"), i18n("Copy All Tasks") );
821  if (response == KMessageBox::Yes) // This task only
822  {
823  TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::TotalTime));
824  }
825  else // All tasks
826  {
827  TDEApplication::clipboard()->setText(t.totalsAsText(this, false, TimeKard::TotalTime));
828  }
829  }
830  else
831  {
832  TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::TotalTime));
833  }
834 }
835 
837 {
838  TimeKard t;
839  if (current_item() && current_item()->isRoot())
840  {
841  int response = KMessageBox::questionYesNo( 0,
842  i18n("Copy session time for just this task and its subtasks, or copy session time for all tasks?"),
843  i18n("Copy Session Time to Clipboard"),
844  i18n("Copy This Task"), i18n("Copy All Tasks") );
845  if (response == KMessageBox::Yes) // this task only
846  {
847  TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::SessionTime));
848  }
849  else // only task
850  {
851  TDEApplication::clipboard()->setText(t.totalsAsText(this, false, TimeKard::SessionTime));
852  }
853  }
854  else
855  {
856  TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::SessionTime));
857  }
858 }
859 
861 {
862  PrintDialog dialog;
863  if (dialog.exec()== TQDialog::Accepted)
864  {
865  TimeKard t;
866  TDEApplication::clipboard()->
867  setText( t.historyAsText(this, dialog.from(), dialog.to(), !dialog.allTasks(), dialog.perWeek(), dialog.totalsOnly() ) );
868  }
869 }
870 
871 #include "taskview.moc"
A utility to associate tasks with desktops As soon as a desktop is activated/left - an signal is emit...
Dialog to add a new task or edit an existing task.
Keep track of how long the computer has been idle.
void startIdleDetection()
Starts detecting idle time.
void stopIdleDetection()
Stops detecting idle time.
Singleton to store/retrieve KArm data to/from persistent storage.
Definition: karmstorage.h:68
TQString loadFromFlatFile(TaskView *taskview, const TQString &filename)
Read tasks and their total times from a text file (legacy storage).
TQString addTask(const Task *task, const Task *parent)
Add this task from iCalendar file.
TQString report(TaskView *taskview, const ReportCriteria &rc)
Output a report based on contents of ReportCriteria.
TQValueList< HistoryEvent > getHistory(const TQDate &from, const TQDate &to)
Return a list of start/stop events for the given date range.
this class is here to import tasks from a planner project file to karm.
Definition: plannerparser.h:38
Provide an interface to the configuration options for the program.
Definition: preferences.h:17
Stores entries from export dialog.
this is the karm-taskview-specific implementation of qwhatsthis
Preferences * preferences()
Return preferences user selected on settings dialog.
Definition: taskview.cpp:363
KarmStorage * storage()
Returns a pointer to storage object.
Definition: taskview.cpp:114
void clipTotals()
Copy totals for current and all sub tasks to clipboard.
Definition: taskview.cpp:812
void iCalFileChanged(TQString file)
User might have picked a new iCalendar file on preferences screen.
Definition: taskview.cpp:769
Task * first_child() const
Return the first item in the view, cast to a Task pointer.
Definition: taskview.cpp:172
void loadFromFlatFile()
Used to import a legacy file format.
Definition: taskview.cpp:275
long count()
Return the total number if items in the view.
Definition: taskview.cpp:379
TQString exportcsvHistory()
Export comma-separated values format for task history.
Definition: taskview.cpp:341
void iCalFileModified(ResourceCalendar *)
React on another process having modified the iCal file we rely on.
Definition: taskview.cpp:239
void stopCurrentTimer()
Stop the timer for the current item in the view.
Definition: taskview.cpp:477
void resetTimeForAllTasks()
Reset session and total time to zero for all tasks.
Definition: taskview.cpp:453
void deletingTask(Task *deletedTask)
receiving signal that a task is being deleted
Definition: taskview.cpp:759
TQString importPlanner(TQString fileName="")
used to import tasks from imendio planner
Definition: taskview.cpp:308
void refresh()
Used to refresh (e.g.
Definition: taskview.cpp:248
void startCurrentTimer()
Start the timer on the current item (task) in view.
Definition: taskview.cpp:374
void closeStorage()
Close the storage and release lock.
Definition: taskview.cpp:237
TQString addTask(const TQString &taskame, long total, long session, const DesktopList &desktops, Task *parent=0)
Add a task to view and storage.
Definition: taskview.cpp:529
void extractTime(int minutes)
Subtracts time from all active tasks, and does not log event.
Definition: taskview.cpp:704
TQString report(const ReportCriteria &rc)
call export function for csv totals or history
Definition: taskview.cpp:322
void clipSession()
Copy session times for current and all sub tasks to clipboard.
Definition: taskview.cpp:836
Task * current_item() const
Return the current item in the view, cast to a Task pointer.
Definition: taskview.cpp:177
TQString save()
Save to persistent storage.
Definition: taskview.cpp:365
void exportcsvFile()
Export comma separated values format for task time totals.
Definition: taskview.cpp:327
Task * item_at_index(int i)
Return the i'th item (zero-based), cast to a Task pointer.
Definition: taskview.cpp:182
void clearActiveTasks()
clears all active tasks.
Definition: taskview.cpp:408
void newTask()
Calls newTask dialog with caption "New Task".
Definition: taskview.cpp:493
void load(TQString filename="")
Load the view from storage.
Definition: taskview.cpp:187
void clipHistory()
Copy history for current and all sub tasks to clipboard.
Definition: taskview.cpp:860
void deleteTask(bool markingascomplete=false)
Delete task (and children) from view.
Definition: taskview.cpp:640
void startTimerFor(Task *task, TQDateTime startTime=TQDateTime::currentDateTime())
starts timer for task.
Definition: taskview.cpp:386
void newSubTask()
Calls newTask dialog with caption "New Sub Task".
Definition: taskview.cpp:555
void scheduleSave()
Schedule that we should save very soon.
Definition: taskview.cpp:356
void itemStateChanged(TQListViewItem *item)
item state stores if a task is expanded so you can see the subtasks
Definition: taskview.cpp:227
void reinstateTask(int completion)
Reinstates the current task as incomplete.
Definition: taskview.cpp:622
void stopAllTimers()
Stop all running timers.
Definition: taskview.cpp:413
void stopAllTimersAt(TQDateTime qdt)
Stop all running timers as if it was qdt.
Definition: taskview.cpp:426
TQValueList< HistoryEvent > getHistory(const TQDate &from, const TQDate &to) const
Return list of start/stop events for given date range.
Definition: taskview.cpp:782
void startNewSession()
Reset session time to zero for all tasks.
Definition: taskview.cpp:444
A class representing a task.
Definition: task.h:42
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 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
void setName(const TQString &name, KarmStorage *storage)
sets the name of the task
Definition: task.cpp:137
void setPixmapProgress()
Sets an appropriate icon for this task based on its level of completion.
Definition: task.cpp:184
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
bool remove(TQPtrList< Task > &activeTasks, KarmStorage *storage)
remove Task with all it's children
Definition: task.cpp:258
void startNewSession()
sets session time to zero.
Definition: task.h:140
void setUid(const TQString uid)
Set unique id for the task.
Definition: task.cpp:128
Routines to output timecard data.
Definition: timekard.h:86
TQString totalsAsText(TaskView *taskview, bool justThisTask, WhichTime which)
Generates ascii text of task totals, for current task on down.
Definition: timekard.cpp:48
TQString historyAsText(TaskView *taskview, const TQDate &from, const TQDate &to, bool justThisTask, bool perWeek, bool totalsOnly)
Generates ascii text of weekly task history, for current task on down.
Definition: timekard.cpp:308