[hamster-applet] range popup now disappears properly; moved it out to widgets; moved bunch of date utils to stuff



commit 6a1634b98cff8260a2c5e6695c4c360a154ebb52
Author: Toms Bauģis <toms baugis gmail com>
Date:   Sat Jun 12 18:30:07 2010 +0100

    range popup now disappears properly; moved it out to widgets; moved bunch of date utils to stuff

 data/overview.ui                 |  304 +-------------------------------------
 data/range_pick.ui               |  264 +++++++++++++++++++++++++++++++++
 src/hamster/overview.py          |  112 ++------------
 src/hamster/stuff.py             |   50 ++++++
 src/hamster/widgets/__init__.py  |    4 +-
 src/hamster/widgets/rangepick.py |  136 +++++++++++++++++
 6 files changed, 471 insertions(+), 399 deletions(-)
---
diff --git a/data/overview.ui b/data/overview.ui
index c0f98ba..04fcdfb 100644
--- a/data/overview.ui
+++ b/data/overview.ui
@@ -3,265 +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="GtkWindow" id="range_popup">
-    <property name="border_width">12</property>
-    <property name="resizable">False</property>
-    <property name="window_position">mouse</property>
-    <property name="destroy_with_parent">True</property>
-    <property name="skip_taskbar_hint">True</property>
-    <property name="skip_pager_hint">True</property>
-    <property name="decorated">False</property>
-    <child>
-      <object class="GtkVBox" id="vbox3">
-        <property name="visible">True</property>
-        <property name="spacing">8</property>
-        <child>
-          <object class="GtkButton" id="day_range">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="related_action">day</property>
-            <property name="use_action_appearance">False</property>
-            <property name="relief">none</property>
-            <child>
-              <object class="GtkHBox" id="hbox6">
-                <property name="visible">True</property>
-                <property name="spacing">8</property>
-                <child>
-                  <object class="GtkLabel" id="label2">
-                    <property name="width_request">100</property>
-                    <property name="visible">True</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Day:</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="day_preview">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label">Jun 17</property>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="week_range">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="related_action">week</property>
-            <property name="use_action_appearance">False</property>
-            <property name="relief">none</property>
-            <child>
-              <object class="GtkHBox" id="hbox7">
-                <property name="visible">True</property>
-                <property name="spacing">8</property>
-                <child>
-                  <object class="GtkLabel" id="label4">
-                    <property name="width_request">100</property>
-                    <property name="visible">True</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Week:</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="week_preview">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label">Jun 14 - 20, 2010</property>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="month_range">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="related_action">month</property>
-            <property name="use_action_appearance">False</property>
-            <property name="relief">none</property>
-            <child>
-              <object class="GtkHBox" id="hbox8">
-                <property name="visible">True</property>
-                <property name="spacing">8</property>
-                <child>
-                  <object class="GtkLabel" id="label6">
-                    <property name="width_request">100</property>
-                    <property name="visible">True</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Month:</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="month_preview">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label">Jun 1-30, 2010</property>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="alignment6">
-            <property name="visible">True</property>
-            <property name="left_padding">4</property>
-            <child>
-              <object class="GtkHBox" id="hbox9">
-                <property name="visible">True</property>
-                <property name="spacing">8</property>
-                <child>
-                  <object class="GtkLabel" id="label8">
-                    <property name="width_request">100</property>
-                    <property name="visible">True</property>
-                    <property name="xalign">1</property>
-                    <property name="yalign">0</property>
-                    <property name="ypad">7</property>
-                    <property name="label" translatable="yes">Range:</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkVBox" id="vbox4">
-                    <property name="visible">True</property>
-                    <property name="spacing">5</property>
-                    <child>
-                      <object class="GtkHBox" id="hbox2">
-                        <property name="visible">True</property>
-                        <property name="spacing">12</property>
-                        <child>
-                          <object class="GtkAlignment" id="range_start_box">
-                            <property name="visible">True</property>
-                            <child>
-                              <object class="GtkCalendar" id="start_calendar">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="year">2010</property>
-                                <property name="month">5</property>
-                                <property name="day">11</property>
-                                <signal name="day-selected-double-click" handler="on_manual_range_apply_clicked" swapped="no"/>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label1">
-                            <property name="visible">True</property>
-                            <property name="yalign">0</property>
-                            <property name="ypad">7</property>
-                            <property name="label" translatable="yes">to</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkAlignment" id="range_end_box">
-                            <property name="visible">True</property>
-                            <child>
-                              <object class="GtkCalendar" id="end_calendar">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="year">2010</property>
-                                <property name="month">5</property>
-                                <property name="day">11</property>
-                                <signal name="day-selected-double-click" handler="on_manual_range_apply_clicked" swapped="no"/>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkHButtonBox" id="hbuttonbox1">
-                        <property name="visible">True</property>
-                        <property name="layout_style">end</property>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <object class="GtkButton" id="manual_range_apply">
-                            <property name="label" translatable="yes">Apply</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                            <property name="use_action_appearance">False</property>
-                            <signal name="clicked" handler="on_manual_range_apply_clicked" swapped="no"/>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="position">3</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
   <object class="GtkActionGroup" id="view">
     <child>
       <object class="GtkAction" id="day">
