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