Merge lp:~rohanm/gtimelog/custom-date-range-report into lp:~gtimelog-dev/gtimelog/trunk

Proposed by Rohan Mitchell
Status: Merged
Merged at revision: 255
Proposed branch: lp:~rohanm/gtimelog/custom-date-range-report
Merge into: lp:~gtimelog-dev/gtimelog/trunk
Diff against target: 170 lines (+114/-1)
4 files modified
NEWS.txt (+1/-1)
src/gtimelog/gtimelog.ui (+11/-0)
src/gtimelog/main.py (+34/-0)
src/gtimelog/test_gtimelog.py (+68/-0)
To merge this branch: bzr merge lp:~rohanm/gtimelog/custom-date-range-report
Reviewer Review Type Date Requested Status
Marius Gedminas Approve
Review via email: mp+162547@code.launchpad.net

Description of the change

Added a custom date range report so that you can generate a report between any two dates.
This feature can be reached at Report -> Report for a Custom Date Range.
This branch includes tests for the new report.

To post a comment you must log in.
Revision history for this message
Marius Gedminas (mgedmin) wrote :

Looks good, thanks!

I'd like to play with Glade and create a single dialog for selecting both the start and end dates in one go, instead of dealing with two distinct unlabeled popup dialogs asking for same thing. Or maybe you'd care to do that? ;-)

review: Approve
Revision history for this message
Rohan Mitchell (rohanm) wrote :

I'll see if I can find some time to hack on it, perhaps Monday :)

> Looks good, thanks!
>
> I'd like to play with Glade and create a single dialog for selecting both the
> start and end dates in one go, instead of dealing with two distinct unlabeled
> popup dialogs asking for same thing. Or maybe you'd care to do that? ;-)

Revision history for this message
Marius Gedminas (mgedmin) wrote :

