[hamster-applet] humble beginnings of statistics



commit 452d255657740889c853d8ee31a4c6eab65c3721
Author: Toms Bauģis <toms baugis gmail com>
Date:   Sat Jun 13 23:37:48 2009 +0100

    humble beginnings of statistics

 data/stats.ui    |  842 ++++++++++++++++++++++++++++++++++++------------------
 hamster/stats.py |  273 +++++++++++++++++-
 2 files changed, 822 insertions(+), 293 deletions(-)
---
diff --git a/data/stats.ui b/data/stats.ui
index 3b34071..d56559e 100644
--- a/data/stats.ui
+++ b/data/stats.ui
@@ -15,281 +15,331 @@
     <signal name="key_press_event" handler="on_window_key_pressed"/>
     <signal name="delete_event" handler="on_close"/>
     <child>
-      <object class="GtkVBox" id="vbox1">
+      <object class="GtkAlignment" id="alignment1">
         <property name="visible">True</property>
-        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="top_padding">12</property>
+        <property name="bottom_padding">12</property>
+        <property name="left_padding">12</property>
+        <property name="right_padding">12</property>
         <child>
-          <object class="GtkToolbar" id="toolbar3">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="toolbar_style">both-horiz</property>
-            <child>
-              <object class="GtkToolButton" id="prev">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="tooltip_text" translatable="yes">Earlier activities</property>
-                <property name="stock_id">gtk-go-back</property>
-                <signal name="clicked" handler="on_prev_clicked"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="home">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="tooltip_text" translatable="yes">Today</property>
-                <property name="label" translatable="yes">Today</property>
-                <property name="use_underline">True</property>
-                <property name="stock_id">gtk-home</property>
-                <signal name="clicked" handler="on_home_clicked"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="next">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="tooltip_text" translatable="yes">Newer activities</property>
-                <property name="stock_id">gtk-go-forward</property>
-                <signal name="clicked" handler="on_next_clicked"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkSeparatorToolItem" id="toolbutton3">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="remove">
-                <property name="visible">True</property>
-                <property name="sensitive">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="tooltip_text" translatable="yes">Delete activity</property>
-                <property name="stock_id">gtk-remove</property>
-                <signal name="clicked" handler="on_remove_clicked"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="add">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="tooltip_text" translatable="yes">Add activity</property>
-                <property name="stock_id">gtk-add</property>
-                <signal name="clicked" handler="on_add_clicked"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="edit">
-                <property name="visible">True</property>
-                <property name="sensitive">False</property>
-                <property name="tooltip_text" translatable="yes">Edit activity</property>
-                <property name="stock_id">gtk-edit</property>
-                <signal name="clicked" handler="on_edit_clicked"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkSeparatorToolItem" id="toolbutton1">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkRadioToolButton" id="week">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="tooltip_text" translatable="yes">Show week</property>
-                <property name="is_important">True</property>
-                <property name="label" translatable="yes"> _Week</property>
-                <property name="use_underline">True</property>
-                <property name="icon_widget">week_icon</property>
-                <property name="active">True</property>
-                <signal name="toggled" handler="on_week_toggled"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkRadioToolButton" id="month">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="tooltip_text" translatable="yes">Show month</property>
-                <property name="is_important">True</property>
-                <property name="label" translatable="yes"> _Month</property>
-                <property name="use_underline">True</property>
-                <property name="icon_widget">month_icon</property>
-                <signal name="toggled" handler="on_month_toggled"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkSeparatorToolItem" id="&lt;separator&gt;">
-                <property name="visible">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="report_button">
-                <property name="visible">True</property>
-                <property name="tooltip_text" translatable="yes">Save as HTML</property>
-                <property name="label" translatable="yes">Save as HTML</property>
-                <property name="use_underline">True</property>
-                <property name="stock_id">gtk-save</property>
-                <signal name="clicked" handler="on_report_button_clicked"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="alignment1">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="top_padding">12</property>
-            <child>
-              <object class="GtkLabel" id="overview_label">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="xalign">0</property>
-                <property name="xpad">12</property>
-                <property name="label" translatable="yes">&lt;b&gt;Overview&lt;/b&gt;</property>
-                <property name="use_markup">True</property>
-                <property name="single_line_mode">True</property>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkHPaned" id="hpaned1">
+          <object class="GtkNotebook" id="notebook1">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="border_width">12</property>
-            <property name="position">300</property>
+            <property name="tab_hborder">8</property>
+            <property name="tab_vborder">4</property>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow1">
-                <property name="width_request">300</property>
+              <object class="GtkVBox" id="vbox1">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="hscrollbar_policy">automatic</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">in</property>
+                <property name="orientation">vertical</property>
                 <child>