@@ -467,51 +208,10 @@
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkToggleButton" id="date_pick">
+                          <object class="GtkAlignment" id="range_pick_box">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                            <property name="use_action_appearance">False</property>
-                            <signal name="toggled" handler="on_date_pick_toggled" swapped="no"/>
                             <child>
-                              <object class="GtkAlignment" id="alignment4">
-                                <property name="visible">True</property>
-                                <child>
-                                  <object class="GtkHBox" id="hbox1">
-                                    <property name="visible">True</property>
-                                    <property name="spacing">3</property>
-                                    <child>
-                                      <object class="GtkAlignment" id="alignment5">
-                                        <property name="visible">True</property>
-                                        <property name="top_padding">2</property>
-                                        <property name="bottom_padding">2</property>
-                                        <property name="left_padding">2</property>
-                                        <property name="right_padding">2</property>
-                                        <child>
-                                          <object class="GtkLabel" id="range_title">
-                                            <property name="visible">True</property>
-                                            <property name="xalign">0</property>
-                                            <property name="label">Range</property>
-                                            <attributes>
-                                              <attribute name="weight" value="bold"/>
-                                              <attribute name="size" value="15000"/>
-                                            </attributes>
-                                          </object>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                  </object>
-                                </child>
-                              </object>
+                              <placeholder/>
                             </child>
                           </object>
                           <packing>
diff --git a/data/range_pick.ui b/data/range_pick.ui
new file mode 100644
index 0000000..4c1ba9e
--- /dev/null
+++ b/data/range_pick.ui
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="range_popup">
+    <property name="border_width">12</property>
+    <property name="resizable">False</property>
+    <property name="window_position">mouse</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="skip_pager_hint">True</property>
+    <property name="decorated">False</property>
+    <child>
+      <object class="GtkVBox" id="vbox3">
+        <property name="visible">True</property>
+        <property name="spacing">8</property>
+        <child>
+          <object class="GtkButton" id="day">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="use_action_appearance">False</property>
+            <property name="relief">none</property>
+            <signal name="clicked" handler="on_day_clicked" swapped="no"/>
+            <child>
+              <object class="GtkHBox" id="hbox6">
+                <property name="visible">True</property>
+                <property name="spacing">8</property>
+                <child>
+                  <object class="GtkLabel" id="label2">
+                    <property name="width_request">100</property>
+                    <property name="visible">True</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Day:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="day_preview">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label">Jun 17</property>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="week">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="use_action_appearance">False</property>
+            <property name="relief">none</property>
+            <signal name="clicked" handler="on_week_clicked" swapped="no"/>
+            <child>
+              <object class="GtkHBox" id="hbox7">
+                <property name="visible">True</property>
+                <property name="spacing">8</property>
+                <child>
+                  <object class="GtkLabel" id="label4">
+                    <property name="width_request">100</property>
+                    <property name="visible">True</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Week:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="week_preview">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label">Jun 14 - 20, 2010</property>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="month">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="use_action_appearance">False</property>
+            <property name="relief">none</property>
+            <signal name="clicked" handler="on_month_clicked" swapped="no"/>
+            <child>
+              <object class="GtkHBox" id="hbox8">
+                <property name="visible">True</property>
+                <property name="spacing">8</property>
+                <child>
+                  <object class="GtkLabel" id="label6">
+                    <property name="width_request">100</property>
+                    <property name="visible">True</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Month:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="month_preview">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label">Jun 1-30, 2010</property>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkAlignment" id="alignment6">
+            <property name="visible">True</property>
+            <property name="left_padding">4</property>
+            <child>
+              <object class="GtkHBox" id="hbox9">
+                <property name="visible">True</property>
+                <property name="spacing">8</property>
+                <child>
+                  <object class="GtkLabel" id="label8">
+                    <property name="width_request">100</property>
+                    <property name="visible">True</property>
+                    <property name="xalign">1</property>
+                    <property name="yalign">0</property>
+                    <property name="ypad">7</property>
+                    <property name="label" translatable="yes">Range:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkVBox" id="vbox4">
+                    <property name="visible">True</property>
+                    <property name="spacing">5</property>
+                    <child>
+                      <object class="GtkHBox" id="hbox2">
+                        <property name="visible">True</property>
+                        <property name="spacing">12</property>
+                        <child>
+                          <object class="GtkAlignment" id="range_start_box">
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkCalendar" id="start_calendar">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="year">2010</property>
+                                <property name="month">5</property>
+                                <property name="day">11</property>
+                                <signal name="day-selected-double-click" handler="on_manual_range_apply_clicked" swapped="no"/>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="yalign">0</property>
+                            <property name="ypad">7</property>
+                            <property name="label" translatable="yes">to</property>
+                          </object>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkAlignment" id="range_end_box">
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkCalendar" id="end_calendar">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="year">2010</property>
+                                <property name="month">5</property>
+                                <property name="day">11</property>
+                                <signal name="day-selected-double-click" handler="on_manual_range_apply_clicked" swapped="no"/>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkHButtonBox" id="hbuttonbox1">
+                        <property name="visible">True</property>
+                        <property name="layout_style">end</property>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="manual_range_apply">
+                            <property name="label" translatable="yes">Apply</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="use_action_appearance">False</property>
+                            <signal name="clicked" handler="on_manual_range_apply_clicked" swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/hamster/overview.py b/src/hamster/overview.py
index dc90ec0..ca70c51 100644
--- a/src/hamster/overview.py
+++ b/src/hamster/overview.py
@@ -54,6 +54,10 @@ class Overview(object):
         self.view_date = (dt.datetime.today() - dt.timedelta(hours = self.day_start.hour,
                                                         minutes = self.day_start.minute)).date()
 