No need any more, I found some time to play with Glade today.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS.txt'
2--- NEWS.txt 2013-02-10 19:56:21 +0000
3+++ NEWS.txt 2013-05-06 00:11:25 +0000
4@@ -1,6 +1,6 @@
5 0.8.2 (unreleased)
6 ==================
7-
8+* New custom date range report
9
10 0.8.1 (2013-02-10)
11 ==================
12
13=== modified file 'src/gtimelog/gtimelog.ui'
14--- src/gtimelog/gtimelog.ui 2012-08-23 05:20:13 +0000
15+++ src/gtimelog/gtimelog.ui 2013-05-06 00:11:25 +0000
16@@ -425,6 +425,17 @@
17 </object>
18 </child>
19 <child>
20+ <object class="GtkImageMenuItem" id="custom_range_report">
21+ <property name="label">Report for a Custom Date Range...</property>
22+ <property name="visible">True</property>
23+ <property name="can_focus">False</property>
24+ <property name="use_action_appearance">False</property>
25+ <property name="use_underline">True</property>
26+ <property name="use_stock">True</property>
27+ <signal name="activate" handler="on_custom_range_report_activate" swapped="no"/>
28+ </object>
29+ </child>
30+ <child>
31 <object class="GtkSeparatorMenuItem" id="separator1">
32 <property name="visible">True</property>
33 <property name="can_focus">False</property>
34
35=== modified file 'src/gtimelog/main.py'
36--- src/gtimelog/main.py 2013-02-07 08:33:21 +0000
37+++ src/gtimelog/main.py 2013-05-06 00:11:25 +0000
38@@ -738,6 +738,17 @@
39 period_name='month',
40 estimated_column=estimated_column)
41
42+ def custom_range_report_categorized(self, output, email, who,
43+ estimated_column=False):
44+ """Format a custom range report with entries displayed under categories."""
45+ min = self.window.min_timestamp.strftime('%Y-%m-%d')
46+ max = self.window.max_timestamp - datetime.timedelta(1)
47+ max = max.strftime('%Y-%m-%d')
48+ subject = u'Custom date range report for %s (%s - %s)' % (who, min, max)
49+ return self._categorizing_report(output, email, who, subject,
50+ period_name='custom range',
51+ estimated_column=estimated_column)
52+
53 def daily_report(self, output, email, who):
54 """Format a daily report.
55
56@@ -884,6 +895,12 @@
57 first_of_next_month, self.virtual_midnight)
58 return self.window_for(min, max)
59
60+ def window_for_date_range(self, min, max):
61+ min = datetime.datetime.combine(min, self.virtual_midnight)
62+ max = datetime.datetime.combine(max, self.virtual_midnight)
63+ max = max + datetime.timedelta(1)
64+ return self.window_for(min, max)
65+
66 def whole_history(self):
67 """Return a TimeWindow for the whole history."""
68 # XXX I don't like this solution. Better make the min/max filtering
69@@ -1967,6 +1984,23 @@
70 report = reports.monthly_report_plain
71 self.mail(report)
72
73+ def range_window(self, min, max):
74+ if not min:
75+ min = self.timelog.day
76+ if not max:
77+ max = self.timelog.day
78+ if max < min:
79+ max = min
80+ return self.timelog.window_for_date_range(min, max)
81+
82+ def on_custom_range_report_activate(self, widget):
83+ """File -> Report for a Custom Date Range"""
84+ min = self.choose_date()
85+ max = self.choose_date()
86+ if min and max:
87+ reports = Reports(self.range_window(min, max))
88+ self.mail(reports.custom_range_report_categorized)
89+
90 def on_open_complete_spreadsheet_activate(self, widget):
91 """Report -> Complete Report in Spreadsheet"""
92 tempfn = tempfile.mktemp(suffix='gtimelog.csv') # XXX unsafe!
93
94=== modified file 'src/gtimelog/test_gtimelog.py'
95--- src/gtimelog/test_gtimelog.py 2013-02-06 09:26:32 +0000
96+++ src/gtimelog/test_gtimelog.py 2013-05-06 00:11:25 +0000
97@@ -587,6 +587,74 @@
98
99 """
100
101+def doctest_Reports_custom_range_report_categorized():
102+ r"""Tests for Reports.custom_range_report_categorized
103+
104+ >>> import sys
105+
106+ >>> from datetime import datetime, time
107+ >>> from tempfile import NamedTemporaryFile
108+ >>> from gtimelog.main import TimeWindow, Reports
109+
110+ >>> vm = time(2, 0)
111+ >>> min = datetime(2010, 1, 25)
112+ >>> max = datetime(2010, 2, 1)
113+ >>> fh = NamedTemporaryFile()
114+
115+ >>> window = TimeWindow(fh.name, min, max, vm)
116+ >>> reports = Reports(window)
117+ >>> reports.custom_range_report_categorized(sys.stdout, 'foo@bar.com',
118+ ... 'Bob Jones')
119+ To: foo@bar.com
120+ Subject: Custom date range report for Bob Jones (2010-01-25 - 2010-01-31)
121+ <BLANKLINE>
122+ No work done this custom range.
123+
124+ >>> _ = [fh.write(s + '\n') for s in [
125+ ... '2010-01-20 09:00: arrived',
126+ ... '2010-01-20 09:30: asdf',
127+ ... '2010-01-20 10:00: Bar: Foo',
128+ ... ''
129+ ... '2010-01-30 09:00: arrived',
130+ ... '2010-01-30 09:23: Bing: stuff',
131+ ... '2010-01-30 12:54: Bong: other stuff',
132+ ... '2010-01-30 13:32: lunch **',
133+ ... '2010-01-30 23:46: misc',
134+ ... '']]
135+ >>> fh.flush()
136+
137+ >>> window = TimeWindow(fh.name, min, max, vm)
138+ >>> reports = Reports(window)
139+ >>> reports.custom_range_report_categorized(sys.stdout, 'foo@bar.com',
140+ ... 'Bob Jones')
141+ To: foo@bar.com
142+ Subject: Custom date range report for Bob Jones (2010-01-25 - 2010-01-31)
143+ <BLANKLINE>
144+ time
145+ Bing:
146+ Stuff 0:23
147+ ----------------------------------------------------------------------
148+ 0:23
149+ <BLANKLINE>
150+ Bong:
151+ Other stuff 3:31
152+ ----------------------------------------------------------------------
153+ 3:31
154+ <BLANKLINE>
155+ No category:
156+ Misc 10:14
157+ ----------------------------------------------------------------------
158+ 10:14
159+ <BLANKLINE>
160+ Total work done this custom range: 14:08
161+ <BLANKLINE>
162+ Categories by time spent:
163+ No category 10:14
164+ Bong 3:31
165+ Bing 0:23
166+
167+ """
168+
169 def doctest_Settings_get_config_dir():
170 """Test for Settings.get_config_dir
171

Subscribers

People subscribed via source and target branches