[hamster-applet] general progress towards using tags in overview (too much going on to remember)



commit 5b12a234e252a4004794b2e58b4bc9e927d5f4fd
Author: Toms Bauģis <toms baugis gmail com>
Date:   Sat Dec 5 22:03:29 2009 +0000

    general progress towards using tags in overview (too much going on to remember)

 data/stats.ui                    |  180 ----------------------------------
 data/stats_overview.ui           |    9 +-
 data/stats_reports.ui            |  196 +++++++++++++++++++++++++++++++++++---
 hamster/stats_overview.py        |   95 ++++++++++++++++---
 hamster/stats_reports.py         |  137 ++++++++++++++++++++++++++
 hamster/stats_stats.py           |   11 ++
 hamster/widgets/activityentry.py |    6 +-
 hamster/widgets/tags.py          |   33 +++++--
 8 files changed, 449 insertions(+), 218 deletions(-)
---
diff --git a/data/stats.ui b/data/stats.ui
index 8c8a229..deb15d7 100644
--- a/data/stats.ui
+++ b/data/stats.ui
@@ -3,186 +3,6 @@
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
   <!-- interface-local-resource-path /home/toms/cvs/hamster/data/art -->
-  <object class="GtkFileChooserDialog" id="save_report_dialog">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Save report &#x2013; Time Tracker</property>
-    <property name="window_position">center</property>
-    <property name="type_hint">normal</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox1">
-        <property name="visible">True</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child>
-          <object class="GtkAlignment" id="alignment2">
-            <property name="visible">True</property>
-            <property name="top_padding">8</property>
-            <property name="left_padding">8</property>
-            <property name="right_padding">8</property>
-            <child>
-              <object class="GtkTable" id="table1">
-                <property name="visible">True</property>
-                <property name="n_rows">2</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">8</property>
-                <property name="row_spacing">8</property>
-                <child>
-                  <object class="GtkLabel" id="date_interval_label">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Date interval:</property>
-                  </object>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label2">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="yalign">0</property>
-                    <property name="label" translatable="yes">Categories:</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment6">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="xscale">0</property>
-                    <child>
-                      <object class="GtkHBox" id="hbox2">
-                        <property name="visible">True</property>
-                        <child>
-                          <object class="GtkAlignment" id="from_date_box">
-                            <property name="visible">True</property>
-                            <child>
-                              <placeholder/>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label11">
-                            <property name="visible">True</property>
-                            <property name="xpad">6</property>
-                            <property name="label" translatable="yes">to</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkAlignment" id="to_date_box">
-                            <property name="visible">True</property>
-                            <child>
-                              <placeholder/>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment8">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="xscale">0</property>
-                    <child>
-                      <object class="GtkTable" id="category_box">
-                        <property name="visible">True</property>
-                        <property name="n_columns">3</property>
-                        <property name="column_spacing">12</property>
-                        <property name="row_spacing">4</property>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                      </object>
-                    </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>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area1">
-            <property name="visible">True</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="cancel_button">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="save_button">
-                <property name="label">gtk-save</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="0">cancel_button</action-widget>
-      <action-widget response="0">save_button</action-widget>
-    </action-widgets>
-  </object>
   <object class="GtkWindow" id="tabs_window">
     <property name="border_width">12</property>
     <property name="title" translatable="yes">Overview - Hamster</property>
diff --git a/data/stats_overview.ui b/data/stats_overview.ui
index 72f74d1..2093c3f 100644
--- a/data/stats_overview.ui
+++ b/data/stats_overview.ui
@@ -13,11 +13,12 @@
             <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>
             <child>
-              <object class="GtkToolButton" id="prev2">
+              <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="label" translatable="yes">Previous</property>
                 <property name="stock_id">gtk-go-back</property>
+                <signal name="clicked" handler="on_prev_clicked"/>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -25,12 +26,13 @@
               </packing>
             </child>
             <child>
-              <object class="GtkToolButton" id="home2">
+              <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">This Week</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>
@@ -38,11 +40,12 @@
               </packing>
             </child>
             <child>
-              <object class="GtkToolButton" id="next2">
+              <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="label" translatable="yes">Next</property>
                 <property name="stock_id">gtk-go-forward</property>
