~nmu-sscheel/gtg/rework-task-editor

« back to all changes in this revision

Viewing changes to GTG/gtk/browser/browser.py

  • Committer: Bertrand Rousseau
  • Date: 2012-05-09 22:33:25 UTC
  • mfrom: (1178 trunk)
  • mto: This revision was merged to the branch mainline in revision 1179.
  • Revision ID: bertrand.rousseau@gmail.com-20120509223325-a53d8nwo0x9g93bc
Merge nimit branch and trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 
23
23
#=== IMPORT ===================================================================
24
24
#system imports
25
 
import locale
26
25
import time
27
 
import webbrowser
28
26
import threading
29
 
import unicodedata
 
27
from webbrowser import open as openurl
30
28
 
31
29
import pygtk
32
30
pygtk.require('2.0')
34
32
import gtk
35
33
 
36
34
#our own imports
37
 
import GTG
 
35
from GTG import _, info, ngettext
38
36
from GTG.backends.backendsignals import BackendSignals
 
37
from GTG.core import CoreConfig
 
38
from GTG.core.search import parse_search_query, SEARCH_COMMANDS, InvalidQuery
 
39
from GTG.core.task import Task
 
40
from GTG.gtk.tag_completion import TagCompletion
 
41
from GTG.gtk.browser import GnomeConfig
39
42
from GTG.gtk.browser.custominfobar import CustomInfoBar
40
 
from GTG.core                       import CoreConfig
41
 
from GTG                         import _, info, ngettext
42
 
from GTG.core.task               import Task
43
 
from GTG.gtk.browser             import GnomeConfig
 
43
from GTG.gtk.browser.modifytags_dialog import ModifyTagsDialog
 
44
from GTG.gtk.browser.tag_context_menu import TagContextMenu
44
45
from GTG.gtk.browser.treeview_factory import TreeviewFactory
45
 
from GTG.tools                   import openurl
46
 
from GTG.tools.dates             import Date
47
 
from GTG.tools.logger            import Log
48
 
from GTG.tools.tags              import extract_tags_from_text
49
 
from GTG.core.search             import parse_search_query, search_commands, InvalidQuery
50
 
#FIXME Why is this commented?
51
 
#from GTG.tools                   import clipboard
 
46
from GTG.tools.dates import Date
 
47
from GTG.tools.logger import Log
52
48
 
53
49
#=== MAIN CLASS ===============================================================
54
50
 
55
51
WINDOW_TITLE = "Getting Things GNOME!"
56
 
DOCUMENTATION_URL = "http://live.gnome.org/gtg/documentation"
57
 
 
58
 
#Some default preferences that we should save in a file
59
 
TIME             = 0
60
52
 
61
53
class Timer:
62
 
    def __init__(self,st):
63
 
        self.st = st
64
 
    def __enter__(self): self.start = time.time()
 
54
    def __init__(self, name):
 
55
        self.name = name 
 
56
 
 
57
    def __enter__(self):
 
58
        self.start = time.time()
 
59
 
65
60
    def __exit__(self, *args): 
66
 
        print "%s : %s" %(self.st,time.time() - self.start)
 
61
        print "%s : %s" % (self.name, time.time() - self.start)
67
62
 
68
63
 
69
64
class TaskBrowser(gobject.GObject):
78
73
    def __init__(self, requester, vmanager):
79
74
        gobject.GObject.__init__(self)
80
75
        # Object prime variables
81
 
        self.req    = requester
 
76
        self.req = requester
82
77
        self.vmanager = vmanager
83
78
        self.config = self.req.get_config('browser')
84
79
        self.tag_active = False
85
 
        self.filter_cbs = []
86
80
        
87
81
        #treeviews handlers
88
82
        self.vtree_panes = {}
99
93
 
100
94
        # Set up models
101
95
        # Active Tasks
102
 
        self.activetree.apply_filter('active',refresh=False)
 
96
        self.activetree.apply_filter('active')
103
97
        # Tags
104
98
        self.tagtree = None
105
99
        self.tagtreeview = None
