Bug 85328

Summary: Auto tracking by app not only by desktop
Product: [Applications] ktimetracker Reporter: Jos <jpablo>
Component: generalAssignee: René Mérou <ochominutosdearco>
Status: CLOSED FIXED    
Severity: wishlist CC: daniel.vos, dev, shafff
Priority: NOR    
Version: Git (master)   
Target Milestone: ---   
Platform: unspecified   
OS: All   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: patch to autotrack the focused windows and start / restart timers for tasks and stop timers for last focused windows
please base your development on this patch from now on
code cleanUp
this time I forgot to svn add some files
now in C code, not in bash

Description Jos 2004-07-16 13:32:47 UTC
Version:            (using KDE KDE 3.2.2)
Installed from:    RedHat RPMs
OS:                Linux

Auto tracking by desktop is a good idea. I think auto tracking by active application is also util.
I want to know the time I spend using kmail, developing in kdevelop or the time spend playing a game.
Comment 1 Mark Bucciarelli 2004-07-25 16:51:10 UTC
Yes, of course.  Thanks.
Comment 2 Thorsten Staerk 2006-04-06 22:00:49 UTC
And what do you want to do if two programs are running ? Sorry, this bug report is not complete - and if it was, I doubt it wouldn't make everything far too complicated.
Comment 3 Helge Hielscher 2006-04-07 06:09:07 UTC
The RFE was not about running apps, but about active ones, for me that means tracking the applications that have focus.
Comment 4 Thorsten Staerk 2007-01-14 00:17:25 UTC
*** Bug 137366 has been marked as a duplicate of this bug. ***
Comment 5 Thorsten Staerk 2007-07-25 13:31:47 UTC
found someone who is doing it
Comment 6 René Mérou 2007-07-25 15:00:04 UTC
Created attachment 21245 [details]
patch to autotrack the focused windows and start / restart timers for tasks  and stop timers for last focused windows
Comment 7 René Mérou 2007-07-25 15:13:20 UTC
Comment on attachment 21245 [details]
patch to autotrack the focused windows and start / restart timers for tasks  and stop timers for last focused windows

Index: taskview.h
===================================================================
--- taskview.h	(revisión: 692380)
+++ taskview.h	(copia de trabajo)
@@ -30,8 +30,19 @@
 #include "desktoplist.h"
 #include "karmstorage.h"
 #include "reportcriteria.h"
+<<<<<<< .mine
+#include "focusdetector.h"
+#include <QTimer>
+#include <QTableWidget>
+#include <QTreeWidget>
+=======
+>>>>>>> .r692366

+<<<<<<< .mine
+
+=======
 class QMouseEvent;
+>>>>>>> .r692366
 class QString;
 class QTableWidget;
 class QTextStream;
@@ -39,6 +50,7 @@

 class DesktopTracker;
 class IdleTimeDetector;
+class FocusDetector;
 class Preferences;
 class Task;
 class KarmStorage;
@@ -138,6 +150,10 @@
     /** Calls newTask dialog with caption "New Sub Task". */
     void newSubTask();

+    /** start the autotracking system to add tasks to control time for every
focused windows **/
+    void startAutoTracking();
+    /** stop the autotracking system to add tasks to control time for every
focused windows **/    void stopAutoTracking();
+
     void editTask();

     /**
@@ -181,7 +197,7 @@
      * @param startTime if taskview has been modified by another program, we
			     have to set the starting time to not-now. */
     void startTimerFor( Task* task, QDateTime startTime =
QDateTime::currentDateTime() );
-     void stopTimerFor( Task* task );
+    void  stopTimerFor( Task* task );

     /** clears all active tasks. Needed e.g. if iCal file was modified by
	another program and taskview is cleared without stopping tasks
@@ -198,8 +214,15 @@

     /** Copy history for current and all sub tasks to clipboard. */
     QString clipHistory();
+<<<<<<< .mine

+
+
+  signals:
+=======
+
   Q_SIGNALS:
+>>>>>>> .r692366
     void totalTimesChanged( long session, long total );
     void updateButtons();
     void timersActive();
@@ -209,11 +232,13 @@

   private: // member variables
     IdleTimeDetector *_idleTimeDetector;