+                <signal name="clicked" handler="on_next_clicked"/>
               </object>
               <packing>
                 <property name="expand">False</property>
diff --git a/data/stats_reports.ui b/data/stats_reports.ui
index 68a2cd5..5dad34a 100644
--- a/data/stats_reports.ui
+++ b/data/stats_reports.ui
@@ -154,26 +154,18 @@
                 <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="position">300</property>
+                <property name="position">400</property>
                 <property name="position_set">True</property>
                 <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow1">
-                    <property name="width_request">300</property>
+                  <object class="GtkScrolledWindow" id="totals_tree_box">
                     <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="hscrollbar_policy">never</property>
                     <property name="vscrollbar_policy">automatic</property>
                     <property name="shadow_type">in</property>
                     <child>
-                      <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="enable_search">False</property>
-                        <signal name="key_press_event" handler="on_key_pressed"/>
-                        <signal name="row_activated" handler="on_facts_row_activated"/>
-                      </object>
+                      <placeholder/>
                     </child>
                   </object>
                   <packing>
@@ -332,4 +324,184 @@
     <property name="tooltip_text" translatable="yes">Show month</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 &#x2013; Time Tracker</property>
+    <property name="window_position">center</property>
+    <property name="type_hint">normal</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkAlignment" id="alignment2">
+            <property name="visible">True</property>
+            <property name="top_padding">8</property>
+            <property name="left_padding">8</property>
+            <property name="right_padding">8</property>
+            <child>
+              <object class="GtkTable" id="table1">
+                <property name="visible">True</property>
+                <property name="n_rows">2</property>
+                <property name="n_columns">2</property>
+                <property name="column_spacing">8</property>
+                <property name="row_spacing">8</property>
+                <child>
+                  <object class="GtkLabel" id="date_interval_label">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Date interval:</property>
+                  </object>
+                  <packing>
+                    <property name="x_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label2">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="yalign">0</property>
+                    <property name="label" translatable="yes">Categories:</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment6">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="xscale">0</property>
+                    <child>
+                      <object class="GtkHBox" id="hbox2">
+                        <property name="visible">True</property>
+                        <child>
+                          <object class="GtkAlignment" id="from_date_box">
+                            <property name="visible">True</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label11">
+                            <property name="visible">True</property>
+                            <property name="xpad">6</property>
+                            <property name="label" translatable="yes">to</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkAlignment" id="to_date_box">
+                            <property name="visible">True</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment8">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="xscale">0</property>
+                    <child>
+                      <object class="GtkTable" id="category_box">
+                        <property name="visible">True</property>
+                        <property name="n_columns">3</property>
+                        <property name="column_spacing">12</property>
+                        <property name="row_spacing">4</property>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                    </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>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel_button">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="save_button">
+                <property name="label">gtk-save</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">cancel_button</action-widget>
+      <action-widget response="0">save_button</action-widget>
+    </action-widgets>
+  </object>
 </interface>
diff --git a/hamster/stats_overview.py b/hamster/stats_overview.py
index ea356da..fe5d417 100644
--- a/hamster/stats_overview.py
+++ b/hamster/stats_overview.py
@@ -49,16 +49,11 @@ from hamster.i18n import C_
 class OverviewBox(gtk.VBox):
     def __init__(self):
         gtk.VBox.__init__(self)
-        
         self._gui = stuff.load_ui_file("stats_overview.ui")
-
-        
         self.get_widget("overview_box").reparent(self) #mine!
 
 
-
         self.view_date = dt.date.today()
-        
         #set to monday
         self.start_date = self.view_date - \
                                       dt.timedelta(self.view_date.weekday() + 1)
@@ -68,16 +63,24 @@ class OverviewBox(gtk.VBox):
         
         self.end_date = self.start_date + dt.timedelta(6)
 
+        self.fact_tree = widgets.FactTree()
+        self.get_widget("overview_facts_box").add(self.fact_tree)
+        self.fill_facts_tree()
+        self.fact_tree.connect("cursor-changed", self.on_fact_selection_changed)
+        self.fact_tree.connect("row-activated", self.on_facts_row_activated)
 
+        self._gui.connect_signals(self)
+        runtime.dispatcher.add_handler('activity_updated', self.after_activity_update)
+        runtime.dispatcher.add_handler('day_updated', self.after_activity_update)
 