120
114
        # Initialize "About" dialog
121
115
        self._init_about_dialog()
122
116
 
123
 
        # Initialize tag completion
124
 
        self._init_tag_completion()
125
 
 
126
117
        #Create our dictionary and connect it
127
118
        self._init_signal_connections()
128
119
 
132
123
        # Initialize search completion
133
124
        self._init_search_completion()
134
125
 
135
 
        # Rember values from last time
136
 
        self.last_added_tags = "NewTag"
137
 
        self.last_apply_tags_to_subtasks = False
138
 
        
139
126
        self.restore_state_from_conf()
140
127
 
141
128
        self.on_select_tag()
142
129
        self.browser_shown = False
143
130
        
144
131
        #Update the title when a task change
145
 
        self.activetree.register_cllbck('node-added-inview',self._update_window_title)
146
 
        self.activetree.register_cllbck('node-deleted-inview',self._update_window_title)
 
132
        self.activetree.register_cllbck('node-added-inview', self._update_window_title)
 
133
        self.activetree.register_cllbck('node-deleted-inview', self._update_window_title)
 
134
        self._update_window_title()
147
135
 
148
136
### INIT HELPER FUNCTIONS #####################################################
149
137
#
162
150
        defines aliases for UI elements found in the glide file
163
151
        """
164
152
        self.window             = self.builder.get_object("MainWindow")
165
 
        self.tagpopup           = self.builder.get_object("tag_context_menu")
166
153
        self.searchpopup          = self.builder.get_object("search_context_menu")
167
 
        self.nonworkviewtag_cb  = self.builder.get_object("nonworkviewtag_mi")
168
 
        self.nonworkviewtag_cb.set_label(GnomeConfig.TAG_IN_WORKVIEW_TOGG)
169
154
        self.taskpopup          = self.builder.get_object("task_context_menu")
170
155
        self.defertopopup       = self.builder.get_object("defer_to_context_menu")
171
156
        self.ctaskpopup         = self.builder.get_object("closed_task_context_menu")
195
180
        self.vbox_toolbars      = self.builder.get_object("vbox_toolbars")
196
181
        
197
182
        self.closed_pane        = None
 
183
        self.tagpopup           = TagContextMenu(self.req)
198
184
 
199
185
    def _init_ui_widget(self):
200
186
        """
201
 
        sets the main pane with the tree with active tasks
 
187
        sets the main pane with the tree with active tasks and create ModifyTagsDialog
202
188
        """
203
189
        # The Active tasks treeview
204
190
        self.main_pane.add(self.vtree_panes['active'])
 
191
 
 
192
        tag_completion = TagCompletion(self.req.get_tag_tree())
 
193
        self.modifytags_dialog = ModifyTagsDialog(tag_completion, self.req)
205
194
        
206
195
    def init_tags_sidebar(self):
207
196
        """
217
206
            self.on_select_tag)
218
207
        self.tagtreeview.connect('button-press-event',\
219
208
            self.on_tag_treeview_button_press_event)
 
209
        self.tagtreeview.connect('key-press-event',\
 
210
            self.on_tag_treeview_key_press_event)
220
211
        self.sidebar_container.add(self.tagtreeview)
221
212
 
 
213
        # Refresh tree 
 
214
        self.tagtree.reset_filters(transparent_only=True)
 
215
 
222
216
        # expanding search tag does not work automatically, request it
223
217
        self.expand_search_tag()
224
218
 
240
234
        """
241
235
        Show the about dialog
242
236
        """
243
 
        gtk.about_dialog_set_url_hook(lambda dialog, url: openurl.openurl(url))
 
237
        gtk.about_dialog_set_url_hook(lambda dialog, url: openurl(url))
244
238
        self.about.set_website(info.URL)
245
239
        self.about.set_website_label(info.URL)
246
240
        self.about.set_version(info.VERSION)
261
255
                self.on_edit_done_task,
262
256
            "on_delete_task":
263
257
                self.on_delete_tasks,
264
 
            "on_add_new_tag":