+    FocusDetector *_focusDetector;
     QTimer *_minuteTimer;
     QTimer *_autoSaveTimer;
     QTimer *_manualSaveTimer;
     Preferences *_preferences;
     QList<Task*> activeTasks;
+    Task*  lastTaskWithFocus;
     DesktopTracker* _desktopTracker;
     bool _isloading;
     Task* dragTask;
@@ -236,6 +261,8 @@
     void mousePressEvent( QMouseEvent* );

   protected Q_SLOTS:
+    /** newfocuswindowdetected will have the name of that windows at the
QString **/
+    void newFocusWindowDetected (QString);
     void autoSaveChanged( bool );
     void autoSavePeriodChanged( int period );
     void minuteUpdate();
Index: focusdetector.h
===================================================================
--- focusdetector.h	(revisión: 0)
+++ focusdetector.h	(revisión: 0)
@@ -0,0 +1,90 @@
+/*
+ *	Copyright (C) 2007 René Mérou
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License along
+ *   with this program; if not, write to the
+ *	 Free Software Foundation, Inc.
+ *	 51 Franklin Street, Fifth Floor
+ *	 Boston, MA  02110-1301  USA.
+ *
+ * @short Logic that gets and stores tasks from focused windows.
+ * @author René Mérou <ochominutosdearco@gmail.com>
+ */
+
+#ifndef KARM_IDLE_TIME_DETECTOR_H
+#define KARM_IDLE_TIME_DETECTOR_H
+
+#include <QDateTime>
+#include <QObject>
+#include "config-karm.h" // HAVE_LIBXSS
+
+class QTimer;
+
+//#if defined(HAVE_LIBXSS) && defined(Q_WS_X11)
+// #include <X11/Xlib.h>
+// #include <X11/Xutil.h>
+// #include <X11/extensions/scrnsaver.h>
+// #include <fixx11h.h>
+//#endif // HAVE_LIBXSS
+
+const int periodInterval = 1000;//mil veces por segundo y 5 segundos  es una
vez cada cinco seguntos
+
+/**
+ * Keep track of what windonw has the focus.
+ */
+
+class FocusDetector :public QObject
+{
+Q_OBJECT
+
+public:
+  /**
+     Initializes the time period
+     @param periodFocus minutes before every focus detection.
+  **/
+  FocusDetector(int periodFocus);
+
+  /**
+     Sets the period of time before every focus search.
+     @param periodFocus period of time in minutes
+  **/
+  void setPeriodFocus(int periodFocus);
+
+  /**
+     Starts detecting focus
+  **/
+  void startFocusDetection();
+
+  /**
+      Stops detecting focus.
+  **/
+  void stopFocusDetection();
+
+signals:
+
+    void newFocus(QString);
+
+
+
+protected slots:
+  void check();
+
+private:
+
+  int _periodFocus;
+  QTimer *_timer;
+  QDateTime start; // when the periodFocus restarted
+
+};
+
+#endif // KARM_IDLE_TIME_DETECTOR_H
Index: taskview.cpp
===================================================================
--- taskview.cpp	(revisión: 692380)
+++ taskview.cpp	(copia de trabajo)
@@ -34,6 +34,15 @@
 #include <QList>
 #include <QListWidget>

+<<<<<<< .mine
+#include <kapplication.h>	 // kapp  con < > y no con ""
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <klocale.h>		 // i18n
+#include <kmessagebox.h>
+#include <kurlrequester.h>
+=======
 #include <KApplication>       // kapp
 #include <KConfig>
 #include <KDebug>
@@ -41,11 +50,17 @@
 #include <KLocale>	       // i18n
 #include <KMessageBox>
 #include <KUrlRequester>
+>>>>>>> .r692366

 #include "csvexportdialog.h"
 #include "desktoptracker.h"
 #include "edittaskdialog.h"
 #include "idletimedetector.h"
+<<<<<<< .mine
+#include "focusdetector.h"
+#include "karmstorage.h"
+=======
+>>>>>>> .r692366
 #include "plannerparser.h"
 #include "preferences.h"
 #include "printdialog.h"
@@ -116,6 +131,7 @@
	    this, SLOT(slotItemDoubleClicked(QTreeWidgetItem*, int)) );

   QStringList labels;