-        facts_tree = widgets.FactTree()
-        self.get_widget("overview_facts_box").add(facts_tree)
-        
+    def fill_facts_tree(self):
         facts = runtime.storage.get_facts(self.start_date, self.end_date)
-
-
+        
+        self.fact_tree.clear()
+        
         #create list of all required dates
-        dates = [(self.start_date + dt.timedelta(i), []) for i in range((self.end_date - self.start_date).days  + 1)]
+        dates = [(self.start_date + dt.timedelta(i), [])
+                    for i in range((self.end_date - self.start_date).days  + 1)]
         
         #update with facts for the day
         for date, facts in groupby(facts, lambda fact: fact["date"]):
@@ -87,7 +90,64 @@ class OverviewBox(gtk.VBox):
         for date, facts in dates:
             fact_date = date.strftime(C_("overview list", "%A, %b %d"))
 
-            facts_tree.add_group(fact_date, facts)
+            self.fact_tree.add_group(fact_date, facts)
+
+
+    """ events """
+    def after_activity_update(self, widget, renames):
+        self.fill_facts_tree()
+
+    def on_prev_clicked(self, button):
+        self.start_date -= dt.timedelta(7)
+        self.end_date -= dt.timedelta(7)
+        self.fill_facts_tree()
+
+    def on_next_clicked(self, button):
+        self.start_date += dt.timedelta(7)
+        self.end_date += dt.timedelta(7)        
+        self.fill_facts_tree()
+    
+    def on_home_clicked(self, button):
+        self.view_date = dt.date.today()
+
+        self.start_date = self.view_date - dt.timedelta(self.view_date.weekday() + 1)
+        self.start_date = self.start_date + dt.timedelta(stuff.locale_first_weekday())
+        self.end_date = self.start_date + dt.timedelta(6)
+        
+        self.fill_facts_tree()
+
+
+    def on_fact_selection_changed(self, tree):
+        """ enables and disables action buttons depending on selected item """
+        selection = tree.get_selection()
+        (model, iter) = selection.get_selected()
+
+        id = -1
+        if iter:
+            id = model[iter][0]
+
+        self.get_widget('remove').set_sensitive(id != -1)
+        self.get_widget('edit').set_sensitive(id != -1)
+
+        return True
+
+    def on_facts_row_activated(self, tree, path, column):
+        selection = tree.get_selection()
+        (model, iter) = selection.get_selected()
+        custom_fact = CustomFactController(self, None, model[iter][0])
+        custom_fact.show()
+        
+
+    def on_add_clicked(self, button):
+        selection = self.fact_tree.get_selection()
+        (model, iter) = selection.get_selected()
+
+        selected_date = self.view_date
+        if iter:
+            selected_date = model[iter][6]["date"]
+
+        custom_fact = CustomFactController(self, selected_date)
+        custom_fact.show()
 
     def on_remove_clicked(self, button):
         self.delete_selected()
@@ -202,3 +262,14 @@ class OverviewBox(gtk.VBox):
 
 
 
+if __name__ == "__main__":
+    gtk.window_set_default_icon_name("hamster-applet")
+    
+    window = gtk.Window()
+    window.set_title("Hamster - overview")
+    window.set_size_request(800, 600)
+    
+    window.add(OverviewBox())
+
+    window.show_all()    
+    gtk.main()    
diff --git a/hamster/stats_reports.py b/hamster/stats_reports.py
index c20487e..7b9f039 100644
--- a/hamster/stats_reports.py
+++ b/hamster/stats_reports.py
@@ -45,6 +45,102 @@ import time
 from hamster.i18n import C_
 
 
+def parent_painter(column, cell, model, iter):
+    cell_text = "%s (&#215;%s)" % (stuff.escape_pango(model.get_value(iter, 0)), model.get_value(iter, 3))
+    
+    if model.iter_parent(iter) is None:
+        if model.get_path(iter) == (0,):
+            text = '<span weight="heavy">%s</span>' % cell_text
+        else:
+            text = '<span weight="heavy" rise="-20000">%s</span>' % cell_text
+            
+        cell.set_property('markup', text)
+
+    else:
+        cell.set_property('markup', cell_text)
+
+def duration_painter(column, cell, model, iter):
+    cell.set_property('xalign', 1)
+
+
+    text = model.get_value(iter, 2)
+    if model.iter_parent(iter) is None:
+        if model.get_path(iter) == (0,):
+            text = '<span weight="heavy">%s</span>' % text
+        else:
+            text = '<span weight="heavy" rise="-20000">%s</span>' % text
+    cell.set_property('markup', text)
+
+class TotalsTree(gtk.TreeView):
+    def __init__(self):
+        gtk.TreeView.__init__(self)
+        
+        self.set_headers_visible(False)
+        self.set_show_expanders(True)
+
+        # group name / activity name, tags, duration, occurences
+        self.set_model(gtk.TreeStore(str, gobject.TYPE_PYOBJECT, str, str))
+
+        # name
+        nameColumn = gtk.TreeViewColumn()
+        nameColumn.set_expand(True)
+        nameCell = gtk.CellRendererText()
+        #nameCell.set_property("ellipsize", pango.ELLIPSIZE_END)
+        nameColumn.pack_start(nameCell, True)
+        nameColumn.set_cell_data_func(nameCell, parent_painter)
+        self.append_column(nameColumn)
+
+        tag_cell = widgets.TagCellRenderer()
+        tag_cell.font_size = 8;
+        tagColumn = gtk.TreeViewColumn("", tag_cell, data=1)
+        tagColumn.set_expand(True)
+        self.append_column(tagColumn)
+
+        # duration
+        timeColumn = gtk.TreeViewColumn()
+        timeCell = gtk.CellRendererText()
+        timeColumn.pack_end(timeCell, True)
+        timeColumn.set_cell_data_func(timeCell, duration_painter)
+        self.append_column(timeColumn)
+
+
+        self.show()
+    
+    def clear(self):
+        self.model.clear()
+        
+    @property
+    def model(self):
+        return self.get_model()
+        
+    def add_total(self, total, parent = None):
+        duration = 24 * 60 * total[3].days + total[3].seconds / 60
+
+
+        self.model.append(parent, [total[1],
+                                   total[2],
+                                   stuff.format_duration(duration),
+                                   str(total[4])])
+
+    def add_group(self, group_label, totals):
+        total_duration = sum([total[3].seconds for total in totals]) / 60.0
+        total_occurences = sum([total[4] for total in totals])
+
+        
+        # adds group of facts with the given label
+        group_row = self.model.append(None,
+                                    [group_label,
+                                     None,
+                                     stuff.format_duration(total_duration),
+                                     str(total_occurences)])
+        
+        for total in totals:
+            self.add_total(total, group_row)
+
+        self.expand_all()
+
+
+        
 
 class ReportsBox(gtk.VBox):
     def __init__(self):
@@ -63,7 +159,36 @@ class ReportsBox(gtk.VBox):
         
         self.end_date = self.start_date + dt.timedelta(6)
 
+        
+        self.totals_tree = TotalsTree()
+        self.get_widget("totals_tree_box").add(self.totals_tree)
+        
+        
+        
+        facts = runtime.storage.get_facts(self.start_date, self.end_date)
+
+
+        #first group by category, activity and tags
+        #sort before grouping
+        facts = sorted(facts, key = lambda fact:(fact["category"], fact["name"], fact["tags"]))
+
+        totals = []
+        for group, facts in groupby(facts, lambda fact:(fact["category"], fact["name"], fact["tags"])):
+            facts = list(facts)
+            total_duration = dt.timedelta()
+            for fact in facts:
+                total_duration += fact["delta"]
+            
+            group = list(group)
+            group.extend([total_duration, len(facts)])
+            totals.append(group)
 
+        # second iteration - group the interim result by category
+        for category, totals in groupby(totals, lambda total:total[0]):
+            self.totals_tree.add_group(category, list(totals))
+
+
+        return
 
         self.fact_store = gtk.TreeStore(int, str, str, str, str, str, gobject.TYPE_PYOBJECT) 
         self.setup_tree()
@@ -610,3 +735,15 @@ class ReportsBox(gtk.VBox):
     def on_day_start_changed(self, event, new_minutes):
         self.do_graph()
 