265
 
                self.on_add_new_tag,
 
258
            "on_modify_tags":
 
259
                self.on_modify_tags,
266
260
            "on_mark_as_done":
267
261
                self.on_mark_as_done,
268
262
            "on_mark_as_started":
303
297
                self.on_size_allocate,
304
298
            "gtk_main_quit":
305
299
                self.on_close,
306
 
            "on_addtag_confirm":
307
 
                self.on_addtag_confirm,
308
 
            "on_addtag_cancel":
309
 
                lambda x: x.hide,
310
 
            "on_tag_entry_key_press_event":
311
 
                self.on_tag_entry_key_press_event,
312
300
            "on_add_subtask":
313
301
                self.on_add_subtask,
314
 
            "on_colorchooser_activate":
315
 
                self.on_colorchooser_activate,
316
 
            "on_resetcolor_activate":
317
 
                self.on_resetcolor_activate,
318
302
            "on_tagcontext_deactivate":
319
303
                self.on_tagcontext_deactivate,
320
304
            "on_workview_toggled":
325
309
                self.on_closed_toggled,
326
310
            "on_view_sidebar_toggled":
327
311
                self.on_sidebar_toggled,
328
 
            "on_bg_color_toggled":
329
 
                self.on_bg_color_toggled,
330
312
            "on_quickadd_field_activate":
331
313
                self.on_quickadd_activate,
332
314
            "on_quickadd_field_icon_press":
346
328
            "on_about_close":
347
329
                self.on_about_close,
348
330
            "on_documentation_clicked":
349
 
                self.on_documentation_clicked,
350
 
            "on_nonworkviewtag_toggled":
351
 
                self.on_nonworkviewtag_toggled,
 
331
                lambda w: openurl(info.DOCUMENTATION_URL),
 
332
            "on_translate_clicked":
 
333
                lambda w: openurl(info.TRANSLATE_URL),
 
334
            "on_report_bug_clicked":
 
335
                lambda w: openurl(info.REPORT_BUG_URL),
352
336
            "on_preferences_activate":
353
337
                self.open_preferences,
354
338
            "on_edit_backends_activate":
404
388
        self._add_accelerator_for_widget(agr, "done_mi",        "<Control>d")
405
389
        self._add_accelerator_for_widget(agr, "dismiss_mi",     "<Control>i")
406
390
        self._add_accelerator_for_widget(agr, "delete_mi",      "Cancel")
407
 
        self._add_accelerator_for_widget(agr, "tcm_addtag",     "<Control>t")
 
391
        self._add_accelerator_for_widget(agr, "tcm_modifytags", "<Control>t")
408
392
        self._add_accelerator_for_widget(agr, "view_closed",    "<Control>F9")
 
393
        self._add_accelerator_for_widget(agr, "online_help",    "F1")
409
394
        
410
395
        edit_button = self.builder.get_object("edit_b")
411
396
        key, mod    = gtk.accelerator_parse("<Control>e")
415
400
        key, mod = gtk.accelerator_parse("<Control>l")
416
401
        quickadd_field.add_accelerator("grab-focus", agr, key, mod, gtk.ACCEL_VISIBLE)
417
402
 
418
 
    def _init_tag_completion(self):
419
 
        """
420
 
        Entry completation for the add tag to a task dialog
421
 
        """
422
 
        #Initialize tag completion.
423
 
        tagtree = self.req.get_tag_tree()
424
 
        completion_view = self.tv_factory.tags_completion_treeview(tagtree)
425
 
        col_num = 1
426
 
 
427
 
        self.tag_completion = gtk.EntryCompletion()
428
 
        self.tag_completion.set_model(completion_view.get_model())
429
 
        self.tag_completion.set_text_column(col_num)
430
 
        self.tag_completion.set_match_func(self.tag_match_func, col_num)
431
 
        self.tag_completion.set_inline_completion(True)
432
 
        self.tag_completion.set_inline_selection(True)
433
 
        self.tag_completion.set_popup_single_match(False)