-                  <object class="GtkTreeView" id="facts">
+                  <object class="GtkToolbar" id="toolbar3">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="enable_search">False</property>
-                    <signal name="key_press_event" handler="on_key_pressed"/>
-                    <signal name="row_activated" handler="on_facts_row_activated"/>
+                    <property name="toolbar_style">both-horiz</property>
+                    <child>
+                      <object class="GtkToolButton" id="prev">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="stock_id">gtk-go-back</property>
+                        <signal name="clicked" handler="on_prev_clicked"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkToolButton" id="home">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">Today</property>
+                        <property name="use_underline">True</property>
+                        <property name="stock_id">gtk-home</property>
+                        <signal name="clicked" handler="on_home_clicked"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkToolButton" id="next">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="stock_id">gtk-go-forward</property>
+                        <signal name="clicked" handler="on_next_clicked"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorToolItem" id="toolbutton3">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkToolButton" id="remove">
+                        <property name="visible">True</property>
+                        <property name="sensitive">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="stock_id">gtk-remove</property>
+                        <signal name="clicked" handler="on_remove_clicked"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkToolButton" id="add">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="stock_id">gtk-add</property>
+                        <signal name="clicked" handler="on_add_clicked"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkToolButton" id="edit">
+                        <property name="visible">True</property>
+                        <property name="sensitive">False</property>
+                        <property name="stock_id">gtk-edit</property>
+                        <signal name="clicked" handler="on_edit_clicked"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorToolItem" id="toolbutton1">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioToolButton" id="week">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="is_important">True</property>
+                        <property name="label" translatable="yes"> _Week</property>
+                        <property name="use_underline">True</property>
+                        <property name="icon_widget">week_icon</property>
+                        <property name="active">True</property>
+                        <signal name="toggled" handler="on_week_toggled"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioToolButton" id="month">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="is_important">True</property>
+                        <property name="label" translatable="yes"> _Month</property>
+                        <property name="use_underline">True</property>
+                        <property name="icon_widget">month_icon</property>
+                        <property name="active">True</property>
+                        <signal name="toggled" handler="on_month_toggled"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorToolItem" id="&lt;separator&gt;">
+                        <property name="visible">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkToolButton" id="report_button">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Save as HTML</property>
+                        <property name="use_underline">True</property>
+                        <property name="stock_id">gtk-save</property>
+                        <signal name="clicked" handler="on_report_button_clicked"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="homogeneous">True</property>
+                      </packing>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment2">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="top_padding">12</property>
+                    <child>
+                      <object class="GtkLabel" id="overview_label">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="xalign">0</property>
+                        <property name="xpad">12</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Overview&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                        <property name="single_line_mode">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="resize">False</property>
-                <property name="shrink">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow2">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">automatic</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">in</property>
                 <child>
-                  <object class="GtkEventBox" id="graph_frame">
+                  <object class="GtkHPaned" id="hpaned1">
                     <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="border_width">12</property>
+                    <property name="position">300</property>
+                    <property name="position_set">True</property>
                     <child>
-                      <object class="GtkVBox" id="vbox4">
+                      <object class="GtkScrolledWindow" id="scrolledwindow1">
+                        <property name="width_request">300</property>
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="hscrollbar_policy">automatic</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
                         <child>
-                          <object class="GtkVBox" id="graphs">
-                            <property name="width_request">390</property>
+                          <object class="GtkTreeView" id="facts">
                             <property name="visible">True</property>