+  QString namewindowfocus;
   labels << i18n("Task Name") << i18n("Session Time") << i18n("Time") <<
i18n("Total Session Time") << i18n("Total Time") << i18n("Percent Complete") ;
   setHeaderLabels(labels);
   headerItem()->setWhatsThis(0,"The task name is how you call the task, it can
be chose freely.");
@@ -140,23 +156,22 @@

   // Set up the idle detection.
   _idleTimeDetector = new IdleTimeDetector( _preferences->idlenessTimeout() );
-  connect( _idleTimeDetector, SIGNAL( extractTime(int) ),
-	    this, SLOT( extractTime(int) ));
-  connect( _idleTimeDetector, SIGNAL( stopAllTimers(QDateTime) ),
-	    this, SLOT( stopAllTimers(QDateTime) ));
-  connect( _preferences, SIGNAL( idlenessTimeout(int) ),
-	    _idleTimeDetector, SLOT( setMaxIdle(int) ));
-  connect( _preferences, SIGNAL( detectIdleness(bool) ),
-	    _idleTimeDetector, SLOT( toggleOverAllIdleDetection(bool) ));
-  if (!_idleTimeDetector->isIdleDetectionPossible())
-    _preferences->disableIdleDetection();
+  connect( _idleTimeDetector, SIGNAL( extractTime(int) ), this, SLOT(
extractTime(int) ));
+  connect( _idleTimeDetector, SIGNAL( stopAllTimers(QDateTime) ), this, SLOT(
stopAllTimers(QDateTime) ));
+  connect( _preferences, SIGNAL( idlenessTimeout(int) ), _idleTimeDetector,
SLOT( setMaxIdle(int) ));
+  connect( _preferences, SIGNAL( detectIdleness(bool) ), _idleTimeDetector,
SLOT( toggleOverAllIdleDetection(bool) ));

+  if (!_idleTimeDetector->isIdleDetectionPossible())
_preferences->disableIdleDetection();
+
+// Set up the focus detection.
+  _focusDetector = new FocusDetector(30);
+  connect( _focusDetector, SIGNAL( newFocus(QString) ), this, SLOT(
newFocusWindowDetected (QString) ));
+
   // Setup auto save timer
   _autoSaveTimer = new QTimer(this);
   connect( _preferences, SIGNAL( autoSave(bool) ),
	    this, SLOT( autoSaveChanged(bool) ));
-  connect( _preferences, SIGNAL( autoSavePeriod(int) ),
-	    this, SLOT( autoSavePeriodChanged(int) ));
+  connect( _preferences, SIGNAL( autoSavePeriod(int) ),this, SLOT(
autoSavePeriodChanged(int) ));
   connect( _autoSaveTimer, SIGNAL( timeout() ), this, SLOT( save() ));

   // Setup manual save timer (to save changes a little while after they
happen)
@@ -536,7 +551,14 @@

 void TaskView::startTimerFor(Task* task, QDateTime startTime )
 {
+<<<<<<< .mine
+ kDebug(5970) << "Entering TaskView::startTimerFor" << endl;
+
+   _focusDetector->startFocusDetection();
+ if (task != 0 && activeTasks.findRef(task) == -1)
+=======
   if (task != 0 && activeTasks.indexOf(task) == -1)
+>>>>>>> .r692366
   {
     if (_preferences->uniTasking()) stopAllTimers();
     _idleTimeDetector->startIdleDetection();
@@ -552,7 +574,11 @@

 void TaskView::clearActiveTasks()
 {
+ kDebug(5970) << "Entering TaskView::clearActiveTasks" << endl;
   activeTasks.clear();
+  _focusDetector->startFocusDetection();
+
+
 }

 void TaskView::stopAllTimers( QDateTime when )
@@ -562,6 +588,7 @@
     activeTasks.at(i)->setRunning(false, _storage, when);

   _idleTimeDetector->stopIdleDetection();
+  _focusDetector->stopFocusDetection();
   activeTasks.clear();
   emit updateButtons();
   emit timersInactive();
@@ -655,6 +682,8 @@
       desktopList.clear();

     QString uid = addTask( taskName, total, session, desktopList, parent );
+     //kDebug(5970) << "addTask taskname = " << taskName << "total:" << total
<< "totaldif:" << totalDiff << "sesion:" << session << "sesiondif:" <<
sessionDiff << "desktopList" << desktopList <<	endl;
+
     if ( uid.isNull() )
     {
       KMessageBox::error( 0, i18n(
@@ -861,6 +890,59 @@
   autoSaveChanged(_preferences->autoSave());
 }

+void TaskView::newFocusWindowDetected(const QString taskName)
+{
+  const DesktopList desktopList;
+  Task* task=0;
+  QString rval="";
+  QString taskuid;
+  stopTimerFor(lastTaskWithFocus);
+  int i=0;
+  for ( Task* task3 = item_at_index(i); task3; task3 = item_at_index(++i) )
+      {
+	  //kDebug(5970) << "seen this task = -"  << task3->name() << "-" <<
taskName << "-"<< endl;
+	  if (task3->name()==taskName)
+	   {
+	      rval="inside";
+	      //kDebug(5970) << "this task has same codename "	<< taskName <<
" " << task3->name() << endl;
+	      startTimerFor(task3);
+	      lastTaskWithFocus=task3;
+	   }
+      }
+  if  (rval=="")
+      {
+	 //kDebug(5970) << "there is not task with that codename " << taskName 
<< endl;
+	  taskuid= addTask(taskName, 0L, 0L, desktopList,  task );
+	if ( taskuid.isNull() )
+	   {
+		    KMessageBox::error( 0, i18n(
+	    "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 ~/.kde/share/apps/kabc/lock/ " )
);
+	    }
+	 i=0;
+	 for ( Task* task3 = item_at_index(i); task3; task3 =
item_at_index(++i) )
+	   {
+	      //kDebug(5970) << "seen this task (not here) -"  << task3->name()
<< "-" << taskName << "-"<< endl;
+
+	      if (task3->name()==taskName)
+	       {
+		  rval="inside";
+		  //kDebug(5970) << "the task is here = "  << taskName << " "
<< task3->name() << endl;
+		  startTimerFor(task3);
+		  lastTaskWithFocus=task3;
+	       }
+	  }
+	}
+  i=0;
+  //kDebug(5970) << "list of tasks -"	<< task3->name() << "-" << taskName <<
"-"<< endl;
+  //for ( Task* task3 = item_at_index(i); task3; task3 = item_at_index(++i) )
+  //	 {
+  //	    kDebug(5970) << "task: -"  << task3->name() << "-" << taskName <<
"-"<< endl;
+  //	 }
+  emit updateButtons();
+}
+
+
+
 void TaskView::adaptColumns()
 /* This procedure adapts the columns, it can e.g. be called when the user
 changes the time format or requests to hide some columns.
Index: focusdetector.cpp
===================================================================
--- focusdetector.cpp	(revisión: 0)
+++ focusdetector.cpp	(revisión: 0)
@@ -0,0 +1,94 @@
+/*
+ *	Copyright (C) 2007 René Mérou
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License along
+ *   with this program; if not, write to the
+ *	 Free Software Foundation, Inc.
+ *	 51 Franklin Street, Fifth Floor
+ *	 Boston, MA  02110-1301  USA.
+ *
+ * @short Logic that gets and stores tasks from focused windows.
+ * @author René Mérou <ochominutosdearco@gmail.com>
+ */
+#include <QProcess>
+#include "focusdetector.h"
+
+#include <qdatetime.h>
+#include <qmessagebox.h>
+#include <qtimer.h>
+
+#include <kdialog.h>
+#include <kglobal.h>
+#include <klocale.h>	 // i18n
+#include <QLabel>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#ifdef Q_WS_X11
+#include <QX11Info>
+#endif
+  QString lastWindow="";
+FocusDetector::FocusDetector(int periodFocus)
+{
+  _timer = new QTimer(this);
+  connect(_timer, SIGNAL(timeout()), this, SLOT(check()));
+  _timer->start(1000*periodFocus);
+}
+
+void FocusDetector::check()
+{
+ QProcess focusQuestion;
+ QString mensaje="xprop -root";
+ QString trozo1,trozo2,trozo3;
+ QString cadena="_NET_ACTIVE_WINDOW(WINDOW): window id # ";
+
+ focusQuestion.setProcessChannelMode(QProcess::MergedChannels);
+ focusQuestion.start( mensaje );
+
+ if (!focusQuestion.waitForFinished())
+     qDebug() << "Make failed:" << focusQuestion.errorString();
+ else
+     trozo1=focusQuestion.readAll();
+     trozo3=trozo1.mid(trozo1.lastIndexOf(cadena)+40,9);
+     trozo3="xwininfo -id " + trozo3;
+     focusQuestion.start(trozo3);
+ if (!focusQuestion.waitForFinished())
+     qDebug() << "Make failed:" << focusQuestion.errorString();
+ else
+     trozo1=focusQuestion.readAll();
+     trozo2=trozo1.mid(trozo1.lastIndexOf("Window id")+22,200);
+     trozo3=trozo2.left( trozo2.indexOf("Absolute upper-left X")-5);
+     if (lastWindow!=trozo3) {
+	 lastWindow=trozo3;
+	qDebug() << "NEW WINDOW WITH FOCUS; Sending signal:" << trozo3 << endl;
+	 emit (newFocus(trozo3));
+     }
+}
+
+void FocusDetector::setPeriodFocus(int periodFocus)
+{
+  _periodFocus = periodFocus;
+}
+
+void FocusDetector::startFocusDetection()
+{
+  if (!_timer->isActive())
+    _timer->start(periodInterval);
+}
+
+void FocusDetector::stopFocusDetection()
+{
+  if (_timer->isActive())
+    _timer->stop();
+}
+
+#include "focusdetector.moc"
Index: mainwindow.cpp
===================================================================
--- mainwindow.cpp	(revisión: 692380)
+++ mainwindow.cpp	(copia de trabajo)
@@ -159,7 +159,20 @@
   saveGeometry();
   return true;
 }
+void MainWindow::topWindowTracker()
+{
+  int a=0;
+  kDebug(5970) << "entro en topWindowTracker." << endl;
+  //statusBar()->showMessage(i18n("pase por aqui"),1807);
+  statusBar()->showMessage(i18n("Successfullyy saved tasks and
history"),1807);
+  while (a<1000){
+	a=a+1;
+	statusBar()->showMessage(i18n("Successfullyyyy saved tasks and
history"),1807);
+	//statusBar()->showMessage(i18n("pase por aqui %i"),1807,a);
+  }
+}

+
 void MainWindow::exportcsvHistory()
 {
   kDebug(5970) << "Exporting History to disk." << endl;
Index: idletimedetector.h
===================================================================
--- idletimedetector.h	(revisión: 692380)
+++ idletimedetector.h	(copia de trabajo)
@@ -19,8 +19,8 @@
  *
  */

-#ifndef KARM_IDLE_TIME_DETECTOR_H
-#define KARM_IDLE_TIME_DETECTOR_H
+#ifndef KARM_FOCUS_DETECTOR_H
+#define KARM_FOCUS_DETECTOR_H

 #include <QDateTime>
 #include <QObject>
@@ -112,6 +112,9 @@
 protected Q_SLOTS:
   void check();

+  signals:
+  void focusChanged();
+
 private:
 #if defined(HAVE_LIBXSS) && defined(Q_WS_X11)
   XScreenSaverInfo *_mit_info;
Index: mainwindow.h
===================================================================
--- mainwindow.h	(revisión: 692380)
+++ mainwindow.h	(copia de trabajo)
@@ -102,6 +102,8 @@
     QString setpromptdelete( bool prompt );
     QString exportcsvfile( QString filename, QString from, QString to, int
type, bool decimalMinutes, bool allTasks, QString delimiter, QString quote );
     QString importplannerfile( QString filename );
+    /** test topwindowtracker */
+    void topWindowTracker();

   public Q_SLOTS:
     void setStatusBar( const QString& );
@@ -109,7 +111,13 @@
     void quit();
     /** Save the calendar */
     bool save();
+<<<<<<< .mine
+
+
+  protected slots:
+=======
   protected Q_SLOTS:
+>>>>>>> .r692366
     void keyBindings();
     void startNewSession();
     void resetAllTimes();
Index: main.cpp
===================================================================
--- main.cpp	(revisión: 692380)
+++ main.cpp	(copia de trabajo)
@@ -56,6 +56,7 @@
   aboutData.addAuthor( ki18n("Jesper Pedersen"),   KLocalizedString(),
"blackie@kde.org" );
   aboutData.addAuthor( ki18n("Kalle Dalheimer"),   KLocalizedString(),
"kalle@kde.org" );
   aboutData.addAuthor( ki18n("Mark Bucciarelli"),  KLocalizedString(),
"mark@hubcapconsulting.com" );
+  aboutData.addAuthor( ki18n("René Mérou"),	      KLocalizedString(),
"ochominutosdearco@gmail.com" );

   KCmdLineArgs::init( argc, argv, &aboutData );

Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revisión: 692380)
+++ CMakeLists.txt	(copia de trabajo)
@@ -13,7 +13,7 @@
 ########### next target ###############
 set(karm_shared_SRCS
	kaccelmenuwatch.cpp desktoptracker.cpp
-	edittaskdialog.cpp idletimedetector.cpp
+	edittaskdialog.cpp idletimedetector.cpp focusdetector.cpp
	printdialog.cpp timekard.cpp karmutility.cpp ktimewidget.cpp
	karmstorage.cpp mainwindow.cpp preferences.cpp print.cpp
	task.cpp taskview.cpp tray.cpp
Comment 8 Thorsten Staerk 2007-07-26 23:02:35 UTC
please also paste the patch's implementation of startautotracking and stopautotracking.
Comment 9 Thorsten Staerk 2007-07-27 06:19:39 UTC
Created attachment 21258 [details]
please base your development on this patch from now on

guy, that's amazing. It works. I have never had so much fun testing out a patch
- to see it just work is unbelievable. Good work, trebol, I had'nt thought a
beginner would be able to make it.

I refined your patch and attached it, it does no longer contain any conflicts,
it compiles and is taken against the latest version. However, still some
refinements needed.
Comment 10 Thorsten Staerk 2007-07-27 07:04:44 UTC
Created attachment 21259 [details]
code cleanUp
Comment 11 Thorsten Staerk 2007-07-27 07:46:48 UTC
I do not like focusdetector.cpp, in principle, you do not more than executing 

xwininfo -id $(xprop -root | grep "NET_ACTIVE_WINDOW(WINDOW):" | sed "s/_NET_ACTIVE_WINDOW(WINDOW): window id # //") | grep xwininfo | sed "s/xwininfo: Window id: 0x[0-9a-f]* //"

and you should also show this and make the string configurable.
Comment 12 Thorsten Staerk 2007-07-27 09:59:41 UTC
Created attachment 21263 [details]
this time I forgot to svn add some files
Comment 13 Thorsten Staerk 2007-07-27 10:53:10 UTC
SVN commit 693146 by tstaerk:

Allow tracking your time by focus on applications.
BUGS:85328



 M  +1 -1      CMakeLists.txt  
 A             focusdetector.cpp   [License: GPL (v2+)]
 A             focusdetector.h   [License: GPL (v2+)]
 AM            getactivewindowtitle  
 M  +1 -0      karmui.rc  
 M  +6 -1      mainwindow.cpp  
 M  +53 -1     taskview.cpp  
 M  +20 -2     taskview.h  


--- trunk/KDE/kdepim/ktimetracker/CMakeLists.txt #693145:693146
@@ -16,7 +16,7 @@
 	edittaskdialog.cpp idletimedetector.cpp 
 	printdialog.cpp timekard.cpp karmutility.cpp ktimewidget.cpp
 	karmstorage.cpp mainwindow.cpp preferences.cpp print.cpp 
-	task.cpp taskview.cpp tray.cpp  
+	task.cpp taskview.cpp tray.cpp  focusdetector.cpp
 	csvexportdialog.cpp plannerparser.cpp 
 	treeviewheadercontextmenu.cpp edithistorydialog.cpp
  )
** trunk/KDE/kdepim/ktimetracker/getactivewindowtitle #property svn:executable
   + *
--- trunk/KDE/kdepim/ktimetracker/karmui.rc #693145:693146
@@ -15,6 +15,7 @@
     <Action name="start" />
     <Action name="stop" />
     <Action name="stopAll" />
+    <Action name="focustracking" />
   </Menu>
   <Menu name="task" >
     <text>&amp;Task</text>
--- trunk/KDE/kdepim/ktimetracker/mainwindow.cpp #693145:693146
@@ -313,7 +313,7 @@
   actionStop->setShortcut(QKeySequence(Qt::Key_S));
   actionStop->setToolTip( i18n("Stop timing of the selected task") );
   actionStop->setWhatsThis( i18n("Stop timing of the selected task") );
-  
+
   // Stop all timers
   actionStopAll  = new KAction(i18n("Stop &All Timers"), this);
   actionCollection()->addAction("stopAll", actionStopAll );
@@ -323,6 +323,11 @@
   actionStopAll->setToolTip( i18n("Stop all of the active timers") );
   actionStopAll->setWhatsThis( i18n("Stop all of the active timers") );
 
+  // Focus tracking
+  QAction* actionFocusTracking = new KAction(i18n("Track active applications"), this);
+  actionCollection()->addAction("focustracking", actionFocusTracking );
+  connect(actionFocusTracking, SIGNAL(triggered(bool)), _taskView, SLOT( slotfocustracking()));
+
   // New task
   actionNew  = new KAction(KIcon(QString::fromLatin1("document-new")), i18n("&New..."), this);
   actionCollection()->addAction("new_task", actionNew );
--- trunk/KDE/kdepim/ktimetracker/taskview.cpp #693145:693146
@@ -107,6 +107,8 @@
 {
   _preferences = Preferences::instance( icsfile );
   _storage = KarmStorage::instance();
+  _focusDetector = new FocusDetector(1);
+  focustrackingactive = false;
 
   connect( this, SIGNAL(itemExpanded(QTreeWidgetItem*)),
            this, SLOT(itemStateChanged(QTreeWidgetItem*)) );
@@ -114,6 +116,8 @@
            this, SLOT(itemStateChanged(QTreeWidgetItem*)) );
   connect( this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
            this, SLOT(slotItemDoubleClicked(QTreeWidgetItem*, int)) );
+  connect( _focusDetector, SIGNAL( newFocus(QString) ), 
+           this, SLOT(newFocusWindowDetected (QString)) ); 
 
   QStringList labels;
   labels << i18n("Task Name") << i18n("Session Time") << i18n("Time") << i18n("Total Session Time") << i18n("Total Time") << i18n("Percent Complete") ;
@@ -179,6 +183,47 @@
   connect( headerContextMenu, SIGNAL(columnToggled(int)), this, SLOT(slotColumnToggled(int)) );
 }
 
+void TaskView::newFocusWindowDetected(const QString taskName)
+{
+  if (focustrackingactive)
+  {
+    bool found=false;  // has taskName been found in our tasks
+    stopTimerFor(lastTaskWithFocus);
+    int i=0;
+    for ( Task* task = item_at_index(i); task; task = item_at_index(++i) )
+    {
+      QString q1=taskName;
+      q1.replace("\n","");
+      if (q1==task->name())
+      {
+         found=true;
+         startTimerFor(task);
+         lastTaskWithFocus=task;
+      }
+    }
+    if  (!found)
+    {
+      QString taskuid = addTask( taskName );
+      if ( taskuid.isNull() )
+      {
+        KMessageBox::error( 0, i18n(
+        "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 ~/.kde/share/apps/kabc/lock/ " ) );
+      }
+      i=0;
+      for ( Task* task = item_at_index(i); task; task = item_at_index(++i) )
+      {
+        if (task->name()==taskName)
+        {
+          startTimerFor(task);
+          lastTaskWithFocus=task;
+        }
+      }
+    }
+    emit updateButtons();
+  } // focustrackingactive
+} 
+
+
 void TaskView::dropEvent(QDropEvent* qde)
 {
   kDebug(5970) << "This is dropEvent" << endl;
@@ -552,7 +597,8 @@
 
 void TaskView::clearActiveTasks()
 {
-  activeTasks.clear();
+  activeTasks.clear(); 
+  _focusDetector->startFocusDetection(); 
 }
 
 void TaskView::stopAllTimers( QDateTime when )
@@ -562,12 +608,18 @@
     activeTasks.at(i)->setRunning(false, _storage, when);
 
   _idleTimeDetector->stopIdleDetection();
+  _focusDetector->stopFocusDetection(); 
   activeTasks.clear();
   emit updateButtons();
   emit timersInactive();
   emit tasksChanged( activeTasks);
 }
 
+void TaskView::slotfocustracking()
+{
+  focustrackingactive=true;
+}
+
 void TaskView::startNewSession()
 /* This procedure starts a new session. Technically, a session is just an additionally 
 stored time that is always contain in the overall time. We speak of session times, 
--- trunk/KDE/kdepim/ktimetracker/taskview.h #693145:693146
@@ -30,6 +30,7 @@
 #include "desktoplist.h"
 #include "karmstorage.h"
 #include "reportcriteria.h"
+#include "focusdetector.h"
 
 class QMouseEvent;
 class QString;
@@ -92,7 +93,7 @@
     Preferences *preferences();
 
     /** Add a task to view and storage. */
-    QString addTask( const QString& taskame, long total, long session, const DesktopList& desktops,
+    QString addTask( const QString& taskame, long total = 0, long session = 0, const DesktopList& desktops = QVector<int>(0,0),
                      Task* parent = 0 );
 
   public Q_SLOTS:
@@ -111,6 +112,8 @@
      */
     void stopAllTimers(QDateTime when=QDateTime::currentDateTime());
 
+    void slotfocustracking();
+
     /** Calls newTask dialog with caption "New Task".  */
     void newTask();
 
@@ -138,6 +141,12 @@
     /** Calls newTask dialog with caption "New Sub Task". */
     void newSubTask();
 
+    /** start the autotracking system to add tasks to control time for every focused windows **/
+    void startAutoTracking(){};
+
+    /** stop the autotracking system to add tasks to control time for every focused windows **/    
+    void stopAutoTracking(){};
+ 
     void editTask();
 
     /**
@@ -208,7 +217,9 @@
     void setStatusBarText(QString);
 
   private: // member variables
-    IdleTimeDetector *_idleTimeDetector;
+    IdleTimeDetector* _idleTimeDetector;
+    FocusDetector* _focusDetector;
+    bool focustrackingactive;  // do we track by which application has the focus ?
     QTimer *_minuteTimer;
     QTimer *_autoSaveTimer;
     QTimer *_manualSaveTimer;
@@ -218,6 +229,7 @@
     bool _isloading;
     Task* dragTask;
     QTableWidget* historywidget;
+    Task*  lastTaskWithFocus;
 
     //KCal::CalendarLocal _calendar;
     KarmStorage * _storage;
@@ -239,12 +251,18 @@
     void autoSaveChanged( bool );
     void autoSavePeriodChanged( int period );
     void minuteUpdate();
+
     /** item state stores if a task is expanded so you can see the subtasks */
     void itemStateChanged( QTreeWidgetItem *item );
+
     /** React on another process having modified the iCal file we rely on. 
        This is not iCalFileChanged. */
     void iCalFileModified(ResourceCalendar *);
     void slotItemDoubleClicked( QTreeWidgetItem *item, int );
+
+    /** React on the focus having changed to Window QString **/
+    void newFocusWindowDetected (QString);
+
     void slotColumnToggled( int );
 };
 
Comment 14 René Mérou 2007-07-27 13:01:39 UTC
"I do not like focusdetector.cpp, in principle, you do not more than executing
..."

Yes, this is not the best solution. It just do the job with not too much cpu work.

The best way to solve it is to say (DBUSS / X server / anyother) to inform of the event "new focused window with name:XXX" i was not able to find that.

Now some improvements ideas are:  
1-to add one buton to delete all tasks with les than one minute.
2-to add the other button to stop/restart focus detection.
3-To add one preference for period of time to check that can be sected from: 
     0 seconds (autotracking all focused, in one core2duo it charges cpu to 7% ) 
     or select 1...100 seconds betwing every check.
    Now default is 30 seconds, i have seen that 0 secs can add too much 0m. tasks
Comment 15 Thorsten Staerk 2007-07-28 19:34:27 UTC
Created attachment 21282 [details]
now in C code, not in bash
Comment 16 Thorsten Staerk 2007-08-03 08:01:47 UTC
> Now some improvements ideas are:
This bug is closed, new ideas will not be taken from here
Comment 17 Alexander Potashev 2019-11-12 22:05:10 UTC
*** Bug 154506 has been marked as a duplicate of this bug. ***