434
 
 
435
403
### HELPER FUNCTIONS ########################################################
436
404
 
437
405
    def open_preferences(self, widget):
442
410
 
443
411
    def quit(self,widget=None):
444
412
        self.vmanager.close_browser()
445
 
        
 
413
 
 
414
    def on_window_state_event(self,widget,event,data=None):
 
415
        """This event checks for the window state: maximized?
 
416
           and stores the state in self.config.max
 
417
           This is used to check the window state afterwards
 
418
           and maximize it if needed """
 
419
        mask = gtk.gdk.WINDOW_STATE_MAXIMIZED
 
420
        if widget.get_window().get_state() & mask == mask:      
 
421
            self.config.set("max", True)
 
422
        else:
 
423
            self.config.set("max", False) 
 
424
 
446
425
    def restore_state_from_conf(self):
447
426
 
448
427
#        # Extract state from configuration dictionary
457
436
        if width and height:
458
437
            self.window.resize(width, height)
459
438
 
 
439
        # checks for maximum size of window
 
440
        self.window.connect('window-state-event', self.on_window_state_event)
 
441
        if self.config.get("max"):
 
442
            self.window.maximize()
 
443
 
460
444
        xpos = self.config.get("x_pos")
461
445
        ypos = self.config.get("y_pos")
462
446
        if ypos and xpos:
510
494
            sort_column, sort_order = int(sort_column), int(sort_order)
511
495
            model.set_sort_column_id(sort_column, sort_order)
512
496
 
513
 
        bgcol_enable = self.config.get("bg_color_enable")
514
 
        self.builder.get_object("bgcol_enable").set_active(bgcol_enable)
515
 
        
516
497
        for path_s in self.config.get("collapsed_tasks"):
517
498
            #the tuple was stored as a string. we have to reconstruct it
518
499
            path = ()
603
584
                                   count) % {'tasks': count}
604
585
        self.window.set_title("%s - "%parenthesis + WINDOW_TITLE)
605
586
 
606
 
    def tag_match_func(self, completion, key, iter, column):
607
 
        """
608
 
        function that defines autocompletation on the add tag dialog
609
 
        """
610
 
        model = completion.get_model()
611
 
        text = model.get_value(iter, column)
612
 
        if text:
613
 
            # key is always lowercase => convert text also into lowercase
614
 
            text = text.lower()
615
 
 
616
 
            # Exclude the special tags.
617
 
            if text.startswith("<span") or text.startswith('gtg-tags-'):
618
 
                return False
619
 
            else:
620
 
                # Compare normalized unicode representation
621
 
                text = unicodedata.normalize('NFC', unicode(text))
622
 
                key =  unicodedata.normalize('NFC', unicode(key))
623
 
                return text.startswith(key)
624
 
 
625
587
    def _add_page(self, notebook, label, page):
626
588
        notebook.append_page(page, label)
627
589
        if notebook.get_n_pages() > 1:
693
655
        self.about.hide()
694
656
        return True
695
657
 
696
 
    def on_documentation_clicked(self, widget):
697
 
        webbrowser.open(DOCUMENTATION_URL)
698
 
 
699
 
    def on_color_changed(self, widget):
700
 
        gtkcolor = widget.get_current_color()
701
 
        strcolor = gtk.color_selection_palette_to_string([gtkcolor])
702
 
        tags = self.get_selected_tags()
703
 
        for tname in tags:
704
 
            t = self.req.get_tag(tname)
705
 
            t.set_attribute("color", strcolor)
706
 
 
707
 
    def on_colorchooser_activate(self, widget):
708
 
        #TODO: Color chooser should be refactorized in its own class. Well, in
709
 
        #fact we should have a TagPropertiesEditor (like for project) Also,
710
 
        #color change should be immediate. There's no reason for a Ok/Cancel
711
 
        self.set_target_cursor()
712
 
        color_dialog = gtk.ColorSelectionDialog('Choose color')
713
 
        colorsel = color_dialog.colorsel
714
 
        colorsel.connect("color_changed", self.on_color_changed)
