From 5ff71d5008af130f26ea60daff3060a1163d7e6c Mon Sep 17 00:00:00 2001
From: Claude Brisson <claude@renegat.net>
Date: Tue, 26 Feb 2019 12:31:23 +0100
Subject: [PATCH] Take sleeping periods into account

---
 Makefile          | 10 +++++++---
 src/timeslice.cpp | 43 ++++++++++++++++++++++++++++++-------------
 src/timeslice.h   | 11 +++++++----
 3 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/Makefile b/Makefile
index 4863674..c762975 100644
--- a/Makefile
+++ b/Makefile
@@ -18,16 +18,16 @@ CXXFLAGS += -I/usr/include/atk-1.0 -I/usr/include/atkmm-1.6
 CXXFLAGS += -I/usr/include/mysql
 
 # link flags
-LDFLAGS += -L/usr/local/lib -L/usr/lib -L/usr/lib/x86_64-linux-gnu -lgtkmm-3.0 -latkmm-1.6 -lglibmm-2.4 -lsigc-2.0 -lmysqlpp -ldl
+LDFLAGS += -L/usr/local/lib -L/usr/lib -L/usr/lib/x86_64-linux-gnu -lgtkmm-3.0 -latkmm-1.6 -lglibmm-2.4 -lsigc-2.0 -lmysqlpp -lXss -lX11 -lgdkmm-3.0 -ldl
 
 all: timeslice
 
 .PHONY: all clean
 
-timeslice: obj/timeslice.o obj/main.o
+timeslice: obj/timeslice.o obj/main.o obj/idle.o
 	$(CXX) $^ -o $@ $(LDFLAGS)
 
-obj/timeslice.o: src/timeslice.cpp src/timeslice.h src/config.h
+obj/timeslice.o: src/timeslice.cpp src/timeslice.h src/config.h src/idle.h
 	mkdir -p obj
 	$(CXX) $(CXXFLAGS) -o $@ -c $<
 
@@ -35,5 +35,9 @@ obj/main.o: src/main.cpp src/timeslice.h
 	mkdir -p obj
 	$(CXX) $(CXXFLAGS) -o $@ -c $<
 
+obj/idle.o: src/idle.cpp src/idle.h
+	mkdir -p obj
+	$(CXX) $(CXXFLAGS) -o $@ -c $<
+
 clean:
 	rm -rf obj timeslice
diff --git a/src/timeslice.cpp b/src/timeslice.cpp
index 5056559..656dc35 100644
--- a/src/timeslice.cpp
+++ b/src/timeslice.cpp
@@ -3,6 +3,7 @@
 #include <iostream>
 #include <mysql++/mysql++.h>
 #include "config.h"
+#include "idle.h"
 
 static TimeSlice *app = nullptr;
 
@@ -17,7 +18,6 @@ Project::Project(int id, std::string name) : id(id), name(name)
 void Project::on_button_clicked()
 {
   app->setActive(this);
-  app->resetStart();
 }
 
 TimeSlice::TimeSlice()
