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, TQT_SIGNAL( expanded( TQListViewItem * ) ),
46 this, TQT_SLOT( itemStateChanged( TQListViewItem * ) ) );
47 connect(
this, TQT_SIGNAL( collapsed( TQListViewItem * ) ),
48 this, TQT_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, TQT_SIGNAL( timeout() ),
this, TQT_SLOT( minuteUpdate() ));
69 _minuteTimer->start(1000 * secsPerMinute);
72 connect(_preferences, TQT_SIGNAL(iCalFile(TQString)),
73 this, TQT_SLOT(iCalFileChanged(TQString)));
76 connect(_preferences, TQT_SIGNAL( setupChanged() ),
this,TQT_SLOT( adaptColumns() ));
78 _minuteTimer->start(1000 * secsPerMinute);
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();
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() ));
102 _manualSaveTimer =
new TQTimer(
this);
103 connect( _manualSaveTimer, TQT_SIGNAL( timeout() ),
this, TQT_SLOT( save() ));
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*) ));
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() == Qt::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);
487 void TaskView::minuteUpdate()
489 addTimeToActiveTasks(1,
false);
492 void TaskView::addTimeToActiveTasks(
int minutes,
bool save_data)
494 for(
unsigned int i = 0; i < activeTasks.count(); i++ )
495 activeTasks.at(i)->changeTime(minutes, ( save_data ? _storage : 0 ) );
506 long total, totalDiff, session, sessionDiff;
507 DesktopList desktopList;
509 int result = dialog->exec();
510 if ( result == TQDialog::Accepted ) {
511 TQString taskName = i18n(
"Unnamed Task" );
512 if ( !dialog->taskName().isEmpty()) taskName = dialog->taskName();
514 total = totalDiff = session = sessionDiff = 0;
515 dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList );
519 if ( desktopList.size() == (
unsigned int ) _desktopTracker->desktopCount() )
522 TQString uid =
addTask( taskName, total, session, desktopList, parent );
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/ " ) );
534 (
const TQString& taskname,
long total,
long session,
535 const DesktopList& desktops,
Task* parent )
538 kdDebug(5970) <<
"TaskView::addTask: taskname = " << taskname << endl;
540 if ( parent ) task =
new Task( taskname, total, session, desktops, parent );
541 else task =
new Task( taskname, total, session, desktops,
this );
543 task->
setUid( _storage->addTask( task, parent ) );
544 TQString taskuid=task->
uid();
545 if ( ! taskuid.isNull() )
547 _desktopTracker->registerForDesktops( task, desktops );
548 setCurrentItem( task );
549 setSelected( task,
true );
565 newTask(i18n(
"New Sub Task"), task);
570 void TaskView::editTask()
576 DesktopList desktopList = task->getDesktops();
578 dialog->setTask( task->
name(),
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();
588 task->
setName(taskName, _storage);
591 long total, session, totalDiff, sessionDiff;
592 total = totalDiff = session = sessionDiff = 0;
593 DesktopList desktopList;
594 dialog->status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
596 if( totalDiff != 0 || sessionDiff != 0)
597 task->
changeTimes( sessionDiff, totalDiff, _storage );
601 if (desktopList.size() == (
unsigned int)_desktopTracker->desktopCount())
604 task->setDesktopList(desktopList);
606 _desktopTracker->registerForDesktops( task, desktopList );
608 emit updateButtons();
631 KMessageBox::information(0,i18n(
"No task selected."));
635 if (completion<0) completion=0;
641 emit updateButtons();
649 KMessageBox::information(0,i18n(
"No task selected."));
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?")
660 i18n(
"Deleting Task"), KStdGuiItem::del());
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());
672 if (response == KMessageBox::Continue)
674 if (markingascomplete)
679 emit updateButtons();
689 TQString uid=task->
uid();
690 task->
remove(activeTasks, _storage);
692 if( _preferences ) _preferences->deleteEntry( uid );
700 if (activeTasks.count() == 0) {
702 emit timersInactive();
705 emit tasksChanged( activeTasks );
716 kdDebug(5970) <<
"Entering extractTime" << endl;
717 addTimeToActiveTasks(-minutes,
false);
720 void TaskView::autoSaveChanged(
bool on)
722 if (on) _autoSaveTimer->start(_preferences->autoSavePeriod()*1000*secsPerMinute);
723 else if (_autoSaveTimer->isActive()) _autoSaveTimer->stop();
726 void TaskView::autoSavePeriodChanged(
int )
728 autoSaveChanged(_preferences->autoSave());
731 void TaskView::adaptColumns()
742 for(
int x=1; x <= 4; x++) {
744 if( _preferences->displayColumn(x-1)
745 && previousColumnWidths[x-1] != HIDDEN_COLUMN )
747 setColumnWidth( x, previousColumnWidths[x-1] );
748 previousColumnWidths[x-1] = HIDDEN_COLUMN;
749 setColumnWidthMode( x, TQListView::Maximum );
753 if( ! _preferences->displayColumn(x-1)
754 && previousColumnWidths[x-1] == HIDDEN_COLUMN )
756 setColumnWidthMode( x, TQListView::Manual );
758 previousColumnWidths[x-1] = columnWidth( x );
759 setColumnWidth( x, 0 );
766 DesktopList desktopList;
768 _desktopTracker->registerForDesktops( deletedTask, desktopList );
769 activeTasks.removeRef( deletedTask );
771 emit tasksChanged( activeTasks);
778 kdDebug(5970) <<
"TaskView:iCalFileChanged: " << file << endl;
779 if (_storage->icalfile() != file)
782 _storage->save(
this);
788 const TQDate& to)
const
793 void TaskView::markTaskAsComplete()
796 kdDebug(5970) <<
"TaskView::markTaskAsComplete: "
799 kdDebug(5970) <<
"TaskView::markTaskAsComplete: null current_item()" << endl;
801 bool markingascomplete =
true;
805 void TaskView::markTaskAsIncomplete()
808 kdDebug(5970) <<
"TaskView::markTaskAsComplete: "
811 kdDebug(5970) <<
"TaskView::markTaskAsComplete: null current_item()" << endl;
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)
828 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
true, TimeKard::TotalTime));
832 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
false, TimeKard::TotalTime));
837 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
true, TimeKard::TotalTime));
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)
852 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
true, TimeKard::SessionTime));
856 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
false, TimeKard::SessionTime));
861 TDEApplication::clipboard()->setText(t.
totalsAsText(
this,
true, TimeKard::SessionTime));
868 if (dialog.exec()== TQDialog::Accepted)
871 TDEApplication::clipboard()->
872 setText( t.
historyAsText(
this, dialog.from(), dialog.to(), !dialog.allTasks(), dialog.perWeek(), dialog.totalsOnly() ) );
876 #include "taskview.moc"
void iCalFileModified(ResourceCalendar *)
React on another process having modified the iCal file we rely on.
void stopIdleDetection()
Stops detecting idle time.
TQString report(const ReportCriteria &rc)
call export function for csv totals or history
TQValueList< HistoryEvent > getHistory(const TQDate &from, const TQDate &to)
Return a list of start/stop events for the given date range.
TQString name() const
returns the name of this task.
Task * first_child() const
Return the first item in the view, cast to a Task pointer.
void startIdleDetection()
Starts detecting idle time.
Task * current_item() const
Return the current item in the view, cast to a Task pointer.
void startNewSession()
sets session time to zero.
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.
void load(TQString filename="")
Load the view from storage.
long count()
Return the total number if items in the view.
void setPercentComplete(const int percent, KarmStorage *storage)
Update percent complete for this task.
Keep track of how long the computer has been idle.
void scheduleSave()
Schedule that we should save very soon.
void stopCurrentTimer()
Stop the timer for the current item in the view.
Routines to output timecard data.
void clipHistory()
Copy history for current and all sub tasks to clipboard.
bool isComplete()
Return true if task is complete (percent complete equals 100).
void stopAllTimersAt(TQDateTime qdt)
Stop all running timers as if it was qdt.
void loadFromFlatFile()
Used to import a legacy file format.
void clearActiveTasks()
clears all active tasks.
void resetTimes()
Reset all times to 0.
void newTask()
Calls newTask dialog with caption "New Task".
void deleteTask(bool markingascomplete=false)
Delete task (and children) from view.
void startNewSession()
Reset session time to zero for all tasks.
TQString report(TaskView *taskview, const ReportCriteria &rc)
Output a report based on contents of ReportCriteria.
Task * item_at_index(int i)
Return the i'th item (zero-based), cast to a Task pointer.
void refresh()
Used to refresh (e.g.
void startTimerFor(Task *task, TQDateTime startTime=TQDateTime::currentDateTime())
starts timer for task.
void startCurrentTimer()
Start the timer on the current item (task) in view.
void exportcsvFile()
Export comma separated values format for task time totals.
void closeStorage()
Close the storage and release lock.
Singleton to store/retrieve KArm data to/from persistent storage.
Stores entries from export dialog.
Dialog to add a new task or edit an existing task.
void setUid(const TQString uid)
Set unique id for the task.
void removeFromView()
Remove current task and all it's children from the view.
TQString addTask(const TQString &taskame, long total, long session, const DesktopList &desktops, Task *parent=0)
Add a task to view and storage.
TQString totalsAsText(TaskView *taskview, bool justThisTask, WhichTime which)
Generates ascii text of task totals, for current task on down.
TQString save()
Save to persistent storage.
Preferences * preferences()
Return preferences user selected on settings dialog.
void itemStateChanged(TQListViewItem *item)
item state stores if a task is expanded so you can see the subtasks
void extractTime(int minutes)
Subtracts time from all active tasks, and does not log event.
void resetTimeCurrentTask()
Reset session and total time to zero for the current item in the view.
TQString importPlanner(TQString fileName="")
used to import tasks from imendio planner
void setName(const TQString &name, KarmStorage *storage)
sets the name of the task
TQString uid() const
Return unique iCalendar Todo ID for this task.
this class is here to import tasks from a planner project file to karm.
void clipSession()
Copy session times for current and all sub tasks to clipboard.
A utility to associate tasks with desktops As soon as a desktop is activated/left - an signal is emit...
TQString exportcsvHistory()
Export comma-separated values format for task history.
void newSubTask()
Calls newTask dialog with caption "New Sub Task".
Provide an interface to the configuration options for the program.
void deletingTask(Task *deletedTask)
receiving signal that a task is being deleted
KarmStorage * storage()
Returns a pointer to storage object.
void setPixmapProgress()
Sets an appropriate icon for this task based on its level of completion.
void stopAllTimers()
Stop all running timers.
A class representing a task.
void iCalFileChanged(TQString file)
User might have picked a new iCalendar file on preferences screen.
void changeTimes(long minutesSession, long minutes, KarmStorage *storage=0)
Add minutes to time and session time, and write to storage.
void clipTotals()
Copy totals for current and all sub tasks to clipboard.
void setRunning(bool on, KarmStorage *storage, TQDateTime whenStarted=TQDateTime::currentDateTime(), TQDateTime whenStopped=TQDateTime::currentDateTime())
starts or stops a task
void resetTimeForAllTasks()
Reset session and total time to zero for all tasks.
TQValueList< HistoryEvent > getHistory(const TQDate &from, const TQDate &to) const
Return list of start/stop events for given date range.
bool remove(TQPtrList< Task > &activeTasks, KarmStorage *storage)
remove Task with all it's children
TQString loadFromFlatFile(TaskView *taskview, const TQString &filename)
Read tasks and their total times from a text file (legacy storage).
void reinstateTask(int completion)
Reinstates the current task as incomplete.
this is the karm-taskview-specific implementation of qwhatsthis