Fix bug - adding current values to previous day on stop
[pedometerwidget] / src / usr / lib / hildon-desktop / pedometer_widget_home.py
index 00ca45d..57f1c98 100644 (file)
@@ -35,6 +35,7 @@ import hildon
 PATH = "/apps/pedometerhomewidget"
 MODE = PATH + "/mode"
 HEIGHT = PATH + "/height"
+WEIGHT = PATH + "/weight"
 UNIT = PATH + "/unit"
 ASPECT = PATH + "/aspect"
 SECONDVIEW = PATH + "/secondview"
@@ -218,7 +219,7 @@ class PedoValues():
         return str(self.steps)
 
     def get_print_calories(self):
-        return str(self.calories)
+        return "%.2f" % self.calories
 
 class PedoRepository(Singleton):
     values = {}
@@ -240,7 +241,9 @@ class PedoRepository(Singleton):
     def get_values(self):
         return self.values
 
-    def add_values(self, values, when=date.today()):
+    def add_values(self, values, when=None):
+        if when is None:
+            when = date.today()
         """add PedoValues values to repository """
         try:
             self.values[when] = self.values[when] + values
@@ -400,6 +403,9 @@ class PedoController(Singleton):
 
     observers = []
 
+    midnight_set = False
+    midnight_source_id = None
+
     def __init__(self):
         self.pedometer = PedoCounter(self.steps_detected)
         self.pedometerInterval = PedoIntervalCounter()
@@ -409,6 +415,29 @@ class PedoController(Singleton):
 
         self.load_values()
 
+        if not self.midnight_set:
+            self.update_at_midnight()
+            self.midnight_set = True
+
+    def update_at_midnight(self):
+        next_day = date.today() + timedelta(days=1)
+        diff = time.mktime(next_day.timetuple()) - time.time()
+        diff = int(diff+5)
+        self.midnight_source_id = gobject.timeout_add_seconds(diff, self.midnight_callback, True)
+
+    def stop_midnight_callback(self):
+        if self.midnight_source_id is not None:
+            gobject.source_remove(self.midnight_source_id)
+
+    def midnight_callback(self, first=False):
+        self.load_values()
+        self.notify()
+        if first:
+            self.midnight_source_id = gobject.timeout_add_seconds(24*3600, self.midnight_callback)
+            return False
+        else:
+            return True
+
     def load_values(self):
         if self.second_view == 0:
             self.v[1] = self.repository.get_alltime_values()
@@ -459,7 +488,7 @@ class PedoController(Singleton):
         else:
             self.v[0].steps += cnt
             self.v[0].dist += self.get_distance(cnt)
-            self.v[0].calories += self.get_distance(cnt)
+            self.v[0].calories += self.get_calories(self.get_distance(cnt))
             self.v[0].time += time.time() - self.last_time
             if last_steps:
                 self.save_values()
@@ -468,6 +497,24 @@ class PedoController(Singleton):
                 self.notify(True)
         self.last_time = time.time()
 
+    def get_calories(self, distance):
+        """calculate lost calories for the distance and weight given as parameters
+        """
+        #different coefficient for running and walking
+        if self.mode == 0:
+            coef = 0.53
+        else:
+            coef = 0.75
+
+        #convert distance from meters to miles
+        distance *= 0.000621371192
+
+        weight = self.weight
+        #convert weight from kg to pounds
+        if self.unit == 0:
+            weight *= 2.20462262
+        return weight * distance * coef
+
     def set_mode(self, mode):
         self.mode = mode
         self.set_height(self.height_interval)
@@ -477,6 +524,19 @@ class PedoController(Singleton):
         self.unit = new_unit
         unit = new_unit
 
+    def get_str_weight_unit(self):
+        if self.unit == 0:
+            return "kg"
+        else:
+            return "lb"
+
+    def set_weight(self, value):
+        self.weight = value
+        self.notify()
+
+    def get_weight(self):
+        return self.weight
+
     def set_second_view(self, second_view):
         self.second_view = second_view
         self.load_values()
@@ -511,9 +571,6 @@ class PedoController(Singleton):
             steps = self.counter
         return self.STEP_LENGTH * steps;
 
-    def get_calories(self, steps):
-        return steps
-
     def add_observer(self, func):
         try:
             self.observers.index(func)
