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
38class DesktopTracker;
39
40TaskView::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
119void 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
142void 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 {
161 }
162 else stopCurrentTimer();
163 }
164 }
165}
166
167TaskView::~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
187void 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
216void 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
227void 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
237void TaskView::closeStorage() { _storage->closeStorage( this ); }
238
239void 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 {
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
308TQString 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
322TQString 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
363Preferences* TaskView::preferences() { return _preferences; }
364
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
386void 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
426void 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
462void 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
487void TaskView::minuteUpdate()
488{
489 addTimeToActiveTasks(1, false);
490}
491
492void 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
503void 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
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
570void 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
627void 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
645void 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
709void 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
720void TaskView::autoSaveChanged(bool on)
721{
722 if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute);
723 else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop();
724}
725
726void TaskView::autoSavePeriodChanged(int /*minutes*/)
727{
728 autoSaveChanged(_preferences->autoSave());
729}
730
731void 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
764void 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
774void 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 {
782 _storage->save(this);
783 load();
784 }
785}
786
787TQValueList<HistoryEvent> TaskView::getHistory(const TQDate& from,
788 const TQDate& to) const
789{
790 return _storage->getHistory(from, to);
791}
792
793void 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
805void 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"
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:817
void iCalFileChanged(TQString file)
User might have picked a new iCalendar file on preferences screen.
Definition: taskview.cpp:774
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:764
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:534
void extractTime(int minutes)
Subtracts time from all active tasks, and does not log event.
Definition: taskview.cpp:709
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:841
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 resetTimeCurrentTask()
Reset session and total time to zero for the current item in the view.
Definition: taskview.cpp:482
void newTask()
Calls newTask dialog with caption "New Task".
Definition: taskview.cpp:498
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:865
void deleteTask(bool markingascomplete=false)
Delete task (and children) from view.
Definition: taskview.cpp:645
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:560
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:627
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:787
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