715
 
 
716
 
        # Get previous color
717
 
        tags= self.get_selected_tags()
718
 
        init_color = None
719
 
        if len(tags) == 1:
720
 
            ta = self.req.get_tag(tags[0])
721
 
            color = ta.get_attribute("color")
722
 
            if color is not None:
723
 
                colorspec = gtk.gdk.color_parse(color)
724
 
                colorsel.set_previous_color(colorspec)
725
 
                colorsel.set_current_color(colorspec)
726
 
                init_color = colorsel.get_current_color()
727
 
        response = color_dialog.run()
728
 
        # Check response and set color if required
729
 
        if response != gtk.RESPONSE_OK and init_color:
730
 
            strcolor = gtk.color_selection_palette_to_string([init_color])
731
 
            tags = self.get_selected_tags()
732
 
            for t in tags:
733
 
                t.set_attribute("color", strcolor)
734
 
        self.reset_cursor()
735
 
        color_dialog.destroy()
736
 
        
737
 
    def on_resetcolor_activate(self, widget):
738
 
        """
739
 
        handler for the right click popup menu item from tag tree, when its a @tag
740
 
        """
741
 
        self.set_target_cursor()
742
 
        tags = self.get_selected_tags()
743
 
        for tname in tags:
744
 
            t = self.req.get_tag(tname)
745
 
            t.del_attribute("color")
746
 
        self.reset_cursor()
747
 
        
748
658
    def on_tagcontext_deactivate(self, menushell):
749
659
        self.reset_cursor()
750
660
 
819
729
        self.builder.get_object("view_closed").set_active(False)
820
730
        self.config.set('closed_task_pane',False)
821
731
 
822
 
    def on_bg_color_toggled(self, widget):
823
 
        if widget.get_active():
824
 
            self.config.set("bg_color_enable",True)
825
 
        else:
826
 
            self.config.set("bg_color_enable",False)
827
 
 
828
732
    def on_toolbar_toggled(self, widget):
829
733
        if widget.get_active():
830
734
            self.toolbar.show()
940
844
                    # Then we are looking at single, normal tag rather than
941
845
                    # the special 'All tags' or 'Tasks without tags'. We only
942
846
                    # want to popup the menu for normal tags.
943
 
 
944
 
                    display_in_workview_item = self.tagpopup.get_children()[2]
945
847
                    selected_tag = self.req.get_tag(selected_tags[0])
946
 
                    nonworkview = selected_tag.get_attribute("nonworkview")
947
 
                    # We must invert because the tagstore has "True" for tasks
948
 
                    # that are *not* in workview, and the checkbox is set if
949
 
                    # the tag *is* shown in the workview.
950
 
                    if nonworkview == "True":
951
 
                        shown = False
952
 
                    else:
953
 
                        shown = True
954
 
                    # HACK: CheckMenuItem.set_active() emits a toggled() when 
955
 
                    # switching between True and False, which will reset 
956
 
                    # the cursor. Using self.dont_reset to work around that.
957
 
                    # Calling set_target_cursor after set_active() is another
958
 
                    # option, but there's noticeable amount of lag when right
959
 
                    # clicking tags that way.
960
 
                    self.dont_reset = True
961
 
                    display_in_workview_item.set_active(shown)
962
 
                    self.dont_reset = False
 
848
                    self.tagpopup.set_tag(selected_tag)
963
849
                    self.tagpopup.popup(None, None, None, event.button, time)
964
850
                else:
965
851
                    self.reset_cursor()
966
 
            return 1
 
852
            return True
967
853
 
968
 
    def on_nonworkviewtag_toggled(self, widget):
969
 
        self.set_target_cursor()
970
 
        tag_id = self.get_selected_tags()[0]
971
 
        #We must inverse because the tagstore has True
972
 
        #for tasks that are not in workview (and also convert to string)
973
 
        toset = not self.nonworkviewtag_cb.get_active()
974
 
        tag = self.req.get_tag(tag_id)
975
 
        tag.set_attribute("nonworkview", str(toset))
976
 
        if toset:
977
 
            label = GnomeConfig.TAG_NOTIN_WORKVIEW_TOGG
978
 
        else:
979
 
            label = GnomeConfig.TAG_IN_WORKVIEW_TOGG
980
 
        self.nonworkviewtag_cb.set_label(label)
981
 
        if not self.dont_reset:
982
 
            self.reset_cursor()
 
854
    def on_tag_treeview_key_press_event(self, treeview, event):
 
855
        keyname = gtk.gdk.keyval_name(event.keyval)
 
856
        is_shift_f10 = keyname == "F10" and event.get_state() & gtk.gdk.SHIFT_MASK
 
857
        if is_shift_f10 or keyname == "Menu":
 
858
            selected_tags = self.get_selected_tags(nospecial=True)
 
859
            selected_search = self.get_selected_search()
 
860
            #popup menu for searches
 
861
            if selected_search is not None:
 
862
                self.searchpopup.popup(None, None, None, 0, event.time)
 
863
            elif len(selected_tags) > 0:
 
864
                # Then we are looking at single, normal tag rather than
 
865
                # the special 'All tags' or 'Tasks without tags'. We only
 
866
                # want to popup the menu for normal tags.
 
867
                selected_tag = self.req.get_tag(selected_tags[0])
 
868
                self.tagpopup.set_tag(selected_tag)
 
869
                self.tagpopup.popup(None, None, None, 0, event.time)
 
870
            else:
 
871
                self.reset_cursor()
 
872
            return True
983
873
 
984
874
    def on_task_treeview_button_press_event(self, treeview, event):
985
875
        """Pop up context menu on right mouse click in the main task tree view"""
999
889
                    treeview.set_cursor(path, col, 0)
1000
890
                treeview.grab_focus()
1001
891
                self.taskpopup.popup(None, None, None, event.button, time)
1002
 
            return 1
 
892
            return True
1003
893
 
1004
894
    def on_task_treeview_key_press_event(self, treeview, event):
1005
 
        if gtk.gdk.keyval_name(event.keyval) == "Delete":
 
895
        keyname = gtk.gdk.keyval_name(event.keyval)
 
896
        is_shift_f10 = keyname == "F10" and event.get_state() & gtk.gdk.SHIFT_MASK
 
897
 
 
898
        if keyname == "Delete":
1006
899
            self.on_delete_tasks()
 
900
            return True
 
901
        elif is_shift_f10 or keyname == "Menu":
 
902
            self.taskpopup.popup(None, None, None, 0, event.time)
 
903
            return True
1007
904
 
1008
905
    def on_closed_task_treeview_button_press_event(self, treeview, event):
1009
906
        if event.button == 3:
1016
913
                treeview.grab_focus()
1017
914
                treeview.set_cursor(path, col, 0)
1018
915
                self.ctaskpopup.popup(None, None, None, event.button, time)
1019
 
            return 1
 
916
            return True
1020
917
 
1021
918
    def on_closed_task_treeview_key_press_event(self, treeview, event):
1022
 
        if gtk.gdk.keyval_name(event.keyval) == "Delete":
 
919
        keyname = gtk.gdk.keyval_name(event.keyval)
 
920
        is_shift_f10 = keyname == "F10" and event.get_state() & gtk.gdk.SHIFT_MASK
 
921
 
 
922
        if keyname == "Delete":
1023
923
            self.on_delete_tasks()
 
924
            return True
 
925
        elif is_shift_f10 or keyname == "Menu":
 
926
            self.ctaskpopup.popup(None, None, None, 0, event.time)
 
927
            return True
1024
928
 
1025
929
    def on_add_task(self, widget, status=None):
1026
930
        tags = [tag for tag in self.get_selected_tags() if tag.startswith('@')]
1129
1033
    def on_set_due_clear(self, widget):
1130
1034
        self.update_due_date(widget, None)
1131
1035
 
1132
 
    def on_add_new_tag(self, widget=None, tid=None, tryagain = False):
1133
 
        if not tid:
1134
 
            self.tids_to_addtag = self.get_selected_tasks()
1135
 
        else:
1136
 
            self.tids_to_addtag = [tid]
1137
 
 
1138
 
        if not self.tids_to_addtag == [None]:
1139
 
            tag_entry = self.builder.get_object("tag_entry")
1140
 
            apply_to_subtasks = self.builder.get_object("apply_to_subtasks")
1141
 
            # We don't want to reset the text entry and checkbox if we got
1142
 
            # sent back here after a warning.
1143
 
            if not tryagain:
1144
 
                tag_entry.set_text(self.last_added_tags)
1145
 
                tag_entry.set_completion(self.tag_completion)
1146
 
                apply_to_subtasks.set_active(self.last_apply_tags_to_subtasks)
1147
 
            tag_entry.grab_focus()
1148
 
            addtag_dialog = self.builder.get_object("addtag_dialog")
1149
 
            addtag_dialog.run()
1150
 
            addtag_dialog.hide()
1151
 
            self.tids_to_addtag = None            
1152
 
        else:
1153
 
            return False
1154
 
    
1155
 
    def on_addtag_confirm(self, widget):
1156
 
        tag_entry = self.builder.get_object("tag_entry")
1157
 
        addtag_dialog = self.builder.get_object("addtag_dialog")
1158
 
        apply_to_subtasks = self.builder.get_object("apply_to_subtasks")
1159
 
        addtag_error = False
1160
 
        entry_text = tag_entry.get_text()
1161
 
        #use spaces and commas as separators
1162
 
        new_tags = []
1163
 
        for text in entry_text.split(","):
1164
 
            tags = [t.strip() for t in text.split(" ")]
1165
 
            for tag in tags:
1166
 
                if tag:
1167
 
                    if not tag.startswith('@'):
1168
 
                        tag = "@" + tag 
1169
 
                    new_tags.append(tag)
1170
 
        # If the checkbox is checked, add all the subtasks to the list of
1171
 
        # tasks to add.
1172
 
        if apply_to_subtasks.get_active():
1173
 
            for tid in self.tids_to_addtag:
1174
 
                task = self.req.get_task(tid)
1175
 
                # FIXME: Python not reinitialize the default value of its parameter
1176
 
                # therefore it must be done manually. This function should be refractored
1177
 
                # as far it is marked as depricated
1178
 
                for i in task.get_self_and_all_subtasks(tasks=[]):
1179
 
                    taskid = i.get_id()
1180
 
                    if taskid not in self.tids_to_addtag: 
1181
 
                        self.tids_to_addtag.append(taskid)        
1182
 
        for tid in self.tids_to_addtag:
1183
 
            task = self.req.get_task(tid)
1184
 
            for new_tag in new_tags:
1185
 
                task.add_tag(new_tag)
1186
 
            task.sync()
1187
 
 
1188
 
        # Rember the last actions
1189
 
        self.last_added_tags = tag_entry.get_text()
1190
 
        self.last_apply_tags_to_subtasks = apply_to_subtasks.get_active()
1191
 
      
1192
 
    def on_tag_entry_key_press_event(self, widget, event):
1193
 
        if gtk.gdk.keyval_name(event.keyval) == "Return":
1194
 
            self.on_addtag_confirm()
 
1036
    def on_modify_tags(self, widget):
 
1037
        """ Run Modify Tags dialog on selected tasks """
 
1038
        tasks = self.get_selected_tasks()
 
1039
        self.modifytags_dialog.modify_tags(tasks)
1195
1040
    
1196
1041
    def close_all_task_editors(self, task_id):
1197
1042
        """ Including editors of subtasks """
1663
1508
            if tagname.startswith("@") :
1664
1509
                self.search_complete_store.append([tagname])
1665
1510
 
1666
 
        for command in search_commands:
 
1511
        for command in SEARCH_COMMANDS:
1667
1512
            self.search_complete_store.append([command])
1668
1513
 
1669
1514
        self.search_completion.set_model(self.search_complete_store)