@@ -542,16 +599,11 @@ class AlarmController(Singleton):
 
     def __init__(self):
         self.client = gconf.client_get_default()
-        try:
-            self.enable = self.client.get_bool(ALARM_ENABLE)
-            self.fname = self.client.get_string(ALARM_FNAME)
-            self.interval = self.client.get_int(ALARM_INTERVAL)
-            self.type = self.client.get_int(ALARM_TYPE)
-        except:
-            self.client.set_bool(ALARM_ENABLE, self.enable)
-            self.client.set_string(ALARM_FNAME, self.fname)
-            self.client.set_int(ALARM_INTERVAL, self.interval)
-            self.client.set_int(ALARM_TYPE, self.type)
+
+        self.enable = self.client.get_bool(ALARM_ENABLE)
+        self.fname = self.client.get_string(ALARM_FNAME)
+        self.interval = self.client.get_int(ALARM_INTERVAL)
+        self.type = self.client.get_int(ALARM_TYPE)
 
         self.pedo_controller = PedoController()
         if self.enable:
@@ -647,7 +699,7 @@ class PedoCounter(Singleton):
     COORD_FNAME_SDK = "/home/andrei/pedometer-widget-0.1/date.txt"
     LOGFILE = "/home/user/log_pedometer"
     #time in ms between two accelerometer data reads
-    COORD_GET_INTERVAL = 10
+    COORD_GET_INTERVAL = 25
 
     COUNT_INTERVAL = 5
 
@@ -1031,12 +1083,11 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
     second_view_labels = ["All-time", "Today", "This week"]
 
     controller = None
-    pedometer = None
-    pedometerInterval = None
     graph_controller = None
 
     mode = 0
     height = 0
+    weight = 70
     unit = 0
     aspect = 0
     second_view = 0
@@ -1051,28 +1102,20 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
         gobject.type_register(GraphWidget)
 
         self.client = gconf.client_get_default()
-        try:
-            self.mode = self.client.get_int(MODE)
-            self.height = self.client.get_int(HEIGHT)
-            self.unit = self.client.get_int(UNIT)
-            self.aspect = self.client.get_int(ASPECT)
-            self.second_view = self.client.get_int(SECONDVIEW)
-            self.graph_view = self.client.get_int(GRAPHVIEW)
-            self.no_idle_time = self.client.get_bool(NOIDLETIME)
-            self.logging = self.client.get_bool(LOGGING)
 
-        except:
-            self.client.set_int(MODE, 0)
-            self.client.set_int(HEIGHT, 0)
-            self.client.set_int(UNIT, 0)
-            self.client.set_int(ASPECT, 0)
-            self.client.set_int(SECONDVIEW, 0)
-            self.client.set_int(GRAPHVIEW, 0)
-            self.client.set_bool(NOIDLETIME, False)
-            self.client.set_bool(LOGGING, False)
+        self.mode = self.client.get_int(MODE)
+        self.height = self.client.get_int(HEIGHT)
+        self.weight = self.client.get_int(WEIGHT)
+        self.unit = self.client.get_int(UNIT)
+        self.aspect = self.client.get_int(ASPECT)
+        self.second_view = self.client.get_int(SECONDVIEW)
+        self.graph_view = self.client.get_int(GRAPHVIEW)
+        self.no_idle_time = self.client.get_bool(NOIDLETIME)
+        self.logging = self.client.get_bool(LOGGING)
 
         self.controller = PedoController()
         self.controller.set_height(self.height)
+        self.controller.set_weight(self.weight)
         self.controller.set_mode(self.mode)
         self.controller.set_unit(self.unit)
         self.controller.set_second_view(self.second_view)
@@ -1148,6 +1191,7 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
         self.graph = graph
         eventBoxGraph.connect("button-press-event", self.eventBoxGraph_clicked)
         eventBoxGraph.connect("button-release-event", self.eventBoxGraph_clicked_release)
+        self.graphBox = eventBoxGraph
 
         self.mainvbox = gtk.VBox()
 
@@ -1194,16 +1238,25 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
             new_labels[label] = l
 
     def update_aspect(self):
-        if self.aspect == 0:
+
+        if self.aspect > 0:
+            self.graphBox.hide_all()
+        else:
+            self.graphBox.show_all()
+
+        if self.aspect == 0 or self.aspect == 1:
             self.currentBox.show_all()
             self.totalBox.show_all()
