1 #include <tqclipboard.h>
5 #include <tqlistview.h>
7 #include <tqptrstack.h>
9 #include <tqtextstream.h>
13 #include "tdeapplication.h"
14 #include <tdeconfig.h>
16 #include <tdefiledialog.h>
17 #include <tdelocale.h>
18 #include <tdemessagebox.h>
19 #include <kurlrequester.h>
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"
33 #include "taskviewwhatsthis.h"
35 #define T_LINESIZE 1023
36 #define HIDDEN_COLUMN -10
40 TaskView::TaskView(TQWidget *parent,
const char *name,
const TQString &icsfile ):TDEListView(parent,name)
42 _preferences = Preferences::instance( icsfile );
43 _storage = KarmStorage::instance();
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 * ) ) );
51 previousColumnWidths[0] = previousColumnWidths[1]
52 = previousColumnWidths[2] = previousColumnWidths[3] = HIDDEN_COLUMN;
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 );
64 setAllColumnsShowFocus(
true );
67 _minuteTimer =
new TQTimer(
this);
68 connect( _minuteTimer, TQ_SIGNAL( timeout() ),
this, TQ_SLOT( minuteUpdate() ));
69 _minuteTimer->start(1000 * secsPerMinute);
72 connect(_preferences, TQ_SIGNAL(iCalFile(TQString)),
73 this, TQ_SLOT(iCalFileChanged(TQString)));
76 connect(_preferences, TQ_SIGNAL( setupChanged() ),
this,TQ_SLOT( adaptColumns() ));
78 _minuteTimer->start(1000 * secsPerMinute);
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();
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() ));
102 _manualSaveTimer =
new TQTimer(
this);
103 connect( _manualSaveTimer, TQ_SIGNAL( timeout() ),
this, TQ_SLOT( save() ));
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*) ));
119 void TaskView::contentsMousePressEvent ( TQMouseEvent * e )
121 kdDebug(5970) <<
"entering contentsMousePressEvent" << endl;
122 TDEListView::contentsMousePressEvent(e);
131 int leftborder = treeStepSize() * ( task->depth() + ( rootIsDecorated() ? 1 : 0)) + itemMargin();
132 if ((leftborder < e->x()) && (e->x() < 19 + leftborder ))
134 if ( e->button() == TQt::LeftButton )
138 emit updateButtons();
142 void TaskView::contentsMouseDoubleClickEvent ( TQMouseEvent * e )
147 kdDebug(5970) <<
"entering contentsMouseDoubleClickEvent" << endl;
148 TDEListView::contentsMouseDoubleClickEvent(e);
154 if ( e->pos().y() >= task->itemPos() &&
155 e->pos().y() < task->itemPos()+task->height() )
157 if ( activeTasks.findRef(task) == -1 )
167 TaskView::~TaskView()
169 _preferences->save();
174 return static_cast<Task*
>(firstChild());
179 return static_cast<Task*
>(currentItem());
184 return static_cast<Task*
>(itemAtIndex(i));
192 TQString err = _storage->load(
this, _preferences, fileName);
196 KMessageBox::error(
this, err);
204 _desktopTracker->registerForDesktops( t, t->getDesktops() );
210 if ( _desktopTracker->startTracking() != TQString() )
211 KMessageBox::error( 0, i18n(
"You are on a too high logical desktop, desktop tracking will not work") );
216 void TaskView::restoreItemState( TQListViewItem *item )
221 t->setOpen( _preferences->readBoolEntry( t->
uid() ) );
222 if( item->childCount() > 0 ) restoreItemState( item->firstChild() );
223 item = item->nextSibling();
229 if ( !item || _isloading )
return;
231 kdDebug(5970) <<
"TaskView::itemStateChanged()"
232 <<
" uid=" << t->
uid() <<
" state=" << t->isOpen()
234 if( _preferences ) _preferences->writeEntry( t->
uid(), t->isOpen() );
241 kdDebug(5970) <<
"entering iCalFileModified" << endl;
242 kdDebug(5970) << rc->infoText() << endl;
244 _storage->buildTaskView(rc,
this);
245 kdDebug(5970) <<
"exiting iCalFileModified" << endl;
250 kdDebug(5970) <<
"entering TaskView::refresh()" << endl;
251 this->setRootIsDecorated(
true);
259 bool anyChilds =
false;
262 child = child->nextSibling()) {
263 if (child->childCount() != 0) {
269 setRootIsDecorated(
false);
271 emit updateButtons();
272 kdDebug(5970) <<
"exiting TaskView::refresh()" << endl;
277 kdDebug(5970) <<
"TaskView::loadFromFlatFile()" << endl;
281 TQString fileName(KFileDialog::getOpenFileName(TQString(), TQString(),
283 if (!fileName.isEmpty()) {
287 KMessageBox::error(
this, err);
296 _desktopTracker->registerForDesktops( task, task->getDesktops() );
303 if ( _desktopTracker->startTracking() != TQString() )
304 KMessageBox::error(0, i18n(
"You are on a too high logical desktop, desktop tracking will not work") );
310 kdDebug(5970) <<
"entering importPlanner" << endl;
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 );
324 return _storage->
report(
this, rc );
329 kdDebug(5970) <<
"TaskView::exportcsvFile()" << endl;
331 CSVExportDialog dialog( ReportCriteria::CSVTotalsExport,
this );
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()) );
343 kdDebug(5970) <<
"TaskView::exportcsvHistory()" << endl;
346 CSVExportDialog dialog( ReportCriteria::CSVHistoryExport,
this );
348 dialog.enableTasksToExportQuestion();
349 dialog.urlExportTo->KURLRequester::setMode(KFile::File);
350 if ( dialog.exec() ) {
351 err = _storage->
report(
this, dialog.reportCriteria() );
358 kdDebug(5970) <<
"Entering TaskView::scheduleSave" << endl;
360 _manualSaveTimer->start( 10,
true );
368 kdDebug(5970) <<
"Entering TaskView::save" << endl;
369 TQString err = _storage->save(
this);
370 emit(setStatusBar(err));
388 kdDebug(5970) <<
"Entering TaskView::startTimerFor" << endl;
389 if (
save()==TQString())
391 if (task != 0 && activeTasks.findRef(task) == -1)
397 activeTasks.append(task);
398 emit updateButtons();
399 if ( activeTasks.count() == 1 )
401 emit tasksChanged( activeTasks);
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."));
415 kdDebug(5970) <<
"Entering TaskView::stopAllTimers()" << endl;
416 for (
unsigned int i = 0; i < activeTasks.count(); i++ )
417 activeTasks.at(i)->setRunning(
false, _storage);
421 emit updateButtons();
422 emit timersInactive();
423 emit tasksChanged( activeTasks );
430 kdDebug(5970) <<
"Entering TaskView::stopAllTimersAt " << qdt << endl;
431 for (
unsigned int i = 0; i < activeTasks.count(); i++ )
433 activeTasks.at(i)->setRunning(
false, _storage, qdt, qdt);
434 kdDebug() << activeTasks.at(i)->name() << endl;
439 emit updateButtons();
440 emit timersInactive();
441 emit tasksChanged( activeTasks );
447 for ( ; item.current(); ++item ) {
448 Task * task = (
Task *) item.current();
456 for ( ; item.current(); ++item ) {
457 Task * task = (
Task *) item.current();
462 void TaskView::stopTimerFor(
Task* task)
464 kdDebug(5970) <<
"Entering stopTimerFor. task = " << task->
name() << endl;
465 if ( task != 0 && activeTasks.findRef(task) != -1 ) {
466 activeTasks.removeRef(task);
468 if ( activeTasks.count() == 0 ) {
470 emit timersInactive();
472 emit updateButtons();
474 emit tasksChanged( activeTasks);
482 void TaskView::minuteUpdate()
484 addTimeToActiveTasks(1,
false);
487 void TaskView::addTimeToActiveTasks(
int minutes,
bool save_data)
489 for(
unsigned int i = 0; i < activeTasks.count(); i++ )
490 activeTasks.at(i)->changeTime(minutes, ( save_data ? _storage : 0 ) );
501 long total, totalDiff, session, sessionDiff;
502 DesktopList desktopList;
504 int result = dialog->exec();
505 if ( result == TQDialog::Accepted ) {
506 TQString taskName = i18n(
"Unnamed Task" );
507 if ( !dialog->taskName().isEmpty()) taskName = dialog->taskName();
509 total = totalDiff = session = sessionDiff = 0;
510 dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList );
514 if ( desktopList.size() == (
unsigned int ) _desktopTracker->desktopCount() )
517 TQString uid =
addTask( taskName, total, session, desktopList, parent );
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/ " ) );
529 (
const TQString& taskname,
long total,
long session,
530 const DesktopList& desktops,
Task* parent )
533 kdDebug(5970) <<
"TaskView::addTask: taskname = " << taskname << endl;
535 if ( parent ) task =
new Task( taskname, total, session, desktops, parent );
536 else task =
new Task( taskname, total, session, desktops,
this );
539 TQString taskuid=task->
uid();
540 if ( ! taskuid.isNull() )
542 _desktopTracker->registerForDesktops( task, desktops );
543 setCurrentItem( task );
544 setSelected( task,
true );
560 newTask(i18n(
"New Sub Task"), task);
565 void TaskView::editTask()
571 DesktopList desktopList = task->getDesktops();
573 dialog->setTask( task->
name(),
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();
583 task->
setName(taskName, _storage);
586 long total, session, totalDiff, sessionDiff;
587 total = totalDiff = session = sessionDiff = 0;
588 DesktopList desktopList;
589 dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
591 if( totalDiff != 0 || sessionDiff != 0)
592 task->
changeTimes( sessionDiff, totalDiff, _storage );
596 if (desktopList.size() == (
unsigned int)_desktopTracker->desktopCount())
599 task->setDesktopList(desktopList);
601 _desktopTracker->registerForDesktops( task, desktopList );
603 emit updateButtons();
626 KMessageBox::information(0,i18n(
"No task selected."));
630 if (completion<0) completion=0;
636 emit updateButtons();
644 KMessageBox::information(0,i18n(
"No task selected."));
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?")
655 i18n(
"Deleting Task"), KStdGuiItem::del());
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());
667 if (response == KMessageBox::Continue)
669 if (markingascomplete)
674 emit updateButtons();
684 TQString uid=task->
uid();
685 task->
remove(activeTasks, _storage);
687 if( _preferences ) _preferences->deleteEntry( uid );
695 if (activeTasks.count() == 0) {
697 emit timersInactive();
700 emit tasksChanged( activeTasks );
711 kdDebug(5970) <<
"Entering extractTime" << endl;
712 addTimeToActiveTasks(-minutes,
false);
715 void TaskView::autoSaveChanged(
bool on)
717 if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute);
718 else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop();
721 void TaskView::autoSavePeriodChanged(
int )
723 autoSaveChanged(_preferences->autoSave());
726 void TaskView::adaptColumns()
737 for(
int x=1; x <= 4; x++) {
739 if( _preferences->displayColumn(x-1)
740 && previousColumnWidths[x-1] != HIDDEN_COLUMN )
742 setColumnWidth( x, previousColumnWidths[x-1] );
743 previousColumnWidths[x-1] = HIDDEN_COLUMN;
744 setColumnWidthMode( x, TQListView::Maximum );
748 if( ! _preferences->displayColumn(x-1)
749 && previousColumnWidths[x-1] == HIDDEN_COLUMN )
751 setColumnWidthMode( x, TQListView::Manual );
753 previousColumnWidths[x-1] = columnWidth( x );
754 setColumnWidth( x, 0 );
761 DesktopList desktopList;
763 _desktopTracker->registerForDesktops( deletedTask, desktopList );
764 activeTasks.removeRef( deletedTask );
766 emit tasksChanged( activeTasks);
773 kdDebug(5970) <<
"TaskView:iCalFileChanged: " << file << endl;
774 if (_storage->icalfile() != file)
777 _storage->save(
this);
783 const TQDate& to)
const
788 void TaskView::markTaskAsComplete()
791 kdDebug(5970) <<
"TaskView::markTaskAsComplete: "
794 kdDebug(5970) <<
"TaskView::markTaskAsComplete: null current_item()" << endl;
796 bool markingascomplete =
true;
800 void TaskView::markTaskAsIncomplete()
803 kdDebug(5970) <<
"TaskView::markTaskAsComplete: "
806 kdDebug(5970) <<
"TaskView::markTaskAsComplete: null current_item()" << endl;
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)
823 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
true, TimeKard::TotalTime));
827 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
false, TimeKard::TotalTime));
832 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
true, TimeKard::TotalTime));
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)
847 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
true, TimeKard::SessionTime));
851 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
false, TimeKard::SessionTime));
856 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
true, TimeKard::SessionTime));
863 if (dialog.exec()== TQDialog::Accepted)
866 TDEApplication::clipboard()->
867 setText( t.
historyAsText(
this, dialog.from(), dialog.to(), !dialog.allTasks(), dialog.perWeek(), dialog.totalsOnly() ) );
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.
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.
Provide an interface to the configuration options for the program.
Stores entries from export dialog.
this is the karm-taskview-specific implementation of qwhatsthis
Preferences * preferences()
Return preferences user selected on settings dialog.
KarmStorage * storage()
Returns a pointer to storage object.
void clipTotals()
Copy totals for current and all sub tasks to clipboard.
void iCalFileChanged(TQString file)
User might have picked a new iCalendar file on preferences screen.
Task * first_child() const
Return the first item in the view, cast to a Task pointer.
void loadFromFlatFile()
Used to import a legacy file format.
long count()
Return the total number if items in the view.
TQString exportcsvHistory()
Export comma-separated values format for task history.
void iCalFileModified(ResourceCalendar *)
React on another process having modified the iCal file we rely on.
void stopCurrentTimer()
Stop the timer for the current item in the view.
void resetTimeForAllTasks()
Reset session and total time to zero for all tasks.
void deletingTask(Task *deletedTask)
receiving signal that a task is being deleted
TQString importPlanner(TQString fileName="")
used to import tasks from imendio planner
void refresh()
Used to refresh (e.g.
void startCurrentTimer()
Start the timer on the current item (task) in view.
void closeStorage()
Close the storage and release lock.
TQString addTask(const TQString &taskame, long total, long session, const DesktopList &desktops, Task *parent=0)
Add a task to view and storage.
void extractTime(int minutes)
Subtracts time from all active tasks, and does not log event.
TQString report(const ReportCriteria &rc)
call export function for csv totals or history
void clipSession()
Copy session times for current and all sub tasks to clipboard.
Task * current_item() const
Return the current item in the view, cast to a Task pointer.
TQString save()
Save to persistent storage.
void exportcsvFile()
Export comma separated values format for task time totals.
Task * item_at_index(int i)
Return the i'th item (zero-based), cast to a Task pointer.
void clearActiveTasks()
clears all active tasks.
void newTask()
Calls newTask dialog with caption "New Task".
void load(TQString filename="")
Load the view from storage.
void clipHistory()
Copy history for current and all sub tasks to clipboard.
void deleteTask(bool markingascomplete=false)
Delete task (and children) from view.
void startTimerFor(Task *task, TQDateTime startTime=TQDateTime::currentDateTime())
starts timer for task.
void newSubTask()
Calls newTask dialog with caption "New Sub Task".
void scheduleSave()
Schedule that we should save very soon.
void itemStateChanged(TQListViewItem *item)
item state stores if a task is expanded so you can see the subtasks
void reinstateTask(int completion)
Reinstates the current task as incomplete.
void stopAllTimers()
Stop all running timers.
void stopAllTimersAt(TQDateTime qdt)
Stop all running timers as if it was qdt.
TQValueList< HistoryEvent > getHistory(const TQDate &from, const TQDate &to) const
Return list of start/stop events for given date range.
void startNewSession()
Reset session time to zero for all tasks.
A class representing a task.
void changeTimes(long minutesSession, long minutes, KarmStorage *storage=0)
Add minutes to time and session time, and write to storage.
void resetTimes()
Reset all times to 0.
void setRunning(bool on, KarmStorage *storage, TQDateTime whenStarted=TQDateTime::currentDateTime(), TQDateTime whenStopped=TQDateTime::currentDateTime())
starts or stops a task
bool isComplete()
Return true if task is complete (percent complete equals 100).
void removeFromView()
Remove current task and all it's children from the view.
TQString name() const
returns the name of this task.
void setName(const TQString &name, KarmStorage *storage)
sets the name of the task
void setPixmapProgress()
Sets an appropriate icon for this task based on its level of completion.
TQString uid() const
Return unique iCalendar Todo ID for this task.
void setPercentComplete(const int percent, KarmStorage *storage)
Update percent complete for this task.
bool remove(TQPtrList< Task > &activeTasks, KarmStorage *storage)
remove Task with all it's children
void startNewSession()
sets session time to zero.
void setUid(const TQString uid)
Set unique id for the task.
Routines to output timecard data.
TQString totalsAsText(TaskView *taskview, bool justThisTask, WhichTime which)
Generates ascii text of task totals, for current task on down.
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.