+                            <property name="can_focus">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="border_width">4</property>
-                            <property name="orientation">vertical</property>
-                            <property name="spacing">24</property>
-                            <property name="homogeneous">True</property>
+                            <property name="enable_search">False</property>
+                            <signal name="key_press_event" handler="on_key_pressed"/>
+                            <signal name="row_activated" handler="on_facts_row_activated"/>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="resize">False</property>
+                        <property name="shrink">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkScrolledWindow" id="scrolledwindow2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hscrollbar_policy">automatic</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <object class="GtkEventBox" id="graph_frame">
+                            <property name="visible">True</property>
                             <child>
-                              <object class="GtkFrame" id="fram1">
+                              <object class="GtkVBox" id="vbox4">
                                 <property name="visible">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="label_xalign">0</property>
-                                <property name="shadow_type">none</property>
+                                <property name="orientation">vertical</property>
                                 <child>
-                                  <object class="GtkHBox" id="hbox1">
+                                  <object class="GtkVBox" id="graphs">
+                                    <property name="width_request">390</property>
                                     <property name="visible">True</property>
-                                    <property name="border_width">9</property>
-                                    <property name="spacing">36</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <property name="border_width">4</property>
+                                    <property name="orientation">vertical</property>
+                                    <property name="spacing">24</property>
+                                    <property name="homogeneous">True</property>
                                     <child>
-                                      <object class="GtkEventBox" id="totals_by_category">
-                                        <property name="width_request">50</property>
+                                      <object class="GtkFrame" id="fram1">
                                         <property name="visible">True</property>
+                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                        <property name="label_xalign">0</property>
+                                        <property name="shadow_type">none</property>
                                         <child>
-                                          <placeholder/>
+                                          <object class="GtkHBox" id="hbox1">
+                                            <property name="visible">True</property>
+                                            <property name="border_width">9</property>
+                                            <property name="spacing">36</property>
+                                            <child>
+                                              <object class="GtkEventBox" id="totals_by_category">
+                                                <property name="width_request">50</property>
+                                                <property name="visible">True</property>
+                                                <child>
+                                                  <placeholder/>
+                                                </child>
+                                              </object>
+                                              <packing>
+                                                <property name="expand">False</property>
+                                                <property name="position">0</property>
+                                              </packing>
+                                            </child>
+                                            <child>
+                                              <object class="GtkEventBox" id="totals_by_day">
+                                                <property name="visible">True</property>
+                                                <child>
+                                                  <placeholder/>
+                                                </child>
+                                              </object>
+                                              <packing>
+                                                <property name="position">1</property>
+                                              </packing>
+                                            </child>
+                                          </object>
+                                        </child>
+                                        <child type="label">
+                                          <object class="GtkLabel" id="dayview_caption">
+                                            <property name="visible">True</property>
+                                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                            <property name="label" translatable="yes">Week</property>
+                                            <property name="use_markup">True</property>
+                                          </object>
                                         </child>
                                       </object>
                                       <packing>
-                                        <property name="expand">False</property>
                                         <property name="position">0</property>
                                       </packing>
                                     </child>
                                     <child>
-                                      <object class="GtkEventBox" id="totals_by_day">
+                                      <object class="GtkFrame" id="frame39">
                                         <property name="visible">True</property>
+                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                        <property name="label_xalign">0</property>
+                                        <property name="shadow_type">none</property>
                                         <child>
-                                          <placeholder/>
+                                          <object class="GtkEventBox" id="totals_by_activity">
+                                            <property name="visible">True</property>
+                                            <property name="border_width">12</property>
+                                            <child>
+                                              <placeholder/>
+                                            </child>
+                                          </object>
+                                        </child>
+                                        <child type="label">
+                                          <object class="GtkLabel" id="label4">
+                                            <property name="visible">True</property>
+                                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                            <property name="label" translatable="yes">Activity</property>
+                                            <property name="use_markup">True</property>
+                                          </object>
                                         </child>
                                       </object>
                                       <packing>