@@ -103,34 +103,52 @@ void TimeSlice::setActive(Project *project)
 {
     if (active)
     {
-        timestamp now = std::chrono::system_clock::now();
-        std::cerr << "@@@ old:" << (now - start).count() << std::endl;
-        std::cerr << "@@@ new:" << time_diff(now, start) << std::endl;
-        active->elapsed += time_diff(now, start);
+        timestamp now = TIME_NOW();
+        int diff = TIME_DIFF(now, start) - slept;
+        active->elapsed += diff;
     }
     active = project;
+    start = TIME_NOW();
+    lastElapsed = slept = 0;
 }
 
 bool TimeSlice::on_timer()
 {
     if (active)
     {
-        timestamp now = std::chrono::system_clock::now();
-        long elapsed = active->elapsed + time_diff(now, start);
-        long hours = elapsed / 3600;
-        long minutes = (elapsed % 3600) / 60;
-        long seconds = elapsed % 60;
+std::ostringstream dbg;
+        timestamp now = TIME_NOW();
+        int diff = TIME_DIFF(now, start);
+dbg<<"@@ raw diff = " << diff << ", sleeped " << (diff - lastElapsed - 1);
+        slept += std::max(0, diff - lastElapsed - 1);
+dbg<<", total sleep = " << slept;
+        lastElapsed = diff;
+        diff -= slept;
+dbg<<", actual diff = " << diff << std::endl;
+std::cerr << dbg.str();
+        int elapsed = active->elapsed + diff;
+        int hours = elapsed / 3600;
+        int minutes = (elapsed % 3600) / 60;
+        int seconds = elapsed % 60;
         std::ostringstream oss;
         oss << std::setfill('0') << std::setw(2) << hours << ':' << std::setw(2) << minutes << ':' << std::setw(2) << seconds;
         std::string hms = oss.str();
         active->label->set_text(hms);
         active->label->queue_draw();
-        registerTimeSlice(active->id, start, elapsed);
+        registerTimeSlice(active->id, start, diff);
+        // now check for inactivity
+        int idleSeconds = GetIdleTime();
+        if (idleSeconds > IDLE)
+        {
+            idle->clicked();
+            Glib::RefPtr<Gdk::Window> window = get_window();
+            if (window) window->beep();
+        }
     }
     return true;
 }
 
-void TimeSlice::registerTimeSlice(int id, timestamp start, long elapsed)
+void TimeSlice::registerTimeSlice(int id, timestamp start, int elapsed)
 {
     mysqlpp::Connection conn;
     mysqlpp::SetCharsetNameOption *scno = new mysqlpp::SetCharsetNameOption("utf8");
@@ -138,7 +156,6 @@ void TimeSlice::registerTimeSlice(int id, timestamp start, long elapsed)
     conn.connect(TS_DB, TS_HOST, TS_USER, TS_PASSWORD);
     mysqlpp::Query query = conn.query();
     std::time_t time = std::chrono::system_clock::to_time_t(start);
-    std::cerr << "@@@ " << std::put_time(std::localtime(&time), "%F %T") << std::endl;
     query << "INSERT INTO timeslice (pr_id, starttime, duration) VALUES (" << id << ", '" << std::put_time(std::localtime(&time), "%F %T") << "', " << elapsed << ") ON DUPLICATE KEY UPDATE duration = VALUES(duration)";
     if (!query.exec()) throw std::runtime_error("could not update time slice");
 }
diff --git a/src/timeslice.h b/src/timeslice.h
index bd6f63a..c629134 100644
--- a/src/timeslice.h
+++ b/src/timeslice.h
@@ -3,8 +3,10 @@
 #include <gtkmm-3.0/gtkmm.h>
 
 #define TIMEOUT 1000
+#define IDLE    300000 // 5 min
 typedef std::chrono::time_point<std::chrono::system_clock> timestamp;
-#define time_diff(a,b) (std::chrono::duration_cast<std::chrono::seconds>((a) - (b)).count())
+#define TIME_DIFF(a,b) (std::chrono::duration_cast<std::chrono::seconds>((a) - (b)).count())
+#define TIME_NOW() (std::chrono::system_clock::now())
 
 struct Project
 {
@@ -14,7 +16,7 @@ struct Project
     std::shared_ptr<Gtk::RadioButton> button;
     std::shared_ptr<Gtk::Label> label;
     void on_button_clicked();
-    long elapsed = 0;
+    int elapsed = 0;
 };
 
 class TimeSlice : public Gtk::Window
@@ -30,8 +32,7 @@ public:
   void on_idle_clicked();
   bool on_timer();
   void setActive(Project *project);
-  void resetStart() { start = std::chrono::system_clock::now(); }
-  void registerTimeSlice(int id, timestamp start, long elapsed);
+  void registerTimeSlice(int id, timestamp start, int elapsed);
 
 protected:
   std::shared_ptr<Gtk::RadioButtonGroup> group;
@@ -41,4 +42,6 @@ protected:
   sigc::connection timer;
   Project * active = nullptr;
   timestamp start;
+  int lastElapsed = 0;
+  int slept = 0; // seconds
 };
-- 
GitLab