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, TQT_SIGNAL( expanded( TQListViewItem * ) ),
46  this, TQT_SLOT( itemStateChanged( TQListViewItem * ) ) );
47  connect( this, TQT_SIGNAL( collapsed( TQListViewItem * ) ),
48  this, TQT_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, TQT_SIGNAL( timeout() ), this, TQT_SLOT( minuteUpdate() ));
69  _minuteTimer->start(1000 * secsPerMinute);
70 
71  // React when user changes iCalFile
72  connect(_preferences, TQT_SIGNAL(iCalFile(TQString)),
73  this, TQT_SLOT(iCalFileChanged(TQString)));
74 
75  // resize columns when config is changed
76  connect(_preferences, TQT_SIGNAL( setupChanged() ), this,TQT_SLOT( adaptColumns() ));
77 
78  _minuteTimer->start(1000 * secsPerMinute);
79 
80  // Set up the idle detection.
81  _idleTimeDetector = new IdleTimeDetector( _preferences->idlenessTimeout() );
82  connect( _idleTimeDetector, TQT_SIGNAL( extractTime(int) ),
83  this, TQT_SLOT( extractTime(int) ));
84  connect( _idleTimeDetector, TQT_SIGNAL( stopAllTimersAt(TQDateTime) ),
85  this, TQT_SLOT( stopAllTimersAt(TQDateTime) ));
86  connect( _preferences, TQT_SIGNAL( idlenessTimeout(int) ),
87  _idleTimeDetector, TQT_SLOT( setMaxIdle(int) ));
88  connect( _preferences, TQT_SIGNAL( detectIdleness(bool) ),
89  _idleTimeDetector, TQT_SLOT( toggleOverAllIdleDetection(bool) ));
90  if (!_idleTimeDetector->isIdleDetectionPossible())
91  _preferences->disableIdleDetection();
92 
93  // Setup auto save timer
94  _autoSaveTimer = new TQTimer(this);
95  connect( _preferences, TQT_SIGNAL( autoSave(bool) ),
96  this, TQT_SLOT( autoSaveChanged(bool) ));
97  connect( _preferences, TQT_SIGNAL( autoSavePeriod(int) ),
98  this, TQT_SLOT( autoSavePeriodChanged(int) ));
99  connect( _autoSaveTimer, TQT_SIGNAL( timeout() ), this, TQT_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, TQT_SIGNAL( timeout() ), this, TQT_SLOT( save() ));
104 
105  // Connect desktop tracker events to task starting/stopping
106  _desktopTracker = new DesktopTracker();
107  connect( _desktopTracker, TQT_SIGNAL( reachedtActiveDesktop( Task* ) ),
108  this, TQT_SLOT( startTimerFor(Task*) ));
109  connect( _desktopTracker, TQT_SIGNAL( leftActiveDesktop( Task* ) ),
110  this, TQT_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() == Qt::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 
483 {
485 }
486 
487 void TaskView::minuteUpdate()
488 {
489  addTimeToActiveTasks(1, false);
490 }
491 
492 void TaskView::addTimeToActiveTasks(int minutes, bool save_data)
493 {
494  for( unsigned int i = 0; i < activeTasks.count(); i++ )
495  activeTasks.at(i)->changeTime(minutes, ( save_data ? _storage : 0 ) );
496 }
497 
499 {
500  newTask(i18n("New Task"), 0);
501 }
502 
503 void TaskView::newTask(TQString caption, Task *parent)
504 {
505  EditTaskDialog *dialog = new EditTaskDialog(caption, false);
506  long total, totalDiff, session, sessionDiff;
507  DesktopList desktopList;
508 
509  int result = dialog->exec();
510  if ( result == TQDialog::Accepted ) {
511  TQString taskName = i18n( "Unnamed Task" );
512  if ( !dialog->taskName().isEmpty()) taskName = dialog->taskName();
513 
514  total = totalDiff = session = sessionDiff = 0;
515  dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList );
516 
517  // If all available desktops are checked, disable auto tracking,
518  // since it makes no sense to track for every desktop.
519  if ( desktopList.size() == ( unsigned int ) _desktopTracker->desktopCount() )
520  desktopList.clear();
521 
522  TQString uid = addTask( taskName, total, session, desktopList, parent );
523  if ( uid.isNull() )
524  {
525  KMessageBox::error( 0, i18n(
526  "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/ " ) );
527  }
528 
529  delete dialog;
530  }
531 }
532 
533 TQString TaskView::addTask
534 ( const TQString& taskname, long total, long session,
535  const DesktopList& desktops, Task* parent )
536 {
537  Task *task;
538  kdDebug(5970) << "TaskView::addTask: taskname = " << taskname << endl;
539 
540  if ( parent ) task = new Task( taskname, total, session, desktops, parent );
541  else task = new Task( taskname, total, session, desktops, this );
542 
543  task->setUid( _storage->addTask( task, parent ) );
544  TQString taskuid=task->uid();
545  if ( ! taskuid.isNull() )
546  {
547  _desktopTracker->registerForDesktops( task, desktops );
548  setCurrentItem( task );
549  setSelected( task, true );
550  task->setPixmapProgress();
551  save();
552  }
553  else
554  {
555  delete task;
556  }
557  return taskuid;
558 }
559 
561 {
562  Task* task = current_item();
563  if(!task)
564  return;
565  newTask(i18n("New Sub Task"), task);
566  task->setOpen(true);
567  refresh();
568 }
569 
570 void TaskView::editTask()
571 {
572  Task *task = current_item();
573  if (!task)
574  return;
575 
576  DesktopList desktopList = task->getDesktops();
577  EditTaskDialog *dialog = new EditTaskDialog(i18n("Edit Task"), true, &desktopList);
578  dialog->setTask( task->name(),
579  task->time(),
580  task->sessionTime() );
581  int result = dialog->exec();
582  if (result == TQDialog::Accepted) {
583  TQString taskName = i18n("Unnamed Task");
584  if (!dialog->taskName().isEmpty()) {
585  taskName = dialog->taskName();
586  }
587  // setName only does something if the new name is different
588  task->setName(taskName, _storage);
589 
590  // update session time as well if the time was changed
591  long total, session, totalDiff, sessionDiff;
592  total = totalDiff = session = sessionDiff = 0;
593  DesktopList desktopList;
594  dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
595 
596  if( totalDiff != 0 || sessionDiff != 0)
597  task->changeTimes( sessionDiff, totalDiff, _storage );
598 
599  // If all available desktops are checked, disable auto tracking,
600  // since it makes no sense to track for every desktop.
601  if (desktopList.size() == (unsigned int)_desktopTracker->desktopCount())
602  desktopList.clear();
603 
604  task->setDesktopList(desktopList);
605 
606  _desktopTracker->registerForDesktops( task, desktopList );
607 
608  emit updateButtons();
609  }
610  delete dialog;
611 }
612 
613 //void TaskView::addCommentToTask()
614 //{
615 // Task *task = current_item();
616 // if (!task)
617 // return;
618 
619 // bool ok;
620 // TQString comment = KLineEditDlg::getText(i18n("Comment"),
621 // i18n("Log comment for task '%1':").arg(task->name()),
622 // TQString(), &ok, this);
623 // if ( ok )
624 // task->addComment( comment, _storage );
625 //}
626 
627 void TaskView::reinstateTask(int completion)
628 {
629  Task* task = current_item();
630  if (task == 0) {
631  KMessageBox::information(0,i18n("No task selected."));
632  return;
633  }
634 
635  if (completion<0) completion=0;
636  if (completion<100)
637  {
638  task->setPercentComplete(completion, _storage);
639  task->setPixmapProgress();
640  save();
641  emit updateButtons();
642  }
643 }
644 
645 void TaskView::deleteTask(bool markingascomplete)
646 {
647  Task *task = current_item();
648  if (task == 0) {
649  KMessageBox::information(0,i18n("No task selected."));
650  return;
651  }
652 
653  int response = KMessageBox::Continue;
654  if (!markingascomplete && _preferences->promptDelete()) {
655  if (task->childCount() == 0) {
656  response = KMessageBox::warningContinueCancel( 0,
657  i18n( "Are you sure you want to delete "
658  "the task named\n\"%1\" and its entire history?")
659  .arg(task->name()),
660  i18n( "Deleting Task"), KStdGuiItem::del());
661  }
662  else {
663  response = KMessageBox::warningContinueCancel( 0,
664  i18n( "Are you sure you want to delete the task named"
665  "\n\"%1\" and its entire history?\n"
666  "NOTE: all its subtasks and their history will also "
667  "be deleted.").arg(task->name()),
668  i18n( "Deleting Task"), KStdGuiItem::del());
669  }
670  }
671 
672  if (response == KMessageBox::Continue)
673  {
674  if (markingascomplete)
675  {
676  task->setPercentComplete(100, _storage);
677  task->setPixmapProgress();
678  save();
679  emit updateButtons();
680 
681  // Have to remove after saving, as the save routine only affects tasks
682  // that are in the view. Otherwise, the new percent complete does not
683  // get saved. (No longer remove when marked as complete.)
684  //task->removeFromView();
685 
686  }
687  else
688  {
689  TQString uid=task->uid();
690  task->remove(activeTasks, _storage);
691  task->removeFromView();
692  if( _preferences ) _preferences->deleteEntry( uid ); // forget if the item was expanded or collapsed
693  save();
694  }
695 
696  // remove root decoration if there is no more children.
697  refresh();
698 
699  // Stop idle detection if no more counters are running
700  if (activeTasks.count() == 0) {
701  _idleTimeDetector->stopIdleDetection();
702  emit timersInactive();
703  }
704 
705  emit tasksChanged( activeTasks );
706  }
707 }
708 
709 void TaskView::extractTime(int minutes)
710 // This procedure subtracts ''minutes'' from the active task's time in the memory.
711 // It is called by the idletimedetector class.
712 // When the desktop has been idle for the past 20 minutes, the past 20 minutes have
713 // already been added to the task's time in order for the time to be displayed correctly.
714 // That is why idletimedetector needs to subtract this time first.
715 {
716  kdDebug(5970) << "Entering extractTime" << endl;
717  addTimeToActiveTasks(-minutes,false); // subtract minutes, but do not store it
718 }
719 
720 void TaskView::autoSaveChanged(bool on)
721 {
722  if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute);
723  else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop();
724 }
725 
726 void TaskView::autoSavePeriodChanged(int /*minutes*/)
727 {
728  autoSaveChanged(_preferences->autoSave());
729 }
730 
731 void TaskView::adaptColumns()
732 {
733  // to hide a column X we set it's width to 0
734  // at that moment we'll remember the original column within
735  // previousColumnWidths[X]
736  //
737  // When unhiding a previously hidden column
738  // (previousColumnWidths[X] != HIDDEN_COLUMN !)
739  // we restore it's width from the saved value and set
740  // previousColumnWidths[X] to HIDDEN_COLUMN
741 
742  for( int x=1; x <= 4; x++) {
743  // the column was invisible before and were switching it on now
744  if( _preferences->displayColumn(x-1)
745  && previousColumnWidths[x-1] != HIDDEN_COLUMN )
746  {
747  setColumnWidth( x, previousColumnWidths[x-1] );
748  previousColumnWidths[x-1] = HIDDEN_COLUMN;
749  setColumnWidthMode( x, TQListView::Maximum );
750  }
751  // the column was visible before and were switching it off now
752  else
753  if( ! _preferences->displayColumn(x-1)
754  && previousColumnWidths[x-1] == HIDDEN_COLUMN )
755  {
756  setColumnWidthMode( x, TQListView::Manual ); // we don't want update()
757  // to resize/unhide the col
758  previousColumnWidths[x-1] = columnWidth( x );
759  setColumnWidth( x, 0 );
760  }
761  }
762 }
763 
764 void TaskView::deletingTask(Task* deletedTask)
765 {
766  DesktopList desktopList;
767 
768  _desktopTracker->registerForDesktops( deletedTask, desktopList );
769  activeTasks.removeRef( deletedTask );
770 
771  emit tasksChanged( activeTasks);
772 }
773 
774 void TaskView::iCalFileChanged(TQString file)
775 // User might have picked a new file in the preferences dialog.
776 // This is not iCalFileModified.
777 {
778  kdDebug(5970) << "TaskView:iCalFileChanged: " << file << endl;
779  if (_storage->icalfile() != file)
780  {
781  stopAllTimers();
782  _storage->save(this);
783  load();
784  }
785 }
786 
787 TQValueList<HistoryEvent> TaskView::getHistory(const TQDate& from,
788  const TQDate& to) const
789 {
790  return _storage->getHistory(from, to);
791 }
792 
793 void TaskView::markTaskAsComplete()
794 {
795  if (current_item())
796  kdDebug(5970) << "TaskView::markTaskAsComplete: "
797  << current_item()->uid() << endl;
798  else
799  kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
800 
801  bool markingascomplete = true;
802  deleteTask(markingascomplete);
803 }
804 
805 void TaskView::markTaskAsIncomplete()
806 {
807  if (current_item())
808  kdDebug(5970) << "TaskView::markTaskAsComplete: "
809  << current_item()->uid() << endl;
810  else
811  kdDebug(5970) << "TaskView::markTaskAsComplete: null current_item()" << endl;
812 
813  reinstateTask(50); // if it has been reopened, assume half-done
814 }
815 
816 
818 {
819  TimeKard t;
820  if (current_item() && current_item()->isRoot())
821  {
822  int response = KMessageBox::questionYesNo( 0,
823  i18n("Copy totals for just this task and its subtasks, or copy totals for all tasks?"),
824  i18n("Copy Totals to Clipboard"),
825  i18n("Copy This Task"), i18n("Copy All Tasks") );
826  if (response == KMessageBox::Yes) // This task only
827  {
828  TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::TotalTime));
829  }
830  else // All tasks
831  {
832  TDEApplication::clipboard()->setText(t.totalsAsText(this, false, TimeKard::TotalTime));
833  }
834  }
835  else
836  {
837  TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::TotalTime));
838  }
839 }
840 
842 {
843  TimeKard t;
844  if (current_item() && current_item()->isRoot())
845  {
846  int response = KMessageBox::questionYesNo( 0,
847  i18n("Copy session time for just this task and its subtasks, or copy session time for all tasks?"),
848  i18n("Copy Session Time to Clipboard"),
849  i18n("Copy This Task"), i18n("Copy All Tasks") );
850  if (response == KMessageBox::Yes) // this task only
851  {
852  TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::SessionTime));
853  }
854  else // only task
855  {
856  TDEApplication::clipboard()->setText(t.totalsAsText(this, false, TimeKard::SessionTime));
857  }
858  }
859  else
860  {
861  TDEApplication::clipboard()->setText(t.totalsAsText(this, true, TimeKard::SessionTime));
862  }
863 }
864 
866 {
867  PrintDialog dialog;
868  if (dialog.exec()== TQDialog::Accepted)
869  {
870  TimeKard t;
871  TDEApplication::clipboard()->
872  setText( t.historyAsText(this, dialog.from(), dialog.to(), !dialog.allTasks(), dialog.perWeek(), dialog.totalsOnly() ) );
873  }
874 }
875 
876 #include "taskview.moc"
void iCalFileModified(ResourceCalendar *)
React on another process having modified the iCal file we rely on.
Definition: taskview.cpp:239
void stopIdleDetection()
Stops detecting idle time.
TQString report(const ReportCriteria &rc)
call export function for csv totals or history
Definition: taskview.cpp:322
TQValueList< HistoryEvent > getHistory(const TQDate &from, const TQDate &to)
Return a list of start/stop events for the given date range.
TQString name() const
returns the name of this task.
Definition: task.h:162
Task * first_child() const
Return the first item in the view, cast to a Task pointer.
Definition: taskview.cpp:172
void startIdleDetection()
Starts detecting idle time.
Task * current_item() const
Return the current item in the view, cast to a Task pointer.
Definition: taskview.cpp:177
void startNewSession()
sets session time to zero.
Definition: task.h:140
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
void load(TQString filename="")
Load the view from storage.
Definition: taskview.cpp:187
long count()
Return the total number if items in the view.
Definition: taskview.cpp:379
void setPercentComplete(const int percent, KarmStorage *storage)
Update percent complete for this task.
Definition: task.cpp:149
Keep track of how long the computer has been idle.
void scheduleSave()
Schedule that we should save very soon.
Definition: taskview.cpp:356
void stopCurrentTimer()
Stop the timer for the current item in the view.
Definition: taskview.cpp:477
Routines to output timecard data.
Definition: timekard.h:85
void clipHistory()
Copy history for current and all sub tasks to clipboard.
Definition: taskview.cpp:865
bool isComplete()
Return true if task is complete (percent complete equals 100).
Definition: task.cpp:194
void stopAllTimersAt(TQDateTime qdt)
Stop all running timers as if it was qdt.
Definition: taskview.cpp:426
void loadFromFlatFile()
Used to import a legacy file format.
Definition: taskview.cpp:275
void clearActiveTasks()
clears all active tasks.
Definition: taskview.cpp:408
void resetTimes()
Reset all times to 0.
Definition: task.cpp:236
void newTask()
Calls newTask dialog with caption "New Task".
Definition: taskview.cpp:498
void deleteTask(bool markingascomplete=false)
Delete task (and children) from view.
Definition: taskview.cpp:645
void startNewSession()
Reset session time to zero for all tasks.
Definition: taskview.cpp:444
TQString report(TaskView *taskview, const ReportCriteria &rc)
Output a report based on contents of ReportCriteria.
Task * item_at_index(int i)
Return the i'th item (zero-based), cast to a Task pointer.
Definition: taskview.cpp:182
void refresh()
Used to refresh (e.g.
Definition: taskview.cpp:248
void startTimerFor(Task *task, TQDateTime startTime=TQDateTime::currentDateTime())
starts timer for task.
Definition: taskview.cpp:386
void startCurrentTimer()
Start the timer on the current item (task) in view.
Definition: taskview.cpp:374
void exportcsvFile()
Export comma separated values format for task time totals.
Definition: taskview.cpp:327
void closeStorage()
Close the storage and release lock.
Definition: taskview.cpp:237
Singleton to store/retrieve KArm data to/from persistent storage.
Definition: karmstorage.h:67
Stores entries from export dialog.
Dialog to add a new task or edit an existing task.
void setUid(const TQString uid)
Set unique id for the task.
Definition: task.cpp:128
void removeFromView()
Remove current task and all it's children from the view.
Definition: task.cpp:196
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:534
TQString totalsAsText(TaskView *taskview, bool justThisTask, WhichTime which)
Generates ascii text of task totals, for current task on down.
Definition: timekard.cpp:48
TQString save()
Save to persistent storage.
Definition: taskview.cpp:365
Preferences * preferences()
Return preferences user selected on settings dialog.
Definition: taskview.cpp:363
void itemStateChanged(TQListViewItem *item)
item state stores if a task is expanded so you can see the subtasks
Definition: taskview.cpp:227
void extractTime(int minutes)
Subtracts time from all active tasks, and does not log event.
Definition: taskview.cpp:709
void resetTimeCurrentTask()
Reset session and total time to zero for the current item in the view.
Definition: taskview.cpp:482
TQString importPlanner(TQString fileName="")
used to import tasks from imendio planner
Definition: taskview.cpp:308
void setName(const TQString &name, KarmStorage *storage)
sets the name of the task
Definition: task.cpp:137
TQString uid() const
Return unique iCalendar Todo ID for this task.
Definition: task.h:70
this class is here to import tasks from a planner project file to karm.
Definition: plannerparser.h:37
void clipSession()
Copy session times for current and all sub tasks to clipboard.
Definition: taskview.cpp:841
A utility to associate tasks with desktops As soon as a desktop is activated/left - an signal is emit...
TQString exportcsvHistory()
Export comma-separated values format for task history.
Definition: taskview.cpp:341
void newSubTask()
Calls newTask dialog with caption "New Sub Task".
Definition: taskview.cpp:560
Provide an interface to the configuration options for the program.
Definition: preferences.h:16
void deletingTask(Task *deletedTask)
receiving signal that a task is being deleted
Definition: taskview.cpp:764
KarmStorage * storage()
Returns a pointer to storage object.
Definition: taskview.cpp:114
void setPixmapProgress()
Sets an appropriate icon for this task based on its level of completion.
Definition: task.cpp:184
void stopAllTimers()
Stop all running timers.
Definition: taskview.cpp:413
A class representing a task.
Definition: task.h:41
void iCalFileChanged(TQString file)
User might have picked a new iCalendar file on preferences screen.
Definition: taskview.cpp:774
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 clipTotals()
Copy totals for current and all sub tasks to clipboard.
Definition: taskview.cpp:817
void setRunning(bool on, KarmStorage *storage, TQDateTime whenStarted=TQDateTime::currentDateTime(), TQDateTime whenStopped=TQDateTime::currentDateTime())
starts or stops a task
Definition: task.cpp:97
void resetTimeForAllTasks()
Reset session and total time to zero for all tasks.
Definition: taskview.cpp:453
TQValueList< HistoryEvent > getHistory(const TQDate &from, const TQDate &to) const
Return list of start/stop events for given date range.
Definition: taskview.cpp:787
bool remove(TQPtrList< Task > &activeTasks, KarmStorage *storage)
remove Task with all it's children
Definition: task.cpp:258
TQString loadFromFlatFile(TaskView *taskview, const TQString &filename)
Read tasks and their total times from a text file (legacy storage).
void reinstateTask(int completion)
Reinstates the current task as incomplete.
Definition: taskview.cpp:627
this is the karm-taskview-specific implementation of qwhatsthis