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"