+        self.range_pick = widgets.RangePick()
+        self.get_widget("range_pick_box").add(self.range_pick)
+        self.range_pick.connect("range-selected", self.on_range_selected)
+
         #set to monday
         self.start_date = self.view_date - dt.timedelta(self.view_date.weekday() + 1)
 
@@ -90,9 +94,6 @@ class Overview(object):
 
         conf.connect('conf-changed', self.on_conf_change)
 
-        #self.get_widget("hbox1").pack_start(gtk.VSeparator())
-        self.get_widget("hbox1").pack_start(gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_ETCHED_IN))
-
         if conf.get("overview_window_maximized"):
             self.window.maximize()
         else:
@@ -108,7 +109,6 @@ class Overview(object):
         self.window.show_all()
         self.search()
 
-
     def on_fact_tree_button_press(self, treeview, event):
         if event.button == 3:
             x = int(event.x)
@@ -133,6 +133,8 @@ class Overview(object):
 
         self.set_title()
 
+        self.range_pick.set_range(self.start_date, self.end_date, self.view_date)
+
         durations = [(fact["start_time"], fact["delta"]) for fact in self.facts]
         self.timechart.draw(durations, self.start_date, self.end_date)
 
@@ -145,41 +147,9 @@ class Overview(object):
             self.overview.search(self.start_date, self.end_date, self.facts)
 
     def set_title(self):
-        self.title = self.format_range(self.start_date, self.end_date)
+        self.title = stuff.format_range(self.start_date, self.end_date)
         self.window.set_title(self.title.decode("utf-8"))
