[hamster-applet] range popup now disappears properly; moved it out to widgets; moved bunch of date utils to stuff
- From: Toms Baugis <tbaugis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hamster-applet] range popup now disappears properly; moved it out to widgets; moved bunch of date utils to stuff
- Date: Sat, 12 Jun 2010 17:31:28 +0000 (UTC)
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]