+
+
+if __name__ == "__main__":
+    gtk.window_set_default_icon_name("hamster-applet")    
+    window = gtk.Window()
+    window.set_title("Hamster - reports")
+    window.set_size_request(800, 600)
+    window.add(ReportsBox())
+
+    window.show_all()    
+    gtk.main()    
+
diff --git a/hamster/stats_stats.py b/hamster/stats_stats.py
index 10988c1..56cd3a2 100644
--- a/hamster/stats_stats.py
+++ b/hamster/stats_stats.py
@@ -414,3 +414,14 @@ than 15 minutes you seem to be a busy bee." % ("<b>%d</b>" % short_percent))
 
 
 
+if __name__ == "__main__":
+    gtk.window_set_default_icon_name("hamster-applet")
+    
+    window = gtk.Window()
+    window.set_title("Hamster - statistics")
+    window.set_size_request(800, 600)
+    
+    window.add(StatsBox())
+
+    window.show_all()    
+    gtk.main()    
diff --git a/hamster/widgets/activityentry.py b/hamster/widgets/activityentry.py
index d4cfa31..17634ba 100644
--- a/hamster/widgets/activityentry.py
+++ b/hamster/widgets/activityentry.py
@@ -20,10 +20,10 @@
 import gtk, gobject
 import datetime as dt
 
-from hamster.configuration import runtime
+from .hamster.configuration import runtime
 
-from hamster import stuff
-from hamster.stuff import format_duration
+from .hamster import stuff
+from .hamster.stuff import format_duration
 
 class ActivityEntry(gtk.Entry):
     __gsignals__ = {
diff --git a/hamster/widgets/tags.py b/hamster/widgets/tags.py
index ef8befc..27b058a 100644
--- a/hamster/widgets/tags.py
+++ b/hamster/widgets/tags.py
@@ -21,9 +21,9 @@ import gtk, gobject
 import pango, cairo
 from math import pi
 
-from hamster import graphics
+from .hamster import graphics
 
-from hamster.configuration import runtime
+from .hamster.configuration import runtime
 
 class TagsEntry(gtk.Entry):
     __gsignals__ = {
@@ -317,11 +317,12 @@ class TagCellRenderer(gtk.GenericCellRenderer):
     def __init__(self):
         gtk.GenericCellRenderer.__init__(self)
         self.height = 25
-        self.width = 200
+        self.width = 80 #that's like, two tags or something
         self.data = None
         
         self._font = pango.FontDescription(gtk.Style().font_desc.to_string())
         self._font_size = 10
+        self.layout = None
     
     @property
     def font_size(self):
@@ -356,7 +357,10 @@ class TagCellRenderer(gtk.GenericCellRenderer):
         if not self.data: return
         context = window.cairo_create()
 
-        tags = self.data["tags"]
+        if isinstance(self.data, dict):
+            tags = self.data["tags"]
+        else:
+            tags = self.data
 
         x, y, width, h = cell_area
 
@@ -396,8 +400,12 @@ class TagCellRenderer(gtk.GenericCellRenderer):
         """
 
     def on_get_size (self, widget, cell_area = None):
+        if isinstance(self.data, dict):
+            tags = self.data["tags"]
+        else:
+            tags = self.data
 
-        if not self.width or not self.data or not self.data["tags"]:
+        if not self.width or not tags:
             height = 30
         else:
             pixmap = gtk.gdk.Pixmap(None, self.width, 500, 24)
@@ -407,11 +415,20 @@ class TagCellRenderer(gtk.GenericCellRenderer):
             default_font.set_size(pango.SCALE * 10)
             self.layout.set_font_description(default_font)
 
+            #make sure we fit in
+            max_width = 0
+            for tag in tags:
+                max_width = max(max_width, self.tag_size(tag)[0])
+
+            self.width = max(self.width, max_width)
+            
+            
+
             cur_x, cur_y = 4, 2
-            for tag in self.data["tags"]:
+            for tag in tags:
                 w, h = self.tag_size(tag)
-                if cur_x + w >= self.width - 5:  #if we don't fit, we wrap
-                    cur_x = 5
+                if cur_x > 0 and cur_x + w >= self.width - 8:  #if we don't fit, we wrap
+                    cur_x = 4
                     cur_y += h + 6
                 
                 cur_x += w + 8 #some padding too, please



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