-        self.get_widget("range_title").set_text(self.title)
-
-
-    def format_range(self, start_date, end_date):
-        dates_dict = stuff.dateDict(start_date, "start_")
-        dates_dict.update(stuff.dateDict(end_date, "end_"))
-
-        if start_date == end_date:
-            # Overview label if looking on single day
-            # date format for overview label when only single day is visible
-            # Using python datetime formatting syntax. See:
-            # http://docs.python.org/library/time.html#time.strftime
-            title = start_date.strftime(_("%B %d, %Y"))
-        elif start_date.year != end_date.year:
-            # overview label if start and end years don't match
-            # letter after prefixes (start_, end_) is the one of
-            # standard python date formatting ones- you can use all of them
-            # see http://docs.python.org/library/time.html#time.strftime
-            title = _(u"%(start_B)s %(start_d)s, %(start_Y)s â?? %(end_B)s %(end_d)s, %(end_Y)s") % dates_dict
-        elif start_date.month != end_date.month:
-            # overview label if start and end month do not match
-            # letter after prefixes (start_, end_) is the one of
-            # standard python date formatting ones- you can use all of them
-            # see http://docs.python.org/library/time.html#time.strftime
-            title = _(u"%(start_B)s %(start_d)s â?? %(end_B)s %(end_d)s, %(end_Y)s") % dates_dict
-        else:
-            # overview label for interval in same month
-            # letter after prefixes (start_, end_) is the one of
-            # standard python date formatting ones- you can use all of them
-            # see http://docs.python.org/library/time.html#time.strftime
-            title = _(u"%(start_B)s %(start_d)s â?? %(end_d)s, %(end_Y)s") % dates_dict
 
-        return title
 
     def on_conf_change(self, event, key, value):
         if key == "day_start_minutes":
@@ -238,10 +208,15 @@ class Overview(object):
 
 
     def apply_range_select(self):
-        self.get_widget("range_popup").hide()
-        self.get_widget("date_pick").set_active(False)
         self.search()
 
+
+    def on_range_selected(self, widget, range, start, end):
+        self.current_range = range
+        self.start_date = start
+        self.end_date = end
+        self.apply_range_select()
+
     def on_day_activate(self, button):
         self.current_range = "day"
         self.start_date = self.view_date
@@ -250,12 +225,12 @@ class Overview(object):
 
     def on_week_activate(self, button):
         self.current_range = "week"
-        self.start_date, self.end_date = self.week()
+        self.start_date, self.end_date = stuff.week(self.view_date)
         self.apply_range_select()
 
     def on_month_activate(self, button):
         self.current_range = "month"
-        self.start_date, self.end_date = self.month()
+        self.start_date, self.end_date = stuff.month(self.view_date)
         self.apply_range_select()
 
     def on_manual_range_apply_clicked(self, button):
@@ -269,38 +244,11 @@ class Overview(object):
         self.apply_range_select()
 
 
-
-
-    def week(self):
-        # aligns start and end date to week
-        start_date = self.view_date - dt.timedelta(self.view_date.weekday() + 1)
-        start_date = start_date + dt.timedelta(stuff.locale_first_weekday())
-        end_date = start_date + dt.timedelta(6)
-        return start_date, end_date
-
-    def month(self):
-        # aligns start and end date to month
-        start_date = self.view_date - dt.timedelta(self.view_date.day - 1) #set to beginning of month
-        first_weekday, days_in_month = calendar.monthrange(self.view_date.year, self.view_date.month)
-        end_date = start_date + dt.timedelta(days_in_month - 1)
-        return start_date, end_date
-
-
     def on_tabs_window_configure_event(self, window, event):
         # this is required so that the rows would grow on resize
         self.fact_tree.fix_row_heights()
 
 
-    def on_start_date_entered(self, input):
-        self.start_date = input.get_date()
-        self.view_date = self.start_date
-        self.search()
-
-    def on_end_date_entered(self, input):
-        self.end_date = input.get_date()
-        self.search()
-
-
     def on_prev_activate(self, action):
         if self.current_range == "day":
             self.start_date -= dt.timedelta(1)
@@ -392,34 +340,6 @@ class Overview(object):
         self.overview.delete_selected()
 
 
-    def on_date_pick_toggled(self, button):
-        if button.get_active():
-            popup = self.get_widget("range_popup")
-
-
-            window = button.get_window()
-            x, y = window.get_origin()
-
-            alloc = button.get_allocation()
-
-            popup.move(x + alloc.x,y + alloc.y + alloc.height)
-
-            self.get_widget("day_preview").set_text(self.format_range(self.view_date, self.view_date).decode("utf-8"))
-            self.get_widget("week_preview").set_text(self.format_range(*self.week()).decode("utf-8"))
-            self.get_widget("month_preview").set_text(self.format_range(*self.month()).decode("utf-8"))
-
-            start_cal = self.get_widget("start_calendar")
-            start_cal.select_month(self.start_date.month, self.start_date.year)
-            start_cal.select_day(self.start_date.day)
-
-            end_cal = self.get_widget("end_calendar")
-            end_cal.select_month(self.end_date.month, self.end_date.year)
-            end_cal.select_day(self.end_date.day)
-
-            popup.show_all()
-        else:
-            self.get_widget("range_popup").hide()
-
     def on_edit_activate(self, button):
         fact = self.fact_tree.get_selected_fact()
         if not fact or isinstance(fact, dt.date):