@@ -297,87 +347,301 @@
                                       </packing>
                                     </child>
                                   </object>
+                                  <packing>
+                                    <property name="position">0</property>
+                                  </packing>
                                 </child>
-                                <child type="label">
-                                  <object class="GtkLabel" id="dayview_caption">
-                                    <property name="visible">True</property>
-                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="label" translatable="yes">Week</property>
-                                    <property name="use_markup">True</property>
+                                <child>
+                                  <object class="GtkLabel" id="no_data_label">
+                                    <property name="label" translatable="yes">No data for this interval</property>
                                   </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
                                 </child>
                               </object>
-                              <packing>
-                                <property name="position">0</property>
-                              </packing>
                             </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="resize">True</property>
+                        <property name="shrink">True</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">300</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Overview</property>
+              </object>
+              <packing>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="vbox2">
+                <property name="visible">True</property>
+                <property name="border_width">8</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment4">
+                    <property name="visible">True</property>
+                    <property name="yscale">0</property>
+                    <child>
+                      <object class="GtkTable" id="table1">
+                        <property name="visible">True</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">4</property>
+                        <property name="row_spacing">8</property>
+                        <child>
+                          <object class="GtkLabel" id="label3">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Year:</property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkAlignment" id="alignment5">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="xscale">0</property>
                             <child>
-                              <object class="GtkFrame" id="frame39">
+                              <object class="GtkHBox" id="year_box">
                                 <property name="visible">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="label_xalign">0</property>
-                                <property name="shadow_type">none</property>
                                 <child>
-                                  <object class="GtkEventBox" id="totals_by_activity">
+                                  <object class="GtkToggleButton" id="togglebutton2">
+                                    <property name="label" translatable="yes">All</property>
+                                    <property name="width_request">60</property>
                                     <property name="visible">True</property>
-                                    <property name="border_width">12</property>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
                                   </object>
+                                  <packing>
+                                    <property name="position">0</property>
+                                  </packing>
                                 </child>
-                                <child type="label">
-                                  <object class="GtkLabel" id="label3">
+                                <child>
+                                  <object class="GtkToggleButton" id="togglebutton1">
+                                    <property name="label" translatable="yes">2009</property>
                                     <property name="visible">True</property>
-                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="label" translatable="yes">Activity</property>
-                                    <property name="use_markup">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
                                   </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <placeholder/>
                                 </child>
                               </object>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
                             </child>
                           </object>
                           <packing>
-                            <property name="position">0</property>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
                           </packing>
                         </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">never</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkEventBox" id="explore_frame">
+                        <property name="visible">True</property>
                         <child>
-                          <object class="GtkLabel" id="no_data_label">
-                            <property name="label" translatable="yes">No data for this interval</property>
+                          <object class="GtkAlignment" id="alignment3">
+                            <property name="visible">True</property>
+                            <property name="top_padding">12</property>
+                            <property name="bottom_padding">12</property>
+                            <property name="left_padding">12</property>
+                            <property name="right_padding">12</property>
+                            <child>
+                              <object class="GtkVBox" id="vbox66">
+                                <property name="visible">True</property>
+                                <property name="orientation">vertical</property>
+                                <property name="spacing">12</property>
+                                <child>
+                                  <object class="GtkAlignment" id="explore_everything">
+                                    <property name="height_request">50</property>
+                                    <property name="visible">True</property>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkTable" id="table2">
+                                    <property name="visible">True</property>
+                                    <property name="n_rows">4</property>
+                                    <property name="n_columns">3</property>
+                                    <child>
+                                      <object class="GtkLabel" id="label7">
+                                        <property name="visible">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">&lt;b&gt;Starts and ends&lt;/b&gt;</property>
+                                        <property name="use_markup">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="y_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkLabel" id="label8">
+                                        <property name="visible">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">&lt;b&gt;Totals&lt;/b&gt;</property>
+                                        <property name="use_markup">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                        <property name="y_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkLabel" id="label6">
+                                        <property name="visible">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">&lt;b&gt;Averages&lt;/b&gt;</property>
+                                        <property name="use_markup">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">2</property>
+                                        <property name="right_attach">3</property>
+                                        <property name="y_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkAlignment" id="explore_weekday_starts_ends">
+                                        <property name="visible">True</property>
+                                        <child>
+                                          <placeholder/>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="top_attach">1</property>
+                                        <property name="bottom_attach">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkAlignment" id="explore_category_starts_ends">
+                                        <property name="visible">True</property>
+                                        <child>
+                                          <placeholder/>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="top_attach">2</property>
+                                        <property name="bottom_attach">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkAlignment" id="explore_weekday_totals">
+                                        <property name="visible">True</property>
+                                        <child>
+                                          <placeholder/>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                        <property name="top_attach">1</property>
+                                        <property name="bottom_attach">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkAlignment" id="explore_category_totals">
+                                        <property name="visible">True</property>
+                                        <child>
+                                          <placeholder/>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                        <property name="top_attach">2</property>
+                                        <property name="bottom_attach">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                            </child>
                           </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
                   </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
               </object>
               <packing>
