Merge lp://staging/~bryce/gtg/scheduling into lp://staging/~gtg/gtg/old-trunk
- scheduling
- Merge into old-trunk
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp://staging/~bryce/gtg/scheduling |
Merge into: | lp://staging/~gtg/gtg/old-trunk |
Diff against target: |
294 lines (+147/-25) 4 files modified
GTG/core/task.py (+6/-2) GTG/taskbrowser/browser.py (+57/-13) GTG/taskbrowser/taskbrowser.glade (+58/-0) GTG/taskbrowser/tasktree.py (+26/-10) |
To merge this branch: | bzr merge lp://staging/~bryce/gtg/scheduling |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Luca Invernizzi (community) | Approve | ||
Bertrand Rousseau (community) | Approve | ||
Bryce Harrington (community) | Needs Resubmitting | ||
Lionel Dricot | Pending | ||
Review via email: mp+17646@code.staging.launchpad.net |
This proposal supersedes a proposal from 2010-01-17.
Commit message
Description of the change
Bryce Harrington (bryce) wrote : Posted in a previous version of this proposal | # |
Lionel Dricot (ploum-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
Interesting but I fail to see the usefulness of "Start today". I think that this patch should come along with renaming "start date" to "defer to" or something similar
Traceback (most recent call last):
File "/home/
self.
TypeError: iter should be a GtkTreeIter
Lionel Dricot (ploum-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
Also, I think that bug #340022 should be solved before we can merge your patch and at a startdate column.
That startdate column should not be displayed in the workview.
Lionel Dricot (ploum-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
I would also prefer a single menu entry "Defer to…" with submenu for : tomorrow, next week, next month" so we can also have the same for the due date.
Bryce Harrington (bryce) wrote : Posted in a previous version of this proposal | # |
> Also, I think that bug #340022 should be solved before we can merge your patch and at a startdate column.
Why? Bug #340022 seems to have nothing in common with this except that it also thinks the Due date column should go away (but that is already covered by bug #497227.) The format for displaying things that #340022 suggests might be useful but I have no interest in implementing it myself. No one is working on #340022 afaik so predicating acceptance of this branch on solution of that bug just blocks me from being able to make this contribution, which is very discouraging to me.
> I think that this patch should come along with renaming "start date" to "defer to" or something similar
It is unclear what you mean by that.
> Interesting but I fail to see the usefulness of "Start today".
By default, no start date is set on tasks. If you want to indicate "I have started these tasks today" the only way to do it currently is to open each task individually and mark them such. This permits a simpler method for setting the start date to now for a range of tasks. This is helpful when you have a lot of tasks and are using start_date to help organize your tasks.
This functionality increases in importance with the defer to... functionality. The reason is because these functions make it easy to postpone tasks off into the future. For instance, I might write down 50 tasks for a project due in a few months, and then postpone the 20 tasks to next month. Now my 'Work View' is not cluttered with this future project. But then later I realize that 7 tasks need started sooner. I turn off 'Work View' so I can see the whole project, select the 7 tasks, and mark them 'Start Today'. Now those 4 tasks show up in my Work View.
Lionel Dricot (ploum-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
> Why?
I agree. But I said byg#34022, I was thinking about bug #497227 and did my search quickly without reading. I was thinking about the idea to put the due date above a certain threshold and the number of days below it so everything fits in one column.
My bad.
> It is unclear what you mean by that.
It's not required. It's just that we discussed about that change a while ago (there should be a bug about it) because it's better to have an "action" in a menu than a concept. I was thinking that your branch might be a good opportunity for such a change.
>> Start today
That's a good explanation, I'm sold ;-) Indeed, it's very important when you want to "undefer" a bunch of tasks.
Could we review this branch again ?
Bryce Harrington (bryce) wrote : Posted in a previous version of this proposal | # |
Some further comments from Bertrand:
>Bryce: Your implementation is nice. As for the wording, if the submenu
contains "today" as an option then I think "Schedule this task" would be
better ("Postpone to today" sounds weird). Their should be an option
below "Schedule this task" allowing to clear the satrt date as well,
that appears when (at least one) start date is defined in the selected
task(s).
Bryce Harrington (bryce) wrote : Posted in a previous version of this proposal | # |
Resubmitting for merge at Lionel's request.
Bryce Harrington (bryce) wrote : Posted in a previous version of this proposal | # |
> It's not required. It's just that we discussed about that change a while ago (there should be a bug about it) because it's better to have an "action" in a menu than a concept. I was thinking that your branch might be a good opportunity for such a change.
I can change that as well, but I'm not clear on where the menu is that this "Start Date" is being improperly shown in.
Lionel Dricot (ploum-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
Hello Bryce,
I've just read the code and it seems really nice.
I think it only needs some cleaning (see "<<<<<<< TREE" and stuffs like that in browser.py)
I personally believe it should go in 0.2.1, what do you think ?
Bryce Harrington (bryce) wrote : Posted in a previous version of this proposal | # |
Odd, not sure what that is, maybe it just needs re-merged against trunk?
Bryce Harrington (bryce) wrote : | # |
Resubmitting after merge to trunk
Lionel Dricot (ploum-deactivatedaccount) wrote : | # |
There's still some <<<<<<< TREE (see the diff below on this same page)
Bryce Harrington (bryce) wrote : | # |
I'm confused by this - I don't see this in my own bzr tree. Where is that coming from, and how do I get rid of it?
- 542. By Bryce Harrington
-
Merge with trunk
Bryce Harrington (bryce) wrote : | # |
Should be straight now.
Bertrand Rousseau (bertrand-rousseau) wrote : | # |
This is fine for me. Since trunk is supposed to be frozen for 0.2.1 release, I'd ask another developer to agree on merging this before actually doing it.
- 543. By Bryce Harrington
-
Add some further scheduling targets.
- 544. By Bryce Harrington
-
Need to explicitly cast to int
Bertrand Rousseau (bertrand-rousseau) wrote : | # |
I'd like to process this merge request, could another developer take some time to review it, please?
Luca Invernizzi (invernizzi) wrote : | # |
Is fine for me.
Maybe, in the future, we could add support for FuzzyDates
- 545. By Bryce Harrington
-
Get rid of warning for stray handler function
- 546. By Bryce Harrington
-
Try adding an accelerator for scheduling for tomorrow
- 547. By Bryce Harrington
-
Add accelerator keys for postponing tasks 1/2/3 days/weeks/months
Preview Diff
1 | === modified file 'GTG/core/task.py' |
2 | --- GTG/core/task.py 2010-01-08 20:51:01 +0000 |
3 | +++ GTG/core/task.py 2010-01-22 06:34:12 +0000 |
4 | @@ -204,7 +204,7 @@ |
5 | def set_start_date(self, fulldate): |
6 | assert(isinstance(fulldate, Date)) |
7 | self.start_date = fulldate |
8 | - # why don't we sync here if we do in set_due_date? |
9 | + self.sync() |
10 | |
11 | def get_start_date(self): |
12 | return self.start_date |
13 | @@ -216,7 +216,11 @@ |
14 | #results in a datetime.timedelta object |
15 | #that does have a 'days' member. |
16 | difference = date_today() - self.start_date |
17 | - return difference.days >= 0 #pylint: disable-msg=E1101 |
18 | + if difference.days == 0: |
19 | + # Don't count today's tasks started until morning |
20 | + return datetime.now().hour > 4 |
21 | + else: |
22 | + return difference.days > 0 #pylint: disable-msg=E1101 |
23 | else: |
24 | return True |
25 | |
26 | |
27 | === modified file 'GTG/taskbrowser/browser.py' |
28 | --- GTG/taskbrowser/browser.py 2010-01-19 17:37:24 +0000 |
29 | +++ GTG/taskbrowser/browser.py 2010-01-22 06:34:12 +0000 |
30 | @@ -233,6 +233,7 @@ |
31 | self.tagpopup = self.builder.get_object("TagContextMenu") |
32 | self.nonworkviewtag_checkbox = self.builder.get_object("nonworkviewtag") |
33 | self.taskpopup = self.builder.get_object("TaskContextMenu") |
34 | + self.defertopopup = self.builder.get_object("DeferToContextMenu") |
35 | self.ctaskpopup = \ |
36 | self.builder.get_object("ClosedTaskContextMenu") |
37 | self.editbutton = self.builder.get_object("edit_b") |
38 | @@ -313,6 +314,16 @@ |
39 | self.on_add_new_tag, |
40 | "on_mark_as_done": |
41 | self.on_mark_as_done, |
42 | + "on_mark_as_started": |
43 | + self.on_mark_as_started, |
44 | + "on_schedule_for_tomorrow": |
45 | + self.on_schedule_for_tomorrow, |
46 | + "on_schedule_for_next_week": |
47 | + self.on_schedule_for_next_week, |
48 | + "on_schedule_for_next_month": |
49 | + self.on_schedule_for_next_month, |
50 | + "on_schedule_for_next_year": |
51 | + self.on_schedule_for_next_year, |
52 | "on_dismiss_task": |
53 | self.on_dismiss_task, |
54 | "on_delete": |
55 | @@ -738,7 +749,8 @@ |
56 | def get_canonical_date(self, arg): |
57 | """ |
58 | Transform "arg" in a valid yyyy-mm-dd date or return None. |
59 | - "arg" can be a yyyy-mm-dd, yyyymmdd, mmdd, today or a weekday name. |
60 | + "arg" can be a yyyy-mm-dd, yyyymmdd, mmdd, today, next week, |
61 | + next month, next year, or a weekday name. |
62 | """ |
63 | day_names_en = ["monday", "tuesday", "wednesday", "thursday", |
64 | "friday", "saturday", "sunday"] |
65 | @@ -754,19 +766,24 @@ |
66 | year = datetime.date.today().year |
67 | date = "%i-%s-%s" % (year, arg[:2], arg[2:]) |
68 | elif arg.lower() == "today" or arg.lower() == _("today"): |
69 | - today = datetime.date.today() |
70 | - year = today.year |
71 | - month = today.month |
72 | - day = today.day |
73 | - date = "%i-%i-%i" % (year, month, day) |
74 | + t = datetime.date.today() |
75 | + date = "%i-%i-%i" % (t.year, t.month, t.day) |
76 | elif arg.lower() == "tomorrow" or\ |
77 | arg.lower() == _("tomorrow"): |
78 | - today = datetime.date.today() |
79 | - tomorrow = today + datetime.timedelta(days=1) |
80 | - year = tomorrow.year |
81 | - month = tomorrow.month |
82 | - day = tomorrow.day |
83 | - date = "%i-%i-%i" % (year, month, day) |
84 | + t = datetime.date.today() + datetime.timedelta(days=1) |
85 | + date = "%i-%i-%i" % (t.year, t.month, t.day) |
86 | + elif arg.lower() == "next week" or\ |
87 | + arg.lower() == _("next week"): |
88 | + t = datetime.date.today() + datetime.timedelta(days=7) |
89 | + date = "%i-%i-%i" % (t.year, t.month, t.day) |
90 | + elif arg.lower() == "next month" or\ |
91 | + arg.lower() == _("next month"): |
92 | + t = datetime.date.today() + datetime.timedelta(days=30) |
93 | + date = "%i-%i-%i" % (t.year, t.month, t.day) |
94 | + elif arg.lower() == "next year" or\ |
95 | + arg.lower() == _("next year"): |
96 | + t = datetime.date.today() + datetime.timedelta(days=365) |
97 | + date = "%i-%i-%i" % (t.year, t.month, t.day) |
98 | elif arg.lower() in day_names_en or arg.lower() in day_names: |
99 | today = datetime.date.today() |
100 | today_day = today.weekday() |
101 | @@ -1516,6 +1533,33 @@ |
102 | else: |
103 | return False |
104 | |
105 | + def update_start_date(self, widget, new_start_date): |
106 | + tasks_uid = filter(lambda uid: uid != None, self.get_selected_tasks()) |
107 | + if len(tasks_uid) == 0: |
108 | + return |
109 | + tasks = [self.req.get_task(uid) for uid in tasks_uid] |
110 | + tasks_status = [task.get_status() for task in tasks] |
111 | + for uid, task, status in zip(tasks_uid, tasks, tasks_status): |
112 | + task.set_start_date(self.get_canonical_date(new_start_date)) |
113 | + if self.refresh_lock.acquire(False): |
114 | + gobject.idle_add(self.general_refresh) |
115 | + #FIXME: If the task dialog is displayed, refresh its start_date widget |
116 | + |
117 | + def on_mark_as_started(self, widget): |
118 | + self.update_start_date(widget, "today") |
119 | + |
120 | + def on_schedule_for_tomorrow(self, widget): |
121 | + self.update_start_date(widget, "tomorrow") |
122 | + |
123 | + def on_schedule_for_next_week(self, widget): |
124 | + self.update_start_date(widget, "next week") |
125 | + |
126 | + def on_schedule_for_next_month(self, widget): |
127 | + self.update_start_date(widget, "next month") |
128 | + |
129 | + def on_schedule_for_next_year(self, widget): |
130 | + self.update_start_date(widget, "next year") |
131 | + |
132 | def on_add_new_tag(self, widget=None, tid=None, tryagain = False): |
133 | if not tid: |
134 | self.tids_to_addtag = self.get_selected_tasks() |
135 | @@ -1628,7 +1672,7 @@ |
136 | gobject.idle_add(self.ctask_tv.scroll_to_task, task_to_scroll_to) |
137 | if self.refresh_lock.acquire(False): |
138 | gobject.idle_add(self.general_refresh) |
139 | - |
140 | + |
141 | def on_select_tag(self, widget, row=None, col=None): |
142 | #When you clic on a tag, you want to unselect the tasks |
143 | self.task_tv.get_selection().unselect_all() |
144 | |
145 | === modified file 'GTG/taskbrowser/taskbrowser.glade' |
146 | --- GTG/taskbrowser/taskbrowser.glade 2010-01-17 23:07:20 +0000 |
147 | +++ GTG/taskbrowser/taskbrowser.glade 2010-01-22 06:34:12 +0000 |
148 | @@ -863,6 +863,16 @@ |
149 | </object> |
150 | </child> |
151 | <child> |
152 | + <object class="GtkImageMenuItem" id="tcm_schedule_menu"> |
153 | + <property name="label" translatable="yes">_Schedule for...</property> |
154 | + <property name="visible">True</property> |
155 | + <property name="submenu">ScheduleForContextMenu</property> |
156 | + <property name="use_underline">True</property> |
157 | + <property name="use_stock">False</property> |
158 | + <signal name="activate" handler="on_schedule_for_menu"/> |
159 | + </object> |
160 | + </child> |
161 | + <child> |
162 | <object class="GtkImageMenuItem" id="tcm_mark_as_done"> |
163 | <property name="label" translatable="yes">Mark as _Done</property> |
164 | <property name="visible">True</property> |
165 | @@ -909,6 +919,54 @@ |
166 | </object> |
167 | </child> |
168 | </object> |
169 | + <object class="GtkMenu" id="ScheduleForContextMenu"> |
170 | + <property name="visible">True</property> |
171 | + <child> |
172 | + <object class="GtkImageMenuItem" id="tcm_mark_as_started"> |
173 | + <property name="label" translatable="yes">t_oday</property> |
174 | + <property name="visible">True</property> |
175 | + <property name="use_underline">True</property> |
176 | + <property name="use_stock">False</property> |
177 | + <signal name="activate" handler="on_mark_as_started"/> |
178 | + </object> |
179 | + </child> |
180 | + <child> |
181 | + <object class="GtkImageMenuItem" id="tcm_schedule_for_tomorrow"> |
182 | + <property name="label" translatable="yes">_tomorrow</property> |
183 | + <property name="visible">True</property> |
184 | + <property name="use_underline">True</property> |
185 | + <property name="use_stock">False</property> |
186 | + <signal name="activate" handler="on_schedule_for_tomorrow"/> |
187 | + </object> |
188 | + </child> |
189 | + <child> |
190 | + <object class="GtkImageMenuItem" id="tcm_schedule_for_next_week"> |
191 | + <property name="label" translatable="yes">next _week</property> |
192 | + <property name="visible">True</property> |
193 | + <property name="use_underline">True</property> |
194 | + <property name="use_stock">False</property> |
195 | + <signal name="activate" handler="on_schedule_for_next_week"/> |
196 | + </object> |
197 | + </child> |
198 | + <child> |
199 | + <object class="GtkImageMenuItem" id="tcm_schedule_for_next_month"> |
200 | + <property name="label" translatable="yes">next _month</property> |
201 | + <property name="visible">True</property> |
202 | + <property name="use_underline">True</property> |
203 | + <property name="use_stock">False</property> |
204 | + <signal name="activate" handler="on_schedule_for_next_month"/> |
205 | + </object> |
206 | + </child> |
207 | + <child> |
208 | + <object class="GtkImageMenuItem" id="tcm_schedule_for_next_year"> |
209 | + <property name="label" translatable="yes">next _year</property> |
210 | + <property name="visible">True</property> |
211 | + <property name="use_underline">True</property> |
212 | + <property name="use_stock">False</property> |
213 | + <signal name="activate" handler="on_schedule_for_next_year"/> |
214 | + </object> |
215 | + </child> |
216 | + </object> |
217 | <object class="GtkMenu" id="ClosedTaskContextMenu"> |
218 | <property name="visible">True</property> |
219 | <child> |
220 | |
221 | === modified file 'GTG/taskbrowser/tasktree.py' |
222 | --- GTG/taskbrowser/tasktree.py 2009-12-21 00:05:04 +0000 |
223 | +++ GTG/taskbrowser/tasktree.py 2010-01-22 06:34:12 +0000 |
224 | @@ -37,6 +37,7 @@ |
225 | COL_DLEFT = 6 |
226 | COL_TAGS = 7 |
227 | COL_LABEL = 9 |
228 | +COL_SDATE = 10 |
229 | |
230 | class TaskTreeModel(gtk.GenericTreeModel): |
231 | |
232 | @@ -50,6 +51,7 @@ |
233 | str,\ |
234 | gobject.TYPE_PYOBJECT,\ |
235 | str,\ |
236 | + str,\ |
237 | str) |
238 | |
239 | def __init__(self, requester): |
240 | @@ -110,6 +112,8 @@ |
241 | return task |
242 | elif column == COL_TITLE: |
243 | return saxutils.escape(task.get_title()) |
244 | + elif column == COL_SDATE: |
245 | + return str(task.get_start_date()) |
246 | elif column == COL_DDATE: |
247 | return str(task.get_due_date()) |
248 | elif column == COL_CDATE: |
249 | @@ -414,6 +418,18 @@ |
250 | self.append_column(title_col) |
251 | self.columns.insert(COL_TITLE, title_col) |
252 | |
253 | + # Start date column |
254 | + sdate_col = gtk.TreeViewColumn() |
255 | + render_text = gtk.CellRendererText() |
256 | + sdate_col.set_title(_("Start date")) |
257 | + sdate_col.pack_start(render_text, expand=False) |
258 | + sdate_col.add_attribute(render_text, "markup", COL_SDATE) |
259 | + sdate_col.set_resizable(False) |
260 | + sdate_col.set_sort_column_id(COL_SDATE) |
261 | + sdate_col.set_cell_data_func(render_text, self._celldatafunction) |
262 | + self.append_column(sdate_col) |
263 | + self.columns.insert(COL_SDATE, sdate_col) |
264 | + |
265 | # Due date column |
266 | ddate_col = gtk.TreeViewColumn() |
267 | render_text = gtk.CellRendererText() |
268 | @@ -427,16 +443,16 @@ |
269 | self.columns.insert(COL_DDATE, ddate_col) |
270 | |
271 | # days left |
272 | - dleft_col = gtk.TreeViewColumn() |
273 | - render_text = gtk.CellRendererText() |
274 | - dleft_col.set_title(_("Days left")) |
275 | - dleft_col.pack_start(render_text, expand=False) |
276 | - dleft_col.add_attribute(render_text, "markup", COL_DLEFT) |
277 | - dleft_col.set_resizable(False) |
278 | - dleft_col.set_sort_column_id(COL_DLEFT) |
279 | - dleft_col.set_cell_data_func(render_text, self._celldatafunction) |
280 | - self.append_column(dleft_col) |
281 | - self.columns.insert(COL_DLEFT, dleft_col) |
282 | +# dleft_col = gtk.TreeViewColumn() |
283 | +# render_text = gtk.CellRendererText() |
284 | +# dleft_col.set_title(_("Days left")) |
285 | +# dleft_col.pack_start(render_text, expand=False) |
286 | +# dleft_col.add_attribute(render_text, "markup", COL_DLEFT) |
287 | +# dleft_col.set_resizable(False) |
288 | +# dleft_col.set_sort_column_id(COL_DLEFT) |
289 | +# dleft_col.set_cell_data_func(render_text, self._celldatafunction) |
290 | +# self.append_column(dleft_col) |
291 | +# self.columns.insert(COL_DLEFT, dleft_col) |
292 | |
293 | # Global treeview properties |
294 | self.set_property("expander-column", title_col) |
I'm already finding these changes quite useful, I think they're ready for review and to into trunk.