diff --git a/src/hamster/stuff.py b/src/hamster/stuff.py
index 6ad646d..2ff2d4a 100644
--- a/src/hamster/stuff.py
+++ b/src/hamster/stuff.py
@@ -28,6 +28,7 @@ from pango import ELLIPSIZE_END
 
 from itertools import groupby
 import datetime as dt
+import calendar
 import time
 import re
 import gettext, locale
@@ -95,6 +96,55 @@ def format_duration(minutes, human = True):
 
     return formatted_duration
 
+
+def format_range(start_date, end_date):
+    dates_dict = dateDict(start_date, "start_")
+    dates_dict.update(dateDict(end_date, "end_"))
+
+    if start_date == end_date:
+        # label of date range if looking on single day
+        # date format for overview label when only single day is visible
+        # Using python datetime formatting syntax. See:
+        # http://docs.python.org/library/time.html#time.strftime
+        title = start_date.strftime(_("%B %d, %Y"))
+    elif start_date.year != end_date.year:
+        # label of date range if start and end years don't match
+        # letter after prefixes (start_, end_) is the one of
+        # standard python date formatting ones- you can use all of them
+        # see http://docs.python.org/library/time.html#time.strftime
+        title = _(u"%(start_B)s %(start_d)s, %(start_Y)s â?? %(end_B)s %(end_d)s, %(end_Y)s") % dates_dict
+    elif start_date.month != end_date.month:
+        # label of date range if start and end month do not match
+        # letter after prefixes (start_, end_) is the one of
+        # standard python date formatting ones- you can use all of them
+        # see http://docs.python.org/library/time.html#time.strftime
+        title = _(u"%(start_B)s %(start_d)s â?? %(end_B)s %(end_d)s, %(end_Y)s") % dates_dict
+    else:
+        # label of date range for interval in same month
+        # letter after prefixes (start_, end_) is the one of
+        # standard python date formatting ones- you can use all of them
+        # see http://docs.python.org/library/time.html#time.strftime
+        title = _(u"%(start_B)s %(start_d)s â?? %(end_d)s, %(end_Y)s") % dates_dict
+
+    return title
+
+
+
+def week(view_date):
+    # aligns start and end date to week
+    start_date = view_date - dt.timedelta(view_date.weekday() + 1)
+    start_date = start_date + dt.timedelta(locale_first_weekday())
+    end_date = start_date + dt.timedelta(6)
+    return start_date, end_date
+
+def month(view_date):
+    # aligns start and end date to month
+    start_date = view_date - dt.timedelta(view_date.day - 1) #set to beginning of month
+    first_weekday, days_in_month = calendar.monthrange(view_date.year, view_date.month)
+    end_date = start_date + dt.timedelta(days_in_month - 1)
+    return start_date, end_date
+
+
 def duration_minutes(duration):
     """returns minutes from duration, otherwise we keep bashing in same math"""
     return duration.seconds / 60 + duration.days * 24 * 60
diff --git a/src/hamster/widgets/__init__.py b/src/hamster/widgets/__init__.py
index 3017d57..6d2eaa7 100644
--- a/src/hamster/widgets/__init__.py
+++ b/src/hamster/widgets/__init__.py
@@ -37,6 +37,9 @@ from reportchooserdialog import ReportChooserDialog
 
 from facttree import FactTree
 
+from rangepick import RangePick
+
+
 # handy wrappers
 def add_hint(entry, hint):
     entry.hint = hint
@@ -85,4 +88,3 @@ def add_hint(entry, hint):
     entry.connect('changed', entry._on_changed)
 
     entry._set_hint(entry, None)