-        elif self.aspect == 1:
+        elif self.aspect == 2:
             self.currentBox.show_all()
             self.totalBox.hide_all()
         else:
             self.currentBox.hide_all()
             self.totalBox.show_all()
 
+        x,y = self.size_request()
+        self.resize(x,y)
+
     def update_ui_values(self, labels, values):
         labels["timer"].set_label(values.get_print_time())
         labels["count"].set_label(values.get_print_steps())
@@ -1351,6 +1404,40 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
             widget.client.set_bool(NOIDLETIME, widget.no_idle_time)
             widget.controller.set_no_idle_time(widget.no_idle_time)
 
+        def weight_dialog(button):
+            dialog = gtk.Dialog("Weight", self.dialog)
+            dialog.add_button("OK", gtk.RESPONSE_OK)
+
+            label = gtk.Label("Weight:")
+            entry = gtk.Entry()
+            entry.set_text(str(self.controller.get_weight()))
+
+            suffixLabel = gtk.Label(self.controller.get_str_weight_unit())
+
+            hbox = gtk.HBox()
+            hbox.add(label)
+            hbox.add(entry)
+            hbox.add(suffixLabel)
+
+            dialog.vbox.add(hbox)
+            dialog.show_all()
+            while 1:
+                response = dialog.run()
+                if response != gtk.RESPONSE_OK:
+                    break
+                try:
+                    value = int(entry.get_text())
+                    if value <= 0:
+                        raise ValueError
+                    self.controller.set_weight(value)
+                    self.client.set_int(WEIGHT, value)
+                    weightButton.set_value(str(self.controller.get_weight()) + \
+                                           " " + self.controller.get_str_weight_unit() )
+                    break
+                except:
+                    hildon.hildon_banner_show_information(self, "None", "Invalid weight")
+            dialog.destroy()
+
         dialog = gtk.Dialog()
         dialog.set_title("Settings")
         dialog.add_button("OK", gtk.RESPONSE_OK)
@@ -1378,7 +1465,7 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
 
         modePicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
         modePicker.set_alignment(0.0, 0.5, 1.0, 1.0)
-        modePicker.set_title("Select mode")
+        modePicker.set_title("Mode")
         modePicker.set_selector(selector)
         modePicker.set_active(widget.mode)
 
@@ -1393,10 +1480,16 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
 
         heightPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
         heightPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
-        heightPicker.set_title("Select height")
+        heightPicker.set_title("Height")
         heightPicker.set_selector(selectorH)
         heightPicker.set_active(widget.height)
 
+        weightButton = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        weightButton.set_title("Weight")
+        weightButton.set_alignment(0, 0.8, 1, 1)
+        weightButton.set_value(str(self.controller.get_weight()) + " " + self.controller.get_str_weight_unit() )
+        weightButton.connect("clicked", weight_dialog)
+
         selectorUnit = hildon.TouchSelector(text=True)
         selectorUnit.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
         selectorUnit.append_text("Metric (km)")
@@ -1405,13 +1498,14 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
 
         unitPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
         unitPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
-        unitPicker.set_title("Units")
+        unitPicker.set_title("Unit")
         unitPicker.set_selector(selectorUnit)
         unitPicker.set_active(widget.unit)
 
         selectorUI = hildon.TouchSelector(text=True)
         selectorUI = hildon.TouchSelector(text=True)
         selectorUI.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
+        selectorUI.append_text("Show current + total + graph")
         selectorUI.append_text("Show current + total")
         selectorUI.append_text("Show only current")
         selectorUI.append_text("Show only total")
@@ -1438,6 +1532,7 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
         vbox.add(alarmButton)
         vbox.add(modePicker)
         vbox.add(heightPicker)
+        vbox.add(weightButton)
         vbox.add(unitPicker)
         vbox.add(UIPicker)
         vbox.add(idleButton)
@@ -1454,10 +1549,9 @@ class PedometerHomePlugin(hildondesktop.HomePluginItem):
         dialog.destroy()
 
     def close_requested(self, widget):
-        if self.pedometer is None:
-            return
-
-        self.pedometer.request_stop()
+        if self.controller.is_running:
+            self.controller.stop_pedometer()
+        self.controller.stop_midnight_callback()
 
     def update_values(self):
         #TODO: do not update if the widget is not on the active desktop