-                <property name="resize">True</property>
-                <property name="shrink">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Statistics</property>
+              </object>
+              <packing>
+                <property name="position">1</property>
+                <property name="tab_fill">False</property>
               </packing>
             </child>
           </object>
-          <packing>
-            <property name="position">2</property>
-          </packing>
         </child>
       </object>
     </child>
   </object>
-  <object class="GtkImage" id="week_icon">
-    <property name="visible">True</property>
-    <property name="pixbuf">art/stock_calendar-view-week.png</property>
-  </object>
-  <object class="GtkImage" id="month_icon">
-    <property name="visible">True</property>
-    <property name="pixbuf">art/stock_calendar-view-month.png</property>
-  </object>
   <object class="GtkFileChooserDialog" id="save_report_dialog">
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Save report - Time Tracker</property>
@@ -553,4 +817,12 @@
       <action-widget response="0">cancel_button</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkImage" id="week_icon">
+    <property name="visible">True</property>
+    <property name="pixbuf">art/stock_calendar-view-week.png</property>
+  </object>
+  <object class="GtkImage" id="month_icon">
+    <property name="visible">True</property>
+    <property name="pixbuf">art/stock_calendar-view-month.png</property>
+  </object>
 </interface>
diff --git a/hamster/stats.py b/hamster/stats.py
index 9d30320..448a729 100644
--- a/hamster/stats.py
+++ b/hamster/stats.py
@@ -32,6 +32,8 @@ from hamster.edit_activity import CustomFactController
 from hamster import reports, widgets
 import webbrowser
 
+from itertools import groupby
+
 import datetime as dt
 import calendar
 import time
@@ -160,20 +162,20 @@ class StatsViewer(object):
         self.parent = parent# determine if app shut shut down on close
         self._gui = stuff.load_ui_file("stats.ui")
         self.window = self.get_widget('stats_window')
+        self.stat_facts = None
 
         #id, caption, duration, date (invisible), description, category
         self.fact_store = gtk.TreeStore(int, str, str, str, str, str) 
         self.setup_tree()
         
-        graph_frame = self.get_widget("graph_frame")
-        background = (0.975,0.975,0.975)
-        graph_frame.modify_bg(gtk.STATE_NORMAL,
-                              gtk.gdk.Color(*[int(b*65536.0) for b in background]))
+        self.background = (0.975,0.975,0.975)
+        self.get_widget("graph_frame").modify_bg(gtk.STATE_NORMAL,
+                      gtk.gdk.Color(*[int(b*65536.0) for b in self.background]))
 
         
         x_offset = 90 # let's nicely align all graphs
         