-
diff --git a/src/hamster/widgets/rangepick.py b/src/hamster/widgets/rangepick.py
new file mode 100644
index 0000000..45266ae
--- /dev/null
+++ b/src/hamster/widgets/rangepick.py
@@ -0,0 +1,136 @@
+# - coding: utf-8 -
+
+# Copyright (C) 2008-2009 Toms Bauģis <toms.baugis at gmail.com>
+
+# This file is part of Project Hamster.
+
+# Project Hamster is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# Project Hamster is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with Project Hamster.  If not, see <http://www.gnu.org/licenses/>.
+
+from .hamster import stuff
+
+
+import gtk, gobject, pango
+import datetime as dt
+import calendar
+import gobject
+import re
+
+class RangePick(gtk.ToggleButton):
+    """ a text entry widget with calendar popup"""
+    __gsignals__ = {
+        # day|week|month|manual, start, end
+        'range-selected': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)),
+    }
+
+
+    def __init__(self, date = None):
+        gtk.ToggleButton.__init__(self)
+
+        self._gui = stuff.load_ui_file("range_pick.ui")
+        self.popup = self.get_widget("range_popup")
+
+        hbox = gtk.HBox()
+        hbox.set_spacing(3)
+        self.label = gtk.Label()
+        hbox.pack_start(self.label, False)
+        #self.get_widget("hbox1").pack_start(gtk.VSeparator())
+        hbox.pack_start(gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_ETCHED_IN), False)
+        self.add(hbox)
+
+        self.start_date, self.end_date, self.view_date = None, None, None
+
+        self.popup.connect("focus-out-event", self.on_focus_out)
+        self.connect("toggled", self.on_toggle)
+
+        self._gui.connect_signals(self)
+
+
+    def on_toggle(self, button):
+        if self.get_active():
+            self.show()
+        else:
+            self.hide()
+
+    def set_range(self, start_date, end_date, view_date):
+        self.start_date, self.end_date, self.view_date = start_date, end_date, view_date
+        self.label.set_markup('<big><b>%s</b></big>' % stuff.format_range(start_date, end_date).encode("utf-8"))
+
+    def get_widget(self, name):
+        """ skip one variable (huh) """
+        return self._gui.get_object(name)
+
+    def on_focus_out(self, window, event):
+        # avoid double-toggling when focus goes from window to the toggle button
+        if gtk.STATE_PRELIGHT & self.get_state():
+            return
+
+        self.set_active(False)
+
+
+
+    def hide(self):
+        self.set_active(False)
+        self.popup.hide()
+
+    def show(self):
+        x, y = self.get_window().get_origin()
+
+        alloc = self.get_allocation()
+
+        self.popup.move(x + alloc.x,y + alloc.y + alloc.height)
+
+        self.get_widget("day_preview").set_text(stuff.format_range(self.view_date, self.view_date).decode("utf-8"))
+        self.get_widget("week_preview").set_text(stuff.format_range(*stuff.week(self.view_date)).decode("utf-8"))
+        self.get_widget("month_preview").set_text(stuff.format_range(*stuff.month(self.view_date)).decode("utf-8"))
+
+        start_cal = self.get_widget("start_calendar")
+        start_cal.select_month(self.start_date.month - 1, self.start_date.year)
+        start_cal.select_day(self.start_date.day)
+
+        end_cal = self.get_widget("end_calendar")
+        end_cal.select_month(self.end_date.month - 1, self.end_date.year)
+        end_cal.select_day(self.end_date.day)
+
+        self.popup.show_all()
+        self.get_widget("day").grab_focus()
+        self.set_active(True)
+
+    def emit_range(self, range, start, end):
+        self.hide()
+        self.emit("range-selected", range, start, end)
+
+    def on_day_clicked(self, button):
+        self.emit_range("day", self.view_date, self.view_date)
+
+    def on_week_clicked(self, button):
+        self.start_date, self.end_date = stuff.week(self.view_date)
+        self.emit_range("week", self.start_date, self.end_date)
+
+    def on_month_clicked(self, button):
+        self.start_date, self.end_date = stuff.month(self.view_date)
+        self.emit_range("month", self.start_date, self.end_date)
+
+    def on_manual_range_apply_clicked(self, button):
+        self.current_range = "manual"
+        cal_date = self.get_widget("start_calendar").get_date()
+        self.start_date = dt.date(cal_date[0], cal_date[1] + 1, cal_date[2])
+
+        cal_date = self.get_widget("end_calendar").get_date()
+        self.end_date = dt.date(cal_date[0], cal_date[1] + 1, cal_date[2])
+
+        # make sure we always have a valid range
+        if self.end_date < self.start_date:
+            self.start_date, self.end_date = self.end_date, self.start_date
+
+        self.emit_range("manual", self.start_date, self.end_date)



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