69
72
print "%s : %s" %(self.st,time.time() - self.start)
75
class TaskBrowser(gobject.GObject):
73
76
""" The UI for browsing open and closed tasks, and listing tags in a tree """
78
__string_signal__ = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str, ))
79
__none_signal__ = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, tuple())
80
__gsignals__ = {'task-added-via-quick-add' : __string_signal__, \
81
'visibility-toggled': __none_signal__,
75
84
def __init__(self, requester, vmanager, config):
85
gobject.GObject.__init__(self)
76
86
# Object prime variables
78
88
self.req = requester
331
343
# Connect requester signals to TreeModels
332
344
self.req.connect("task-added", self.on_task_added)
333
345
self.req.connect("task-deleted", self.on_task_deleted)
346
#this causes changed be shouwn only on save
347
#tree = self.task_tree_model.get_tree()
348
#tree.connect("task-added-inview", self.on_task_added)
349
#tree.connect("task-deleted-inview", self.on_task_deleted)
350
b_signals = BackendSignals()
351
b_signals.connect(b_signals.BACKEND_FAILED, self.on_backend_failed)
352
b_signals.connect(b_signals.BACKEND_STATE_TOGGLED, \
353
self.remove_backend_infobar)
354
b_signals.connect(b_signals.INTERACTION_REQUESTED, \
355
self.on_backend_needing_interaction)
336
356
# Selection changes
337
357
self.selection = self.vtree_panes['active'].get_selection()
338
358
self.selection.connect("changed", self.on_task_cursor_changed)
746
768
self.show_closed_pane()
748
770
self.hide_closed_pane()
772
def __create_closed_tree(self):
773
closedtree = self.req.get_tasks_tree(name='closed')
774
closedtree.apply_filter('closed')
750
777
def show_closed_pane(self):
751
# The done/dismissed taks treeview
778
# The done/dismissed tasks treeview
752
779
if not self.vtree_panes.has_key('closed'):
753
closedtree = self.req.get_tasks_tree(name='closed')
754
780
self.vtree_panes['closed'] = \
755
self.tv_factory.closed_tasks_treeview(closedtree)
756
closedtree.apply_filter('closed')
781
self.tv_factory.closed_tasks_treeview(\
782
self.__create_closed_tree())
757
783
# Closed tasks TreeView
758
784
self.vtree_panes['closed'].connect('row-activated',\
759
785
self.on_edit_done_task)
812
838
self.config['browser']["collapsed_tasks"].append(tid)
814
840
def on_quickadd_activate(self, widget):
815
text = self.quickadd_entry.get_text()
841
text = unicode(self.quickadd_entry.get_text())
817
845
tags, notagonly = self.get_selected_tags()
818
846
task = self.req.new_task(newtask=True)
819
847
task.set_complex_title(text,tags=tags)
820
848
self.quickadd_entry.set_text('')
821
for f in self.priv['quick_add_cbs']:
849
gobject.idle_add(self.emit, "task-added-via-quick-add",
824
852
def on_tag_treeview_button_press_event(self, treeview, event):
853
Log.debug("Received button event #%d at %d,%d" %(event.button, event.x, event.y))
825
854
if event.button == 3:
888
917
self.reset_cursor()
890
919
def on_task_treeview_button_press_event(self, treeview, event):
920
"""Pop up context menu on right mouse click in the main task tree view"""
921
Log.debug("Received button event #%d at %d,%d" %(event.button, event.x, event.y))
891
922
if event.button == 3:
894
925
time = event.time
895
926
pthinfo = treeview.get_path_at_pos(x, y)
896
927
if pthinfo is not None:
897
if treeview.get_selection().count_selected_rows() <= 0:
898
path, col, cellx, celly = pthinfo
928
path, col, cellx, celly = pthinfo
929
selection = treeview.get_selection()
930
if selection.count_selected_rows() <= 0:
899
931
treeview.set_cursor(path, col, 0)
933
selection.select_path(path)
900
934
treeview.grab_focus()
901
935
self.taskpopup.popup(None, None, None, event.button, time)
1328
1369
""" Returns true if window is the currently active window """
1329
1370
return self.window.get_property("is-active")
1372
def get_builder(self):
1375
def get_window(self):
1378
def get_active_tree(self):
1380
Returns the browser tree with all the filters applied. The tasks in
1381
the tree are the same as the ones shown in the browser current view
1383
return self.activetree
1385
def get_closed_tree(self):
1387
Returns the browser tree with all the filters applied. The tasks in
1388
the tree are the same as the ones shown in the browser current closed
1391
return self.__create_closed_tree()
1394
return self.browser_shown
1396
## BACKENDS RELATED METHODS ##################################################
1398
def on_backend_failed(self, sender, backend_id, error_code):
1401
When a backend fails to work, loads a gtk.Infobar to alert the user
1403
@param sender: not used, only here for signal compatibility
1404
@param backend_id: the id of the failing backend
1405
@param error_code: a backend error code, as specified in BackendsSignals
1407
infobar = self._new_infobar(backend_id)
1408
infobar.set_error_code(error_code)
1410
def on_backend_needing_interaction(self, sender, backend_id, description, \
1411
interaction_type, callback):
1414
When a backend needs some kind of feedback from the user,
1415
loads a gtk.Infobar to alert the user.
1416
This is used, for example, to request confirmation after authenticating
1419
@param sender: not used, only here for signal compatibility
1420
@param backend_id: the id of the failing backend
1421
@param description: a string describing the interaction needed
1422
@param interaction_type: a string describing the type of interaction
1423
(yes/no, only confirm, ok/cancel...)
1424
@param callback: the function to call when the user provides the
1427
infobar = self._new_infobar(backend_id)
1428
infobar.set_interaction_request(description, interaction_type, callback)
1431
def __remove_backend_infobar(self, child, backend_id):
1433
Helper function to remove an gtk.Infobar related to a backend
1435
@param child: a gtk.Infobar
1436
@param backend_id: the id of the backend which gtk.Infobar should be
1439
if isinstance(child, CustomInfoBar) and\
1440
child.get_backend_id() == backend_id:
1441
if self.vbox_toolbars:
1442
self.vbox_toolbars.remove(child)
1444
def remove_backend_infobar(self, sender, backend_id):
1447
Deletes the gtk.Infobars related to a backend
1449
@param sender: not used, only here for signal compatibility
1450
@param backend_id: the id of the backend which gtk.Infobar should be
1453
backend = self.req.get_backend(backend_id)
1454
if not backend or (backend and backend.is_enabled()):
1455
#remove old infobar related to backend_id, if any
1456
if self.vbox_toolbars:
1457
self.vbox_toolbars.foreach(self.__remove_backend_infobar, \
1460
def _new_infobar(self, backend_id):
1462
Helper function to create a new infobar for a backend
1464
@param backend_id: the backend for which we're creating the infobar
1465
@returns gtk.Infobar: the created infobar
1467
#remove old infobar related to backend_id, if any
1468
if not self.vbox_toolbars:
1470
self.vbox_toolbars.foreach(self.__remove_backend_infobar, backend_id)
1472
infobar = CustomInfoBar(self.req, self, self.vmanager, backend_id)
1473
self.vbox_toolbars.pack_start(infobar, True)