-        self.category_chart = charting.BarChart(background = background,
+        self.category_chart = charting.BarChart(background = self.background,
                                              bar_base_color = (238,221,221),
                                              bars_beveled = False,
                                              legend_width = x_offset,
@@ -185,7 +187,7 @@ class StatsViewer(object):
         category_box.set_size_request(130, -1)
         
 
-        self.day_chart = charting.BarChart(background = background,
+        self.day_chart = charting.BarChart(background = self.background,
                                         bar_base_color = (220, 220, 220),
                                         bars_beveled = False,
                                         show_scale = True,
@@ -201,7 +203,7 @@ class StatsViewer(object):
                                              stretch_grid = True,
                                              legend_width = x_offset,
                                              value_format = "%.1f",
-                                             background = background,
+                                             background = self.background,
                                              bars_beveled = False,
                                              animate = False)
         self.get_widget("totals_by_activity").add(self.activity_chart);
@@ -240,6 +242,261 @@ class StatsViewer(object):
 
         self.report_chooser = None
         self.do_graph()
+        self.init_stats()
+
+
+    
+    def init_stats(self):
+        self.get_widget("explore_frame").modify_bg(gtk.STATE_NORMAL,
+                      gtk.gdk.Color(*[int(b*65536.0) for b in self.background]))
+
+        if not self.stat_facts:
+            self.stat_facts = storage.get_facts(dt.date(1970, 1, 1), dt.date.today())
+        
+        by_year = self._totals(self.stat_facts,
+                               lambda fact: fact["start_time"].year,
+                               lambda fact: 1)
+        
+        year_box = self.get_widget("year_box")
+        for child in year_box.get_children():
+            year_box.remove(child)
+        
+        class YearButton(gtk.ToggleButton):
+            def __init__(self, label, year, on_clicked):
+                gtk.ToggleButton.__init__(self, label)
+                self.year = year
+                self.connect("clicked", on_clicked)
+        
+        all_button = YearButton(_("All"), None, self.on_year_changed)
+        year_box.pack_start(all_button)
+        self.bubbling = True # TODO figure out how to properly work with togglebuttons as radiobuttons
+        all_button.set_active(True)
+        self.bubbling = False # TODO figure out how to properly work with togglebuttons as radiobuttons
+
+        years = sorted(by_year.keys())
+        for year in years:
+            year_box.pack_start(YearButton(str(year), year, self.on_year_changed))
+
+        year_box.show_all()
+
+
+
+
+        self.chart_everything = charting.BarChart(value_format = "%.1f",
+                                       bars_beveled = False,
+                                       animate = False,
+                                       background = self.background,
+                                       max_bar_width = 35,
+                                       show_labels = False)
+        self.get_widget("explore_everything").add(self.chart_everything)
+
+
+        self.chart_category_totals = charting.HorizontalBarChart(value_format = "%.1f",
+                                                            bars_beveled = False,
+                                                            animate = False,
+                                                            background = self.background,
+                                                            max_bar_width = 20,
+                                                            legend_width = 70)
+        self.get_widget("explore_category_totals").add(self.chart_category_totals)
+
+
+        self.chart_weekday_totals = charting.HorizontalBarChart(value_format = "%.1f",
+                                                            bars_beveled = False,
+                                                            animate = False,
+                                                            background = self.background,
+                                                            max_bar_width = 20,
+                                                            legend_width = 70)
+        self.get_widget("explore_weekday_totals").add(self.chart_weekday_totals)
+
+        self.chart_weekday_starts_ends = charting.HorizontalDayChart(bars_beveled = False,
+                                                                animate = False,
+                                                                background = self.background,
+                                                                max_bar_width = 20,
+                                                                legend_width = 70)
+        self.get_widget("explore_weekday_starts_ends").add(self.chart_weekday_starts_ends)
+        
+        self.chart_category_starts_ends = charting.HorizontalDayChart(bars_beveled = False,
+                                                                animate = False,
+                                                                background = self.background,
+                                                                max_bar_width = 20,
+                                                                legend_width = 70)
+        self.get_widget("explore_category_starts_ends").add(self.chart_category_starts_ends)
+
+        self.stats(self.stat_facts)
+    
+    def on_year_changed(self, button):
+        if self.bubbling:
+            return
+        
+        for child in button.parent.get_children():
+            if child != button and child.get_active():
+                self.bubbling = True
+                child.set_active(False)
+                self.bubbling = False
+        
+        facts = self.stat_facts
+        if button.year:
+            facts = filter(lambda fact: fact["start_time"].year == button.year,
+                           facts)
+        
+        self.stats(facts)
+        
+    def stats(self, facts):
+        # All dates in the scope
+        just_totals = self._totals(facts,
+                                   lambda fact: fact["start_time"].date(),
+                                   lambda fact: fact["delta"].seconds / 60 / 60.0)
+        just_totals_keys = sorted(just_totals.keys())
+        
+        just_totals = [just_totals[key][0] for key in just_totals_keys]
+        just_totals_keys = [key.strftime("%d %m %Y") for key in just_totals_keys]
+
+        self.chart_everything.plot(just_totals_keys, just_totals)
+
+
+        # Totals by category
+        categories = self._totals(facts,
+                                  lambda fact: fact["category"],
+                                  lambda fact: fact['delta'].seconds / 60 / 60.0)
+        category_keys = sorted(categories.keys())
+        categories = [categories[key][0] for key in category_keys]
+        self.chart_category_totals.plot(category_keys, categories)
+        
+
+        # Totals by weekday
+        weekdays = self._totals(facts,
+                                  lambda fact: (fact["start_time"].weekday(),
+                                                fact["start_time"].strftime("%a")),
+                                  lambda fact: fact['delta'].seconds / 60 / 60.0)
+
+        weekday_keys = sorted(weekdays.keys(), key = lambda x: x[0]) #sort 
+        weekdays = [weekdays[key][0] for key in weekday_keys] #get values in the order
+        weekday_keys = [key[1] for key in weekday_keys] #now remove the weekday and keep just the abbreviated one
+
+        self.chart_weekday_totals.plot(weekday_keys, weekdays)
+
+
+
+        # now we will try to figure out average start and end times.
+        # first we need to group facts by date
+        # they are already sorted in db, so we can rely on that
+        by_weekday = {}
+        for date, date_facts in groupby(facts, lambda fact: fact["start_time"].date()):
+            date_facts = list(date_facts)
+            weekday = (date_facts[0]["start_time"].weekday(),
+                       date_facts[0]["start_time"].strftime("%a"))
+            by_weekday.setdefault(weekday, {"min": [], "max": []})
+
+            min_time = min([fact["start_time"].time() for fact in date_facts])
+            by_weekday[weekday]["min"].append(min_time.minute + min_time.hour * 60)
+            
+            same_date_facts = [fact["end_time"].time() for fact in date_facts if fact["end_time"] and fact["start_time"].date() == fact["end_time"].date()]
+            if same_date_facts:
+                max_time = max(same_date_facts)
+                by_weekday[weekday]["max"].append(max_time.minute + max_time.hour * 60)
+
+        for day in by_weekday:
+            by_weekday[day]["min"] = int(sum(by_weekday[day]["min"]) / float(len(by_weekday[day]["min"])))
+            by_weekday[day]["min"] = dt.time(by_weekday[day]["min"] / 60, by_weekday[day]["min"] % 60)
+                                             
+            by_weekday[day]["max"] = int(sum(by_weekday[day]["max"]) / float(len(by_weekday[day]["max"])))
+            by_weekday[day]["max"] = dt.time(by_weekday[day]["max"] / 60, by_weekday[day]["max"] % 60)
+
+        min_weekday = min([by_weekday[day]["min"] for day in by_weekday])
+        max_weekday = max([by_weekday[day]["max"] for day in by_weekday])
+
+        weekday_keys = sorted(by_weekday.keys(), key = lambda x: x[0])
+        weekdays = [(by_weekday[key]["min"], by_weekday[key]["max"])
+                                                        for key in weekday_keys]
+        
+        weekday_keys = [key[1] for key in weekday_keys] # get rid of the weekday number as int
+
+
+        # and now try to figure out average min and max times per day per category
+
+        # now we will try to figure out average start and end times.
+        # first we need to group facts by date
+        # they are already sorted in db, so we can rely on that
+        by_category = {}
+        for date, date_facts in groupby(facts, lambda fact: fact["start_time"].date()):
+            date_facts = sorted(list(date_facts), key = lambda x: x["category"])
+            
+            for category, category_facts in groupby(date_facts, lambda x: x["category"]):
+                category_facts = list(category_facts)
+                by_category.setdefault(category, {"min": [], "max": []})
+
+                min_time = min([fact["start_time"].time() for fact in category_facts])
+                by_category[category]["min"].append(min_time.minute + min_time.hour * 60)
+            
+                same_date_facts = [fact["end_time"].time() for fact in category_facts if fact["end_time"] and fact["start_time"].date() == fact["end_time"].date()]
+                if same_date_facts:
+                    max_time = max(same_date_facts)
+                    by_category[category]["max"].append(max_time.minute + max_time.hour * 60)
+
+        for key in by_category:
+            by_category[key]["min"] = int(sum(by_category[key]["min"]) / float(len(by_category[key]["min"])))
+            by_category[key]["min"] = dt.time(by_category[key]["min"] / 60, by_category[key]["min"] % 60)
+                                             
+            by_category[key]["max"] = int(sum(by_category[key]["max"]) / float(len(by_category[key]["max"])))
+            by_category[key]["max"] = dt.time(by_category[key]["max"] / 60, by_category[key]["max"] % 60)
+
+        min_category = min([by_category[day]["min"] for day in by_category])
+        max_category = max([by_category[day]["max"] for day in by_category])
+
+
+        category_keys = sorted(by_category.keys(), key = lambda x: x[0])
+        categories = [(by_category[key]["min"], by_category[key]["max"])
+                                                        for key in category_keys]
+
+
+        #get starting and ending hours for graph and turn them into exact hours that divide by 3
+        min_hour = min([min_weekday, min_category])
+        min_hour = dt.time((min_hour.hour * 60 + min_hour.minute) / (3 * 60) * (3 * 60) / 60, 0)
+        max_hour = max([max_weekday, max_category])
+        max_hour = dt.time((max_hour.hour * 60 + max_hour.minute) / (3 * 60) * (3 * 60) / 60 + 3, 0) 
+
+
+        self.chart_weekday_starts_ends.plot_day(weekday_keys, weekdays, min_hour, max_hour)
+
+        self.chart_category_starts_ends.plot_day(category_keys, categories, min_hour, max_hour)
+
+        
+        """
+        cat_activities = self._totals(facts,
+                                  lambda fact: "%s-%s" % (fact["name"], fact["category"]),
+                                  lambda fact: fact['delta'].seconds / 60)
+
+        weekdays = self._totals(facts,
+                                  lambda fact: fact["start_time"].weekday,
+                                  lambda fact: fact['delta'].seconds / 60)
+        
+        dates = self._totals(facts,
+                                  lambda fact: fact["start_time"].day,
+                                  lambda fact: fact['delta'].seconds / 60)
+        
+        months = self._totals(facts,
+                                  lambda fact: fact["start_time"].month,
+                                  lambda fact: fact['delta'].seconds / 60)
+        """
+
+
+    
+    def _totals(self, iter, keyfunc, sumfunc):
+        """groups items by field described in keyfunc and counts totals using value
+           from sumfunc
+        """
+        data = sorted(iter, key=keyfunc)
+    
+        totals = {}
+        max_total = -10000
+        for k, group in groupby(data, keyfunc):
+            totals[k] = sum([sumfunc(entry) for entry in group])
+            max_total = max(max_total, totals[k])
+        
+        for total in totals: #add normalized version too
+            totals[total] = (totals[total], totals[total] / float(max_total))
+        
+        return totals
 
     def more_on_left(self):
         z = min(round((self.end_date - self.start_date).days / 21.0)+1, 5)
@@ -476,7 +733,7 @@ class StatsViewer(object):
         
         
         label = self.get_widget("overview_label")
-        label.set_text(overview_label)
+        label.set_markup("<b>%s</b>" % overview_label)
 
         label2 = self.get_widget("dayview_caption")
         label2.set_markup("%s" % (dayview_caption))



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]