Bug 84152

Summary: Persistent Time Data option
Product: [Applications] ktimetracker Reporter: Jason Curl <j.m.curl>
Component: generalAssignee: Thorsten Staerk <dev>
Status: RESOLVED FIXED    
Severity: wishlist    
Priority: NOR    
Version: Git (master)   
Target Milestone: ---   
Platform: RedHat Enterprise Linux   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: next try
set dtStart when the timer starts, dtEnd when the timer stops
set dtStart when the timer starts, dtEnd not before timer stops
seems to work now
works now

Description Jason Curl 2004-06-28 12:51:06 UTC
Version:           1.2 (using KDE KDE 3.2.1KDE 1.2)
Installed from:    RedHat RPMsRedHat RPMs
Compiler:          - -
OS:                Linux

It would be very useful to have two modes of operation - the mode that KArm has at the moment (it tracks time while it is running) and a "Persistent" mode.

The persistent mode could be enabled through a preferences window and would change the behaviour of the application (i.e. all tasks). If the program was closed (or crashed, or the machine crashed, server shutdown, or whatever), on exit it would save the session data, the current task active, the time the program shutdown, so that on the next power on it can calculate how long it was down for, and on the next startup it can resume (adding to the task the time the system was down).

This is useful for example, where there is a main server and I'm running Windoze on my laptop. I need to move my laptop, and consequently must shutdown Karm for some period of time. Later connecting my laptop and running Karm, it would look like as if the program never had been exited. 

Of course, if a user forgets to stop the task before they exit the program, it will come up with some rediculously long duration. A dialog box might appear to ask if "xxx minutes" should be added to task "yyy".
Comment 1 Mark Bucciarelli 2004-07-05 15:18:09 UTC
Thanks for your report!

Currently, I am working on the documentation for the 3.3 release.  Once that is out, I'll go over all open bugs and prioritize them.
Comment 2 Thorsten Staerk 2007-03-29 10:30:35 UTC
That is a cool idea. I plan to implement it for KDE 4 (that is due on October 23rd, 2007).
Comment 3 Thorsten Staerk 2007-09-08 20:35:43 UTC
Here's some pseudo-code how we could accomplish this.

Index: karmstorage.h
===================================================================
--- karmstorage.h       (revision 709914)
+++ karmstorage.h       (working copy)
@@ -223,12 +223,12 @@
     /**
      * Log the event that a timer has started for a task.
      *
-     * For the iCalendar storage, there is no need to log anything for this
-     * event.  We log an event when the timer is stopped.
+     * Set dtStart to the starttime. So, if karm crashes, it can
+     * ask the user if it may continue timing.
      *
      * @param task    The task the timer was started for.
      */
-    void startTimer(const Task* task) { Q_UNUSED(task); }
+    void startTimer(const Task* task);

     /**
      * Log the event that the timer has stopped for this task.
Index: karmstorage.cpp
===================================================================
--- karmstorage.cpp     (revision 709914)
+++ karmstorage.cpp     (working copy)
@@ -1049,6 +1049,11 @@
   return err;
 }

+void KarmStorage::startTimer(const Task* task)
+{
+  task->setDtEnd(QDateTime::currentDateTime());
+}
+
 void KarmStorage::stopTimer(const Task* task, QDateTime when)
 {
   kdDebug(5970) << "Entering KarmStorage::stopTimer" << endl;
Comment 4 Thorsten Staerk 2007-09-10 22:39:46 UTC
near to a solution:

Index: taskview.cpp
===================================================================
--- taskview.cpp        (revision 710266)
+++ taskview.cpp        (working copy)
@@ -644,10 +644,12 @@

 void TaskView::stopTimerFor(Task* task)
 {
-  if ( task != 0 && d->mActiveTasks.indexOf(task) != -1 ) {
+  if ( task != 0 && d->mActiveTasks.indexOf(task) != -1 )
+  {
     d->mActiveTasks.removeAll(task);
     task->setRunning(false, d->mStorage);
-    if ( d->mActiveTasks.count() == 0 ) {
+    if ( d->mActiveTasks.count() == 0 )
+    {
       _idleTimeDetector->stopIdleDetection();
       emit timersInactive();
     }
@@ -659,7 +661,8 @@
 void TaskView::stopCurrentTimer()
 {
   stopTimerFor( currentItem() );
-  if ( d->mFocusTrackingActive && d->mLastTaskWithFocus == currentItem() ) {
+  if ( d->mFocusTrackingActive && d->mLastTaskWithFocus == currentItem() )
+  {
     toggleFocusTracking();
   }
 }
Index: karmstorage.h
===================================================================
--- karmstorage.h       (revision 710266)
+++ karmstorage.h       (working copy)
@@ -199,7 +199,7 @@
      *
      * @param task    The task the timer was started for.
      */
-    void startTimer(const Task* task) { Q_UNUSED(task); }
+    void startTimer(const Task* task, const KDateTime &when=KDateTime::currentLocalDateTime());

     /**
      * Log the event that the timer has stopped for this task.
Index: karmstorage.cpp
===================================================================
--- karmstorage.cpp     (revision 710362)
+++ karmstorage.cpp     (working copy)
@@ -873,12 +873,34 @@
   return err;
 }

+void KarmStorage::startTimer( const Task* task, const KDateTime &when )
+{
+  KCal::Event* e;
+  QDateTime end;
+
+  e = baseEvent(task);
+
+  e->setDtStart(when);
+
+  d->mCalendar->addEvent(e);
+
+  task->taskView()->scheduleSave();
+}
+
 void KarmStorage::stopTimer( const Task* task, const QDateTime &when )
 {
   kDebug(5970) <<"Entering stopTimer when=" << when;
   kDebug(5970) <<"task->startTime=" << task->startTime();
-  long delta = task->startTime().secsTo(when);
-  changeTime(task, delta);
+  KCal::Event::List eventList = d->mCalendar->rawEvents();
+  for(KCal::Event::List::iterator i = eventList.begin();
+      i != eventList.end();
+      ++i)
+  {
+    if ( (*i)->uid() == task->uid() )
+    {
+      if ((*i)->dtEnd().isNull()) (*i)->setDtEnd((KDateTime&) when);
+    };
+  }
 }

 bool KarmStorage::bookTime(const Task* task,
@@ -924,14 +946,6 @@

   d->mCalendar->addEvent(e);

-  // This saves the entire iCal file each time, which isn't efficient but
-  // ensures no data loss.  A faster implementation would be to append events
-  // to a file, and then when KArm closes, append the data in this file to the
-  // iCal file.
-  //
-  // Meanwhile, we simply use a timer to delay the full-saving until the GUI
-  // has updated, for better user feedback. Feel free to get rid of this
-  // if/when implementing the faster saving (DF).
   task->taskView()->scheduleSave();
 }
Comment 5 Thorsten Staerk 2007-09-11 21:13:23 UTC
Created attachment 21608 [details]
next try
Comment 6 Thorsten Staerk 2007-09-14 06:36:07 UTC
Created attachment 21624 [details]
set dtStart when the timer starts, dtEnd when the timer stops
Comment 7 Thorsten Staerk 2007-09-15 12:41:49 UTC
Created attachment 21629 [details]
set dtStart when the timer starts, dtEnd not before timer stops

discovered hasEndDate(); this is much cleaner than provoking an invalid date.
Comment 8 Thorsten Staerk 2007-09-15 13:51:25 UTC
SVN commit 712828 by tstaerk:

Allow saving an ics file that has not yet an end-date.
CCBUGS:84152


 M  +25 -11    karmstorage.cpp  
 M  +1 -1      karmstorage.h  
 M  +1 -2      mainwindow.cpp  
 M  +6 -3      taskview.cpp  


WebSVN link: http://websvn.kde.org/?view=rev&revision=712828
Comment 9 Thorsten Staerk 2007-12-03 08:43:48 UTC
Created attachment 22298 [details]
seems to work now
Comment 10 Thorsten Staerk 2007-12-03 13:38:21 UTC
SVN commit 744312 by tstaerk:

Allow saving a task that is running (e.g. has no endtime).
CCBUGS:84152 



 M  +5 -4      karmstorage.cpp  
 M  +3 -1      mainwindow.cpp  
 M  +0 -1      taskview.cpp  
 M  +16 -7     timetrackerwidget.cpp  


WebSVN link: http://websvn.kde.org/?view=rev&revision=744312
Comment 11 Thorsten Staerk 2008-03-27 22:41:06 UTC
The problem is that we can never find out if a task has been stopped or not with KDE 4, because of bug 159976
Comment 12 Thorsten Staerk 2008-04-27 11:19:11 UTC
Created attachment 24534 [details]
works now

This works now, but, hey, we have already waited almost 4 years... and I want
to celebrate this bug's fourth birthday, come on, we can spend these few days
also.
Comment 13 Thorsten Staerk 2008-04-27 11:29:36 UTC
SVN commit 801639 by tstaerk:

Allow a task to be timed accross a time when ktimetracker is not
running.
BUGS:84152


 M  +21 -3     karmstorage.cpp  
 M  +10 -0     karmstorage.h  
 M  +15 -2     task.cpp  
 M  +9 -1      task.h  
 M  +19 -3     taskview.cpp  


WebSVN link: http://websvn.kde.org/?view=rev&revision=801639