GTG

Merge lp:~jml/gtg/random-cleanups into lp:~gtg/gtg/old-trunk

Proposed by Jonathan Lange
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jml/gtg/random-cleanups
Merge into: lp:~gtg/gtg/old-trunk
Diff against target: None lines
To merge this branch: bzr merge lp:~jml/gtg/random-cleanups
Reviewer Review Type Date Requested Status
Bertrand Rousseau (community) Approve
Review via email: mp+8980@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jonathan Lange (jml) wrote :

Absolutely no behavioural changes here, just getting rid of all of the valid PEP 8 warnings in browser.py.

Revision history for this message
Bertrand Rousseau (bertrand-rousseau) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'GTG/taskbrowser/browser.py'
--- GTG/taskbrowser/browser.py 2009-07-16 16:17:56 +0000
+++ GTG/taskbrowser/browser.py 2009-07-18 03:17:09 +0000
@@ -58,16 +58,16 @@
58class TaskBrowser:58class TaskBrowser:
5959
60 def __init__(self, requester, config):60 def __init__(self, requester, config):
61 61
62 self.priv = {}62 self.priv = {}
63 63
64 #The locks used to avoid unecessary refresh64 #The locks used to avoid unecessary refresh
65 self.refresh_lock = threading.Lock()65 self.refresh_lock = threading.Lock()
66 self.refresh_lock_lock = threading.Lock()66 self.refresh_lock_lock = threading.Lock()
67 # Set the configuration dictionary67 # Set the configuration dictionary
68 self.config = config68 self.config = config
69 self.notes = EXPERIMENTAL_NOTES69 self.notes = EXPERIMENTAL_NOTES
70 70
71 # Setup default values for view71 # Setup default values for view
72 self.priv["collapsed_tid"] = []72 self.priv["collapsed_tid"] = []
73 self.priv["tasklist"] = {}73 self.priv["tasklist"] = {}
@@ -76,11 +76,11 @@
76 self.priv["ctasklist"] = {}76 self.priv["ctasklist"] = {}
77 self.priv["ctasklist"]["sort_column"] = None77 self.priv["ctasklist"]["sort_column"] = None
78 self.priv["ctasklist"]["sort_order"] = gtk.SORT_ASCENDING78 self.priv["ctasklist"]["sort_order"] = gtk.SORT_ASCENDING
79 79
80 #Set the Glade file80 #Set the Glade file
81 self.gladefile = GnomeConfig.GLADE_FILE 81 self.gladefile = GnomeConfig.GLADE_FILE
82 self.wTree = gtk.glade.XML(self.gladefile) 82 self.wTree = gtk.glade.XML(self.gladefile)
83 83
84 #Get the Main Window, and connect the "destroy" event84 #Get the Main Window, and connect the "destroy" event
85 self.window = self.wTree.get_widget("MainWindow")85 self.window = self.wTree.get_widget("MainWindow")
86 if (self.window):86 if (self.window):
@@ -102,14 +102,14 @@
102 self.dismissbutton = self.wTree.get_widget("dismiss")102 self.dismissbutton = self.wTree.get_widget("dismiss")
103 self.about = self.wTree.get_widget("aboutdialog1")103 self.about = self.wTree.get_widget("aboutdialog1")
104 self.edit_mi = self.wTree.get_widget("edit_mi")104 self.edit_mi = self.wTree.get_widget("edit_mi")
105 105
106 #Set the tooltip for the toolbar buttons106 #Set the tooltip for the toolbar buttons
107 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)107 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)
108 self.editbutton.set_tooltip_text(_("Edit the selected task"))108 self.editbutton.set_tooltip_text(_("Edit the selected task"))
109 self.dismissbutton.set_tooltip_text(GnomeConfig.MARK_DISMISS_TOOLTIP)109 self.dismissbutton.set_tooltip_text(GnomeConfig.MARK_DISMISS_TOOLTIP)
110 self.newtask.set_tooltip_text(_("Create a new task"))110 self.newtask.set_tooltip_text(_("Create a new task"))
111 self.newsubtask.set_tooltip_text(_("Create a new subtask"))111 self.newsubtask.set_tooltip_text(_("Create a new subtask"))
112 112
113 # Initialize "About" dialog113 # Initialize "About" dialog
114 gtk.about_dialog_set_url_hook(lambda dialog, url: openurl.openurl(url))114 gtk.about_dialog_set_url_hook(lambda dialog, url: openurl.openurl(url))
115 self.about.set_website(GTG.URL)115 self.about.set_website(GTG.URL)
@@ -118,68 +118,73 @@
118 self.about.set_authors(GTG.AUTHORS)118 self.about.set_authors(GTG.AUTHORS)
119 self.about.set_artists(GTG.ARTISTS)119 self.about.set_artists(GTG.ARTISTS)
120 self.about.set_translator_credits(GTG.TRANSLATORS)120 self.about.set_translator_credits(GTG.TRANSLATORS)
121 121
122 # Initialize menu122 # Initialize menu
123123
124 #Create our dictionay and connect it124 #Create our dictionay and connect it
125 dic = {125 dic = {
126 "on_add_task": self.on_add_task,126 "on_add_task": self.on_add_task,
127 "on_add_note": (self.on_add_task, 'Note'),127 "on_add_note": (self.on_add_task, 'Note'),
128 "on_edit_active_task": self.on_edit_active_task,128 "on_edit_active_task": self.on_edit_active_task,
129 "on_edit_done_task": self.on_edit_done_task,129 "on_edit_done_task": self.on_edit_done_task,
130 "on_edit_note": self.on_edit_note,130 "on_edit_note": self.on_edit_note,
131 "on_delete_task": self.on_delete_task,131 "on_delete_task": self.on_delete_task,
132 "on_mark_as_done": self.on_mark_as_done,132 "on_mark_as_done": self.on_mark_as_done,
133 "on_dismiss_task": self.on_dismiss_task,133 "on_dismiss_task": self.on_dismiss_task,
134 "on_delete": self.on_delete,134 "on_delete": self.on_delete,
135 "on_move": self.on_move,135 "on_move": self.on_move,
136 "on_size_allocate": self.on_size_allocate,136 "on_size_allocate": self.on_size_allocate,
137 "gtk_main_quit": self.close,137 "gtk_main_quit": self.close,
138 "on_select_tag": self.on_select_tag,138 "on_select_tag": self.on_select_tag,
139 "on_delete_confirm": self.on_delete_confirm,139 "on_delete_confirm": self.on_delete_confirm,
140 "on_delete_cancel": lambda x : x.hide,140 "on_delete_cancel": lambda x: x.hide,
141 "on_add_subtask": self.on_add_subtask,141 "on_add_subtask": self.on_add_subtask,
142 "on_closed_task_treeview_button_press_event": self.on_closed_task_treeview_button_press_event,142 "on_closed_task_treeview_button_press_event":
143 "on_closed_task_treeview_key_press_event": self.on_closed_task_treeview_key_press_event,143 self.on_closed_task_treeview_button_press_event,
144 "on_task_treeview_button_press_event": self.on_task_treeview_button_press_event,144 "on_closed_task_treeview_key_press_event":
145 "on_task_treeview_key_press_event": self.on_task_treeview_key_press_event,145 self.on_closed_task_treeview_key_press_event,
146 "on_tag_treeview_button_press_event": self.on_tag_treeview_button_press_event,146 "on_task_treeview_button_press_event":
147 "on_colorchooser_activate": self.on_colorchooser_activate,147 self.on_task_treeview_button_press_event,
148 "on_workview_toggled": self.on_workview_toggled,148 "on_task_treeview_key_press_event":
149 "on_note_toggled": self.on_note_toggled,149 self.on_task_treeview_key_press_event,
150 "on_view_workview_toggled": self.on_workview_toggled,150 "on_tag_treeview_button_press_event":
151 "on_view_closed_toggled": self.on_closed_toggled,151 self.on_tag_treeview_button_press_event,
152 "on_view_sidebar_toggled": self.on_sidebar_toggled,152 "on_colorchooser_activate": self.on_colorchooser_activate,
153 "on_bg_color_toggled": self.on_bg_color_toggled,153 "on_workview_toggled": self.on_workview_toggled,
154 "on_quickadd_field_activate": self.quickadd,154 "on_note_toggled": self.on_note_toggled,
155 "on_quickadd_button_activate": self.quickadd,155 "on_view_workview_toggled": self.on_workview_toggled,
156 "on_view_toolbar_toggled": self.on_toolbar_toggled,156 "on_view_closed_toggled": self.on_closed_toggled,
157 "on_view_quickadd_toggled": self.toggle_quickadd,157 "on_view_sidebar_toggled": self.on_sidebar_toggled,
158 "on_about_clicked": self.on_about_clicked,158 "on_bg_color_toggled": self.on_bg_color_toggled,
159 "on_about_close": self.on_about_close,159 "on_quickadd_field_activate": self.quickadd,
160 "on_nonworkviewtag_toggled": self.on_nonworkviewtag_toggled160 "on_quickadd_button_activate": self.quickadd,
161 }161 "on_view_toolbar_toggled": self.on_toolbar_toggled,
162 "on_view_quickadd_toggled": self.toggle_quickadd,
163 "on_about_clicked": self.on_about_clicked,
164 "on_about_close": self.on_about_close,
165 "on_nonworkviewtag_toggled": self.on_nonworkviewtag_toggled,
166 }
162 self.wTree.signal_autoconnect(dic)167 self.wTree.signal_autoconnect(dic)
163 self.selected_rows = None168 self.selected_rows = None
164 169
165 self.workview = False170 self.workview = False
166 self.req = requester171 self.req = requester
167 172
168 self.noteview = False173 self.noteview = False
169 self.new_note_button = self.wTree.get_widget("new_note_button")174 self.new_note_button = self.wTree.get_widget("new_note_button")
170 self.note_toggle = self.wTree.get_widget("note_toggle")175 self.note_toggle = self.wTree.get_widget("note_toggle")
171 if not self.notes:176 if not self.notes:
172 self.note_toggle.hide()177 self.note_toggle.hide()
173 self.new_note_button.hide()178 self.new_note_button.hide()
174 179
175 #Set the tooltip for the toolbar button180 #Set the tooltip for the toolbar button
176 self.new_note_button.set_tooltip_text("Create a new note")181 self.new_note_button.set_tooltip_text("Create a new note")
177 182
178 # Model constants183 # Model constants
179 self.TASK_MODEL_OBJ = 0184 self.TASK_MODEL_OBJ = 0
180 self.TASK_MODEL_TITLE = 1185 self.TASK_MODEL_TITLE = 1
181 self.TASK_MODEL_TITLE_STR = 2186 self.TASK_MODEL_TITLE_STR = 2
182 #Warning : this one is duplicated in treetools.py187 #Warning: this one is duplicated in treetools.py
183 #They all should go in treetools188 #They all should go in treetools
184 self.TASK_MODEL_DDATE_STR = 3189 self.TASK_MODEL_DDATE_STR = 3
185 self.TASK_MODEL_DLEFT_STR = 4190 self.TASK_MODEL_DLEFT_STR = 4
@@ -196,7 +201,7 @@
196 self.CTASKS_MODEL_DDATE_STR = 4201 self.CTASKS_MODEL_DDATE_STR = 4
197 self.CTASKS_MODEL_BGCOL = 5202 self.CTASKS_MODEL_BGCOL = 5
198 self.CTASKS_MODEL_TAGS = 6203 self.CTASKS_MODEL_TAGS = 6
199 204
200 #The tview and their model205 #The tview and their model
201 self.taskdone_tview = self.wTree.get_widget("taskdone_tview")206 self.taskdone_tview = self.wTree.get_widget("taskdone_tview")
202 self.taskdone_ts = gtk.TreeStore(gobject.TYPE_PYOBJECT,207 self.taskdone_ts = gtk.TreeStore(gobject.TYPE_PYOBJECT,
@@ -217,30 +222,30 @@
217222
218 #Be sure that we are reorderable (not needed normaly)223 #Be sure that we are reorderable (not needed normaly)
219 self.task_tview.set_reorderable(True)224 self.task_tview.set_reorderable(True)
220 225
221 #The menu items widget226 #The menu items widget
222 self.menu_view_workview = self.wTree.get_widget("view_workview")227 self.menu_view_workview = self.wTree.get_widget("view_workview")
223 228
224 #The buttons229 #The buttons
225 self.toggle_workview = self.wTree.get_widget("workview_toggle")230 self.toggle_workview = self.wTree.get_widget("workview_toggle")
226 self.quickadd_entry = self.wTree.get_widget("quickadd_field")231 self.quickadd_entry = self.wTree.get_widget("quickadd_field")
227 232
228 #Set the tooltip for the toolbar button233 #Set the tooltip for the toolbar button
229 self.toggle_workview.set_tooltip_text("Toggle the work view")234 self.toggle_workview.set_tooltip_text("Toggle the work view")
230 235
231 #The panes236 #The panes
232 self.sidebar = self.wTree.get_widget("sidebar")237 self.sidebar = self.wTree.get_widget("sidebar")
233 self.closed_pane = self.wTree.get_widget("closed_pane")238 self.closed_pane = self.wTree.get_widget("closed_pane")
234 self.toolbar = self.wTree.get_widget("task_tb")239 self.toolbar = self.wTree.get_widget("task_tb")
235 self.quickadd_pane = self.wTree.get_widget("quickadd_pane")240 self.quickadd_pane = self.wTree.get_widget("quickadd_pane")
236 241
237 #The tid that will be deleted242 #The tid that will be deleted
238 self.tid_todelete = None243 self.tid_todelete = None
239 244
240 #This is the list of tasks that are already opened in an editor245 #This is the list of tasks that are already opened in an editor
241 #of course it's empty right now246 #of course it's empty right now
242 self.opened_task = {}247 self.opened_task = {}
243 248
244 #Variables used during drag-n-drop249 #Variables used during drag-n-drop
245 self.drag_sources = []250 self.drag_sources = []
246 self.path_source = None251 self.path_source = None
@@ -248,7 +253,7 @@
248 self.tid_tomove = None253 self.tid_tomove = None
249 self.tid_source_parent = None254 self.tid_source_parent = None
250 self.tid_target_parent = None255 self.tid_target_parent = None
251 256
252 #setting the default257 #setting the default
253 self.menu_view_workview.set_active(WORKVIEW)258 self.menu_view_workview.set_active(WORKVIEW)
254 self.wTree.get_widget("view_sidebar").set_active(SIDEBAR)259 self.wTree.get_widget("view_sidebar").set_active(SIDEBAR)
@@ -256,11 +261,11 @@
256 self.wTree.get_widget("view_toolbar").set_active(TOOLBAR)261 self.wTree.get_widget("view_toolbar").set_active(TOOLBAR)
257 self.wTree.get_widget("view_quickadd").set_active(QUICKADD_PANE)262 self.wTree.get_widget("view_quickadd").set_active(QUICKADD_PANE)
258 self.priv["bg_color_enable"] = True263 self.priv["bg_color_enable"] = True
259 264
260 #connecting the refresh signal from the requester265 #connecting the refresh signal from the requester
261 self.lock = threading.Lock()266 self.lock = threading.Lock()
262 self.req.connect("refresh", self.do_refresh)267 self.req.connect("refresh", self.do_refresh)
263 268
264 agr = gtk.AccelGroup()269 agr = gtk.AccelGroup()
265 self.wTree.get_widget("MainWindow").add_accel_group(agr)270 self.wTree.get_widget("MainWindow").add_accel_group(agr)
266271
@@ -286,12 +291,12 @@
286 key, mod = gtk.accelerator_parse("<Control>n")291 key, mod = gtk.accelerator_parse("<Control>n")
287 new_task_mi.add_accelerator("activate",292 new_task_mi.add_accelerator("activate",
288 agr, key, mod, gtk.ACCEL_VISIBLE)293 agr, key, mod, gtk.ACCEL_VISIBLE)
289 294
290 new_subtask_mi = self.wTree.get_widget("new_subtask_mi")295 new_subtask_mi = self.wTree.get_widget("new_subtask_mi")
291 key, mod = gtk.accelerator_parse("<Control><Shift>n")296 key, mod = gtk.accelerator_parse("<Control><Shift>n")
292 new_subtask_mi.add_accelerator("activate",297 new_subtask_mi.add_accelerator("activate",
293 agr, key, mod, gtk.ACCEL_VISIBLE)298 agr, key, mod, gtk.ACCEL_VISIBLE)
294 299
295 edit_button = self.wTree.get_widget("edit_b")300 edit_button = self.wTree.get_widget("edit_b")
296 key, mod = gtk.accelerator_parse("<Control>e")301 key, mod = gtk.accelerator_parse("<Control>e")
297 edit_button.add_accelerator("clicked",302 edit_button.add_accelerator("clicked",
@@ -313,24 +318,24 @@
313 'activate', agr, key, mod, gtk.ACCEL_VISIBLE)318 'activate', agr, key, mod, gtk.ACCEL_VISIBLE)
314319
315 def __restore_state_from_conf(self):320 def __restore_state_from_conf(self):
316 321
317 # Extract state from configuration dictionary322 # Extract state from configuration dictionary
318 if not "browser" in self.config:323 if not "browser" in self.config:
319 return324 return
320 325
321 if "width" in self.config["browser"] and \326 if ("width" in self.config["browser"] and
322 "height" in self.config["browser"]:327 "height" in self.config["browser"]):
323 width = int(self.config["browser"]["width"])328 width = int(self.config["browser"]["width"])
324 height = int(self.config["browser"]["height"])329 height = int(self.config["browser"]["height"])
325 self.window.resize(width, height)330 self.window.resize(width, height)
326 331
327 if "x_pos" in self.config["browser"] and \332 if ("x_pos" in self.config["browser"] and
328 "y_pos" in self.config["browser"]:333 "y_pos" in self.config["browser"]):
329 334
330 xpos = int(self.config["browser"]["x_pos"])335 xpos = int(self.config["browser"]["x_pos"])
331 ypos = int(self.config["browser"]["y_pos"])336 ypos = int(self.config["browser"]["y_pos"])
332 self.window.move(xpos, ypos)337 self.window.move(xpos, ypos)
333 338
334 if "tag_pane" in self.config["browser"]:339 if "tag_pane" in self.config["browser"]:
335 tag_pane = eval(self.config["browser"]["tag_pane"])340 tag_pane = eval(self.config["browser"]["tag_pane"])
336 if not tag_pane:341 if not tag_pane:
@@ -340,7 +345,7 @@
340 self.wTree.get_widget("view_sidebar").set_active(True)345 self.wTree.get_widget("view_sidebar").set_active(True)
341 self.sidebar.show()346 self.sidebar.show()
342347
343 348
344 if "closed_task_pane" in self.config["browser"]:349 if "closed_task_pane" in self.config["browser"]:
345 closed_task_pane = eval(350 closed_task_pane = eval(
346 self.config["browser"]["closed_task_pane"])351 self.config["browser"]["closed_task_pane"])
@@ -355,28 +360,28 @@
355 ctask_pane_height = eval(360 ctask_pane_height = eval(
356 self.config["browser"]["ctask_pane_height"])361 self.config["browser"]["ctask_pane_height"])
357 self.wTree.get_widget("vpaned1").set_position(ctask_pane_height)362 self.wTree.get_widget("vpaned1").set_position(ctask_pane_height)
358 363
359 if "toolbar" in self.config["browser"]:364 if "toolbar" in self.config["browser"]:
360 toolbar = eval(self.config["browser"]["toolbar"])365 toolbar = eval(self.config["browser"]["toolbar"])
361 if not toolbar:366 if not toolbar:
362 self.toolbar.hide()367 self.toolbar.hide()
363 self.wTree.get_widget("view_toolbar").set_active(False)368 self.wTree.get_widget("view_toolbar").set_active(False)
364 369
365 if "quick_add" in self.config["browser"]:370 if "quick_add" in self.config["browser"]:
366 quickadd_pane = eval(self.config["browser"]["quick_add"])371 quickadd_pane = eval(self.config["browser"]["quick_add"])
367 if not quickadd_pane:372 if not quickadd_pane:
368 self.quickadd_pane.hide()373 self.quickadd_pane.hide()
369 self.wTree.get_widget("view_quickadd").set_active(False)374 self.wTree.get_widget("view_quickadd").set_active(False)
370 375
371 if "bg_color_enable" in self.config["browser"]:376 if "bg_color_enable" in self.config["browser"]:
372 bgcol_enable = eval(self.config["browser"]["bg_color_enable"])377 bgcol_enable = eval(self.config["browser"]["bg_color_enable"])
373 self.priv["bg_color_enable"] = bgcol_enable378 self.priv["bg_color_enable"] = bgcol_enable
374 self.wTree.get_widget("bgcol_enable").set_active(bgcol_enable)379 self.wTree.get_widget("bgcol_enable").set_active(bgcol_enable)
375 380
376 if "collapsed_tasks" in self.config["browser"]:381 if "collapsed_tasks" in self.config["browser"]:
377 self.priv["collapsed_tid"] = \382 self.priv["collapsed_tid"] = self.config[
378 self.config["browser"]["collapsed_tasks"]383 "browser"]["collapsed_tasks"]
379 384
380 if "tasklist_sort" in self.config["browser"]:385 if "tasklist_sort" in self.config["browser"]:
381 col_id, order = self.config["browser"]["tasklist_sort"]386 col_id, order = self.config["browser"]["tasklist_sort"]
382 self.priv["sort_column"] = col_id387 self.priv["sort_column"] = col_id
@@ -395,7 +400,7 @@
395 view = self.config["browser"]["view"]400 view = self.config["browser"]["view"]
396 if view == "workview":401 if view == "workview":
397 self.do_toggle_workview()402 self.do_toggle_workview()
398 403
399 if "experimental_notes" in self.config["browser"]:404 if "experimental_notes" in self.config["browser"]:
400 self.notes = eval(self.config["browser"]["experimental_notes"])405 self.notes = eval(self.config["browser"]["experimental_notes"])
401 if self.notes:406 if self.notes:
@@ -414,17 +419,17 @@
414 width, height = self.window.get_size()419 width, height = self.window.get_size()
415 self.priv["window_width"] = width420 self.priv["window_width"] = width
416 self.priv["window_height"] = height421 self.priv["window_height"] = height
417 422
418 def on_delete(self, widget, user_data): #pylint: disable-msg=W0613423 def on_delete(self, widget, user_data): #pylint: disable-msg=W0613
419 424
420 # Save expanded rows425 # Save expanded rows
421 self.task_ts.foreach(self.update_collapsed_row, None)426 self.task_ts.foreach(self.update_collapsed_row, None)
422 427
423 # Cleanup collapsed row list428 # Cleanup collapsed row list
424 for tid in self.priv["collapsed_tid"]:429 for tid in self.priv["collapsed_tid"]:
425 if not self.req.has_task(tid):430 if not self.req.has_task(tid):
426 self.priv["collapsed_tid"].remove(tid)431 self.priv["collapsed_tid"].remove(tid)
427 432
428 # Get configuration values433 # Get configuration values
429 tag_sidebar = self.sidebar.get_property("visible")434 tag_sidebar = self.sidebar.get_property("visible")
430 closed_pane = self.closed_pane.get_property("visible")435 closed_pane = self.closed_pane.get_property("visible")
@@ -434,68 +439,72 @@
434 sort_column = self.priv["tasklist"]["sort_column"]439 sort_column = self.priv["tasklist"]["sort_column"]
435 sort_order = self.priv["tasklist"]["sort_order"]440 sort_order = self.priv["tasklist"]["sort_order"]
436 closed_pane_height = self.wTree.get_widget("vpaned1").get_position()441 closed_pane_height = self.wTree.get_widget("vpaned1").get_position()
437 442
438 if self.workview : view = "workview"443 if self.workview:
439 else : view = "default"444 view = "workview"
445 else:
446 view = "default"
440447
441 # Populate configuration dictionary448 # Populate configuration dictionary
442 self.config["browser"] = {}449 self.config["browser"] = {
443 self.config["browser"]["width"] = self.priv["window_width"]450 'width': self.priv["window_width"],
444 self.config["browser"]["height"] = self.priv["window_height"]451 'height': self.priv["window_height"],
445 self.config["browser"]["x_pos"] = self.priv["window_xpos"]452 'x_pos': self.priv["window_xpos"],
446 self.config["browser"]["y_pos"] = self.priv["window_ypos"]453 'y_pos': self.priv["window_ypos"],
447 self.config["browser"]["tag_pane"] = tag_sidebar454 'bg_color_enable': self.priv["bg_color_enable"],
448 self.config["browser"]["closed_task_pane"] = closed_pane455 'collapsed_tasks': self.priv["collapsed_tid"],
449 self.config["browser"]["ctask_pane_height"] = closed_pane_height456 'tag_pane': tag_sidebar,
450 self.config["browser"]["toolbar"] = toolbar457 'closed_task_pane': closed_pane,
451 self.config["browser"]["quick_add"] = quickadd_pane458 'ctask_pane_height': closed_pane_height,
452 self.config["browser"]["bg_color_enable"] = self.priv["bg_color_enable"]459 'toolbar': toolbar,
453 self.config["browser"]["collapsed_tasks"] = self.priv["collapsed_tid"]460 'quick_add': quickadd_pane,
454 if sort_column is not None and sort_order == gtk.SORT_ASCENDING:461 'view': view,
462 }
463
464 if sort_column is not None and sort_order == gtk.SORT_ASCENDING:
455 sort_col_id = self.priv["tasklist"]["columns"].index(sort_column)465 sort_col_id = self.priv["tasklist"]["columns"].index(sort_column)
456 self.config["browser"]["tasklist_sort"] = [sort_col_id, 0]466 self.config["browser"]["tasklist_sort"] = [sort_col_id, 0]
457 elif sort_column is not None and sort_order == gtk.SORT_DESCENDING:467 elif sort_column is not None and sort_order == gtk.SORT_DESCENDING:
458 sort_col_id = self.priv["tasklist"]["columns"].index(sort_column)468 sort_col_id = self.priv["tasklist"]["columns"].index(sort_column)
459 self.config["browser"]["tasklist_sort"] = [sort_col_id, 1]469 self.config["browser"]["tasklist_sort"] = [sort_col_id, 1]
460 self.config["browser"]["view"] = view470 if self.notes:
461 if self.notes :
462 self.config["browser"]["experimental_notes"] = True471 self.config["browser"]["experimental_notes"] = True
463 472
464 def main(self):473 def main(self):
465 #Here we will define the main TaskList interface474 #Here we will define the main TaskList interface
466 gobject.threads_init()475 gobject.threads_init()
467 476
468 #The tags treeview477 #The tags treeview
469 self.__create_tags_tview()478 self.__create_tags_tview()
470 self.tag_tview.set_model(self.tag_ts)479 self.tag_tview.set_model(self.tag_ts)
471 480
472 #The Active tasks treeview481 #The Active tasks treeview
473 self.__create_task_tview()482 self.__create_task_tview()
474 self.task_tview.set_model(self.task_ts)483 self.task_tview.set_model(self.task_ts)
475 484
476 #The done/dismissed taks treeview485 #The done/dismissed taks treeview
477 self.__create_closed_tasks_tview()486 self.__create_closed_tasks_tview()
478 self.taskdone_tview.set_model(self.taskdone_ts)487 self.taskdone_tview.set_model(self.taskdone_ts)
479 488
480 #The treeview for notes489 #The treeview for notes
481 self.__create_note_tview()490 self.__create_note_tview()
482 self.note_tview.set_model(self.note_ts)491 self.note_tview.set_model(self.note_ts)
483 492
484 #put the content in those treeviews493 #put the content in those treeviews
485 self.do_refresh()494 self.do_refresh()
486 495
487 selection = self.task_tview.get_selection()496 selection = self.task_tview.get_selection()
488 selection.connect("changed",self.task_cursor_changed)497 selection.connect("changed", self.task_cursor_changed)
489 closed_selection = self.taskdone_tview.get_selection()498 closed_selection = self.taskdone_tview.get_selection()
490 closed_selection.connect("changed",self.taskdone_cursor_changed)499 closed_selection.connect("changed", self.taskdone_cursor_changed)
491 note_selection = self.note_tview.get_selection()500 note_selection = self.note_tview.get_selection()
492 note_selection.connect("changed",self.note_cursor_changed)501 note_selection.connect("changed", self.note_cursor_changed)
493 502
494 503
495 # Restore state from config504 # Restore state from config
496 self.__restore_state_from_conf()505 self.__restore_state_from_conf()
497 self.window.show()506 self.window.show()
498 507
499 gtk.main()508 gtk.main()
500 return 0509 return 0
501510
@@ -505,19 +514,17 @@
505 def on_about_close(self, widget, response): #pylint: disable-msg=W0613514 def on_about_close(self, widget, response): #pylint: disable-msg=W0613
506 self.about.hide()515 self.about.hide()
507516
508 def on_colorchooser_activate(self,widget) : #pylint: disable-msg=W0613517 def on_colorchooser_activate(self, widget): #pylint: disable-msg=W0613
509 #TODO : Color chooser should be refactorized in its own class518 #TODO: Color chooser should be refactorized in its own class. Well, in
510 #Well, in fact we should have a TagPropertiesEditor (like for project)519 #fact we should have a TagPropertiesEditor (like for project) Also,
511 #Also, color change should be immediate. There's no reason for a Ok/Cancel520 #color change should be immediate. There's no reason for a Ok/Cancel
512 wTree = gtk.glade.XML(self.gladefile, "ColorChooser") 521 wTree = gtk.glade.XML(self.gladefile, "ColorChooser")
513 #Create our dictionay and connect it522 #Create our dictionay and connect it
514 dic = {523 dic = {"on_color_response": self.on_color_response}
515 "on_color_response" : self.on_color_response
516 }
517 wTree.signal_autoconnect(dic)524 wTree.signal_autoconnect(dic)
518 window = wTree.get_widget("ColorChooser")525 window = wTree.get_widget("ColorChooser")
519 # Get previous color526 # Get previous color
520 tags,notag_only = self.get_selected_tags() #pylint: disable-msg=W0612527 tags, notag_only = self.get_selected_tags() #pylint: disable-msg=W0612
521 if len(tags) == 1:528 if len(tags) == 1:
522 color = tags[0].get_attribute("color")529 color = tags[0].get_attribute("color")
523 if color != None:530 if color != None:
@@ -527,27 +534,27 @@
527 colorsel.set_current_color(colorspec)534 colorsel.set_current_color(colorspec)
528 window.show()535 window.show()
529536
530 def on_color_response(self,widget,response) :537 def on_color_response(self, widget, response):
531 #the OK button return -5. Don't ask me why.538 #the OK button return -5. Don't ask me why.
532 if response == -5 :539 if response == -5:
533 colorsel = widget.colorsel540 colorsel = widget.colorsel
534 gtkcolor = colorsel.get_current_color()541 gtkcolor = colorsel.get_current_color()
535 strcolor = gtk.color_selection_palette_to_string([gtkcolor])542 strcolor = gtk.color_selection_palette_to_string([gtkcolor])
536 tags,notag_only = self.get_selected_tags() #pylint: disable-msg=W0612543 tags, notag_only = self.get_selected_tags()
537 for t in tags :544 for t in tags:
538 t.set_attribute("color",strcolor)545 t.set_attribute("color", strcolor)
539 self.do_refresh()546 self.do_refresh()
540 widget.destroy()547 widget.destroy()
541 548
542 def on_workview_toggled(self,widget) : #pylint: disable-msg=W0613549 def on_workview_toggled(self, widget): #pylint: disable-msg=W0613
543 self.do_toggle_workview()550 self.do_toggle_workview()
544 551
545 def do_toggle_workview(self):552 def do_toggle_workview(self):
546 #We have to be careful here to avoid a loop of signals553 #We have to be careful here to avoid a loop of signals
547 #menu_state = self.menu_view_workview.get_active()554 #menu_state = self.menu_view_workview.get_active()
548 #button_state = self.toggle_workview.get_active()555 #button_state = self.toggle_workview.get_active()
549 #We cannot have note and workview at the same time556 #We cannot have note and workview at the same time
550 if not self.workview and self.note_toggle.get_active() :557 if not self.workview and self.note_toggle.get_active():
551 self.note_toggle.set_active(False)558 self.note_toggle.set_active(False)
552 #We do something only if both widget are in different state559 #We do something only if both widget are in different state
553 tobeset = not self.workview560 tobeset = not self.workview
@@ -556,48 +563,48 @@
556 self.workview = tobeset563 self.workview = tobeset
557 self.do_refresh()564 self.do_refresh()
558565
559 def on_sidebar_toggled(self,widget) :566 def on_sidebar_toggled(self, widget):
560 view_sidebar = self.wTree.get_widget("view_sidebar")567 view_sidebar = self.wTree.get_widget("view_sidebar")
561 if self.sidebar.get_property("visible"):568 if self.sidebar.get_property("visible"):
562 view_sidebar.set_active(False)569 view_sidebar.set_active(False)
563 self.sidebar.hide()570 self.sidebar.hide()
564 else :571 else:
565 view_sidebar.set_active(True)572 view_sidebar.set_active(True)
566 self.sidebar.show()573 self.sidebar.show()
567 574
568 def on_note_toggled(self,widget) :575 def on_note_toggled(self, widget):
569 self.noteview = not self.noteview576 self.noteview = not self.noteview
570 workview_state = self.toggle_workview.get_active()577 workview_state = self.toggle_workview.get_active()
571 if workview_state :578 if workview_state:
572 self.toggle_workview.set_active(False)579 self.toggle_workview.set_active(False)
573 self.do_refresh()580 self.do_refresh()
574 581
575 def on_closed_toggled(self,widget) :582 def on_closed_toggled(self, widget):
576 if widget.get_active() :583 if widget.get_active():
577 self.closed_pane.show()584 self.closed_pane.show()
578 else :585 else:
579 self.closed_pane.hide()586 self.closed_pane.hide()
580587
581 def on_bg_color_toggled(self,widget) :588 def on_bg_color_toggled(self, widget):
582 if widget.get_active() :589 if widget.get_active():
583 self.priv["bg_color_enable"] = True590 self.priv["bg_color_enable"] = True
584 else :591 else:
585 self.priv["bg_color_enable"] = False592 self.priv["bg_color_enable"] = False
586 self.do_refresh()593 self.do_refresh()
587 594
588 def on_toolbar_toggled(self,widget) :595 def on_toolbar_toggled(self, widget):
589 if widget.get_active() :596 if widget.get_active():
590 self.toolbar.show()597 self.toolbar.show()
591 else :598 else:
592 self.toolbar.hide()599 self.toolbar.hide()
593600
594 def toggle_quickadd(self,widget) :601 def toggle_quickadd(self, widget):
595 if widget.get_active() :602 if widget.get_active():
596 self.quickadd_pane.show()603 self.quickadd_pane.show()
597 else :604 else:
598 self.quickadd_pane.hide()605 self.quickadd_pane.hide()
599 606
600 def canonical_date(self, arg) :607 def canonical_date(self, arg):
601 """608 """
602 Transform "arg" in a valid yyyy-mm-dd date or return None.609 Transform "arg" in a valid yyyy-mm-dd date or return None.
603 "arg" can be a yyyy-mm-dd, yyyymmdd, mmdd, today or a weekday name.610 "arg" can be a yyyy-mm-dd, yyyymmdd, mmdd, today or a weekday name.
@@ -607,107 +614,110 @@
607 day_names = [_("monday"), _("tuesday"), _("wednesday"),614 day_names = [_("monday"), _("tuesday"), _("wednesday"),
608 _("thursday"), _("friday"), _("saturday"),615 _("thursday"), _("friday"), _("saturday"),
609 _("sunday")]616 _("sunday")]
610 if re.match(r'\d{4}-\d{2}-\d{2}', arg) :617 if re.match(r'\d{4}-\d{2}-\d{2}', arg):
611 date = arg618 date = arg
612 elif arg.isdigit() :619 elif arg.isdigit():
613 if len(arg) == 8 :620 if len(arg) == 8:
614 date = "%s-%s-%s" % (arg[:4],arg[4:6],arg[6:])621 date = "%s-%s-%s" % (arg[:4], arg[4:6], arg[6:])
615 elif len(arg) == 4 :622 elif len(arg) == 4:
616 year = datetime.date.today().year623 year = datetime.date.today().year
617 date = "%i-%s-%s" % (year,arg[:2],arg[2:])624 date = "%i-%s-%s" % (year, arg[:2], arg[2:])
618 elif arg.lower() == "today" or arg.lower() == _("today"):625 elif arg.lower() == "today" or arg.lower() == _("today"):
619 today = datetime.date.today()626 today = datetime.date.today()
620 year = today.year627 year = today.year
621 month = today.month628 month = today.month
622 day = today.day629 day = today.day
623 date = "%i-%i-%i" % (year,month,day)630 date = "%i-%i-%i" % (year, month, day)
624 elif arg.lower() == "tomorrow" or\631 elif arg.lower() == "tomorrow" or arg.lower() == _("tomorrow"):
625 arg.lower() == _("tomorrow") :
626 today = datetime.date.today()632 today = datetime.date.today()
627 tomorrow = today + datetime.timedelta(days=1)633 tomorrow = today + datetime.timedelta(days=1)
628 year = tomorrow.year634 year = tomorrow.year
629 month = tomorrow.month635 month = tomorrow.month
630 day = tomorrow.day636 day = tomorrow.day
631 date = "%i-%i-%i" % (year,month,day)637 date = "%i-%i-%i" % (year, month, day)
632 elif arg.lower() in day_names_en or arg.lower() in day_names:638 elif arg.lower() in day_names_en or arg.lower() in day_names:
633 today = datetime.date.today()639 today = datetime.date.today()
634 today_day = today.weekday()640 today_day = today.weekday()
635 if arg.lower() in day_names_en :641 if arg.lower() in day_names_en:
636 arg_day = day_names_en.index(arg)642 arg_day = day_names_en.index(arg)
637 else :643 else:
638 arg_day = day_names.index(arg)644 arg_day = day_names.index(arg)
639 if arg_day > today_day :645 if arg_day > today_day:
640 delta = datetime.timedelta(days = arg_day-today_day)646 delta = datetime.timedelta(days = arg_day-today_day)
641 else :647 else:
642 delta = datetime.timedelta(days = arg_day-today_day+7)648 delta = datetime.timedelta(days = arg_day-today_day+7)
643 next_date = today + delta649 next_date = today + delta
644 year = next_date.year650 year = next_date.year
645 month = next_date.month651 month = next_date.month
646 day = next_date.day652 day = next_date.day
647 date = "%i-%i-%i" % (year,month,day)653 date = "%i-%i-%i" % (year, month, day)
648 else :654 else:
649 return None655 return None
650 if self.is_date_valid(date) :656 if self.is_date_valid(date):
651 return date657 return date
652 else :658 else:
653 return None659 return None
654 660
655 def is_date_valid(self, fulldate) :661 def is_date_valid(self, fulldate):
656 """662 """
657 Return True if the date exists. False else.663 Return True if the date exists. False else.
658 "fulldate" is yyyy-mm-dd664 "fulldate" is yyyy-mm-dd
659 """665 """
660 splited_date = fulldate.split("-")666 splited_date = fulldate.split("-")
661 if len(splited_date) != 3 :667 if len(splited_date) != 3:
662 return False668 return False
663 year,month,day = splited_date669 year, month, day = splited_date
664 try :670 try:
665 datetime.date(int(year),int(month),int(day))671 datetime.date(int(year), int(month), int(day))
666 except ValueError :672 except ValueError:
667 return False673 return False
668 else :674 else:
669 return True675 return True
670 676
671 def quickadd(self,widget) : #pylint: disable-msg=W0613677 def quickadd(self, widget): #pylint: disable-msg=W0613
672 text = self.quickadd_entry.get_text()678 text = self.quickadd_entry.get_text()
673 due_date = None679 due_date = None
674 defer_date = None680 defer_date = None
675 if text :681 if text:
676 tags,notagonly = self.get_selected_tags() #pylint: disable-msg=W0612682 tags, notagonly = self.get_selected_tags()
677 # Get tags in the title683 # Get tags in the title
678 for match in re.findall(r'[\s](@[^@,\s]+)',text) :684 for match in re.findall(r'[\s](@[^@,\s]+)', text):
679 tags.append(GTG.core.tagstore.Tag(match))685 tags.append(GTG.core.tagstore.Tag(match))
680 # Remove the @686 # Remove the @
681 #text =text.replace(match,match[1:],1)687 #text =text.replace(match, match[1:], 1)
682 # Get attributes688 # Get attributes
683 regexp = r'([\s]*)([a-zA-Z0-9_-]+):([^\s]+)'689 regexp = r'([\s]*)([a-zA-Z0-9_-]+):([^\s]+)'
684 for spaces,attribute, args in re.findall(regexp, text) :690 for spaces, attribute, args in re.findall(regexp, text):
685 valid_attribute = True691 valid_attribute = True
686 if attribute.lower() == "tags" or attribute.lower() == _("tags"):692 if (attribute.lower() == "tags"
687 for tag in args.split(",") :693 or attribute.lower() == _("tags")):
694 for tag in args.split(","):
688 tags.append(GTG.core.tagstore.Tag("@"+tag))695 tags.append(GTG.core.tagstore.Tag("@"+tag))
689 elif attribute.lower() == "defer" or attribute.lower() == _("defer"):696 elif (attribute.lower() == "defer"
697 or attribute.lower() == _("defer")):
690 defer_date = self.canonical_date(args)698 defer_date = self.canonical_date(args)
691 if defer_date is None :699 if defer_date is None:
692 valid_attribute = False700 valid_attribute = False
693 elif attribute.lower() == "due" or attribute.lower() == _("due"):701 elif (attribute.lower() == "due"
702 or attribute.lower() == _("due")):
694 due_date = self.canonical_date(args)703 due_date = self.canonical_date(args)
695 if due_date is None :704 if due_date is None:
696 valid_attribute = False705 valid_attribute = False
697 else :706 else:
698 # attribute is unknown707 # attribute is unknown
699 valid_attribute = False708 valid_attribute = False
700 if valid_attribute :709 if valid_attribute:
701 # if the command is valid we have to remove it710 # if the command is valid we have to remove it
702 # from the task title711 # from the task title
703 text = text.replace("%s%s:%s" % (spaces,attribute,args), "")712 text = text.replace(
713 "%s%s:%s" % (spaces, attribute, args), "")
704 # Create the new task714 # Create the new task
705 task = self.req.new_task(tags=tags,newtask=True)715 task = self.req.new_task(tags=tags, newtask=True)
706 if text != "" :716 if text != "":
707 task.set_title(text)717 task.set_title(text)
708 if not due_date is None :718 if not due_date is None:
709 task.set_due_date(due_date)719 task.set_due_date(due_date)
710 if not defer_date is None :720 if not defer_date is None:
711 task.set_start_date(defer_date)721 task.set_start_date(defer_date)
712 id_toselect = task.get_id()722 id_toselect = task.get_id()
713 #############723 #############
@@ -715,393 +725,442 @@
715 # Refresh the treeview725 # Refresh the treeview
716 self.do_refresh(toselect=id_toselect)726 self.do_refresh(toselect=id_toselect)
717 #self.select_task(id_toselect)727 #self.select_task(id_toselect)
718 728
719 #This works only in the main task_tview729 def select_task(self, id_toselect):
720 #If it cannot find the requested task, nothing is selected730 """Select a task with tid 'id_toselect'.
721 def select_task(self,id_toselect) :731
732 This works only in the main task_tview. If it cannot find the
733 requested task, nothing is selected.
734 """
722 #We will loop over all task_tview element to find the newly added one735 #We will loop over all task_tview element to find the newly added one
723 model = self.task_tview.get_model()736 model = self.task_tview.get_model()
724 tempit = model.get_iter_first()737 tempit = model.get_iter_first()
725 it = None738 it = None
726 while (tempit and not it) :739 while (tempit and not it):
727 if tempit :740 if tempit:
728 tid = model.get_value(tempit, 0)741 tid = model.get_value(tempit, 0)
729 if tid == id_toselect :742 if tid == id_toselect:
730 it = tempit743 it = tempit
731 #First we try to see if there is child task744 #First we try to see if there is child task
732 tempit2 = model.iter_children(tempit)745 tempit2 = model.iter_children(tempit)
733 #if no children, then take the tasks on the same level746 #if no children, then take the tasks on the same level
734 if not tempit2 :747 if not tempit2:
735 tempit2 = model.iter_next(tempit)748 tempit2 = model.iter_next(tempit)
736 #if no task on the same level, go back to the parent749 #if no task on the same level, go back to the parent
737 #and then to the next task on the parent level750 #and then to the next task on the parent level
738 if not tempit2 :751 if not tempit2:
739 tempit2 = model.iter_parent(tempit)752 tempit2 = model.iter_parent(tempit)
740 if tempit2 :753 if tempit2:
741 tempit2 = model.iter_next(tempit2)754 tempit2 = model.iter_next(tempit2)
742 tempit = tempit2755 tempit = tempit2
743 if it :756 if it:
744 selection = self.task_tview.get_selection() 757 selection = self.task_tview.get_selection()
745 selection.select_iter(it)758 selection.select_iter(it)
746759
747 760 def do_refresh(self, sender=None, param=None, toselect=None):
748
749 def do_refresh(self,sender=None,param=None,toselect=None) : #pylint: disable-msg=W0613
750 #We ask to do the refresh in a gtk thread761 #We ask to do the refresh in a gtk thread
751 #We use a lock_lock like described in 762 #We use a lock_lock like described in
752 #http://ploum.frimouvy.org/?202-the-signals-and-threads-flying-circus763 #http://ploum.frimouvy.org/?202-the-signals-and-threads-flying-circus
753 if self.refresh_lock_lock.acquire(False) :764 if self.refresh_lock_lock.acquire(False):
754 gobject.idle_add(self.refresh_tb,sender,toselect)765 gobject.idle_add(self.refresh_tb, sender, toselect)
755 #If we have something toselect, we cannot skip the refresh766 #If we have something toselect, we cannot skip the refresh
756 elif toselect :767 elif toselect:
757 gobject.idle_add(self.select_task,toselect)768 gobject.idle_add(self.select_task, toselect)
758769
759 #If a task asked for the refresh, we don't refresh it to avoid a loop770 def refresh_tb(self, fromtask=None, toselect=None):
760 #New use refresh_tb directly, use "do_refresh"771 """Refresh the task browser.
761 def refresh_tb(self,fromtask=None,toselect=None):772
773 If a task asked for the refresh, we don't refresh it to avoid a loop
774 New use refresh_tb directly, use "do_refresh".
775 """
762 self.refresh_lock.acquire()776 self.refresh_lock.acquire()
763 try :777 try:
764 self.refresh_lock_lock.release()778 self.refresh_lock_lock.release()
765 current_pane = self.main_pane.get_child()779 current_pane = self.main_pane.get_child()
766 if self.noteview :780 if self.noteview:
767 if current_pane == self.task_tview :781 if current_pane == self.task_tview:
768 self.main_pane.remove(current_pane)782 self.main_pane.remove(current_pane)
769 self.main_pane.add(self.note_tview)783 self.main_pane.add(self.note_tview)
770 self.refresh_note()784 self.refresh_note()
771 else :785 else:
772 if current_pane == self.note_tview :786 if current_pane == self.note_tview:
773 self.main_pane.remove(current_pane)787 self.main_pane.remove(current_pane)
774 self.main_pane.add(self.task_tview)788 self.main_pane.add(self.task_tview)
775 self.refresh_list(toselect=toselect)789 self.refresh_list(toselect=toselect)
776 self.refresh_closed()790 self.refresh_closed()
777 self.refresh_tags()791 self.refresh_tags()
778 #Refreshing the opened editors792 #Refreshing the opened editors
779 for uid in self.opened_task :793 for uid in self.opened_task:
780 if uid != fromtask :794 if uid != fromtask:
781 self.opened_task[uid].refresh_editor()795 self.opened_task[uid].refresh_editor()
782 finally :796 finally:
783 self.refresh_lock.release()797 self.refresh_lock.release()
784798
799 def refresh_tags(self):
800 """Refresh the tag list.
785801
786 #We refresh the tag list. Not needed very often802 Not needed very often.
787 def refresh_tags(self) :803 """
788 select = self.tag_tview.get_selection()804 select = self.tag_tview.get_selection()
789 t_path = None805 t_path = None
790 if select :806 if select:
791 t_model,t_path = select.get_selected_rows() #pylint: disable-msg=W0612807 t_model, t_path = select.get_selected_rows()
792 self.tag_ts.clear()808 self.tag_ts.clear()
793 alltag = self.req.get_alltag_tag()809 alltag = self.req.get_alltag_tag()
794 notag = self.req.get_notag_tag()810 notag = self.req.get_notag_tag()
795 if self.workview :811 if self.workview:
796 count_all_task = len(self.req.get_active_tasks_list(workable=True))812 count_all_task = len(self.req.get_active_tasks_list(workable=True))
797 count_no_tags = len(self.req.get_active_tasks_list(notag_only=True,\813 count_no_tags = len(
798 workable=True))814 self.req.get_active_tasks_list(notag_only=True, workable=True))
799 else :815 else:
800 count_all_task = len(self.req.get_tasks_list(started_only=False))816 count_all_task = len(self.req.get_tasks_list(started_only=False))
801 count_no_tags = len(self.req.get_tasks_list(notag_only=True,\817 count_no_tags = len(
802 started_only=False))818 self.req.get_tasks_list(notag_only=True, started_only=False))
803 819
804 self.tag_ts.append([alltag,None,_("<span weight=\"bold\">All tags</span>"),str(count_all_task),False])820 self.tag_ts.append(
805 self.tag_ts.append([notag,None,_("<span weight=\"bold\">Tasks without tags</span>"),str(count_no_tags),False])821 [alltag, None, _("<span weight=\"bold\">All tags</span>"),
806 self.tag_ts.append([None,None,"","",True])822 str(count_all_task), False])
823 self.tag_ts.append(
824 [notag, None, _("<span weight=\"bold\">Tasks without tags</span>"),
825 str(count_no_tags), False])
826 self.tag_ts.append([None, None, "", "", True])
807827
808 tags = self.req.get_used_tags()828 tags = self.req.get_used_tags()
809 829
810 tags.sort(cmp=lambda x,y: cmp(x.get_name().lower(),y.get_name().lower()))830 tags.sort(
831 cmp=lambda x, y: cmp(x.get_name().lower(), y.get_name().lower()))
811832
812 for tag in tags:833 for tag in tags:
813 color = tag.get_attribute("color")834 color = tag.get_attribute("color")
814 if self.workview :835 if self.workview:
815 count = len(self.req.get_active_tasks_list(tags=[tag],workable=True))836 count = len(
816 else :837 self.req.get_active_tasks_list(tags=[tag], workable=True))
817 count = len(self.req.get_tasks_list(started_only=False,tags=[tag]))838 else:
839 count = len(
840 self.req.get_tasks_list(started_only=False, tags=[tag]))
818 #We display the tags without the "@" (but we could)841 #We display the tags without the "@" (but we could)
819 if count != 0:842 if count != 0:
820 self.tag_ts.append([tag,color,tag.get_name()[1:], str(count), False])843 self.tag_ts.append(
821 844 [tag, color, tag.get_name()[1:], str(count), False])
845
822 #We reselect the selected tag846 #We reselect the selected tag
823 if t_path :847 if t_path:
824 for i in t_path :848 for i in t_path:
825 self.tag_tview.get_selection().select_path(i)849 self.tag_tview.get_selection().select_path(i)
826850
827 def tag_separator_filter(self, model, itera, user_data=None):#pylint: disable-msg=W0613851 def tag_separator_filter(self, model, itera, user_data=None):
828 return model.get_value(itera, self.TAGS_MODEL_SEP)852 return model.get_value(itera, self.TAGS_MODEL_SEP)
829 853
830 def update_collapsed_row(self, model, path, itera, user_data): #pylint: disable-msg=W0613854 def update_collapsed_row(self, model, path, itera, user_data):
831 """Build a list of task that must showed as collapsed in Treeview"""855 """Build a list of task that must showed as collapsed in Treeview"""
832 tid = self.task_ts.get_value(itera,0)856 tid = self.task_ts.get_value(itera, 0)
833 # Remove expanded rows857 # Remove expanded rows
834 if self.task_ts.iter_has_child(itera) and \858 if (self.task_ts.iter_has_child(itera) and
835 self.task_tview.row_expanded(path) and \859 self.task_tview.row_expanded(path) and
836 tid in self.priv["collapsed_tid"]:860 tid in self.priv["collapsed_tid"]):
837861
838 self.priv["collapsed_tid"].remove(tid)862 self.priv["collapsed_tid"].remove(tid)
839863
840 # Append collapsed rows864 # Append collapsed rows
841 elif self.task_ts.iter_has_child(itera) and \865 elif (self.task_ts.iter_has_child(itera) and
842 not self.task_tview.row_expanded(path) and \866 not self.task_tview.row_expanded(path) and
843 tid not in self.priv["collapsed_tid"]:867 tid not in self.priv["collapsed_tid"]):
844868
845 self.priv["collapsed_tid"].append(tid)869 self.priv["collapsed_tid"].append(tid)
846870
847 return False # Return False or the TreeModel.foreach() function ends871 return False # Return False or the TreeModel.foreach() function ends
848 872
849 def restore_collapsed(self,treeview,path,data) :873 def restore_collapsed(self, treeview, path, data):
850 itera = self.task_ts.get_iter(path)874 itera = self.task_ts.get_iter(path)
851 tid = self.task_ts.get_value(itera,0)875 tid = self.task_ts.get_value(itera, 0)
852 if tid in self.priv["collapsed_tid"] :876 if tid in self.priv["collapsed_tid"]:
853 treeview.collapse_row(path)877 treeview.collapse_row(path)
854 878
855 #refresh list build/refresh your TreeStore of task879 def refresh_list(self, a=None, toselect=None):
856 #to keep it in sync with your self.projects 880 """Refresh or build the TreeStore of tasks."""
857 def refresh_list(self,a=None,toselect=None) : #pylint: disable-msg=W0613881
858
859 # Save collapsed rows882 # Save collapsed rows
860 self.task_ts.foreach(self.update_collapsed_row, None)883 self.task_ts.foreach(self.update_collapsed_row, None)
861 884
862 #selected tasks :885 #selected tasks:
863 selected_uid = self.get_selected_task(self.task_tview)886 selected_uid = self.get_selected_task(self.task_tview)
864 tselect = self.task_tview.get_selection()887 tselect = self.task_tview.get_selection()
865 t_path = None888 t_path = None
866 if tselect :889 if tselect:
867 t_model,t_path = tselect.get_selected_rows() #pylint: disable-msg=W0612890 t_model, t_path = tselect.get_selected_rows()
868 891
869 #Scroll position :892 #Scroll position:
870 vscroll_value = self.task_tview.get_vadjustment().get_value()893 vscroll_value = self.task_tview.get_vadjustment().get_value()
871 hscroll_value = self.task_tview.get_hadjustment().get_value() 894 hscroll_value = self.task_tview.get_hadjustment().get_value()
872 895
873 #to refresh the list we build a new treestore then replace the existing896 #to refresh the list we build a new treestore then replace the existing
874 new_taskts = treetools.new_task_ts(dnd_func=self.row_dragndrop)897 new_taskts = treetools.new_task_ts(dnd_func=self.row_dragndrop)
875 tag_list,notag_only = self.get_selected_tags()898 tag_list, notag_only = self.get_selected_tags()
876 nbr_of_tasks = 0899 nbr_of_tasks = 0
877 900
878 #We build the active tasks pane901 #We build the active tasks pane
879 if self.workview :902 if self.workview:
880 tasks = self.req.get_active_tasks_list(tags=tag_list,\903 tasks = self.req.get_active_tasks_list(
881 notag_only=notag_only,workable=True, started_only=False)904 tags=tag_list, notag_only=notag_only, workable=True,
882 for tid in tasks :905 started_only=False)
883 self.add_task_tree_to_list(new_taskts,tid,None,selected_uid,\906 for tid in tasks:
884 treeview=False)907 self.add_task_tree_to_list(
908 new_taskts, tid, None, selected_uid, treeview=False)
885 nbr_of_tasks = len(tasks)909 nbr_of_tasks = len(tasks)
886 910
887 else :911 else:
888 #building the classical treeview912 #building the classical treeview
889 active_root_tasks = self.req.get_active_tasks_list(tags=tag_list,\913 active_root_tasks = self.req.get_active_tasks_list(
890 notag_only=notag_only, is_root=True, started_only=False)914 tags=tag_list, notag_only=notag_only, is_root=True,
891 active_tasks = self.req.get_active_tasks_list(tags=tag_list,\915 started_only=False)
892 notag_only=notag_only, is_root=False, started_only=False)916 active_tasks = self.req.get_active_tasks_list(
893 for tid in active_root_tasks :917 tags=tag_list, notag_only=notag_only, is_root=False,
894 self.add_task_tree_to_list(new_taskts, tid, None,\918 started_only=False)
895 selected_uid,active_tasks=active_tasks)919 for tid in active_root_tasks:
920 self.add_task_tree_to_list(
921 new_taskts, tid, None, selected_uid,
922 active_tasks=active_tasks)
896 nbr_of_tasks = len(active_tasks)923 nbr_of_tasks = len(active_tasks)
897 924
898 #Set the title of the window :925 #Set the title of the window:
899 if nbr_of_tasks == 0 :926 if nbr_of_tasks == 0:
900 parenthesis = _("(no active tasks)")927 parenthesis = _("(no active tasks)")
901 elif nbr_of_tasks == 1 :928 elif nbr_of_tasks == 1:
902 parenthesis = _("(1 active task)")929 parenthesis = _("(1 active task)")
903 else :930 else:
904 parenthesis = "(%s active tasks)"%nbr_of_tasks931 parenthesis = "(%s active tasks)"%nbr_of_tasks
905 self.window.set_title("Getting Things GNOME! %s"%parenthesis)932 self.window.set_title("Getting Things GNOME! %s"%parenthesis)
906 self.task_tview.set_model(new_taskts)933 self.task_tview.set_model(new_taskts)
907 self.task_ts = new_taskts934 self.task_ts = new_taskts
908 #We expand all the we close the tasks who were not saved as "expanded"935 #We expand all the we close the tasks who were not saved as "expanded"
909 self.task_tview.expand_all()936 self.task_tview.expand_all()
910 self.task_tview.map_expanded_rows(self.restore_collapsed,None)937 self.task_tview.map_expanded_rows(self.restore_collapsed, None)
911 # Restore sorting938 # Restore sorting
912 if not self.noteview :939 if not self.noteview:
913 if self.priv["tasklist"].has_key("sort_column") and \940 # XXX: This can be done much more simply using {}.get(). -- jml,
914 self.priv["tasklist"].has_key("sort_order") :941 # 2009-07-18.
915 if self.priv["tasklist"]["sort_column"] is not None and \942 if ('sort_column' in self.priv["tasklist"] and
916 self.priv["tasklist"]["sort_order"] is not None :943 'sort_order' in self.priv["tasklist"]):
917 self.sort_tasklist_rows(self.priv["tasklist"]["sort_column"], \944 if (self.priv["tasklist"]["sort_column"] is not None and
918 self.priv["tasklist"]["sort_order"])945 self.priv["tasklist"]["sort_order"] is not None):
946 self.sort_tasklist_rows(
947 self.priv["tasklist"]["sort_column"],
948 self.priv["tasklist"]["sort_order"])
919 #We reselect the selected tasks949 #We reselect the selected tasks
920 if toselect :950 if toselect:
921 self.select_task(toselect)951 self.select_task(toselect)
922 elif t_path :952 elif t_path:
923 selection = self.task_tview.get_selection()953 selection = self.task_tview.get_selection()
924 for i in t_path :954 for i in t_path:
925 selection.select_path(i)955 selection.select_path(i)
926 956
927 #scroll position957 def restore_vscroll(old_position):
928 #We have to call that in another thread, else it will not work
929 def restore_vscroll(old_position) :
930 vadjust = self.task_tview.get_vadjustment()958 vadjust = self.task_tview.get_vadjustment()
931 #We ensure that we will not scroll out of the window959 #We ensure that we will not scroll out of the window
932 #It was bug #331285960 #It was bug #331285
933 vscroll = min(old_position,(vadjust.upper - vadjust.page_size))961 vscroll = min(old_position, (vadjust.upper - vadjust.page_size))
934 vadjust.set_value(vscroll)962 vadjust.set_value(vscroll)
935 def restore_hscroll(old_position) :963
964 def restore_hscroll(old_position):
936 hadjust = self.task_tview.get_hadjustment()965 hadjust = self.task_tview.get_hadjustment()
937 hscroll = min(old_position,(hadjust.upper - hadjust.page_size))966 hscroll = min(old_position, (hadjust.upper - hadjust.page_size))
938 hadjust.set_value(hscroll)967 hadjust.set_value(hscroll)
939 gobject.idle_add(restore_vscroll,vscroll_value)968
940 gobject.idle_add(restore_hscroll,hscroll_value)969 #scroll position
941970 #We have to call that in another thread, else it will not work
942 #Refresh the closed tasks pane971 gobject.idle_add(restore_vscroll, vscroll_value)
943 def refresh_closed(self) :972 gobject.idle_add(restore_hscroll, hscroll_value)
973
974 def refresh_closed(self):
975 """Refresh the closed tasks pane."""
944 #We build the closed tasks pane976 #We build the closed tasks pane
945 dselect = self.taskdone_tview.get_selection()977 dselect = self.taskdone_tview.get_selection()
946 d_path = None978 d_path = None
947 if dselect :979 if dselect:
948 d_model,d_path = dselect.get_selected_rows() #pylint: disable-msg=W0612980 d_model, d_path = dselect.get_selected_rows()
949 #We empty the pane981 #We empty the pane
950 self.taskdone_ts.clear()982 self.taskdone_ts.clear()
951 #We rebuild it983 #We rebuild it
952 tag_list,notag_only = self.get_selected_tags()984 tag_list, notag_only = self.get_selected_tags()
953 closed_tasks = self.req.get_closed_tasks_list(tags=tag_list,\985 closed_tasks = self.req.get_closed_tasks_list(
954 notag_only=notag_only)986 tags=tag_list, notag_only=notag_only)
955 for tid in closed_tasks :987 for tid in closed_tasks:
956 t = self.req.get_task(tid)988 t = self.req.get_task(tid)
957 title_str = saxutils.escape(t.get_title())989 title_str = saxutils.escape(t.get_title())
958 closeddate = t.get_closed_date()990 closeddate = t.get_closed_date()
959 closeddate_str = closeddate991 closeddate_str = closeddate
960 tags = t.get_tags()992 tags = t.get_tags()
961 if self.priv["bg_color_enable"] and t.has_tags() :993 if self.priv["bg_color_enable"] and t.has_tags():
962 my_color = colors.background_color(t.get_tags())994 my_color = colors.background_color(t.get_tags())
963 else:995 else:
964 my_color = None996 my_color = None
965 if t.get_status() == "Dismiss":997 if t.get_status() == "Dismiss":
966 title_str = "<span color=\"#AAAAAA\">%s</span>" % title_str998 title_str = "<span color=\"#AAAAAA\">%s</span>" % title_str
967 closeddate_str = "<span color=\"#AAAAAA\">%s</span>" % closeddate999 closeddate_str = (
968 self.taskdone_ts.append(None,[tid,t.get_color(),title_str,closeddate,closeddate_str,my_color,tags])1000 "<span color=\"#AAAAAA\">%s</span>" % closeddate)
1001 self.taskdone_ts.append(
1002 None,
1003 [tid, t.get_color(), title_str, closeddate, closeddate_str,
1004 my_color, tags])
969 closed_selection = self.taskdone_tview.get_selection()1005 closed_selection = self.taskdone_tview.get_selection()
970 if d_path :1006 if d_path:
971 for i in d_path :1007 for i in d_path:
972 closed_selection.select_path(i)1008 closed_selection.select_path(i)
973 self.taskdone_ts.set_sort_column_id(self.CTASKS_MODEL_DDATE, gtk.SORT_DESCENDING)1009 self.taskdone_ts.set_sort_column_id(
974 1010 self.CTASKS_MODEL_DDATE, gtk.SORT_DESCENDING)
975 #Refresh the notes pane1011
976 def refresh_note(self) :1012 def refresh_note(self):
1013 """Refresh the notes pane."""
977 #We build the notes pane1014 #We build the notes pane
978 dselect = self.note_tview.get_selection()1015 dselect = self.note_tview.get_selection()
979 d_path = None1016 d_path = None
980 if dselect :1017 if dselect:
981 d_model,d_path = dselect.get_selected_rows() #pylint: disable-msg=W06121018 d_model, d_path = dselect.get_selected_rows()
982 #We empty the pane1019 #We empty the pane
983 self.note_ts.clear()1020 self.note_ts.clear()
984 #We rebuild it1021 #We rebuild it
985 tag_list,notag_only = self.get_selected_tags()1022 tag_list, notag_only = self.get_selected_tags()
986 notes = self.req.get_notes_list(tags=tag_list, notag_only=notag_only)1023 notes = self.req.get_notes_list(tags=tag_list, notag_only=notag_only)
987 for tid in notes :1024 for tid in notes:
988 t = self.req.get_task(tid)1025 t = self.req.get_task(tid)
989 title_str = saxutils.escape(t.get_title())1026 title_str = saxutils.escape(t.get_title())
990 self.note_ts.append(None,[tid,t.get_color(),title_str])1027 self.note_ts.append(None, [tid, t.get_color(), title_str])
991 note_selection = self.note_tview.get_selection()1028 note_selection = self.note_tview.get_selection()
992 if d_path :1029 if d_path:
993 for i in d_path :1030 for i in d_path:
994 note_selection.select_path(i)1031 note_selection.select_path(i)
995 #self.note_ts.set_sort_column_id(self.CTASKS_MODEL_DDATE, gtk.SORT_DESCENDING)1032 #self.note_ts.set_sort_column_id(self.CTASKS_MODEL_DDATE,
996 1033 #gtk.SORT_DESCENDING)
997 #Add tasks to a treeview. If treeview is False, it becomes a flat list1034
998 def add_task_tree_to_list(self, tree_store, tid, parent, selected_uid=None,\1035 def add_task_tree_to_list(self, tree_store, tid, parent, selected_uid=None,
999 active_tasks=[], treeview=True):1036 active_tasks=[], treeview=True):
1000 task = self.req.get_task(tid)1037 """Add tasks to a treeview.
1038
1039 If 'treeview' is False, it becomes a flat list.
1040 """
1041 task = self.req.get_task(tid)
1001 st_count = self.__count_tasks_rec(task, active_tasks)1042 st_count = self.__count_tasks_rec(task, active_tasks)
1002 if selected_uid and selected_uid == tid :1043 if selected_uid and selected_uid == tid:
1003 # Temporarily disabled1044 # Temporarily disabled
1004 #title = self.__build_task_title(task,extended=True)1045 #title = self.__build_task_title(task, extended=True)
1005 title_str = self.__build_task_title(task, st_count, extended=False)1046 title_str = self.__build_task_title(task, st_count, extended=False)
1006 else :1047 else:
1007 title_str = self.__build_task_title(task, st_count, extended=False)1048 title_str = self.__build_task_title(task, st_count, extended=False)
1008 1049
10091050
1010 # Extract data1051 # Extract data
1011 title = saxutils.escape(task.get_title()) 1052 title = saxutils.escape(task.get_title())
1012 duedate_str = task.get_due_date()1053 duedate_str = task.get_due_date()
1013 left_str = task.get_days_left()1054 left_str = task.get_days_left()
1014 tags = task.get_tags()1055 tags = task.get_tags()
1015 if self.priv["bg_color_enable"] :1056 if self.priv["bg_color_enable"]:
1016 my_color = colors.background_color(tags)1057 my_color = colors.background_color(tags)
1017 else:1058 else:
1018 my_color = None1059 my_color = None
1019 1060
1020 if not parent and len(task.get_subtasks()) == 0:1061 if not parent and len(task.get_subtasks()) == 0:
1021 itera = tree_store.get_iter_first()1062 itera = tree_store.get_iter_first()
1022 my_row = tree_store.insert_before(None, itera, row=[tid,title,title_str,duedate_str,left_str,tags,my_color])1063 my_row = tree_store.insert_before(
1064 None, itera,
1065 row=[tid, title, title_str, duedate_str, left_str, tags,
1066 my_color])
1023 else:1067 else:
1024 #None should be "parent" but crashing with thread1068 #None should be "parent" but crashing with thread
1025 my_row = tree_store.append(parent,\1069 my_row = tree_store.append(
1026 [tid,title,title_str,duedate_str,left_str,tags,my_color])1070 parent,
1071 [tid, title, title_str, duedate_str, left_str, tags, my_color])
1027 #If treeview, we add add the active childs1072 #If treeview, we add add the active childs
1028 if treeview :1073 if treeview:
1029 for c in task.get_subtasks():1074 for c in task.get_subtasks():
1030 cid = c.get_id()1075 cid = c.get_id()
1031 if cid in active_tasks:1076 if cid in active_tasks:
1032 #None should be cid1077 #None should be cid
1033 self.add_task_tree_to_list(tree_store, cid, my_row,selected_uid,\1078 self.add_task_tree_to_list(
1034 active_tasks=active_tasks)1079 tree_store, cid, my_row, selected_uid,
1035 1080 active_tasks=active_tasks)
1036 #This function is called when the selection change in the closed task view1081
1037 #It will displays the selected task differently 1082 def taskdone_cursor_changed(self, selection=None):
1038 def taskdone_cursor_changed(self,selection=None) :1083 """Called when selection changes in closed task view.
1084
1085 Changes the way the selected task is displayed.
1086 """
1039 #We unselect all in the active task view1087 #We unselect all in the active task view
1040 #Only if something is selected in the closed task list1088 #Only if something is selected in the closed task list
1041 #And we change the status of the Done/dismiss button1089 #And we change the status of the Done/dismiss button
1042 self.donebutton.set_icon_name("gtg-task-done")1090 self.donebutton.set_icon_name("gtg-task-done")
1043 self.dismissbutton.set_icon_name("gtg-task-dismiss")1091 self.dismissbutton.set_icon_name("gtg-task-dismiss")
1044 if selection.count_selected_rows() > 0 :1092 if selection.count_selected_rows() > 0:
1045 tid = self.get_selected_task(self.taskdone_tview)1093 tid = self.get_selected_task(self.taskdone_tview)
1046 task = self.req.get_task(tid)1094 task = self.req.get_task(tid)
1047 self.task_tview.get_selection().unselect_all()1095 self.task_tview.get_selection().unselect_all()
1048 self.note_tview.get_selection().unselect_all()1096 self.note_tview.get_selection().unselect_all()
1049 if task.get_status() == "Dismiss" :1097 if task.get_status() == "Dismiss":
1050 self.wTree.get_widget("ctcm_mark_as_not_done").set_sensitive(False)1098 self.wTree.get_widget(
1099 "ctcm_mark_as_not_done").set_sensitive(False)
1051 self.wTree.get_widget("ctcm_undismiss").set_sensitive(True)1100 self.wTree.get_widget("ctcm_undismiss").set_sensitive(True)
1052 self.dismissbutton.set_label(GnomeConfig.MARK_UNDISMISS)1101 self.dismissbutton.set_label(GnomeConfig.MARK_UNDISMISS)
1053 self.donebutton.set_label(GnomeConfig.MARK_DONE)1102 self.donebutton.set_label(GnomeConfig.MARK_DONE)
1054 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)1103 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)
1055 self.dismissbutton.set_icon_name("gtg-task-undismiss")1104 self.dismissbutton.set_icon_name("gtg-task-undismiss")
1056 self.dismissbutton.set_tooltip_text(GnomeConfig.MARK_UNDISMISS_TOOLTIP)1105 self.dismissbutton.set_tooltip_text(
1106 GnomeConfig.MARK_UNDISMISS_TOOLTIP)
1057# self.editbutton.connect('clicked', self.on_edit_done_task)1107# self.editbutton.connect('clicked', self.on_edit_done_task)
1058# self.edit_mi.connect('activate', self.on_edit_done_task)1108# self.edit_mi.connect('activate', self.on_edit_done_task)
1059 else :1109 else:
1060 self.wTree.get_widget("ctcm_mark_as_not_done").set_sensitive(True)1110 self.wTree.get_widget(
1111 "ctcm_mark_as_not_done").set_sensitive(True)
1061 self.wTree.get_widget("ctcm_undismiss").set_sensitive(False)1112 self.wTree.get_widget("ctcm_undismiss").set_sensitive(False)
1062 self.donebutton.set_label(GnomeConfig.MARK_UNDONE)1113 self.donebutton.set_label(GnomeConfig.MARK_UNDONE)
1063 self.donebutton.set_tooltip_text(GnomeConfig.MARK_UNDONE_TOOLTIP)1114 self.donebutton.set_tooltip_text(
1115 GnomeConfig.MARK_UNDONE_TOOLTIP)
1064 self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS)1116 self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS)
1065 self.dismissbutton.set_tooltip_text(GnomeConfig.MARK_DISMISS_TOOLTIP)1117 self.dismissbutton.set_tooltip_text(
1118 GnomeConfig.MARK_DISMISS_TOOLTIP)
1066 self.donebutton.set_icon_name("gtg-task-undone")1119 self.donebutton.set_icon_name("gtg-task-undone")
1067# self.editbutton.connect('clicked', self.on_edit_active_task)1120# self.editbutton.connect('clicked', self.on_edit_active_task)
1068# self.edit_mi.connect('activate', self.on_edit_active_task)1121# self.edit_mi.connect('activate', self.on_edit_active_task)
1069 1122
1070 #This function is called when the selection change in the active task view1123 def task_cursor_changed(self, selection=None):
1071 #It will displays the selected task differently1124 """Called when selection changes in the active task view.
1072 def task_cursor_changed(self,selection=None) :1125
1126 Changes the way the selected task is displayed.
1127 """
1073 #We unselect all in the closed task view1128 #We unselect all in the closed task view
1074 #Only if something is selected in the active task list1129 #Only if something is selected in the active task list
1075 self.donebutton.set_icon_name("gtg-task-done")1130 self.donebutton.set_icon_name("gtg-task-done")
1076 self.dismissbutton.set_icon_name("gtg-task-dismiss")1131 self.dismissbutton.set_icon_name("gtg-task-dismiss")
1077 if selection.count_selected_rows() > 0 :1132 if selection.count_selected_rows() > 0:
1078 self.taskdone_tview.get_selection().unselect_all()1133 self.taskdone_tview.get_selection().unselect_all()
1079 self.note_tview.get_selection().unselect_all()1134 self.note_tview.get_selection().unselect_all()
1080 self.donebutton.set_label(GnomeConfig.MARK_DONE)1135 self.donebutton.set_label(GnomeConfig.MARK_DONE)
1081 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)1136 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)
1082 self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS)1137 self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS)
1083 #We reset the previously selected task1138 #We reset the previously selected task
1084 if self.selected_rows and self.task_ts.iter_is_valid(self.selected_rows):1139 if (self.selected_rows
1085 tid = self.task_ts.get_value(self.selected_rows, self.TASK_MODEL_OBJ)1140 and self.task_ts.iter_is_valid(self.selected_rows)):
1141 tid = self.task_ts.get_value(
1142 self.selected_rows, self.TASK_MODEL_OBJ)
1086 task = self.req.get_task(tid)1143 task = self.req.get_task(tid)
1087 title = self.__build_task_title(task,extended=False)1144 title = self.__build_task_title(task, extended=False)
1088 self.task_ts.set_value(self.selected_rows,self.TASK_MODEL_TITLE,title)1145 self.task_ts.set_value(
1146 self.selected_rows, self.TASK_MODEL_TITLE, title)
1089 #We change the selection title1147 #We change the selection title
1090 #if selection :1148 #if selection:
1091 #ts,itera = selection.get_selected() #pylint: disable-msg=W06121149 #ts, itera = selection.get_selected() #pylint: disable-msg=W0612
1092 #if itera and self.task_ts.iter_is_valid(itera) :1150 #if itera and self.task_ts.iter_is_valid(itera):
1093 #tid = self.task_ts.get_value(itera, self.TASK_MODEL_OBJ)1151 #tid = self.task_ts.get_value(itera, self.TASK_MODEL_OBJ)
1094 #task = self.req.get_task(tid)1152 #task = self.req.get_task(tid)
1095 #self.selected_rows = itera1153 #self.selected_rows = itera
1096 # Extended title is temporarily disabled1154 # Extended title is temporarily disabled
1097 #title = self.__build_task_title(task,extended=True)1155 #title = self.__build_task_title(task, extended=True)
1098 #title = self.__build_task_title(task,extended=False)1156 #title = self.__build_task_title(task, extended=False)
1099 #self.task_ts.set_value(self.selected_rows,self.TASK_MODEL_TITLE,title)1157 #self.task_ts.set_value(
1100 1158 # self.selected_rows, self.TASK_MODEL_TITLE, title)
1101 def note_cursor_changed(self,selection=None) :1159
1160 def note_cursor_changed(self, selection=None):
1102 #We unselect all in the closed task view1161 #We unselect all in the closed task view
1103 #Only if something is selected in the active task list1162 #Only if something is selected in the active task list
1104 if selection.count_selected_rows() > 0 :1163 if selection.count_selected_rows() > 0:
1105 self.taskdone_tview.get_selection().unselect_all()1164 self.taskdone_tview.get_selection().unselect_all()
1106 self.task_tview.get_selection().unselect_all()1165 self.task_tview.get_selection().unselect_all()
11071166
@@ -1114,48 +1173,53 @@
1114 else:1173 else:
1115 count = count + 11174 count = count + 1
1116 return count1175 return count
1117 1176
1118 def __build_task_title(self,task,count,extended=False):1177 def __build_task_title(self, task, count, extended=False):
1119 simple_title = saxutils.escape(task.get_title())1178 simple_title = saxutils.escape(task.get_title())
1120 if extended :1179 if extended:
1121 excerpt = task.get_excerpt(lines=2)1180 excerpt = task.get_excerpt(lines=2)
1122 if excerpt.strip() != "" :1181 if excerpt.strip() != "":
1123 title = "<b><big>%s</big></b>\n<small>%s</small>" %(simple_title,excerpt)1182 title = "<b><big>%s</big></b>\n<small>%s</small>" % (
1124 else : 1183 simple_title, excerpt)
1125 title = "<b><big>%s</big></b>" %simple_title 1184 else:
1126 else :1185 title = "<b><big>%s</big></b>" %simple_title
1186 else:
1127 if (not self.workview):1187 if (not self.workview):
1128 if count == 0:1188 if count == 0:
1129 title = "<span>%s</span>" % (simple_title )1189 title = "<span>%s</span>" % simple_title
1130 else:1190 else:
1131 title = "<span>%s (%s)</span>" % (simple_title , count )1191 title = "<span>%s (%s)</span>" % (simple_title, count)
1132 else:1192 else:
1133 title = simple_title 1193 title = simple_title
1134 return title1194 return title
11351195
1136 #If a Task editor is already opened for a given task, we present it1196 def open_task(self, uid):
1137 #Else, we create a new one.1197 """Open the task identified by 'uid'.
1138 def open_task(self,uid) :1198
1199 If a Task editor is already opened for a given task, we present it.
1200 Else, we create a new one.
1201 """
1139 t = self.req.get_task(uid)1202 t = self.req.get_task(uid)
1140 if self.opened_task.has_key(uid) :1203 if uid in self.opened_task:
1141 self.opened_task[uid].present()1204 self.opened_task[uid].present()
1142 else :1205 else:
1143 tv = TaskEditor(self.req,t,self.do_refresh,self.on_delete_task,1206 tv = TaskEditor(
1144 self.close_task,self.open_task,self.get_tasktitle,1207 self.req, t, self.do_refresh, self.on_delete_task,
1145 notes=self.notes)1208 self.close_task, self.open_task, self.get_tasktitle,
1209 notes=self.notes)
1146 #registering as opened1210 #registering as opened
1147 self.opened_task[uid] = tv1211 self.opened_task[uid] = tv
1148 1212
1149 def get_tasktitle(self,tid) :1213 def get_tasktitle(self, tid):
1150 task = self.req.get_task(tid)1214 task = self.req.get_task(tid)
1151 return task.get_title()1215 return task.get_title()
1152 1216
1153 #When an editor is closed, it should deregister itself1217 def close_task(self, tid):
1154 def close_task(self,tid) :1218 # When an editor is closed, it should deregister itself.
1155 if self.opened_task.has_key(tid) :1219 if tid in self.opened_task:
1156 del self.opened_task[tid]1220 del self.opened_task[tid]
11571221
1158 def on_tag_treeview_button_press_event(self,treeview,event) :1222 def on_tag_treeview_button_press_event(self, treeview, event):
1159 if event.button == 3:1223 if event.button == 3:
1160 x = int(event.x)1224 x = int(event.x)
1161 y = int(event.y)1225 y = int(event.y)
@@ -1174,8 +1238,8 @@
1174 selected_tag = selected_tags[0]1238 selected_tag = selected_tags[0]
1175 nonworkview = selected_tag.get_attribute("nonworkview")1239 nonworkview = selected_tag.get_attribute("nonworkview")
1176 # We must invert because the tagstore has "True" for tasks1240 # We must invert because the tagstore has "True" for tasks
1177 # that are *not* in workview, and the checkbox is set if the1241 # that are *not* in workview, and the checkbox is set if
1178 # tag *is* shown in the workview.1242 # the tag *is* shown in the workview.
1179 if nonworkview == "True":1243 if nonworkview == "True":
1180 shown = False1244 shown = False
1181 else:1245 else:
@@ -1184,178 +1248,180 @@
1184 self.tagpopup.popup(None, None, None, event.button, time)1248 self.tagpopup.popup(None, None, None, event.button, time)
1185 return 11249 return 1
11861250
1187 def on_nonworkviewtag_toggled(self,widget) : #pylint: disable-msg=W06131251 def on_nonworkviewtag_toggled(self, widget): #pylint: disable-msg=W0613
1188 tags = self.get_selected_tags()[0]1252 tags = self.get_selected_tags()[0]
1189 nonworkview_item = self.tagpopup.get_children()[1]1253 nonworkview_item = self.tagpopup.get_children()[1]
1190 #We must inverse because the tagstore has True1254 #We must inverse because the tagstore has True
1191 #for tasks that are not in workview (and also convert to string)1255 #for tasks that are not in workview (and also convert to string)
1192 toset = str(not nonworkview_item.get_active())1256 toset = str(not nonworkview_item.get_active())
1193 if len(tags) > 0 :1257 if len(tags) > 0:
1194 tags[0].set_attribute("nonworkview",toset)1258 tags[0].set_attribute("nonworkview", toset)
1195 self.do_refresh()1259 self.do_refresh()
11961260
1197 def on_task_treeview_button_press_event(self,treeview,event) :1261 def on_task_treeview_button_press_event(self, treeview, event):
1198 if event.button == 3:1262 if event.button == 3:
1199 x = int(event.x)1263 x = int(event.x)
1200 y = int(event.y)1264 y = int(event.y)
1201 time = event.time1265 time = event.time
1202 pthinfo = treeview.get_path_at_pos(x, y)1266 pthinfo = treeview.get_path_at_pos(x, y)
1203 if pthinfo is not None:1267 if pthinfo is not None:
1204 path, col, cellx, celly = pthinfo #pylint: disable-msg=W06121268 path, col, cellx, celly = pthinfo #pylint: disable-msg=W0612
1205 treeview.grab_focus()1269 treeview.grab_focus()
1206 treeview.set_cursor( path, col, 0)1270 treeview.set_cursor(path, col, 0)
1207 self.taskpopup.popup( None, None, None, event.button, time)1271 self.taskpopup.popup(None, None, None, event.button, time)
1208 return 11272 return 1
12091273
1210 def on_task_treeview_key_press_event(self,treeview,event) :1274 def on_task_treeview_key_press_event(self, treeview, event):
1211 if gtk.gdk.keyval_name(event.keyval) == "Delete":1275 if gtk.gdk.keyval_name(event.keyval) == "Delete":
1212 self.on_delete_task()1276 self.on_delete_task()
12131277
1214 def on_closed_task_treeview_button_press_event(self,treeview,event) :1278 def on_closed_task_treeview_button_press_event(self, treeview, event):
1215 if event.button == 3:1279 if event.button == 3:
1216 x = int(event.x)1280 x = int(event.x)
1217 y = int(event.y)1281 y = int(event.y)
1218 time = event.time1282 time = event.time
1219 pthinfo = treeview.get_path_at_pos(x, y)1283 pthinfo = treeview.get_path_at_pos(x, y)
1220 if pthinfo is not None:1284 if pthinfo is not None:
1221 path, col, cellx, celly = pthinfo #pylint: disable-msg=W06121285 path, col, cellx, celly = pthinfo #pylint: disable-msg=W0612
1222 treeview.grab_focus()1286 treeview.grab_focus()
1223 treeview.set_cursor( path, col, 0)1287 treeview.set_cursor(path, col, 0)
1224 self.closedtaskpopup.popup( None, None, None, event.button, time)1288 self.closedtaskpopup.popup(
1225 return 11289 None, None, None, event.button, time)
1226 1290 return 1
1227 def on_closed_task_treeview_key_press_event(self,treeview,event) :1291
1228 if gtk.gdk.keyval_name(event.keyval) == "Delete":1292 def on_closed_task_treeview_key_press_event(self, treeview, event):
1229 self.on_delete_task()1293 if gtk.gdk.keyval_name(event.keyval) == "Delete":
12301294 self.on_delete_task()
1231 def on_add_task(self,widget,status=None) : #pylint: disable-msg=W06131295
1232 tags,notagonly = self.get_selected_tags() #pylint: disable-msg=W06121296 def on_add_task(self, widget, status=None): #pylint: disable-msg=W0613
1233 task = self.req.new_task(tags=tags,newtask=True)1297 tags, notagonly = self.get_selected_tags() #pylint: disable-msg=W0612
1298 task = self.req.new_task(tags=tags, newtask=True)
1234 uid = task.get_id()1299 uid = task.get_id()
1235 if status :1300 if status:
1236 task.set_status(status)1301 task.set_status(status)
1237 self.open_task(uid)1302 self.open_task(uid)
12381303
1239 def on_add_subtask(self,widget) : #pylint: disable-msg=W06131304 def on_add_subtask(self, widget): #pylint: disable-msg=W0613
1240 uid = self.get_selected_task()1305 uid = self.get_selected_task()
1241 if uid :1306 if uid:
1242 zetask = self.req.get_task(uid) 1307 zetask = self.req.get_task(uid)
1243 tags = zetask.get_tags()1308 tags = zetask.get_tags()
1244 task = self.req.new_task(tags=tags,newtask=True)1309 task = self.req.new_task(tags=tags, newtask=True)
1245 task.add_parent(uid)1310 task.add_parent(uid)
1246 zetask.add_subtask(task.get_id())1311 zetask.add_subtask(task.get_id())
1247 self.open_task(task.get_id())1312 self.open_task(task.get_id())
1248 self.do_refresh()1313 self.do_refresh()
1249 1314
1250 #Get_selected_task returns the uid :1315 def get_selected_task(self, tv=None):
1251 # uid (example : '21@1')1316 """Return the 'uid' of the selected task
1252 #By default, we select in the task_tview1317
1253 def get_selected_task(self,tv=None) :1318 :param tv: The tree view to find the selected task in. Defaults to
1319 the task_tview.
1320 """
1254 uid = None1321 uid = None
1255 if not tv : 1322 if not tv:
1256 tview = self.task_tview1323 tview = self.task_tview
1257 else : 1324 else:
1258 tview = tv1325 tview = tv
1259 # Get the selection in the gtk.TreeView1326 # Get the selection in the gtk.TreeView
1260 selection = tview.get_selection()1327 selection = tview.get_selection()
1261 #If we don't have anything and no tview specified1328 #If we don't have anything and no tview specified
1262 #Let's have a look in the closed task view1329 #Let's have a look in the closed task view
1263 if selection and selection.count_selected_rows() <= 0 and not tv :1330 if selection and selection.count_selected_rows() <= 0 and not tv:
1264 tview = self.taskdone_tview1331 tview = self.taskdone_tview
1265 selection = tview.get_selection()1332 selection = tview.get_selection()
1266 #Then in the notes pane1333 #Then in the notes pane
1267 if selection and selection.count_selected_rows() <= 0 and not tv :1334 if selection and selection.count_selected_rows() <= 0 and not tv:
1268 tview = self.note_tview1335 tview = self.note_tview
1269 selection = tview.get_selection()1336 selection = tview.get_selection()
1270 # Get the selection iter1337 # Get the selection iter
1271 if selection :1338 if selection:
1272 model, selection_iter = selection.get_selected() #pylint: disable-msg=W06121339 model, selection_iter = selection.get_selected()
1273 if selection_iter :1340 if selection_iter:
1274 ts = tview.get_model()1341 ts = tview.get_model()
1275 uid = ts.get_value(selection_iter, 0)1342 uid = ts.get_value(selection_iter, 0)
1276 return uid1343 return uid
12771344
1278 def get_selected_tags(self) :1345 def get_selected_tags(self):
1279 t_selected = self.tag_tview.get_selection()1346 t_selected = self.tag_tview.get_selection()
1280 t_iter = None1347 t_iter = None
1281 if t_selected :1348 if t_selected:
1282 tmodel, t_iter = t_selected.get_selected() #pylint: disable-msg=W06121349 tmodel, t_iter = t_selected.get_selected()
1283 notag_only = False1350 notag_only = False
1284 tag = []1351 tag = []
1285 if t_iter :1352 if t_iter:
1286 selected = self.tag_ts.get_value(t_iter, 0)1353 selected = self.tag_ts.get_value(t_iter, 0)
1287 special = selected.get_attribute("special")1354 special = selected.get_attribute("special")
1288 if special == "all" : 1355 if special == "all":
1289 tag = []1356 tag = []
1290 selected = None1357 selected = None
1291 #notag means we want to display only tasks without any tag1358 #notag means we want to display only tasks without any tag
1292 if special == "notag" :1359 if special == "notag":
1293 notag_only = True1360 notag_only = True
1294 if not notag_only and selected :1361 if not notag_only and selected:
1295 tag.append(selected)1362 tag.append(selected)
1296 #If no selection, we display all1363 #If no selection, we display all
1297 return tag,notag_only1364 return tag, notag_only
1298 1365
1299 ###################1366 def row_dragndrop(self, tree, path, it, data=None):
1300 #Drag-drop support#1367 """Drag and drop support."""
1301 ###################1368 #Because of bug in pygtk, the rows-reordered signal is never emitted
1302 #Because of bug in pygtk, the rows-reordered signal is never emitted1369 #We workaoround this bug by connecting to row_insert and row_deleted
1303 #We workaoround this bug by connecting to row_insert and row_deleted1370 #Basically, we do the following:
1304 #Basically, we do the following :1371 # 1. If a row is inserted for a task X, look if the task already
1305 # 1. If a row is inserted for a task X, look if the task already1372 # exist elsewhere.
1306 # exist elsewhere.1373 # 2. If yes, it's probably a drag-n-drop so we save those information
1307 # 2. If yes, it's probably a drag-n-drop so we save those information1374 # 3. If the "elsewhere" from point 1 is deleted, we are sure it's a
1308 # 3. If the "elsewhere" from point 1 is deleted, we are sure it's a 1375 # drag-n-drop so we change the parent of the moved task
1309 # drag-n-drop so we change the parent of the moved task1376 if data == "insert":
1310 def row_dragndrop(self,tree, path, it,data=None) : #pylint: disable-msg=W0613
1311 if data == "insert" :
1312 #If the row inserted already exists in another position1377 #If the row inserted already exists in another position
1313 #We are in a drag n drop case1378 #We are in a drag n drop case
1314 def findsource(model, path, it,data):1379
1380 def findsource(model, path, it, data):
1315 path_move = tree.get_path(data[1])1381 path_move = tree.get_path(data[1])
1316 path_actual = tree.get_path(it)1382 path_actual = tree.get_path(it)
1317 if model.get(it,0) == data[0] and path_move != path_actual:1383 if model.get(it, 0) == data[0] and path_move != path_actual:
1318 self.drag_sources.append(path)1384 self.drag_sources.append(path)
1319 self.path_source = path1385 self.path_source = path
1320 return True1386 return True
1321 else :1387 else:
1322 self.path_source = None1388 self.path_source = None
13231389
1324 self.path_target = path1390 self.path_target = path
1325 tid = tree.get(it,0)1391 tid = tree.get(it, 0)
1326 tree.foreach(findsource,[tid,it])1392 tree.foreach(findsource, [tid, it])
1327 if self.path_source :1393 if self.path_source:
1328 #We will prepare the drag-n-drop1394 #We will prepare the drag-n-drop
1329 iter_source = tree.get_iter(self.path_source)1395 iter_source = tree.get_iter(self.path_source)
1330 iter_target = tree.get_iter(self.path_target)1396 iter_target = tree.get_iter(self.path_target)
1331 iter_source_parent = tree.iter_parent(iter_source)1397 iter_source_parent = tree.iter_parent(iter_source)
1332 iter_target_parent = tree.iter_parent(iter_target)1398 iter_target_parent = tree.iter_parent(iter_target)
1333 #the tid_parent will be None for root tasks1399 #the tid_parent will be None for root tasks
1334 if iter_source_parent :1400 if iter_source_parent:
1335 sparent = tree.get(iter_source_parent,0)[0]1401 sparent = tree.get(iter_source_parent, 0)[0]
1336 else :1402 else:
1337 sparent = None1403 sparent = None
1338 if iter_target_parent :1404 if iter_target_parent:
1339 tparent = tree.get(iter_target_parent,0)[0]1405 tparent = tree.get(iter_target_parent, 0)[0]
1340 else :1406 else:
1341 tparent = None1407 tparent = None
1342 #If target and source are the same, we are moving1408 #If target and source are the same, we are moving
1343 #a child of the deplaced task. Indeed, children are 1409 #a child of the deplaced task. Indeed, children are
1344 #also moved in the tree but their parents remain !1410 #also moved in the tree but their parents remain !
1345 if sparent != tparent :1411 if sparent != tparent:
1346 self.tid_source_parent = sparent1412 self.tid_source_parent = sparent
1347 self.tid_target_parent = tparent1413 self.tid_target_parent = tparent
1348 self.tid_tomove = tid[0]1414 self.tid_tomove = tid[0]
1349 # "row %s will move from %s to %s"%(self.tid_tomove,\1415 # "row %s will move from %s to %s"%(self.tid_tomove,\
1350 # self.tid_source_parent,self.tid_target_parent)1416 # self.tid_source_parent, self.tid_target_parent)
1351# def row_deleted(self,tree,path,data=None) : #pylint: disable-msg=W06131417# def row_deleted(self, tree, path, data=None): #pylint: disable-msg=W0613
1352 elif data == "delete" :1418 elif data == "delete":
1353 #If we are removing the path source guessed during the insertion1419 #If we are removing the path source guessed during the insertion
1354 #It confirms that we are in a drag-n-drop1420 #It confirms that we are in a drag-n-drop
1355 if path in self.drag_sources and self.tid_tomove :1421 if path in self.drag_sources and self.tid_tomove:
1356 self.drag_sources.remove(path)1422 self.drag_sources.remove(path)
1357 # "row %s moved from %s to %s"%(self.tid_tomove,\1423 # "row %s moved from %s to %s"%(self.tid_tomove,\
1358 # self.tid_source_parent,self.tid_target_parent)1424 # self.tid_source_parent, self.tid_target_parent)
1359 tomove = self.req.get_task(self.tid_tomove)1425 tomove = self.req.get_task(self.tid_tomove)
1360 tomove.set_to_keep()1426 tomove.set_to_keep()
1361 tomove.remove_parent(self.tid_source_parent)1427 tomove.remove_parent(self.tid_source_parent)
@@ -1368,70 +1434,67 @@
1368 self.tid_tomove = None1434 self.tid_tomove = None
1369 self.tid_source_parent = None1435 self.tid_source_parent = None
1370 self.tid_target_parent = None1436 self.tid_target_parent = None
1371 1437
1372 ###############################1438 def on_edit_active_task(self, widget, row=None, col=None):
1373 ##### End of the drag-n-drop part
1374 ###############################
1375
1376
1377 def on_edit_active_task(self,widget,row=None ,col=None) : #pylint: disable-msg=W0613
1378 tid = self.get_selected_task()1439 tid = self.get_selected_task()
1379 if tid :1440 if tid:
1380 self.open_task(tid)1441 self.open_task(tid)
1381 def on_edit_done_task(self,widget,row=None ,col=None) : #pylint: disable-msg=W06131442
1443 def on_edit_done_task(self, widget, row=None, col=None):
1382 tid = self.get_selected_task(self.taskdone_tview)1444 tid = self.get_selected_task(self.taskdone_tview)
1383 if tid :1445 if tid:
1384 self.open_task(tid)1446 self.open_task(tid)
1385 def on_edit_note(self,widget,row=None,col=None) : #pylint: disable-msg=W06131447
1448 def on_edit_note(self, widget, row=None, col=None):
1386 tid = self.get_selected_task(self.note_tview)1449 tid = self.get_selected_task(self.note_tview)
1387 if tid :1450 if tid:
1388 self.open_task(tid)1451 self.open_task(tid)
1389 1452
1390 #if we pass a tid as a parameter, we delete directly1453 def on_delete_confirm(self, widget):
1391 #otherwise, we will look which tid is selected
1392 def on_delete_confirm(self,widget) : #pylint: disable-msg=W0613
1393 self.req.delete_task(self.tid_todelete)1454 self.req.delete_task(self.tid_todelete)
1394 self.tid_todelete = None1455 self.tid_todelete = None
1395 self.do_refresh()1456 self.do_refresh()
1396 1457
1397 def on_delete_task(self,widget=None,tid=None) : #pylint: disable-msg=W06131458 def on_delete_task(self, widget=None, tid=None): #pylint: disable-msg=W0613
1398 #If we don't have a parameter, then take the selection in the treeview1459 #If we don't have a parameter, then take the selection in the treeview
1399 if not tid :1460 if not tid:
1400 #tid_to_delete is a [project,task] tuple1461 #tid_to_delete is a [project, task] tuple
1401 self.tid_todelete = self.get_selected_task()1462 self.tid_todelete = self.get_selected_task()
1402 else :1463 else:
1403 self.tid_todelete = tid1464 self.tid_todelete = tid
1404 #We must at least have something to delete !1465 #We must at least have something to delete !
1405 if self.tid_todelete :1466 if self.tid_todelete:
1406 delete_dialog = self.wTree.get_widget("confirm_delete")1467 delete_dialog = self.wTree.get_widget("confirm_delete")
1407 delete_dialog.run()1468 delete_dialog.run()
1408 delete_dialog.hide()1469 delete_dialog.hide()
1409 #has the task been deleted ?1470 #has the task been deleted ?
1410 return not self.tid_todelete1471 return not self.tid_todelete
1411 else :1472 else:
1412 return False1473 return False
1413 1474
1414 def on_mark_as_done(self,widget) : #pylint: disable-msg=W06131475 def on_mark_as_done(self, widget): #pylint: disable-msg=W0613
1415 uid = self.get_selected_task()1476 uid = self.get_selected_task()
1416 if uid :1477 if uid:
1417 zetask = self.req.get_task(uid)1478 zetask = self.req.get_task(uid)
1418 status = zetask.get_status() 1479 status = zetask.get_status()
1419 if status == "Done" :1480 if status == "Done":
1420 zetask.set_status("Active")1481 zetask.set_status("Active")
1421 else : zetask.set_status("Done")1482 else:
1422 self.do_refresh()1483 zetask.set_status("Done")
1423 1484 self.do_refresh()
1424 def on_dismiss_task(self,widget) : #pylint: disable-msg=W06131485
1425 uid = self.get_selected_task()1486 def on_dismiss_task(self, widget): #pylint: disable-msg=W0613
1426 if uid :1487 uid = self.get_selected_task()
1427 zetask = self.req.get_task(uid)1488 if uid:
1428 status = zetask.get_status() 1489 zetask = self.req.get_task(uid)
1429 if status == "Dismiss" :1490 status = zetask.get_status()
1430 zetask.set_status("Active")1491 if status == "Dismiss":
1431 else : zetask.set_status("Dismiss")1492 zetask.set_status("Active")
1432 self.do_refresh()1493 else:
1433 1494 zetask.set_status("Dismiss")
1434 def on_select_tag(self, widget, row=None ,col=None) : #pylint: disable-msg=W06131495 self.do_refresh()
1496
1497 def on_select_tag(self, widget, row=None, col=None):
1435 #When you clic on a tag, you want to unselect the tasks1498 #When you clic on a tag, you want to unselect the tasks
1436 self.task_tview.get_selection().unselect_all()1499 self.task_tview.get_selection().unselect_all()
1437 self.taskdone_tview.get_selection().unselect_all()1500 self.taskdone_tview.get_selection().unselect_all()
@@ -1441,56 +1504,64 @@
1441 ##### Useful tools##################1504 ##### Useful tools##################
14421505
1443 def __create_tags_tview(self):1506 def __create_tags_tview(self):
1444 1507
1445 # Tag column1508 # Tag column
1446 tag_col = gtk.TreeViewColumn()1509 tag_col = gtk.TreeViewColumn()
1447 render_text = gtk.CellRendererText()1510 render_text = gtk.CellRendererText()
1448 render_count = gtk.CellRendererText()1511 render_count = gtk.CellRendererText()
1449 render_tags = CellRendererTags()1512 render_tags = CellRendererTags()
1450 tag_col.set_title ("Tags")1513 tag_col.set_title("Tags")
1451 tag_col.set_clickable (False)1514 tag_col.set_clickable(False)
1452 tag_col.pack_start (render_tags , expand=False)1515 tag_col.pack_start(render_tags, expand=False)
1453 tag_col.set_attributes (render_tags , tag=self.TAGS_MODEL_OBJ)1516 tag_col.set_attributes(render_tags, tag=self.TAGS_MODEL_OBJ)
1454 tag_col.pack_start (render_text , expand=True)1517 tag_col.pack_start(render_text, expand=True)
1455 tag_col.set_attributes (render_text , markup=self.TAGS_MODEL_NAME)1518 tag_col.set_attributes(render_text, markup=self.TAGS_MODEL_NAME)
1456 tag_col.pack_end (render_count , expand=False)1519 tag_col.pack_end(render_count, expand=False)
1457 tag_col.set_attributes (render_count , markup=self.TAGS_MODEL_COUNT)1520 tag_col.set_attributes(render_count, markup=self.TAGS_MODEL_COUNT)
1458 render_count.set_property ("foreground","#888a85")1521 render_count.set_property("foreground", "#888a85")
1459 render_count.set_property ('xalign', 1.0)1522 render_count.set_property('xalign', 1.0)
1460 render_tags.set_property ('ypad' , 3)1523 render_tags.set_property('ypad', 3)
1461 render_text.set_property ('ypad' , 3)1524 render_text.set_property('ypad', 3)
1462 render_count.set_property ('xpad' , 3)1525 render_count.set_property('xpad', 3)
1463 render_count.set_property ('ypad' , 3)1526 render_count.set_property('ypad', 3)
1464 tag_col.set_sort_column_id (-1)1527 tag_col.set_sort_column_id(-1)
1465 tag_col.set_expand (True)1528 tag_col.set_expand(True)
1466 self.tag_tview.append_column (tag_col)1529 self.tag_tview.append_column(tag_col)
1467 # Global treeview properties1530 # Global treeview properties
1468 self.tag_tview.set_row_separator_func (self.tag_separator_filter)1531 self.tag_tview.set_row_separator_func(self.tag_separator_filter)
1469 self.tag_tview.set_headers_visible (False)1532 self.tag_tview.set_headers_visible(False)
14701533
1471 def cmp_duedate_str(self, key1, key2):1534 def cmp_duedate_str(self, key1, key2):
1472 if self.priv["tasklist"]["sort_order"] == gtk.SORT_ASCENDING:1535 if self.priv["tasklist"]["sort_order"] == gtk.SORT_ASCENDING:
1473 if key1 == "" and key2 == "" : return 01536 if key1 == "" and key2 == "":
1474 elif key1 == "" and key2 != "" : return -11537 return 0
1475 elif key1 != "" and key2 == "" : return 11538 elif key1 == "" and key2 != "":
1476 else : return cmp(key1,key2)1539 return -1
1540 elif key1 != "" and key2 == "":
1541 return 1
1542 else:
1543 return cmp(key1, key2)
1477 else:1544 else:
1478 if key1 == "" and key2 == "" : return 01545 if key1 == "" and key2 == "":
1479 elif key1 == "" and key2 != "" : return 11546 return 0
1480 elif key1 != "" and key2 == "" : return -11547 elif key1 == "" and key2 != "":
1481 else : return cmp(key1,key2)1548 return 1
1482 1549 elif key1 != "" and key2 == "":
1483 def sort_tasklist_rows(self, column, sort_order=None): 1550 return -1
1551 else:
1552 return cmp(key1, key2)
1553
1554 def sort_tasklist_rows(self, column, sort_order=None):
1484 """ Sort the rows based on the given column """1555 """ Sort the rows based on the given column """
1485 1556
1486 # Extract sorting state1557 # Extract sorting state
1487 last_sort_col = self.priv["tasklist"]["sort_column"]1558 last_sort_col = self.priv["tasklist"]["sort_column"]
1488 last_sort_order = self.priv["tasklist"]["sort_order"]1559 last_sort_order = self.priv["tasklist"]["sort_order"]
1489 1560
1490 # Cleanup1561 # Cleanup
1491 if last_sort_col is not None:1562 if last_sort_col is not None:
1492 last_sort_col.set_sort_indicator(False)1563 last_sort_col.set_sort_indicator(False)
1493 1564
1494 # Ascending or descending?1565 # Ascending or descending?
1495 if sort_order is None:1566 if sort_order is None:
1496 if last_sort_col == column:1567 if last_sort_col == column:
@@ -1503,101 +1574,112 @@
15031574
1504 # Store sorting state1575 # Store sorting state
1505 self.priv["tasklist"]["sort_column"] = column1576 self.priv["tasklist"]["sort_column"] = column
1506 self.priv["tasklist"]["sort_order"] = sort_order1577 self.priv["tasklist"]["sort_order"] = sort_order
15071578
1508 # Determine row sorting depending on column1579 # Determine row sorting depending on column
1509 if column == self.priv["tasklist"]["columns"][self.TASKLIST_COL_TITLE]:1580 if column == self.priv["tasklist"]["columns"][self.TASKLIST_COL_TITLE]:
1510 cmp_func = lambda x,y: locale.strcoll(x.lower(),y.lower())1581 cmp_func = lambda x, y: locale.strcoll(x.lower(), y.lower())
1511 sort_key = lambda x:x[self.TASK_MODEL_TITLE]1582 sort_key = lambda x: x[self.TASK_MODEL_TITLE]
1512 else:1583 else:
1513 cmp_func = self.cmp_duedate_str1584 cmp_func = self.cmp_duedate_str
1514 sort_key = lambda x:x[self.TASK_MODEL_DDATE_STR]1585 sort_key = lambda x: x[self.TASK_MODEL_DDATE_STR]
1515 1586
1516 # Determine sorting direction1587 # Determine sorting direction
1517 if sort_order == gtk.SORT_ASCENDING: sort_reverse = True1588 if sort_order == gtk.SORT_ASCENDING:
1518 else : sort_reverse = False1589 sort_reverse = True
1590 else:
1591 sort_reverse = False
15191592
1520 # Sort rows1593 # Sort rows
1521 rows = [tuple(r) + (i,) for i, r in enumerate(self.task_ts)]1594 rows = [tuple(r) + (i,) for i, r in enumerate(self.task_ts)]
1522 if len(rows) != 0:1595 if len(rows) != 0:
1523 rows.sort(key=lambda x:x[self.TASK_MODEL_TITLE].lower())1596 rows.sort(key=lambda x: x[self.TASK_MODEL_TITLE].lower())
1524 rows.sort(cmp=cmp_func,key=sort_key,reverse=sort_reverse)1597 rows.sort(cmp=cmp_func, key=sort_key, reverse=sort_reverse)
1525 self.task_ts.reorder(None, [r[-1] for r in rows])1598 self.task_ts.reorder(None, [r[-1] for r in rows])
1526 1599
1527 # Display the sort indicator1600 # Display the sort indicator
1528 column.set_sort_indicator(True)1601 column.set_sort_indicator(True)
1529 column.set_sort_order(sort_order)1602 column.set_sort_order(sort_order)
15301603
1531 def __create_task_tview(self):1604 def __create_task_tview(self):
1532 1605
1533 self.priv["tasklist"]["columns"] = []1606 self.priv["tasklist"]["columns"] = []
1534 1607
1535 # Tag column1608 # Tag column
1536 self.TASKLIST_COL_TAGS = 01609 self.TASKLIST_COL_TAGS = 0
1537 tag_col = gtk.TreeViewColumn()1610 tag_col = gtk.TreeViewColumn()
1538 render_tags = CellRendererTags()1611 render_tags = CellRendererTags()
1539 tag_col.set_title (_("Tags"))1612 tag_col.set_title(_("Tags"))
1540 tag_col.pack_start (render_tags, expand=False)1613 tag_col.pack_start(render_tags, expand=False)
1541 tag_col.add_attribute (render_tags, "tag_list", self.TASK_MODEL_TAGS)1614 tag_col.add_attribute(render_tags, "tag_list", self.TASK_MODEL_TAGS)
1542 render_tags.set_property ('xalign', 0.0)1615 render_tags.set_property('xalign', 0.0)
1543 tag_col.set_resizable (False)1616 tag_col.set_resizable(False)
1544 tag_col.add_attribute (render_tags, "cell-background", self.TASK_MODEL_BGCOL)1617 tag_col.add_attribute(
1545 #tag_col.set_clickable (True)1618 render_tags, "cell-background", self.TASK_MODEL_BGCOL)
1546 #tag_col.connect ('clicked', self.sort_tasklist_rows)1619 self.task_tview.append_column(tag_col)
1547 self.task_tview.append_column (tag_col)1620 self.priv["tasklist"]["columns"].insert(
1548 self.priv["tasklist"]["columns"].insert(self.TASKLIST_COL_TAGS, tag_col)1621 self.TASKLIST_COL_TAGS, tag_col)
1549 1622
1550 # Title column1623 # Title column
1551 self.TASKLIST_COL_TITLE = 11624 self.TASKLIST_COL_TITLE = 1
1552 title_col = gtk.TreeViewColumn()1625 title_col = gtk.TreeViewColumn()
1553 render_text = gtk.CellRendererText()1626 render_text = gtk.CellRendererText()
1554 title_col.set_title (_("Title"))1627 title_col.set_title(_("Title"))
1555 title_col.pack_start (render_text, expand=False)1628 title_col.pack_start(render_text, expand=False)
1556 title_col.add_attribute (render_text, "markup", self.TASK_MODEL_TITLE_STR)1629 title_col.add_attribute(
1557 title_col.set_resizable (True)1630 render_text, "markup", self.TASK_MODEL_TITLE_STR)
1558 title_col.set_expand (True)1631 title_col.set_resizable(True)
1632 title_col.set_expand(True)
1559 #The following line seems to fix bug #3174691633 #The following line seems to fix bug #317469
1560 #I don't understand why !!! It's voodoo !1634 #I don't understand why !!! It's voodoo !
1561 #Is there a Rubber Chicken With a Pulley in the Middle ?1635 #Is there a Rubber Chicken With a Pulley in the Middle ?
1562 title_col.set_max_width (100)1636 title_col.set_max_width(100)
1563 title_col.add_attribute (render_text, "cell_background", self.TASK_MODEL_BGCOL)1637 title_col.add_attribute(
1564 title_col.set_clickable (True)1638 render_text, "cell_background", self.TASK_MODEL_BGCOL)
1565 title_col.connect ('clicked', self.sort_tasklist_rows)1639 title_col.set_clickable(True)
1566 self.task_tview.append_column (title_col)1640 title_col.connect('clicked', self.sort_tasklist_rows)
1567 self.priv["tasklist"]["columns"].insert(self.TASKLIST_COL_TITLE, title_col)1641 self.task_tview.append_column(title_col)
1568 1642 self.priv["tasklist"]["columns"].insert(
1643 self.TASKLIST_COL_TITLE, title_col)
1644
1569 # Due date column1645 # Due date column
1570 self.TASKLIST_COL_DDATE = 21646 self.TASKLIST_COL_DDATE = 2
1571 ddate_col = gtk.TreeViewColumn()1647 ddate_col = gtk.TreeViewColumn()
1572 render_text = gtk.CellRendererText()1648 render_text = gtk.CellRendererText()
1573 ddate_col.set_title (_("Due date"))1649 ddate_col.set_title(_("Due date"))
1574 ddate_col.pack_start (render_text, expand=False)1650 ddate_col.pack_start(render_text, expand=False)
1575 ddate_col.add_attribute (render_text, "markup", self.TASK_MODEL_DDATE_STR)1651 ddate_col.add_attribute(
1576 ddate_col.set_resizable (False)1652 render_text, "markup", self.TASK_MODEL_DDATE_STR)
1577 ddate_col.add_attribute (render_text, "cell_background", self.TASK_MODEL_BGCOL)1653 ddate_col.set_resizable(False)
1578 ddate_col.set_clickable (True)1654 ddate_col.add_attribute(
1579 ddate_col.connect ('clicked', self.sort_tasklist_rows)1655 render_text, "cell_background", self.TASK_MODEL_BGCOL)
1580 self.task_tview.append_column (ddate_col)1656 ddate_col.set_clickable(True)
1581 self.priv["tasklist"]["columns"].insert(self.TASKLIST_COL_DDATE, ddate_col)1657 ddate_col.connect('clicked', self.sort_tasklist_rows)
1582 1658 self.task_tview.append_column(ddate_col)
1659 self.priv["tasklist"]["columns"].insert(
1660 self.TASKLIST_COL_DDATE, ddate_col)
1661
1583 # days left1662 # days left
1584 self.TASKLIST_COL_DLEFT = 31663 self.TASKLIST_COL_DLEFT = 3
1585 dleft_col = gtk.TreeViewColumn()1664 dleft_col = gtk.TreeViewColumn()
1586 render_text = gtk.CellRendererText()1665 render_text = gtk.CellRendererText()
1587 dleft_col.set_title (_("Days left"))1666 dleft_col.set_title(_("Days left"))
1588 dleft_col.pack_start (render_text, expand=False)1667 dleft_col.pack_start(render_text, expand=False)
1589 dleft_col.add_attribute (render_text, "markup", self.TASK_MODEL_DLEFT_STR)1668 dleft_col.add_attribute(
1590 dleft_col.set_resizable (False)1669 render_text, "markup", self.TASK_MODEL_DLEFT_STR)
1591 dleft_col.add_attribute (render_text, "cell_background", self.TASK_MODEL_BGCOL)1670 dleft_col.set_resizable(False)
1592 dleft_col.set_clickable (True)1671 dleft_col.add_attribute(
1593 dleft_col.connect ('clicked', self.sort_tasklist_rows)1672 render_text, "cell_background", self.TASK_MODEL_BGCOL)
1594 self.task_tview.append_column (dleft_col)1673 dleft_col.set_clickable(True)
1595 self.priv["tasklist"]["columns"].insert(self.TASKLIST_COL_DLEFT, dleft_col)1674 dleft_col.connect('clicked', self.sort_tasklist_rows)
1675 self.task_tview.append_column(dleft_col)
1676 self.priv["tasklist"]["columns"].insert(
1677 self.TASKLIST_COL_DLEFT, dleft_col)
15961678
1597 # Global treeview properties1679 # Global treeview properties
1598 self.task_tview.set_property ("expander-column", title_col)1680 self.task_tview.set_property("expander-column", title_col)
1599 self.task_tview.set_property ("enable-tree-lines", False)1681 self.task_tview.set_property("enable-tree-lines", False)
1600 self.task_tview.set_rules_hint (False)1682 self.task_tview.set_rules_hint(False)
16011683
1602 def __create_closed_tasks_tview(self):1684 def __create_closed_tasks_tview(self):
16031685
@@ -1605,64 +1687,66 @@
16051687
1606 # Tag column1688 # Tag column
1607 self.CTASKLIST_COL_TAGS = 01689 self.CTASKLIST_COL_TAGS = 0
1608 tag_col = gtk.TreeViewColumn()1690 tag_col = gtk.TreeViewColumn()
1609 render_tags = CellRendererTags()1691 render_tags = CellRendererTags()
1610 tag_col.set_title (_("Tags"))1692 tag_col.set_title(_("Tags"))
1611 tag_col.pack_start (render_tags, expand=False)1693 tag_col.pack_start(render_tags, expand=False)
1612 tag_col.add_attribute (render_tags, "tag_list", self.CTASKS_MODEL_TAGS)1694 tag_col.add_attribute(render_tags, "tag_list", self.CTASKS_MODEL_TAGS)
1613 render_tags.set_property ('xalign', 0.0)1695 render_tags.set_property('xalign', 0.0)
1614 tag_col.set_resizable (False)1696 tag_col.set_resizable(False)
1615 tag_col.add_attribute (render_tags, "cell-background", self.CTASKS_MODEL_BGCOL)1697 tag_col.add_attribute(
1616 #tag_col.set_clickable (True)1698 render_tags, "cell-background", self.CTASKS_MODEL_BGCOL)
1617 #tag_col.connect ('clicked', self.sort_tasklist_rows)1699 self.taskdone_tview.append_column(tag_col)
1618 self.taskdone_tview.append_column (tag_col)1700 self.priv["ctasklist"]["columns"].insert(
1619 self.priv["ctasklist"]["columns"].insert(self.CTASKLIST_COL_TAGS, tag_col)1701 self.CTASKLIST_COL_TAGS, tag_col)
1620 1702
1621 # Done date column1703 # Done date column
1622 self.CTASKLIST_COL_DDATE = 11704 self.CTASKLIST_COL_DDATE = 1
1623 ddate_col = gtk.TreeViewColumn()1705 ddate_col = gtk.TreeViewColumn()
1624 render_text = gtk.CellRendererText()1706 render_text = gtk.CellRendererText()
1625 ddate_col.set_title (_("Closing date"))1707 ddate_col.set_title(_("Closing date"))
1626 ddate_col.pack_start (render_text , expand=True)1708 ddate_col.pack_start(render_text, expand=True)
1627 ddate_col.set_attributes (render_text , markup=self.CTASKS_MODEL_DDATE_STR)1709 ddate_col.set_attributes(
1628 ddate_col.set_sort_column_id (self.CTASKS_MODEL_DDATE)1710 render_text, markup=self.CTASKS_MODEL_DDATE_STR)
1629 ddate_col.add_attribute (render_text, "cell_background", self.CTASKS_MODEL_BGCOL)1711 ddate_col.set_sort_column_id(self.CTASKS_MODEL_DDATE)
1630 self.taskdone_tview.append_column (ddate_col)1712 ddate_col.add_attribute(
1631 self.priv["ctasklist"]["columns"].insert(self.CTASKLIST_COL_DDATE, ddate_col)1713 render_text, "cell_background", self.CTASKS_MODEL_BGCOL)
1632 1714 self.taskdone_tview.append_column(ddate_col)
1715 self.priv["ctasklist"]["columns"].insert(
1716 self.CTASKLIST_COL_DDATE, ddate_col)
1717
1633 # Title column1718 # Title column
1634 self.CTASKLIST_COL_TITLE = 21719 self.CTASKLIST_COL_TITLE = 2
1635 title_col = gtk.TreeViewColumn()1720 title_col = gtk.TreeViewColumn()
1636 render_text = gtk.CellRendererText()1721 render_text = gtk.CellRendererText()
1637 title_col.set_title (_("Title"))1722 title_col.set_title(_("Title"))
1638 title_col.pack_start (render_text , expand=True)1723 title_col.pack_start(render_text, expand=True)
1639 title_col.set_attributes (render_text , markup=self.CTASKS_MODEL_TITLE)1724 title_col.set_attributes(render_text, markup=self.CTASKS_MODEL_TITLE)
1640 title_col.set_sort_column_id (self.CTASKS_MODEL_TITLE)1725 title_col.set_sort_column_id(self.CTASKS_MODEL_TITLE)
1641 title_col.set_expand (True)1726 title_col.set_expand(True)
1642 title_col.add_attribute (render_text, "cell_background", self.CTASKS_MODEL_BGCOL)1727 title_col.add_attribute(
1643 self.taskdone_tview.append_column (title_col)1728 render_text, "cell_background", self.CTASKS_MODEL_BGCOL)
1644 self.priv["ctasklist"]["columns"].insert(self.CTASKLIST_COL_TITLE, title_col)1729 self.taskdone_tview.append_column(title_col)
1645 1730 self.priv["ctasklist"]["columns"].insert(
1731 self.CTASKLIST_COL_TITLE, title_col)
1732
1646 # Global treeview properties1733 # Global treeview properties
1647 self.taskdone_ts.set_sort_column_id(self.CTASKS_MODEL_DDATE, gtk.SORT_DESCENDING)1734 self.taskdone_ts.set_sort_column_id(
1648 1735 self.CTASKS_MODEL_DDATE, gtk.SORT_DESCENDING)
1736
1649 def __create_note_tview(self):1737 def __create_note_tview(self):
1650 # Title column1738 # Title column
1651 title_col = gtk.TreeViewColumn()1739 title_col = gtk.TreeViewColumn()
1652 render_text = gtk.CellRendererText()1740 render_text = gtk.CellRendererText()
1653 title_col.set_title (_("Notes"))1741 title_col.set_title(_("Notes"))
1654 title_col.pack_start (render_text , expand=True)1742 title_col.pack_start(render_text, expand=True)
1655 title_col.set_attributes (render_text , markup=self.CTASKS_MODEL_TITLE)1743 title_col.set_attributes(render_text, markup=self.CTASKS_MODEL_TITLE)
1656 title_col.set_sort_column_id (self.CTASKS_MODEL_TITLE)1744 title_col.set_sort_column_id(self.CTASKS_MODEL_TITLE)
1657 title_col.set_expand (True)1745 title_col.set_expand(True)
1658 self.note_tview.append_column (title_col)1746 self.note_tview.append_column(title_col)
16591747
1660 # Global treeview properties1748 def close(self, widget=None):
1661 #self.taskdone_ts.set_sort_column_id(self.CTASKS_MODEL_DDATE, gtk.SORT_DESCENDING)1749 """Closing the window."""
1662
1663
1664 ######Closing the window
1665 def close(self,widget=None) : #pylint: disable-msg=W0613
1666 #Saving is now done in main.py1750 #Saving is now done in main.py
1667 self.on_delete(None, None)1751 self.on_delete(None, None)
1668 gtk.main_quit()1752 gtk.main_quit()

Subscribers

People subscribed via source and target branches

to status/vote changes: