GTG

Merge lp:~izidor/gtg/pep8-gtk into lp:~gtg/gtg/old-trunk

Proposed by Izidor Matušov
Status: Merged
Merged at revision: 1254
Proposed branch: lp:~izidor/gtg/pep8-gtk
Merge into: lp:~gtg/gtg/old-trunk
Diff against target: 1911 lines (+373/-323)
10 files modified
GTG/gtk/browser/CellRendererTags.py (+21/-21)
GTG/gtk/browser/browser.py (+13/-17)
GTG/gtk/browser/tag_context_menu.py (+4/-5)
GTG/gtk/browser/treeview_factory.py (+95/-95)
GTG/gtk/crashhandler.py (+1/-1)
GTG/gtk/delete_dialog.py (+12/-10)
GTG/gtk/editor/__init__.py (+2/-2)
GTG/gtk/editor/editor.py (+67/-52)
GTG/gtk/editor/taskview.py (+155/-117)
GTG/gtk/editor/taskviewserial.py (+3/-3)
To merge this branch: bzr merge lp:~izidor/gtg/pep8-gtk
Reviewer Review Type Date Requested Status
Bertrand Rousseau (community) code Approve
Review via email: mp+136066@code.launchpad.net

Description of the change

Partial PEP8-ification of GTG/gtk folder (until I ran out of battery during refactoring :/)

To post a comment you must log in.
Revision history for this message
Bertrand Rousseau (bertrand-rousseau) wrote :

Ok for me. There are some comments that could probably be deleted here and there (mainly editor.py), but that can be done in another pass.

review: Approve (code)
Revision history for this message
Izidor Matušov (izidor) wrote :

I didn't want to remove them because of merge/including code from Steve's GSoC editor rework.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'GTG/gtk/browser/CellRendererTags.py'
--- GTG/gtk/browser/CellRendererTags.py 2012-05-23 08:55:31 +0000
+++ GTG/gtk/browser/CellRendererTags.py 2012-11-25 21:29:25 +0000
@@ -32,9 +32,9 @@
3232
33class CellRendererTags(gtk.GenericCellRenderer):33class CellRendererTags(gtk.GenericCellRenderer):
34 __gproperties__ = {34 __gproperties__ = {
35 'tag_list': (gobject.TYPE_PYOBJECT,\35 'tag_list': (gobject.TYPE_PYOBJECT,
36 "Tag list", "A list of tags", gobject.PARAM_READWRITE),36 "Tag list", "A list of tags", gobject.PARAM_READWRITE),
37 'tag': (gobject.TYPE_PYOBJECT, "Tag",\37 'tag': (gobject.TYPE_PYOBJECT, "Tag",
38 "Tag", gobject.PARAM_READWRITE),38 "Tag", gobject.PARAM_READWRITE),
39 }39 }
4040
@@ -66,7 +66,7 @@
66 if self.tag_list != None:66 if self.tag_list != None:
67 for my_tag in self.tag_list:67 for my_tag in self.tag_list:
68 my_tag_color = my_tag.get_attribute("color")68 my_tag_color = my_tag.get_attribute("color")
69 my_tag_icon = my_tag.get_attribute("icon")69 my_tag_icon = my_tag.get_attribute("icon")
70 if my_tag_color or my_tag_icon:70 if my_tag_color or my_tag_icon:
71 count = count + 171 count = count + 1
72 elif self.tag != None:72 elif self.tag != None:
@@ -80,10 +80,10 @@
80 def __init__(self): #pylint: disable-msg=W023180 def __init__(self): #pylint: disable-msg=W0231
81 self.__gobject_init__()81 self.__gobject_init__()
82 self.tag_list = None82 self.tag_list = None
83 self.tag = None83 self.tag = None
84 self.xpad = 184 self.xpad = 1
85 self.ypad = 185 self.ypad = 1
86 self.PADDING = 186 self.PADDING = 1
8787
88 def do_set_property(self, pspec, value):88 def do_set_property(self, pspec, value):
89 if pspec.name == "tag-list":89 if pspec.name == "tag-list":
@@ -97,11 +97,11 @@
97 else:97 else:
98 return getattr(self, pspec.name)98 return getattr(self, pspec.name)
9999
100 def on_render(\100 def on_render(self, window, widget, background_area, cell_area,
101 self, window, widget, background_area, cell_area, expose_area, flags):101 expose_area, flags):
102102
103 vw_tags = self.__count_viewable_tags()103 vw_tags = self.__count_viewable_tags()
104 count = 0104 count = 0
105105
106 # Select source106 # Select source
107 if self.tag_list != None:107 if self.tag_list != None:
@@ -112,25 +112,25 @@
112 return112 return
113113
114 # Drawing context114 # Drawing context
115 cr = window.cairo_create()115 cr = window.cairo_create()
116 gdkcontext = gtk.gdk.CairoContext(cr)116 gdkcontext = gtk.gdk.CairoContext(cr)
117 gdkcontext.set_antialias(cairo.ANTIALIAS_NONE)117 gdkcontext.set_antialias(cairo.ANTIALIAS_NONE)
118118
119 # Coordinates of the origin point119 # Coordinates of the origin point
120 x_align = self.get_property("xalign")120 x_align = self.get_property("xalign")
121 y_align = self.get_property("yalign")121 y_align = self.get_property("yalign")
122 orig_x = cell_area.x + int((cell_area.width - 16*vw_tags -\122 orig_x = cell_area.x + int((cell_area.width - 16*vw_tags - \
123 self.PADDING*2*(vw_tags-1)) * x_align)123 self.PADDING*2*(vw_tags-1)) * x_align)
124 orig_y = cell_area.y + int((cell_area.height - 16) * y_align)124 orig_y = cell_area.y + int((cell_area.height - 16) * y_align)
125125
126 # We draw the icons & squares126 # We draw the icons & squares
127 for my_tag in tags:127 for my_tag in tags:
128128
129 my_tag_icon = my_tag.get_attribute("icon")129 my_tag_icon = my_tag.get_attribute("icon")
130 my_tag_color = my_tag.get_attribute("color")130 my_tag_color = my_tag.get_attribute("color")
131131
132 rect_x = orig_x + self.PADDING*2*count + 16*count132 rect_x = orig_x + self.PADDING*2*count + 16*count
133 rect_y = orig_y133 rect_y = orig_y
134134
135 if my_tag_icon:135 if my_tag_icon:
136 try:136 try:
@@ -162,11 +162,10 @@
162162
163 if self.tag and my_tag: #pylint: disable-msg=W0631163 if self.tag and my_tag: #pylint: disable-msg=W0631
164164
165 my_tag_icon = my_tag.get_attribute("icon")165 my_tag_icon = my_tag.get_attribute("icon")
166 my_tag_color = my_tag.get_attribute("color")166 my_tag_color = my_tag.get_attribute("color")
167167
168 if not my_tag_icon and not my_tag_color:168 if not my_tag_icon and not my_tag_color:
169
170 # Draw rounded rectangle169 # Draw rounded rectangle
171 gdkcontext.set_source_rgba(0.95, 0.95, 0.95, 1)170 gdkcontext.set_source_rgba(0.95, 0.95, 0.95, 1)
172 self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8)171 self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8)
@@ -183,8 +182,9 @@
183 count = self.__count_viewable_tags()182 count = self.__count_viewable_tags()
184183
185 if count != 0:184 if count != 0:
186 return (self.xpad, self.ypad, self.xpad*2 + 16*count +\185 return (self.xpad, self.ypad,
187 2*count*self.PADDING, 16 + 2*self.ypad)186 self.xpad*2 + 16*count + 2*count*self.PADDING,
187 16 + 2*self.ypad)
188 else:188 else:
189 return (self.xpad, self.ypad, self.xpad*2, self.ypad*2)189 return (self.xpad, self.ypad, self.xpad*2, self.ypad*2)
190190
191191
=== modified file 'GTG/gtk/browser/browser.py'
--- GTG/gtk/browser/browser.py 2012-11-01 10:09:06 +0000
+++ GTG/gtk/browser/browser.py 2012-11-25 21:29:25 +0000
@@ -46,9 +46,6 @@
46from GTG.tools.dates import Date46from GTG.tools.dates import Date
47from GTG.tools.logger import Log47from GTG.tools.logger import Log
4848
49#=== MAIN CLASS ===============================================================
50
51
5249
53class Timer:50class Timer:
5451
@@ -96,7 +93,7 @@
9693
97 # Set up models94 # Set up models
98 # Active Tasks95 # Active Tasks
99 self.req.apply_global_filter(self.activetree,'active')96 self.req.apply_global_filter(self.activetree, 'active')
100 # Tags97 # Tags
101 self.tagtree = None98 self.tagtree = None
102 self.tagtreeview = None99 self.tagtreeview = None
@@ -405,7 +402,7 @@
405### HELPER FUNCTIONS ########################################################402### HELPER FUNCTIONS ########################################################
406 def open_preferences(self, widget):403 def open_preferences(self, widget):
407 self.vmanager.open_preferences(self.config)404 self.vmanager.open_preferences(self.config)
408 405
409 def open_plugins(self, widget):406 def open_plugins(self, widget):
410 self.vmanager.configure_plugins()407 self.vmanager.configure_plugins()
411408
@@ -565,10 +562,10 @@
565562
566 def set_view(self, viewname):563 def set_view(self, viewname):
567 if viewname == 'default':564 if viewname == 'default':
568 self.req.unapply_global_filter(self.activetree,'workview')565 self.req.unapply_global_filter(self.activetree, 'workview')
569 workview = False566 workview = False
570 elif viewname == 'workview':567 elif viewname == 'workview':
571 self.req.apply_global_filter(self.activetree,'workview')568 self.req.apply_global_filter(self.activetree, 'workview')
572 workview = True569 workview = True
573 else:570 else:
574 raise Exception('Cannot set the view %s' %viewname)571 raise Exception('Cannot set the view %s' %viewname)
@@ -613,7 +610,6 @@
613### SIGNAL CALLBACKS ##########################################################610### SIGNAL CALLBACKS ##########################################################
614# Typically, reaction to user input & interactions with the GUI611# Typically, reaction to user input & interactions with the GUI
615#612#
616
617 def on_sort_column_changed(self, model):613 def on_sort_column_changed(self, model):
618 sort_column, sort_order = model.get_sort_column_id()614 sort_column, sort_order = model.get_sort_column_id()
619615
@@ -755,7 +751,7 @@
755 colt = self.config.get("collapsed_tasks")751 colt = self.config.get("collapsed_tasks")
756 if tid not in colt:752 if tid not in colt:
757 colt.append(str(tid))753 colt.append(str(tid))
758 754
759 def on_tag_expanded(self, sender, tag):755 def on_tag_expanded(self, sender, tag):
760 colt = self.config.get("expanded_tags")756 colt = self.config.get("expanded_tags")
761 if tag not in colt:757 if tag not in colt:
@@ -980,7 +976,7 @@
980 def on_delete_tasks(self, widget=None, tid=None):976 def on_delete_tasks(self, widget=None, tid=None):
981 #If we don't have a parameter, then take the selection in the treeview977 #If we don't have a parameter, then take the selection in the treeview
982 if not tid:978 if not tid:
983 #tid_to_delete is a [project,task] tuple979 #tid_to_delete is a [project, task] tuple
984 tids_todelete = self.get_selected_tasks()980 tids_todelete = self.get_selected_tasks()
985 if not tids_todelete:981 if not tids_todelete:
986 return982 return
@@ -1110,13 +1106,13 @@
1110 task.set_status(Task.STA_DISMISSED)1106 task.set_status(Task.STA_DISMISSED)
1111 self.close_all_task_editors(uid)1107 self.close_all_task_editors(uid)
11121108
1113 def apply_filter_on_panes(self, filter_name,refresh=True):1109 def apply_filter_on_panes(self, filter_name, refresh=True):
1114 """ Apply filters for every pane: active tasks, closed tasks """1110 """ Apply filters for every pane: active tasks, closed tasks """
1115 for pane in self.vtree_panes:1111 for pane in self.vtree_panes:
1116 vtree = self.req.get_tasks_tree(name=pane, refresh=False)1112 vtree = self.req.get_tasks_tree(name=pane, refresh=False)
1117 vtree.apply_filter(filter_name, refresh=refresh)1113 vtree.apply_filter(filter_name, refresh=refresh)
1118 1114
1119 def unapply_filter_on_panes(self, filter_name,refresh=True):1115 def unapply_filter_on_panes(self, filter_name, refresh=True):
1120 """ Apply filters for every pane: active tasks, closed tasks """1116 """ Apply filters for every pane: active tasks, closed tasks """
1121 for pane in self.vtree_panes:1117 for pane in self.vtree_panes:
1122 vtree = self.req.get_tasks_tree(name=pane, refresh=False)1118 vtree = self.req.get_tasks_tree(name=pane, refresh=False)
@@ -1130,11 +1126,11 @@
11301126
1131 #When you click on a tag, you want to unselect the tasks1127 #When you click on a tag, you want to unselect the tasks
1132 new_taglist = self.get_selected_tags()1128 new_taglist = self.get_selected_tags()
1133 1129
1134 for tagname in self.applied_tags:1130 for tagname in self.applied_tags:
1135 if tagname not in new_taglist:1131 if tagname not in new_taglist:
1136 self.unapply_filter_on_panes(tagname,refresh=False)1132 self.unapply_filter_on_panes(tagname, refresh=False)
1137 1133
1138 for tagname in new_taglist:1134 for tagname in new_taglist:
1139 if tagname not in self.applied_tags:1135 if tagname not in self.applied_tags:
1140 self.apply_filter_on_panes(tagname)1136 self.apply_filter_on_panes(tagname)
@@ -1143,7 +1139,7 @@
1143 tag = self.req.get_tag(tagname)1139 tag = self.req.get_tag(tagname)
1144 if tag.is_search_tag():1140 if tag.is_search_tag():
1145 self.quickadd_entry.set_text(tag.get_attribute("query"))1141 self.quickadd_entry.set_text(tag.get_attribute("query"))
1146 1142
1147 self.applied_tags = new_taglist1143 self.applied_tags = new_taglist
11481144
1149 def on_taskdone_cursor_changed(self, selection=None):1145 def on_taskdone_cursor_changed(self, selection=None):
11501146
=== modified file 'GTG/gtk/browser/tag_context_menu.py'
--- GTG/gtk/browser/tag_context_menu.py 2012-05-23 08:55:31 +0000
+++ GTG/gtk/browser/tag_context_menu.py 2012-11-25 21:29:25 +0000
@@ -21,7 +21,7 @@
21"""21"""
22tag_context_menu:22tag_context_menu:
23Implements a context (pop-up) menu for the tag item in the sidebar.23Implements a context (pop-up) menu for the tag item in the sidebar.
24Right now it is just a void shell It is supposed to become a more generic 24Right now it is just a void shell It is supposed to become a more generic
25sidebar context for all kind of item displayed there.25sidebar context for all kind of item displayed there.
26Also, it is supposed to handle more complex menus (with non-std widgets,26Also, it is supposed to handle more complex menus (with non-std widgets,
27like a color picker)27like a color picker)
@@ -33,6 +33,7 @@
3333
34from GTG import _34from GTG import _
3535
36
36class TagContextMenu(gtk.Menu): # pylint: disable-msg=R090437class TagContextMenu(gtk.Menu): # pylint: disable-msg=R0904
37 """Context menu fo the tag i the sidebar"""38 """Context menu fo the tag i the sidebar"""
3839
@@ -66,15 +67,13 @@
66 # Make it visible67 # Make it visible
67 self.show_all()68 self.show_all()
6869
69 ### PUBLIC API ###70 ### PUBLIC API ############################################################
70
71 def set_tag(self, tag):71 def set_tag(self, tag):
72 """Update the context menu items using the tag attributes."""72 """Update the context menu items using the tag attributes."""
73 self.tag = tag73 self.tag = tag
74 self.__build_menu()74 self.__build_menu()
7575
76 ### CALLBACKS ###76 ### CALLBACKS #############################################################
77
78 def on_mi_cc_activate(self, widget): # pylint: disable-msg=W061377 def on_mi_cc_activate(self, widget): # pylint: disable-msg=W0613
79 """Callback: show the tag editor upon request"""78 """Callback: show the tag editor upon request"""
80 self.vmanager.open_tag_editor(self.tag)79 self.vmanager.open_tag_editor(self.tag)
8180
=== modified file 'GTG/gtk/browser/treeview_factory.py'
--- GTG/gtk/browser/treeview_factory.py 2012-11-01 10:23:05 +0000
+++ GTG/gtk/browser/treeview_factory.py 2012-11-25 21:29:25 +0000
@@ -33,14 +33,14 @@
3333
34class TreeviewFactory():34class TreeviewFactory():
3535
36 def __init__(self,requester,config):36 def __init__(self, requester, config):
37 self.req = requester37 self.req = requester
38 self.mainview = self.req.get_tasks_tree()38 self.mainview = self.req.get_tasks_tree()
39 self.config = config39 self.config = config
40 40
41 #Initial unactive color41 #Initial unactive color
42 #This is a crude hack. As we don't have a reference to the 42 #This is a crude hack. As we don't have a reference to the
43 #treeview to retrieve the style, we save that color when we 43 #treeview to retrieve the style, we save that color when we
44 #build the treeview.44 #build the treeview.
45 self.unactive_color = "#888a85"45 self.unactive_color = "#888a85"
4646
@@ -49,12 +49,12 @@
4949
50 # Cache tags treeview for on_rename_tag callback50 # Cache tags treeview for on_rename_tag callback
51 self.tags_view = None51 self.tags_view = None
52 52
53 #############################53 #############################
54 #Functions for tasks columns54 #Functions for tasks columns
55 ################################55 ################################
56 56
57 def _has_hidden_subtask(self,task):57 def _has_hidden_subtask(self, task):
58 #not recursive58 #not recursive
59 display_count = self.mainview.node_n_children(task.get_id())59 display_count = self.mainview.node_n_children(task.get_id())
60 real_count = 060 real_count = 0
@@ -64,15 +64,15 @@
64 if sub_task and sub_task.get_status() == Task.STA_ACTIVE:64 if sub_task and sub_task.get_status() == Task.STA_ACTIVE:
65 real_count = real_count + 165 real_count = real_count + 1
66 return display_count < real_count66 return display_count < real_count
67 67
68 def task_bg_color(self, node, default_color):68 def task_bg_color(self, node, default_color):
69 if self.config.get('bg_color_enable'):69 if self.config.get('bg_color_enable'):
70 return colors.background_color(node.get_tags(), default_color)70 return colors.background_color(node.get_tags(), default_color)
71 else:71 else:
72 return None72 return None
73 73
74 #return an ordered list of tags of a task74 #return an ordered list of tags of a task
75 def task_tags_column(self,node):75 def task_tags_column(self, node):
76 tags = node.get_tags()76 tags = node.get_tags()
7777
78 search_parent = self.req.get_tag(CoreConfig.SEARCH_TAG)78 search_parent = self.req.get_tag(CoreConfig.SEARCH_TAG)
@@ -84,15 +84,15 @@
8484
85 tags.sort(key = lambda x: x.get_name())85 tags.sort(key = lambda x: x.get_name())
86 return tags86 return tags
87 87
88 #task title88 #task title
89 def task_title_column(self, node):89 def task_title_column(self, node):
90 return saxutils.escape(node.get_title())90 return saxutils.escape(node.get_title())
91 91
92 #task title/label92 #task title/label
93 def task_label_column(self, node):93 def task_label_column(self, node):
94 str_format = "%s"94 str_format = "%s"
95 95
96 if node.get_status() == Task.STA_ACTIVE:96 if node.get_status() == Task.STA_ACTIVE:
97 # we mark in bold tasks which are due today or as Now97 # we mark in bold tasks which are due today or as Now
98 days_left = node.get_days_left()98 days_left = node.get_days_left()
@@ -114,40 +114,40 @@
114 excerpt = saxutils.escape(node.get_excerpt(lines=1,114 excerpt = saxutils.escape(node.get_excerpt(lines=1,
115 strip_tags=True, strip_subtasks=True))115 strip_tags=True, strip_subtasks=True))
116 title += " <span size='small' color='%s'>%s</span>" \116 title += " <span size='small' color='%s'>%s</span>" \
117 % (self.unactive_color, excerpt) 117 % (self.unactive_color, excerpt)
118 return title118 return title
119 119
120 #task start date120 #task start date
121 def task_sdate_column(self,node):121 def task_sdate_column(self, node):
122 return node.get_start_date().to_readable_string()122 return node.get_start_date().to_readable_string()
123 123
124 def task_duedate_column(self,node):124 def task_duedate_column(self, node):
125 # We show the most constraining due date for task with no due dates.125 # We show the most constraining due date for task with no due dates.
126 if node.get_due_date() == Date.no_date():126 if node.get_due_date() == Date.no_date():
127 return node.get_due_date_constraint().to_readable_string()127 return node.get_due_date_constraint().to_readable_string()
128 else:128 else:
129 # Other tasks show their due date (which *can* be fuzzy)129 # Other tasks show their due date (which *can* be fuzzy)
130 return node.get_due_date().to_readable_string()130 return node.get_due_date().to_readable_string()
131 131
132 def task_cdate_column(self,node):132 def task_cdate_column(self, node):
133 return node.get_closed_date().to_readable_string()133 return node.get_closed_date().to_readable_string()
134 134
135 def start_date_sorting(self,task1,task2,order):135 def start_date_sorting(self, task1, task2, order):
136 sort = self.__date_comp(task1,task2,'start',order)136 sort = self.__date_comp(task1, task2, 'start', order)
137 return sort137 return sort
138 138
139 def due_date_sorting(self,task1,task2,order):139 def due_date_sorting(self, task1, task2, order):
140 sort = self.__date_comp(task1,task2,'due',order)140 sort = self.__date_comp(task1, task2, 'due', order)
141 return sort141 return sort
142 142
143 def closed_date_sorting(self,task1,task2,order):143 def closed_date_sorting(self, task1, task2, order):
144 sort = self.__date_comp(task1,task2,'closed',order)144 sort = self.__date_comp(task1, task2, 'closed', order)
145 return sort145 return sort
146 146
147 def title_sorting(self,task1,task2,order):147 def title_sorting(self, task1, task2, order):
148 return cmp(task1.get_title(),task2.get_title())148 return cmp(task1.get_title(), task2.get_title())
149 149
150 def __date_comp(self,task1,task2,para,order):150 def __date_comp(self, task1, task2, para, order):
151 '''This is a quite complex method to sort tasks by date,151 '''This is a quite complex method to sort tasks by date,
152 handling fuzzy date and complex situation.152 handling fuzzy date and complex situation.
153 Return -1 if nid1 is before nid2, return 1 otherwise153 Return -1 if nid1 is before nid2, return 1 otherwise
@@ -168,39 +168,39 @@
168 t2 = task2.get_closed_date()168 t2 = task2.get_closed_date()
169 else:169 else:
170 raise ValueError('invalid date comparison parameter: %s')%para170 raise ValueError('invalid date comparison parameter: %s')%para
171 sort = cmp(t2,t1)171 sort = cmp(t2, t1)
172 else:172 else:
173 sort = 0173 sort = 0
174 174
175 #local function175 #local function
176 def reverse_if_descending(s):176 def reverse_if_descending(s):
177 """Make a cmp() result relative to the top instead of following 177 """Make a cmp() result relative to the top instead of following
178 user-specified sort direction"""178 user-specified sort direction"""
179 if order == gtk.SORT_ASCENDING:179 if order == gtk.SORT_ASCENDING:
180 return s180 return s
181 else:181 else:
182 return -1*s182 return -1*s
183183
184 if sort == 0: # Group tasks with the same tag together for visual cleanness 184 if sort == 0: # Group tasks with the same tag together for visual cleanness
185 t1_tags = task1.get_tags_name()185 t1_tags = task1.get_tags_name()
186 t1_tags.sort()186 t1_tags.sort()
187 t2_tags = task2.get_tags_name()187 t2_tags = task2.get_tags_name()
188 t2_tags.sort()188 t2_tags.sort()
189 sort = reverse_if_descending(cmp(t1_tags, t2_tags))189 sort = reverse_if_descending(cmp(t1_tags, t2_tags))
190 190
191 if sort == 0: # Break ties by sorting by title191 if sort == 0: # Break ties by sorting by title
192 t1_title = task1.get_title()192 t1_title = task1.get_title()
193 t2_title = task2.get_title()193 t2_title = task2.get_title()
194 t1_title = locale.strxfrm(t1_title)194 t1_title = locale.strxfrm(t1_title)
195 t2_title = locale.strxfrm(t2_title)195 t2_title = locale.strxfrm(t2_title)
196 sort = reverse_if_descending(cmp(t1_title, t2_title))196 sort = reverse_if_descending(cmp(t1_title, t2_title))
197 197
198 return sort198 return sort
199 199
200 #############################200 #############################
201 #Functions for tags columns201 #Functions for tags columns
202 #############################202 #############################
203 def tag_name(self,node):203 def tag_name(self, node):
204 label = node.get_attribute("label")204 label = node.get_attribute("label")
205 if label.startswith('@'):205 if label.startswith('@'):
206 label = label[1:]206 label = label[1:]
@@ -209,18 +209,18 @@
209 return "<span color='%s'>%s</span>" %(self.unactive_color, label)209 return "<span color='%s'>%s</span>" %(self.unactive_color, label)
210 else:210 else:
211 return label211 return label
212 212
213 def get_tag_count(self,node):213 def get_tag_count(self, node):
214 if node.get_id() == 'search':214 if node.get_id() == 'search':
215 return ""215 return ""
216 else:216 else:
217 toreturn = node.get_active_tasks_count()217 toreturn = node.get_active_tasks_count()
218 return "<span color='%s'>%s</span>" %(self.unactive_color,toreturn)218 return "<span color='%s'>%s</span>" %(self.unactive_color, toreturn)
219 219
220 def is_tag_separator_filter(self,tag):220 def is_tag_separator_filter(self, tag):
221 return tag.get_attribute('special') == 'sep'221 return tag.get_attribute('special') == 'sep'
222 222
223 def tag_sorting(self,t1,t2,order):223 def tag_sorting(self, t1, t2, order):
224 t1_sp = t1.get_attribute("special")224 t1_sp = t1.get_attribute("special")
225 t2_sp = t2.get_attribute("special")225 t2_sp = t2.get_attribute("special")
226 t1_name = locale.strxfrm(t1.get_name())226 t1_name = locale.strxfrm(t1.get_name())
@@ -235,8 +235,8 @@
235 t1_order = t1.get_attribute("order")235 t1_order = t1.get_attribute("order")
236 t2_order = t2.get_attribute("order")236 t2_order = t2.get_attribute("order")
237 return cmp(t1_order, t2_order)237 return cmp(t1_order, t2_order)
238 238
239 def ontag_task_dnd(self,source,target):239 def ontag_task_dnd(self, source, target):
240 task = self.req.get_task(source)240 task = self.req.get_task(source)
241 if target.startswith('@'):241 if target.startswith('@'):
242 task.add_tag(target)242 task.add_tag(target)
@@ -248,7 +248,7 @@
248 ############################################248 ############################################
249 ######## The Factory #######################249 ######## The Factory #######################
250 ############################################250 ############################################
251 def tags_treeview(self,tree):251 def tags_treeview(self, tree):
252 desc = {}252 desc = {}
253253
254 #Tag id254 #Tag id
@@ -260,32 +260,32 @@
260 col['order'] = 0260 col['order'] = 0
261 col['sorting_func'] = self.tag_sorting261 col['sorting_func'] = self.tag_sorting
262 desc[col_name] = col262 desc[col_name] = col
263 263
264 #Tags color264 #Tags color
265 col_name = 'color'265 col_name = 'color'
266 col = {}266 col = {}
267 render_tags = CellRendererTags()267 render_tags = CellRendererTags()
268 render_tags.set_property('ypad', 3)268 render_tags.set_property('ypad', 3)
269 col['title'] = _("Tags")269 col['title'] = _("Tags")
270 col['renderer'] = ['tag',render_tags]270 col['renderer'] = ['tag', render_tags]
271 col['value'] = [gobject.TYPE_PYOBJECT,lambda node: node]271 col['value'] = [gobject.TYPE_PYOBJECT, lambda node: node]
272 col['expandable'] = False272 col['expandable'] = False
273 col['resizable'] = False273 col['resizable'] = False
274 col['order'] = 1274 col['order'] = 1
275 desc[col_name] = col275 desc[col_name] = col
276 276
277 #Tag names277 #Tag names
278 col_name = 'tagname'278 col_name = 'tagname'
279 col = {}279 col = {}
280 render_text = gtk.CellRendererText()280 render_text = gtk.CellRendererText()
281 render_text.set_property('ypad', 3)281 render_text.set_property('ypad', 3)
282 col['renderer'] = ['markup',render_text]282 col['renderer'] = ['markup', render_text]
283 col['value'] = [str,self.tag_name]283 col['value'] = [str, self.tag_name]
284 col['expandable'] = True284 col['expandable'] = True
285 col['new_column'] = False285 col['new_column'] = False
286 col['order'] = 2286 col['order'] = 2
287 desc[col_name] = col287 desc[col_name] = col
288 288
289 #Tag count289 #Tag count
290 col_name = 'tagcount'290 col_name = 'tagcount'
291 col = {}291 col = {}
@@ -293,26 +293,26 @@
293 render_text.set_property('xpad', 3)293 render_text.set_property('xpad', 3)
294 render_text.set_property('ypad', 3)294 render_text.set_property('ypad', 3)
295 render_text.set_property('xalign', 1.0)295 render_text.set_property('xalign', 1.0)
296 col['renderer'] = ['markup',render_text]296 col['renderer'] = ['markup', render_text]
297 col['value'] = [str,self.get_tag_count]297 col['value'] = [str, self.get_tag_count]
298 col['expandable'] = False298 col['expandable'] = False
299 col['new_column'] = False299 col['new_column'] = False
300 col['order'] = 3300 col['order'] = 3
301 desc[col_name] = col301 desc[col_name] = col
302302
303 return self.build_tag_treeview(tree,desc)303 return self.build_tag_treeview(tree, desc)
304 304
305 def active_tasks_treeview(self,tree):305 def active_tasks_treeview(self, tree):
306 #Build the title/label/tags columns306 #Build the title/label/tags columns
307 desc = self.common_desc_for_tasks(tree)307 desc = self.common_desc_for_tasks(tree)
308 308
309 # "startdate" column309 # "startdate" column
310 col_name = 'startdate'310 col_name = 'startdate'
311 col = {}311 col = {}
312 col['title'] = _("Start date")312 col['title'] = _("Start date")
313 col['expandable'] = False313 col['expandable'] = False
314 col['resizable'] = False314 col['resizable'] = False
315 col['value'] = [str,self.task_sdate_column]315 col['value'] = [str, self.task_sdate_column]
316 col['order'] = 3316 col['order'] = 3
317 col['sorting_func'] = self.start_date_sorting317 col['sorting_func'] = self.start_date_sorting
318 desc[col_name] = col318 desc[col_name] = col
@@ -323,40 +323,40 @@
323 col['title'] = _("Due")323 col['title'] = _("Due")
324 col['expandable'] = False324 col['expandable'] = False
325 col['resizable'] = False325 col['resizable'] = False
326 col['value'] = [str,self.task_duedate_column]326 col['value'] = [str, self.task_duedate_column]
327 col['order'] = 4327 col['order'] = 4
328 col['sorting_func'] = self.due_date_sorting328 col['sorting_func'] = self.due_date_sorting
329 desc[col_name] = col329 desc[col_name] = col
330330
331 #Returning the treeview331 #Returning the treeview
332 treeview = self.build_task_treeview(tree,desc)332 treeview = self.build_task_treeview(tree, desc)
333 treeview.set_sort_column('duedate')333 treeview.set_sort_column('duedate')
334 return treeview334 return treeview
335 335
336 def closed_tasks_treeview(self,tree):336 def closed_tasks_treeview(self, tree):
337 #Build the title/label/tags columns337 #Build the title/label/tags columns
338 desc = self.common_desc_for_tasks(tree)338 desc = self.common_desc_for_tasks(tree)
339 339
340 # "startdate" column340 # "startdate" column
341 col_name = 'closeddate'341 col_name = 'closeddate'
342 col = {}342 col = {}
343 col['title'] = _("Closed date")343 col['title'] = _("Closed date")
344 col['expandable'] = False344 col['expandable'] = False
345 col['resizable'] = False345 col['resizable'] = False
346 col['value'] = [str,self.task_cdate_column]346 col['value'] = [str, self.task_cdate_column]
347 col['order'] = 3347 col['order'] = 3
348 col['sorting_func'] = self.closed_date_sorting348 col['sorting_func'] = self.closed_date_sorting
349 desc[col_name] = col349 desc[col_name] = col
350350
351 #Returning the treeview351 #Returning the treeview
352 treeview = self.build_task_treeview(tree,desc)352 treeview = self.build_task_treeview(tree, desc)
353 treeview.set_sort_column('closeddate')353 treeview.set_sort_column('closeddate')
354 return treeview354 return treeview
355 355
356 356
357 #This build the first tag/title columns, common357 #This build the first tag/title columns, common
358 #to both active and closed tasks treeview358 #to both active and closed tasks treeview
359 def common_desc_for_tasks(self,tree):359 def common_desc_for_tasks(self, tree):
360 desc = {}360 desc = {}
361361
362 #invisible 'task_id' column362 #invisible 'task_id' column
@@ -380,20 +380,20 @@
380 col = {}380 col = {}
381 render_text = gtk.CellRendererText()381 render_text = gtk.CellRendererText()
382 render_text.set_property("ellipsize", pango.ELLIPSIZE_END)382 render_text.set_property("ellipsize", pango.ELLIPSIZE_END)
383 col['renderer'] = ['markup',render_text]383 col['renderer'] = ['markup', render_text]
384 col['value'] = [str,self.task_title_column]384 col['value'] = [str, self.task_title_column]
385 col['visible'] = False385 col['visible'] = False
386 col['order'] = 0386 col['order'] = 0
387 col['sorting_func'] = self.title_sorting387 col['sorting_func'] = self.title_sorting
388 desc[col_name] = col388 desc[col_name] = col
389 389
390 # "tags" column (no title)390 # "tags" column (no title)
391 col_name = 'tags'391 col_name = 'tags'
392 col = {}392 col = {}
393 render_tags = CellRendererTags()393 render_tags = CellRendererTags()
394 render_tags.set_property('xalign', 0.0)394 render_tags.set_property('xalign', 0.0)
395 col['renderer'] = ['tag_list',render_tags]395 col['renderer'] = ['tag_list', render_tags]
396 col['value'] = [gobject.TYPE_PYOBJECT,self.task_tags_column]396 col['value'] = [gobject.TYPE_PYOBJECT, self.task_tags_column]
397 col['expandable'] = False397 col['expandable'] = False
398 col['resizable'] = False398 col['resizable'] = False
399 col['order'] = 1399 col['order'] = 1
@@ -405,18 +405,18 @@
405 col['title'] = _("Title")405 col['title'] = _("Title")
406 render_text = gtk.CellRendererText()406 render_text = gtk.CellRendererText()
407 render_text.set_property("ellipsize", pango.ELLIPSIZE_END)407 render_text.set_property("ellipsize", pango.ELLIPSIZE_END)
408 col['renderer'] = ['markup',render_text]408 col['renderer'] = ['markup', render_text]
409 col['value'] = [str,self.task_label_column]409 col['value'] = [str, self.task_label_column]
410 col['expandable'] = True410 col['expandable'] = True
411 col['resizable'] = True411 col['resizable'] = True
412 col['sorting'] = 'title'412 col['sorting'] = 'title'
413 col['order'] = 2413 col['order'] = 2
414 desc[col_name] = col414 desc[col_name] = col
415 return desc415 return desc
416 416
417 417
418 def build_task_treeview(self,tree,desc):418 def build_task_treeview(self, tree, desc):
419 treeview = TreeView(tree,desc)419 treeview = TreeView(tree, desc)
420 #Now that the treeview is done, we can polish420 #Now that the treeview is done, we can polish
421 treeview.set_main_search_column('label')421 treeview.set_main_search_column('label')
422 treeview.set_expander_column('label')422 treeview.set_expander_column('label')
@@ -431,19 +431,19 @@
431 self.unactive_color = \431 self.unactive_color = \
432 treeview.style.text[gtk.STATE_INSENSITIVE].to_string()432 treeview.style.text[gtk.STATE_INSENSITIVE].to_string()
433 return treeview433 return treeview
434 434
435 def build_tag_treeview(self,tree,desc):435 def build_tag_treeview(self, tree, desc):
436 treeview = TreeView(tree,desc)436 treeview = TreeView(tree, desc)
437 # Global treeview properties437 # Global treeview properties
438 treeview.set_property("enable-tree-lines", False)438 treeview.set_property("enable-tree-lines", False)
439 treeview.set_rules_hint(False)439 treeview.set_rules_hint(False)
440 treeview.set_row_separator_func(self.is_tag_separator_filter)440 treeview.set_row_separator_func(self.is_tag_separator_filter)
441 treeview.set_headers_visible(False)441 treeview.set_headers_visible(False)
442 treeview.set_dnd_name('gtg/tag-iter-str')442 treeview.set_dnd_name('gtg/tag-iter-str')
443 treeview.set_dnd_external('gtg/task-iter-str',self.ontag_task_dnd)443 treeview.set_dnd_external('gtg/task-iter-str', self.ontag_task_dnd)
444 #Updating the unactive color (same for everyone)444 #Updating the unactive color (same for everyone)
445 self.unactive_color = \445 self.unactive_color = \
446 treeview.style.text[gtk.STATE_INSENSITIVE].to_string()446 treeview.style.text[gtk.STATE_INSENSITIVE].to_string()
447 treeview.set_sort_column('tag_id')447 treeview.set_sort_column('tag_id')
448 self.tags_view = treeview448 self.tags_view = treeview
449 return treeview 449 return treeview
450450
=== modified file 'GTG/gtk/crashhandler.py'
--- GTG/gtk/crashhandler.py 2012-07-23 12:04:01 +0000
+++ GTG/gtk/crashhandler.py 2012-11-25 21:29:25 +0000
@@ -332,7 +332,7 @@
332 yield332 yield
333333
334initialize(app_name = "Getting Things GNOME!",334initialize(app_name = "Getting Things GNOME!",
335 message = "GTG" + info.VERSION +335 message = "GTG" + info.VERSION +
336 _(" has crashed. Please report the bug on <a href=\""336 _(" has crashed. Please report the bug on <a href=\""
337 "http://bugs.edge.launchpad.net/gtg\">our Launchpad page</a>."337 "http://bugs.edge.launchpad.net/gtg\">our Launchpad page</a>."
338 " If you have Apport installed, it will be started for you."),338 " If you have Apport installed, it will be started for you."),
339339
=== modified file 'GTG/gtk/delete_dialog.py'
--- GTG/gtk/delete_dialog.py 2012-05-23 08:55:31 +0000
+++ GTG/gtk/delete_dialog.py 2012-11-25 21:29:25 +0000
@@ -24,18 +24,19 @@
2424
2525
26class DeletionUI():26class DeletionUI():
27 27
28 MAXIMUM_TIDS_TO_SHOW = 528 MAXIMUM_TIDS_TO_SHOW = 5
29
29 def __init__(self, req):30 def __init__(self, req):
30 self.req = req31 self.req = req
31 self.tids_todelete = []32 self.tids_todelete = []
32 # Tags which must be updated33 # Tags which must be updated
33 self.update_tags = []34 self.update_tags = []
34 # Load window tree35 # Load window tree
35 self.builder = gtk.Builder() 36 self.builder = gtk.Builder()
36 self.builder.add_from_file(ViewConfig.DELETE_GLADE_FILE)37 self.builder.add_from_file(ViewConfig.DELETE_GLADE_FILE)
37 signals = { "on_delete_confirm": self.on_delete_confirm,38 signals = {"on_delete_confirm": self.on_delete_confirm,
38 "on_delete_cancel": lambda x: x.hide,}39 "on_delete_cancel": lambda x: x.hide, }
39 self.builder.connect_signals(signals)40 self.builder.connect_signals(signals)
4041
41 def on_delete_confirm(self, widget):42 def on_delete_confirm(self, widget):
@@ -43,7 +44,7 @@
43 otherwise, we will look which tid is selected"""44 otherwise, we will look which tid is selected"""
44 for tid in self.tids_todelete:45 for tid in self.tids_todelete:
45 if self.req.has_task(tid):46 if self.req.has_task(tid):
46 self.req.delete_task(tid,recursive=True)47 self.req.delete_task(tid, recursive=True)
47 self.tids_todelete = []48 self.tids_todelete = []
4849
49 # Update tags50 # Update tags
@@ -60,10 +61,11 @@
60 tasklist=[]61 tasklist=[]
61 self.update_tags = []62 self.update_tags = []
62 for tid in self.tids_todelete:63 for tid in self.tids_todelete:
64
63 def recursive_list_tasks(task_list, root):65 def recursive_list_tasks(task_list, root):
64 """Populate a list of all the subtasks and 66 """Populate a list of all the subtasks and
65 their children, recursively.67 their children, recursively.
66 68
67 Also collect the list of affected tags69 Also collect the list of affected tags
68 which should be refreshed"""70 which should be refreshed"""
69 if root not in task_list:71 if root not in task_list:
@@ -78,7 +80,7 @@
78 task = self.req.get_task(tid)80 task = self.req.get_task(tid)
79 recursive_list_tasks(tasklist, task)81 recursive_list_tasks(tasklist, task)
8082
81 # We fill the text and the buttons' labels according to the number 83 # We fill the text and the buttons' labels according to the number
82 # of tasks to delete84 # of tasks to delete
83 label = self.builder.get_object("label1")85 label = self.builder.get_object("label1")
84 label_text = label.get_text()86 label_text = label.get_text()
@@ -104,7 +106,7 @@
104 "Permanently remove tasks",106 "Permanently remove tasks",
105 singular))107 singular))
106 label_text = label_text[0:label_text.find(":") + 1]108 label_text = label_text[0:label_text.find(":") + 1]
107 109
108 #we don't want to end with just one task that doesn't fit the110 #we don't want to end with just one task that doesn't fit the
109 # screen and a line saying "And one more task", so we go a111 # screen and a line saying "And one more task", so we go a
110 # little over our limit112 # little over our limit
@@ -123,7 +125,7 @@
123 cancel_button = self.builder.get_object("cancel")125 cancel_button = self.builder.get_object("cancel")
124 cancel_button.grab_focus()126 cancel_button.grab_focus()
125 if delete_dialog.run() != 1:127 if delete_dialog.run() != 1:
126 tasklist = []128 tasklist = []
127 delete_dialog.hide()129 delete_dialog.hide()
128 return tasklist130 return tasklist
129 else:131 else:
130132
=== modified file 'GTG/gtk/editor/__init__.py'
--- GTG/gtk/editor/__init__.py 2012-05-23 08:55:31 +0000
+++ GTG/gtk/editor/__init__.py 2012-11-25 21:29:25 +0000
@@ -21,12 +21,12 @@
21"""21"""
22import os22import os
2323
24from GTG import _24from GTG import _
2525
2626
27class GnomeConfig:27class GnomeConfig:
28 current_rep = os.path.dirname(os.path.abspath(__file__))28 current_rep = os.path.dirname(os.path.abspath(__file__))
29 GLADE_FILE = os.path.join(current_rep, "taskeditor.glade")29 GLADE_FILE = os.path.join(current_rep, "taskeditor.glade")
3030
31 MARK_DONE = _("Mark as Done")31 MARK_DONE = _("Mark as Done")
32 MARK_UNDONE = _("Mark as not Done")32 MARK_UNDONE = _("Mark as not Done")
3333
=== modified file 'GTG/gtk/editor/editor.py'
--- GTG/gtk/editor/editor.py 2012-08-26 16:41:47 +0000
+++ GTG/gtk/editor/editor.py 2012-11-25 21:29:25 +0000
@@ -28,21 +28,22 @@
28import pango28import pango
29import gtk29import gtk
3030
31from GTG import _, ngettext31from GTG import _, ngettext
32from GTG.gtk.editor import GnomeConfig32from GTG.gtk.editor import GnomeConfig
33from GTG.gtk.editor.taskview import TaskView33from GTG.gtk.editor.taskview import TaskView
34from GTG.core.plugins.engine import PluginEngine34from GTG.core.plugins.engine import PluginEngine
35from GTG.core.plugins.api import PluginAPI35from GTG.core.plugins.api import PluginAPI
36from GTG.core.task import Task36from GTG.core.task import Task
37from GTG.tools.dates import Date37from GTG.tools.dates import Date
38from GTG.gtk.editor.calendar import GTGCalendar38from GTG.gtk.editor.calendar import GTGCalendar
3939
40
40class TaskEditor:41class TaskEditor:
4142
42 def __init__(self, 43 def __init__(self,
43 requester, 44 requester,
44 vmanager, 45 vmanager,
45 task, 46 task,
46 taskconfig = None,47 taskconfig = None,
47 thisisnew = False,48 thisisnew = False,
48 clipboard = None):49 clipboard = None):
@@ -91,13 +92,13 @@
91 "on_move": self.on_move,92 "on_move": self.on_move,
92 }93 }
93 self.builder.connect_signals(dic)94 self.builder.connect_signals(dic)
94 self.window = self.builder.get_object("TaskEditor")95 self.window = self.builder.get_object("TaskEditor")
95 #Removing the Normal textview to replace it by our own96 #Removing the Normal textview to replace it by our own
96 #So don't try to change anything with glade, this is a home-made widget97 #So don't try to change anything with glade, this is a home-made widget
97 textview = self.builder.get_object("textview")98 textview = self.builder.get_object("textview")
98 scrolled = self.builder.get_object("scrolledtask")99 scrolled = self.builder.get_object("scrolledtask")
99 scrolled.remove(textview)100 scrolled.remove(textview)
100 self.textview = TaskView(self.req, self.clipboard)101 self.textview = TaskView(self.req, self.clipboard)
101 self.textview.show()102 self.textview.show()
102 self.textview.set_subtask_callback(self.new_subtask)103 self.textview.set_subtask_callback(self.new_subtask)
103 self.textview.open_task_callback(self.vmanager.open_task)104 self.textview.open_task_callback(self.vmanager.open_task)
@@ -106,13 +107,13 @@
106 scrolled.add(self.textview)107 scrolled.add(self.textview)
107 conf_font_value = self.browser_config.get("font_name")108 conf_font_value = self.browser_config.get("font_name")
108 if conf_font_value!= "":109 if conf_font_value!= "":
109 self.textview.modify_font(pango.FontDescription(conf_font_value)) 110 self.textview.modify_font(pango.FontDescription(conf_font_value))
110 #Voila! it's done111 #Voila! it's done
111 self.calendar = GTGCalendar(self.builder)112 self.calendar = GTGCalendar(self.builder)
112 self.duedate_widget = self.builder.get_object("duedate_entry")113 self.duedate_widget = self.builder.get_object("duedate_entry")
113 self.startdate_widget = self.builder.get_object("startdate_entry")114 self.startdate_widget = self.builder.get_object("startdate_entry")
114 self.closeddate_widget = self.builder.get_object("closeddate_entry")115 self.closeddate_widget = self.builder.get_object("closeddate_entry")
115 self.dayleft_label = self.builder.get_object("dayleft")116 self.dayleft_label = self.builder.get_object("dayleft")
116 self.tasksidebar = self.builder.get_object("tasksidebar")117 self.tasksidebar = self.builder.get_object("tasksidebar")
117 # Define accelerator keys118 # Define accelerator keys
118 self.init_accelerators()119 self.init_accelerators()
@@ -169,14 +170,15 @@
169 if tid in self.config:170 if tid in self.config:
170 if "position" in self.config[tid]:171 if "position" in self.config[tid]:
171 pos = self.config[tid]["position"]172 pos = self.config[tid]["position"]
172 self.move(pos[0],pos[1])173 self.move(pos[0], pos[1])
173 #print "restoring position %s %s" %(pos[0],pos[1])174 #print "restoring position %s %s" %(pos[0], pos[1])
174 if "size" in self.config[tid]:175 if "size" in self.config[tid]:
175 size = self.config[tid]["size"]176 size = self.config[tid]["size"]
176 #print "size %s - %s" %(str(size[0]), str(size[1]))177 #print "size %s - %s" %(str(size[0]), str(size[1]))
177 #this eval(str()) is a ugly (!) hack to accept both int and str178 #this eval(str()) is a ugly (!) hack to accept both int and
179 #str
178 #FIXME: Fix this!180 #FIXME: Fix this!
179 self.window.resize(eval(str(size[0])),eval(str(size[1])))181 self.window.resize(eval(str(size[0])), eval(str(size[1])))
180182
181 self.textview.set_editable(True)183 self.textview.set_editable(True)
182 self.window.show()184 self.window.show()
@@ -201,18 +203,21 @@
201203
202 # Ctrl-Shift-N creates a new subtask204 # Ctrl-Shift-N creates a new subtask
203 insert_subtask = self.builder.get_object("insert_subtask")205 insert_subtask = self.builder.get_object("insert_subtask")
204 key, mod = gtk.accelerator_parse("<Control><Shift>n")206 key, mod = gtk.accelerator_parse("<Control><Shift>n")
205 insert_subtask.add_accelerator('clicked', agr, key, mod, gtk.ACCEL_VISIBLE)207 insert_subtask.add_accelerator('clicked', agr, key, mod,
208 gtk.ACCEL_VISIBLE)
206209
207 # Ctrl-D marks task as done210 # Ctrl-D marks task as done
208 mark_as_done_editor = self.builder.get_object('mark_as_done_editor')211 mark_as_done_editor = self.builder.get_object('mark_as_done_editor')
209 key, mod = gtk.accelerator_parse('<Control>d')212 key, mod = gtk.accelerator_parse('<Control>d')
210 mark_as_done_editor.add_accelerator('clicked', agr, key, mod, gtk.ACCEL_VISIBLE)213 mark_as_done_editor.add_accelerator('clicked', agr, key, mod,
214 gtk.ACCEL_VISIBLE)
211215
212 # Ctrl-I marks task as dismissed216 # Ctrl-I marks task as dismissed
213 dismiss_editor = self.builder.get_object('dismiss_editor')217 dismiss_editor = self.builder.get_object('dismiss_editor')
214 key, mod = gtk.accelerator_parse('<Control>i')218 key, mod = gtk.accelerator_parse('<Control>i')
215 dismiss_editor.add_accelerator('clicked', agr, key, mod, gtk.ACCEL_VISIBLE)219 dismiss_editor.add_accelerator('clicked', agr, key, mod,
220 gtk.ACCEL_VISIBLE)
216221
217 #Can be called at any time to reflect the status of the Task222 #Can be called at any time to reflect the status of the Task
218 #Refresh should never interfere with the TaskView.223 #Refresh should never interfere with the TaskView.
@@ -224,34 +229,37 @@
224 if self.window == None:229 if self.window == None:
225 return230 return
226 to_save = False231 to_save = False
227 #title of the window 232 #title of the window
228 if title:233 if title:
229 self.window.set_title(title)234 self.window.set_title(title)
230 to_save = True235 to_save = True
231 else:236 else:
232 self.window.set_title(self.task.get_title())237 self.window.set_title(self.task.get_title())
233238
234 status = self.task.get_status() 239 status = self.task.get_status()
235 if status == Task.STA_DISMISSED:240 if status == Task.STA_DISMISSED:
236 self.donebutton.set_label(GnomeConfig.MARK_DONE)241 self.donebutton.set_label(GnomeConfig.MARK_DONE)
237 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)242 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)
238 self.donebutton.set_icon_name("gtg-task-done")243 self.donebutton.set_icon_name("gtg-task-done")
239 self.dismissbutton.set_label(GnomeConfig.MARK_UNDISMISS)244 self.dismissbutton.set_label(GnomeConfig.MARK_UNDISMISS)
240 self.dismissbutton.set_tooltip_text(GnomeConfig.MARK_UNDISMISS_TOOLTIP)245 self.dismissbutton.set_tooltip_text(
246 nomeConfig.MARK_UNDISMISS_TOOLTIP)
241 self.dismissbutton.set_icon_name("gtg-task-undismiss")247 self.dismissbutton.set_icon_name("gtg-task-undismiss")
242 elif status == Task.STA_DONE:248 elif status == Task.STA_DONE:
243 self.donebutton.set_label(GnomeConfig.MARK_UNDONE)249 self.donebutton.set_label(GnomeConfig.MARK_UNDONE)
244 self.donebutton.set_tooltip_text(GnomeConfig.MARK_UNDONE_TOOLTIP)250 self.donebutton.set_tooltip_text(GnomeConfig.MARK_UNDONE_TOOLTIP)
245 self.donebutton.set_icon_name("gtg-task-undone")251 self.donebutton.set_icon_name("gtg-task-undone")
246 self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS)252 self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS)
247 self.dismissbutton.set_tooltip_text(GnomeConfig.MARK_DISMISS_TOOLTIP)253 self.dismissbutton.set_tooltip_text(
254 GnomeConfig.MARK_DISMISS_TOOLTIP)
248 self.dismissbutton.set_icon_name("gtg-task-dismiss")255 self.dismissbutton.set_icon_name("gtg-task-dismiss")
249 else:256 else:
250 self.donebutton.set_label(GnomeConfig.MARK_DONE)257 self.donebutton.set_label(GnomeConfig.MARK_DONE)
251 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)258 self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP)
252 self.donebutton.set_icon_name("gtg-task-done")259 self.donebutton.set_icon_name("gtg-task-done")
253 self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS)260 self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS)
254 self.dismissbutton.set_tooltip_text(GnomeConfig.MARK_DISMISS_TOOLTIP)261 self.dismissbutton.set_tooltip_text(
262 GnomeConfig.MARK_DISMISS_TOOLTIP)
255 self.dismissbutton.set_icon_name("gtg-task-dismiss")263 self.dismissbutton.set_icon_name("gtg-task-dismiss")
256 self.donebutton.show()264 self.donebutton.show()
257 self.tasksidebar.show()265 self.tasksidebar.show()
@@ -265,7 +273,7 @@
265 else:273 else:
266 self.builder.get_object("label4").hide()274 self.builder.get_object("label4").hide()
267 self.builder.get_object("hbox4").hide()275 self.builder.get_object("hbox4").hide()
268 self.builder.get_object("label2").show() 276 self.builder.get_object("label2").show()
269 self.builder.get_object("hbox1").show()277 self.builder.get_object("hbox1").show()
270278
271 #refreshing the start date field279 #refreshing the start date field
@@ -277,7 +285,7 @@
277 update_date = True285 update_date = True
278286
279 if update_date:287 if update_date:
280 self.startdate_widget.set_text(str(startdate)) 288 self.startdate_widget.set_text(str(startdate))
281289
282 #refreshing the due date field290 #refreshing the due date field
283 duedate = self.task.get_due_date()291 duedate = self.task.get_due_date()
@@ -297,8 +305,8 @@
297 self.closeddate_widget.set_text(str(closeddate))305 self.closeddate_widget.set_text(str(closeddate))
298306
299 #refreshing the day left label307 #refreshing the day left label
300 #If the task is marked as done, we display the delay between the 308 #If the task is marked as done, we display the delay between the
301 #due date and the actual closing date. If the task isn't marked 309 #due date and the actual closing date. If the task isn't marked
302 #as done, we display the number of days left.310 #as done, we display the number of days left.
303 if status in [Task.STA_DISMISSED, Task.STA_DONE]:311 if status in [Task.STA_DISMISSED, Task.STA_DONE]:
304 delay = self.task.get_days_late()312 delay = self.task.get_days_late()
@@ -307,22 +315,27 @@
307 elif delay == 0:315 elif delay == 0:
308 txt = "Completed on time"316 txt = "Completed on time"
309 elif delay >= 1:317 elif delay >= 1:
310 txt = ngettext("Completed %(days)d day late", "Completed %(days)d days late", delay) % {'days': delay}318 txt = ngettext("Completed %(days)d day late",
319 "Completed %(days)d days late", delay) % {'days': delay}
311 elif delay <= -1:320 elif delay <= -1:
312 abs_delay = abs(delay)321 abs_delay = abs(delay)
313 txt = ngettext("Completed %(days)d day early", "Completed %(days)d days early", abs_delay) % {'days': abs_delay}322 txt = ngettext("Completed %(days)d day early",
323 "Completed %(days)d days early", abs_delay) % \
324 {'days': abs_delay}
314 else:325 else:
315 due_date = self.task.get_due_date()326 due_date = self.task.get_due_date()
316 result = due_date.days_left()327 result = due_date.days_left()
317 if due_date.is_fuzzy():328 if due_date.is_fuzzy():
318 txt = ""329 txt = ""
319 elif result > 0:330 elif result > 0:
320 txt = ngettext("Due tomorrow!", "%(days)d days left", result) % {'days': result}331 txt = ngettext("Due tomorrow!", "%(days)d days left", result) \
332 % {'days': result}
321 elif result == 0:333 elif result == 0:
322 txt = _("Due today!")334 txt = _("Due today!")
323 elif result < 0:335 elif result < 0:
324 abs_result = abs(result)336 abs_result = abs(result)
325 txt = ngettext("Due yesterday!", "Was %(days)d days ago", abs_result) % {'days': abs_result}337 txt = ngettext("Due yesterday!", "Was %(days)d days ago",
338 abs_result) % {'days': abs_result}
326 window_style = self.window.get_style()339 window_style = self.window.get_style()
327 color = str(window_style.text[gtk.STATE_INSENSITIVE])340 color = str(window_style.text[gtk.STATE_INSENSITIVE])
328 self.dayleft_label.set_markup("<span color='"+color+"'>"+txt+"</span>")341 self.dayleft_label.set_markup("<span color='"+color+"'>"+txt+"</span>")
@@ -348,7 +361,7 @@
348 if to_save:361 if to_save:
349 self.light_save()362 self.light_save()
350363
351 def date_changed(self,widget,data):364 def date_changed(self, widget, data):
352 text = widget.get_text()365 text = widget.get_text()
353 valid = True366 valid = True
354 if not text:367 if not text:
@@ -418,7 +431,7 @@
418 for task in all_subtasks:431 for task in all_subtasks:
419 self.vmanager.close_task(task.get_id())432 self.vmanager.close_task(task.get_id())
420433
421 def dismiss(self,widget): #pylint: disable-msg=W0613434 def dismiss(self, widget): #pylint: disable-msg=W0613
422 stat = self.task.get_status()435 stat = self.task.get_status()
423 if stat == "Dismiss":436 if stat == "Dismiss":
424 self.task.set_status("Active")437 self.task.set_status("Active")
@@ -428,7 +441,7 @@
428 self.close_all_subtasks()441 self.close_all_subtasks()
429 self.close(None)442 self.close(None)
430443
431 def change_status(self,widget): #pylint: disable-msg=W0613444 def change_status(self, widget): #pylint: disable-msg=W0613
432 stat = self.task.get_status()445 stat = self.task.get_status()
433 if stat == "Done":446 if stat == "Done":
434 self.task.set_status("Active")447 self.task.set_status("Active")
@@ -447,7 +460,7 @@
447 self.vmanager.ask_delete_tasks([self.task.get_id()])460 self.vmanager.ask_delete_tasks([self.task.get_id()])
448461
449 #Take the title as argument and return the subtask ID462 #Take the title as argument and return the subtask ID
450 def new_subtask(self,title=None,tid=None):463 def new_subtask(self, title=None, tid=None):
451 if tid:464 if tid:
452 self.task.add_child(tid)465 self.task.add_child(tid)
453 elif title:466 elif title:
@@ -462,25 +475,25 @@
462 task_id = task.get_id()475 task_id = task.get_id()
463 self.vmanager.open_task(task_id)476 self.vmanager.open_task(task_id)
464477
465 def insert_subtask(self,widget): #pylint: disable-msg=W0613478 def insert_subtask(self, widget): #pylint: disable-msg=W0613
466 self.textview.insert_newtask()479 self.textview.insert_newtask()
467 self.textview.grab_focus()480 self.textview.grab_focus()
468481
469 def inserttag_clicked(self,widget): #pylint: disable-msg=W0613482 def inserttag_clicked(self, widget): #pylint: disable-msg=W0613
470 itera = self.textview.get_insert()483 itera = self.textview.get_insert()
471 if itera.starts_line():484 if itera.starts_line():
472 self.textview.insert_text("@",itera)485 self.textview.insert_text("@", itera)
473 else:486 else:
474 self.textview.insert_text(" @",itera)487 self.textview.insert_text(" @", itera)
475 self.textview.grab_focus()488 self.textview.grab_focus()
476489
477 def inserttag(self,widget,tag): #pylint: disable-msg=W0613490 def inserttag(self, widget, tag): #pylint: disable-msg=W0613
478 self.textview.insert_tags([tag])491 self.textview.insert_tags([tag])
479 self.textview.grab_focus()492 self.textview.grab_focus()
480493
481 def save(self):494 def save(self):
482 self.task.set_title(self.textview.get_title())495 self.task.set_title(self.textview.get_title())
483 self.task.set_text(self.textview.get_text()) 496 self.task.set_text(self.textview.get_text())
484 self.task.sync()497 self.task.sync()
485 if self.config != None:498 if self.config != None:
486 self.config.write()499 self.config.write()
@@ -499,22 +512,22 @@
499 if tosave:512 if tosave:
500 self.save()513 self.save()
501514
502 #This will bring the Task Editor to front 515 #This will bring the Task Editor to front
503 def present(self):516 def present(self):
504 self.window.present()517 self.window.present()
505518
506 def move(self,x,y):519 def move(self, x, y):
507 try:520 try:
508 xx=int(x)521 xx=int(x)
509 yy=int(y)522 yy=int(y)
510 self.window.move(xx,yy)523 self.window.move(xx, yy)
511 except:524 except:
512 pass525 pass
513526
514 def get_position(self):527 def get_position(self):
515 return self.window.get_position()528 return self.window.get_position()
516529
517 def on_move(self,widget,event):530 def on_move(self, widget, event):
518 #saving the position531 #saving the position
519 if self.config != None:532 if self.config != None:
520 tid = self.task.get_id()533 tid = self.task.get_id()
@@ -525,17 +538,19 @@
525 self.config[tid]["size"] = self.window.get_size()538 self.config[tid]["size"] = self.window.get_size()
526539
527 #We define dummy variable for when close is called from a callback540 #We define dummy variable for when close is called from a callback
528 def close(self,window=None,a=None,b=None,c=None): #pylint: disable-msg=W0613541 def close(self, window=None, a=None, b=None, c=None):
542 #pylint: disable-msg=W0613
529 #We should also destroy the whole taskeditor object.543 #We should also destroy the whole taskeditor object.
530 if self.window:544 if self.window:
531 self.window.destroy()545 self.window.destroy()
532 self.window = None546 self.window = None
533547
534 #The destroy signal is linked to the "close" button. So if we call548 #The destroy signal is linked to the "close" button. So if we call
535 #destroy in the close function, this will cause the close to be called twice549 #destroy in the close function, this will cause the close to be called
550 #twice
536 #To solve that, close will just call "destroy" and the destroy signal551 #To solve that, close will just call "destroy" and the destroy signal
537 #Will be linked to this destruction method that will save the task552 #Will be linked to this destruction method that will save the task
538 def destruction(self,a=None):553 def destruction(self, a=None):
539 #Save should be also called when buffer is modified554 #Save should be also called when buffer is modified
540 self.pengine.onTaskClose(self.plugin_api)555 self.pengine.onTaskClose(self.plugin_api)
541 self.pengine.remove_api(self.plugin_api)556 self.pengine.remove_api(self.plugin_api)
542557
=== modified file 'GTG/gtk/editor/taskview.py'
--- GTG/gtk/editor/taskview.py 2012-10-23 09:31:00 +0000
+++ GTG/gtk/editor/taskview.py 2012-11-25 21:29:25 +0000
@@ -16,8 +16,6 @@
16# You should have received a copy of the GNU General Public License along with16# You should have received a copy of the GNU General Public License along with
17# this program. If not, see <http://www.gnu.org/licenses/>.17# this program. If not, see <http://www.gnu.org/licenses/>.
18# -----------------------------------------------------------------------------18# -----------------------------------------------------------------------------
19
20
21"""19"""
22This class implements a gtk.TextView but with many other features20This class implements a gtk.TextView but with many other features
23like hyperlink and other stuff special for GTG21like hyperlink and other stuff special for GTG
@@ -40,10 +38,10 @@
40from GTG.gtk.editor import taskviewserial38from GTG.gtk.editor import taskviewserial
41from GTG.tools import urlregex39from GTG.tools import urlregex
4240
43separators = [' ', ',', '\n', '\t', '!', '?', ';', '\0','(',')']41separators = [' ', ',', '\n', '\t', '!', '?', ';', '\0', '(', ')']
44#those separators are only separators if followed by a space. Else, they42#those separators are only separators if followed by a space. Else, they
45#are part of the word43#are part of the word
46specials_separators = ['.','/']44specials_separators = ['.', '/']
4745
48bullet1_ltr = '→'46bullet1_ltr = '→'
49bullet1_rtl = '←'47bullet1_rtl = '←'
@@ -51,22 +49,22 @@
5149
52class TaskView(gtk.TextView):50class TaskView(gtk.TextView):
53 __gtype_name__ = 'HyperTextView'51 __gtype_name__ = 'HyperTextView'
54 __gsignals__ = {'anchor-clicked': (gobject.SIGNAL_RUN_LAST, \52 __gsignals__ = {'anchor-clicked': (gobject.SIGNAL_RUN_LAST,
55 None, (str, str, int))}53 None, (str, str, int))}
56 __gproperties__ = {54 __gproperties__ = {
57 'link': (gobject.TYPE_PYOBJECT, 'link color',\55 'link': (gobject.TYPE_PYOBJECT, 'link color',
58 'link color of TextView', gobject.PARAM_READWRITE),56 'link color of TextView', gobject.PARAM_READWRITE),
59 'failedlink': (gobject.TYPE_PYOBJECT, 'failed link color',\57 'failedlink': (gobject.TYPE_PYOBJECT, 'failed link color',
60 'failed link color of TextView', gobject.PARAM_READWRITE),58 'failed link color of TextView', gobject.PARAM_READWRITE),
61 'active': (gobject.TYPE_PYOBJECT, 'active color', \59 'active': (gobject.TYPE_PYOBJECT, 'active color',
62 'active color of TextView', gobject.PARAM_READWRITE),60 'active color of TextView', gobject.PARAM_READWRITE),
63 'hover': (gobject.TYPE_PYOBJECT, 'link:hover color', \61 'hover': (gobject.TYPE_PYOBJECT, 'link:hover color',
64 'link:hover color of TextView', gobject.PARAM_READWRITE),62 'link:hover color of TextView', gobject.PARAM_READWRITE),
65 'tag': (gobject.TYPE_PYOBJECT, 'tag color', \63 'tag': (gobject.TYPE_PYOBJECT, 'tag color',
66 'tag color of TextView', gobject.PARAM_READWRITE),64 'tag color of TextView', gobject.PARAM_READWRITE),
67 'done': (gobject.TYPE_PYOBJECT, 'link color', \65 'done': (gobject.TYPE_PYOBJECT, 'link color',
68 'link color of TextView', gobject.PARAM_READWRITE),66 'link color of TextView', gobject.PARAM_READWRITE),
69 'indent': (gobject.TYPE_PYOBJECT, 'indent color', \67 'indent': (gobject.TYPE_PYOBJECT, 'indent color',
70 'indent color of TextView', gobject.PARAM_READWRITE),68 'indent color of TextView', gobject.PARAM_READWRITE),
71 }69 }
7270
@@ -83,22 +81,23 @@
83 raise AttributeError('unknown property %s' % prop.name)81 raise AttributeError('unknown property %s' % prop.name)
8482
85 #Yes, we want to redefine the buffer. Disabling pylint on that error.83 #Yes, we want to redefine the buffer. Disabling pylint on that error.
86 def __init__(self, requester, clipboard, buffer=None): #pylint: disable-msg=W062284 def __init__(self, requester, clipboard, buffer=None):
85 #pylint: disable-msg=W0622
87 gtk.TextView.__init__(self, buffer)86 gtk.TextView.__init__(self, buffer)
88 self.buff = self.get_buffer()87 self.buff = self.get_buffer()
89 self.req = requester88 self.req = requester
90 #Buffer init89 #Buffer init
91 self.link = {'background': 'white', 'foreground': '#007bff', \90 self.link = {'background': 'white', 'foreground': '#007bff',
92 'underline': pango.UNDERLINE_SINGLE, \91 'underline': pango.UNDERLINE_SINGLE,
93 'strikethrough': False}92 'strikethrough': False}
94 self.failedlink = {'background': 'white', 'foreground': '#ff5454', \93 self.failedlink = {'background': 'white', 'foreground': '#ff5454',
95 'underline': pango.UNDERLINE_NONE, \94 'underline': pango.UNDERLINE_NONE,
96 'strikethrough': False}95 'strikethrough': False}
97 self.done = {'background': 'white', 'foreground': 'gray',\96 self.done = {'background': 'white', 'foreground': 'gray',
98 'strikethrough': True}97 'strikethrough': True}
99 self.active = {'background': 'light gray', 'foreground': '#ff1e00',\98 self.active = {'background': 'light gray', 'foreground': '#ff1e00',
100 'underline': pango.UNDERLINE_SINGLE}99 'underline': pango.UNDERLINE_SINGLE}
101 self.hover = {'background': 'light gray'}100 self.hover = {'background': 'light gray'}
102 self.tag = {'background': "#FFea00", 'foreground': 'black'}101 self.tag = {'background': "#FFea00", 'foreground': 'black'}
103 self.indent = {'scale': 1.4, 'editable': False, 'left-margin': 10,102 self.indent = {'scale': 1.4, 'editable': False, 'left-margin': 10,
104 "accumulative-margin": True}103 "accumulative-margin": True}
@@ -108,7 +107,7 @@
108 # but set in self.modified)107 # but set in self.modified)
109 self.table = self.buff.get_tag_table()108 self.table = self.buff.get_tag_table()
110 # Tag for title109 # Tag for title
111 self.title_tag = self.buff.create_tag("title", foreground="#007bff", \110 self.title_tag = self.buff.create_tag("title", foreground="#007bff",
112 scale=1.6, underline=1)111 scale=1.6, underline=1)
113 self.title_tag.set_property("pixels-above-lines", 10)112 self.title_tag.set_property("pixels-above-lines", 10)
114 self.title_tag.set_property("pixels-below-lines", 10)113 self.title_tag.set_property("pixels-below-lines", 10)
@@ -125,13 +124,14 @@
125124
126 #Signals125 #Signals
127 self.connect('motion-notify-event', self._motion)126 self.connect('motion-notify-event', self._motion)
128 self.connect('focus-out-event', lambda w, \127 self.connect('focus-out-event',
129 e: self.table.foreach(self.__tag_reset, e.window))128 lambda w, e: self.table.foreach(self.__tag_reset, e.window))
130 self.insert_sigid = self.buff.connect('insert-text', \129 self.insert_sigid = self.buff.connect('insert-text',
131 self._insert_at_cursor)130 self._insert_at_cursor)
132 self.delete_sigid = self.buff.connect("delete-range", self._delete_range)131 self.delete_sigid = self.buff.connect("delete-range",
133 self.connect('copy-clipboard', self.copy_clipboard,"copy")132 self._delete_range)
134 self.connect('cut-clipboard', self.copy_clipboard,"cut")133 self.connect('copy-clipboard', self.copy_clipboard, "copy")
134 self.connect('cut-clipboard', self.copy_clipboard, "cut")
135 self.connect('paste-clipboard', self.paste_clipboard)135 self.connect('paste-clipboard', self.paste_clipboard)
136136
137 self.connect('drag-data-received', self.drag_receive)137 self.connect('drag-data-received', self.drag_receive)
@@ -146,8 +146,10 @@
146 self.mime_type = 'application/x-gtg-task'146 self.mime_type = 'application/x-gtg-task'
147 serializer = taskviewserial.Serializer()147 serializer = taskviewserial.Serializer()
148 unserializer = taskviewserial.Unserializer(self)148 unserializer = taskviewserial.Unserializer(self)
149 self.buff.register_serialize_format(self.mime_type, serializer.serialize, None)149 self.buff.register_serialize_format(self.mime_type,
150 self.buff.register_deserialize_format(self.mime_type, unserializer.unserialize, None)150 serializer.serialize, None)
151 self.buff.register_deserialize_format(self.mime_type,
152 unserializer.unserialize, None)
151153
152 #The list of callbacks we have to set154 #The list of callbacks we have to set
153 self.remove_tag_callback = None155 self.remove_tag_callback = None
@@ -156,7 +158,7 @@
156 self.get_subtasks = None158 self.get_subtasks = None
157 self.remove_subtask =None159 self.remove_subtask =None
158 self.__refresh_cb = None # refresh the editor window160 self.__refresh_cb = None # refresh the editor window
159 self.open_task = None # open another task161 self.open_task = None # open another task
160 self.new_subtask_callback = None # create a subtask162 self.new_subtask_callback = None # create a subtask
161 self.save_task = None #This will save the task without refreshing all163 self.save_task = None #This will save the task without refreshing all
162164
@@ -185,7 +187,8 @@
185 #editable means that the user can edit the taskview187 #editable means that the user can edit the taskview
186 #this is initially set at False and then to True once the editor window188 #this is initially set at False and then to True once the editor window
187 #is displayed.189 #is displayed.
188 #this is used to avoid saving the task when the window is still not displayed190 #this is used to avoid saving the task when the window is still
191 #not displayed
189 def set_editable(self, boule):192 def set_editable(self, boule):
190 self.editable = boule193 self.editable = boule
191194
@@ -270,7 +273,8 @@
270273
271 #reconnect274 #reconnect
272 if reconnect_insert:275 if reconnect_insert:
273 self.insert_sigid = self.buff.connect('insert-text', self._insert_at_cursor)276 self.insert_sigid = self.buff.connect('insert-text',
277 self._insert_at_cursor)
274 if reconnect_modified:278 if reconnect_modified:
275 self.modified_sigid = self.buff.connect("changed", self.modified)279 self.modified_sigid = self.buff.connect("changed", self.modified)
276280
@@ -308,7 +312,6 @@
308 else:312 else:
309 return True313 return True
310314
311
312 def create_anchor_tag(self, b, anchor, text=None, typ=None):315 def create_anchor_tag(self, b, anchor, text=None, typ=None):
313 #We cannot have two tags with the same name316 #We cannot have two tags with the same name
314 #That's why the link tag has no name317 #That's why the link tag has no name
@@ -326,7 +329,8 @@
326 if linktype == 'link' and not self.check_link(anchor):329 if linktype == 'link' and not self.check_link(anchor):
327 linktype = 'failedlink'330 linktype = 'failedlink'
328331
329 tag = b.create_tag(None, **self.get_property(linktype)) #pylint: disable-msg=W0142332 #pylint: disable-msg=W0142
333 tag = b.create_tag(None, **self.get_property(linktype))
330 tag.set_data('is_anchor', True)334 tag.set_data('is_anchor', True)
331 tag.set_data('link', anchor)335 tag.set_data('link', anchor)
332 if typ:336 if typ:
@@ -349,7 +353,8 @@
349 if ss.begins_tag(t) and ee.ends_tag(t):353 if ss.begins_tag(t) and ee.ends_tag(t):
350 already = True354 already = True
351 if not texttag:355 if not texttag:
352 texttag = buff.create_tag(None,**self.get_property('tag'))#pylint: disable-msg=W0142356 #pylint: disable-msg=W0142
357 texttag = buff.create_tag(None, **self.get_property('tag'))
353 texttag.set_data('is_tag', True)358 texttag.set_data('is_tag', True)
354 texttag.set_data('tagname', tag)359 texttag.set_data('tagname', tag)
355 #This one is for marks360 #This one is for marks
@@ -371,7 +376,8 @@
371 tex = buff.get_text(i_s, i_e)376 tex = buff.get_text(i_s, i_e)
372 if len(tex) > 0:377 if len(tex) > 0:
373 self.req.get_task(subtask).set_title(tex)378 self.req.get_task(subtask).set_title(tex)
374 texttag = self.create_anchor_tag(buff, subtask, text=tex, typ="subtask")379 texttag = self.create_anchor_tag(buff, subtask, text=tex,
380 typ="subtask")
375 texttag.set_data('is_subtask', True)381 texttag.set_data('is_subtask', True)
376 texttag.set_data('child', subtask)382 texttag.set_data('child', subtask)
377 #This one is for marks383 #This one is for marks
@@ -382,7 +388,8 @@
382 buff.delete_mark(e)388 buff.delete_mark(e)
383389
384 def create_indent_tag(self, buff, level):390 def create_indent_tag(self, buff, level):
385 tag = buff.create_tag(None, **self.get_property('indent'))#pylint: disable-msg=W0142391 #pylint: disable-msg=W0142
392 tag = buff.create_tag(None, **self.get_property('indent'))
386 tag.set_data('is_indent', True)393 tag.set_data('is_indent', True)
387 tag.set_data('indent_level', level)394 tag.set_data('indent_level', level)
388 return tag395 return tag
@@ -409,10 +416,12 @@
409 if tt.get_data('is_tag'):416 if tt.get_data('is_tag'):
410 newline = False417 newline = False
411 firstline.forward_to_line_end()418 firstline.forward_to_line_end()
412 #Now we should check if the current char is a separator or not419 # Now we should check if the current char is
413 #Currently, we insert a space420 # a separator or not
421 # Currently, we insert a space
414 self.insert_text(" ", firstline)422 self.insert_text(" ", firstline)
415 #Now we check if this newline is empty (it contains only " " and ",")423 # Now we check if this newline is empty
424 # (it contains only " " and ",")
416 # if newline:425 # if newline:
417 # endline = firstline.copy()426 # endline = firstline.copy()
418 # if not endline.ends_line():427 # if not endline.ends_line():
@@ -428,13 +437,13 @@
428 self.insert_text("\n", firstline)437 self.insert_text("\n", firstline)
429 firstline = self.buff.get_iter_at_line(1)438 firstline = self.buff.get_iter_at_line(1)
430 line_mark = self.buff.create_mark("firstline", firstline, False)439 line_mark = self.buff.create_mark("firstline", firstline, False)
431 #self.tv.insert_at_mark(buf, line_mark,"\n")440 #self.tv.insert_at_mark(buf, line_mark, "\n")
432 ntags = len(tag_list)441 ntags = len(tag_list)
433 for t in tag_list:442 for t in tag_list:
434 ntags = ntags - 1443 ntags = ntags - 1
435 self.insert_at_mark(self.buff, line_mark, t)444 self.insert_at_mark(self.buff, line_mark, t)
436 if ntags != 0:445 if ntags != 0:
437 self.insert_at_mark(self.buff, line_mark,",")446 self.insert_at_mark(self.buff, line_mark, ",")
438 self.buff.delete_mark(line_mark)447 self.buff.delete_mark(line_mark)
439 self.modified(full=True)448 self.modified(full=True)
440449
@@ -490,9 +499,7 @@
490 stripped = title.strip(' \n\t')499 stripped = title.strip(' \n\t')
491 return stripped500 return stripped
492501
493### PRIVATE FUNCTIONS ##########################################################502 ### PRIVATE FUNCTIONS #####################################################
494
495
496 #This function is called so frequently that we should optimize it more.503 #This function is called so frequently that we should optimize it more.
497 def modified(self, buff=None, full=False, refresheditor=True):504 def modified(self, buff=None, full=False, refresheditor=True):
498 """Called when the buffer has been modified.505 """Called when the buffer has been modified.
@@ -538,9 +545,11 @@
538 #subt_list = self.get_subtasks()545 #subt_list = self.get_subtasks()
539 #First, we remove the olds tags546 #First, we remove the olds tags
540 tag_list = []547 tag_list = []
548
541 def subfunc(texttag, data=None): #pylint: disable-msg=W0613549 def subfunc(texttag, data=None): #pylint: disable-msg=W0613
542 if texttag.get_data('is_subtask'):550 if texttag.get_data('is_subtask'):
543 tag_list.append(texttag)551 tag_list.append(texttag)
552
544 table.foreach(subfunc)553 table.foreach(subfunc)
545 start, end = buff.get_bounds()554 start, end = buff.get_bounds()
546 for t in tag_list:555 for t in tag_list:
@@ -583,9 +592,11 @@
583 #First, we remove the olds tags592 #First, we remove the olds tags
584 tag_list = []593 tag_list = []
585 table = buff.get_tag_table()594 table = buff.get_tag_table()
595
586 def subfunc(texttag, data=None):596 def subfunc(texttag, data=None):
587 if texttag.get_data('is_anchor'):597 if texttag.get_data('is_anchor'):
588 tag_list.append(texttag)598 tag_list.append(texttag)
599
589 table.foreach(subfunc)600 table.foreach(subfunc)
590 for t in tag_list:601 for t in tag_list:
591 buff.remove_tag(t, start, end)602 buff.remove_tag(t, start, end)
@@ -606,7 +617,8 @@
606 # For short URL we must add http:// prefix617 # For short URL we must add http:// prefix
607 if text == "www":618 if text == "www":
608 url = "http://" + url619 url = "http://" + url
609 texttag = self.create_anchor_tag(buff, url, text=None, typ="http")620 texttag = self.create_anchor_tag(buff, url, text=None,
621 typ="http")
610 it = prev.copy()622 it = prev.copy()
611 it.forward_chars(m.end())623 it.forward_chars(m.end())
612 buff.apply_tag(texttag, prev, it)624 buff.apply_tag(texttag, prev, it)
@@ -622,15 +634,18 @@
622 nbr = url.split("#")[1]634 nbr = url.split("#")[1]
623 topoint = None635 topoint = None
624 if url.startswith("bug #") or url.startswith("lp #"):636 if url.startswith("bug #") or url.startswith("lp #"):
625 topoint = "https://launchpad.net/bugs/%s" %nbr637 topoint = "https://launchpad.net/bugs/%s" % nbr
626 elif url.startswith("bgo #"):638 elif url.startswith("bgo #"):
627 topoint = "http://bugzilla.gnome.org/show_bug.cgi?id=%s" %nbr639 topoint = "http://bugzilla.gnome.org/" + \
640 "show_bug.cgi?id=%s" % nbr
628 elif url.startswith("bko #"):641 elif url.startswith("bko #"):
629 topoint = "https://bugs.kde.org/show_bug.cgi?id=%s" %nbr642 topoint = "https://bugs.kde.org/show_bug.cgi?id=%s" \
643 % nbr
630 elif url.startswith("fdo #"):644 elif url.startswith("fdo #"):
631 topoint = "http://bugs.freedesktop.org/show_bug.cgi?id=%s" %nbr645 topoint = "http://bugs.freedesktop.org/" + \
646 "show_bug.cgi?id=%s" % nbr
632 if topoint:647 if topoint:
633 texttag = self.create_anchor_tag(buff,\648 texttag = self.create_anchor_tag(buff,
634 topoint, text=None, typ="http")649 topoint, text=None, typ="http")
635 buff.apply_tag(texttag, prev, it)650 buff.apply_tag(texttag, prev, it)
636651
@@ -659,29 +674,31 @@
659 mark1 = buff.get_mark(tagname)674 mark1 = buff.get_mark(tagname)
660 if mark1:675 if mark1:
661 offset1 = buff.get_iter_at_mark(mark1).get_offset()676 offset1 = buff.get_iter_at_mark(mark1).get_offset()
662 if start.get_offset() <= offset1 <= end.get_offset():677 if start.get_offset() <= offset1 <= \
678 end.get_offset():
663 buff.delete_mark_by_name(tagname)679 buff.delete_mark_by_name(tagname)
664 mark2 = buff.get_mark("/%s"%tagname)680 mark2 = buff.get_mark("/%s"%tagname)
665 if mark2:681 if mark2:
666 offset2 = buff.get_iter_at_mark(mark2).get_offset()682 offset2 = buff.get_iter_at_mark(mark2).get_offset()
667 if start.get_offset() <= offset2 <= end.get_offset():683 if start.get_offset() <= offset2 <= \
684 end.get_offset():
668 buff.delete_mark_by_name("/%s"%tagname)685 buff.delete_mark_by_name("/%s"%tagname)
669 it.forward_char()686 it.forward_char()
670687
671 # Set iterators for word688 # Set iterators for word
672 word_start = start.copy()689 word_start = start.copy()
673 word_end = start.copy()690 word_end = start.copy()
674691
675 # Set iterators for char692 # Set iterators for char
676 char_start = start.copy()693 char_start = start.copy()
677 char_end = start.copy()694 char_end = start.copy()
678 char_end.forward_char()695 char_end.forward_char()
679 last_char = None696 last_char = None
680697
681 # Iterate over characters of the line to get words698 # Iterate over characters of the line to get words
682 while char_end.compare(end) <= 0:699 while char_end.compare(end) <= 0:
683 do_word_check = False700 do_word_check = False
684 my_char = buff.get_text(char_start, char_end)701 my_char = buff.get_text(char_start, char_end)
685 if my_char not in separators:702 if my_char not in separators:
686 last_char = my_char703 last_char = my_char
687 word_end = char_end.copy()704 word_end = char_end.copy()
@@ -707,7 +724,8 @@
707 #and it shouldn't start with @@ (bug 531553)724 #and it shouldn't start with @@ (bug 531553)
708 if len(my_word) > 1 and my_word[0] == '@' \725 if len(my_word) > 1 and my_word[0] == '@' \
709 and not my_word[1] == '@':726 and not my_word[1] == '@':
710 #self.apply_tag_tag(buff, my_word, word_start, word_end)727 #self.apply_tag_tag(buff, my_word, word_start,
728 # word_end)
711 #We will add mark where tag should be applied729 #We will add mark where tag should be applied
712 buff.create_mark(my_word, word_start, True)730 buff.create_mark(my_word, word_start, True)
713 buff.create_mark("/%s"%my_word, word_end, False)731 buff.create_mark("/%s"%my_word, word_end, False)
@@ -718,7 +736,7 @@
718736
719 # We set new word boundaries737 # We set new word boundaries
720 word_start = char_end.copy()738 word_start = char_end.copy()
721 word_end = char_end.copy()739 word_end = char_end.copy()
722740
723 # Stop loop if we are at the end741 # Stop loop if we are at the end
724 if char_end.compare(end) == 0:742 if char_end.compare(end) == 0:
@@ -768,7 +786,7 @@
768# buff.remove_tag(ta, start, endindent)786# buff.remove_tag(ta, start, endindent)
769 #Now we delete all, char after char787 #Now we delete all, char after char
770 it = start.copy()788 it = start.copy()
771 while (it.get_offset() <= end.get_offset()) and (it.get_char() != '\0'):789 while it.get_offset() <= end.get_offset() and it.get_char() != '\0':
772 if it.begins_tag():790 if it.begins_tag():
773 tags = it.get_tags()791 tags = it.get_tags()
774 for ta in tags:792 for ta in tags:
@@ -798,7 +816,8 @@
798 #now we really delete the selected stuffs816 #now we really delete the selected stuffs
799 selec = self.buff.get_selection_bounds()817 selec = self.buff.get_selection_bounds()
800# if selec:818# if selec:
801# print "deleted text is ##%s##" %self.buff.get_text(selec[0], selec[1])#(start, end)819# print "deleted text is ##%s##" %self.buff.get_text(selec[0],
820# selec[1])#(start, end)
802# self.buff.disconnect(self.delete_sigid)821# self.buff.disconnect(self.delete_sigid)
803# self.disconnect(self.backspace_sigid)822# self.disconnect(self.backspace_sigid)
804# self.buff.stop_emission("delete-range")823# self.buff.stop_emission("delete-range")
@@ -807,16 +826,20 @@
807# else:826# else:
808# end.forward_char()827# end.forward_char()
809# self.buff.backspace(end, False, True)828# self.buff.backspace(end, False, True)
810# self.delete_sigid = self.buff.connect("delete-range", self._delete_range)829# self.delete_sigid = self.buff.connect("delete-range",
830# self._delete_range)
811# self.backspace_sigid = self.connect("backspace", self.backspace)831# self.backspace_sigid = self.connect("backspace", self.backspace)
812 #We return false so the parent still get the signal832 #We return false so the parent still get the signal
813 return False833 return False
814834
815 #Apply the title and return an iterator after that title.buff.get_iter_at_mar
816 def _apply_title(self, buff, refresheditor=True):835 def _apply_title(self, buff, refresheditor=True):
817 start = buff.get_start_iter()836 """
818 end = buff.get_end_iter()837 Apply the title and return an iterator after that
819 line_nbr = 1838 title.buff.get_iter_at_mar
839 """
840 start = buff.get_start_iter()
841 end = buff.get_end_iter()
842 line_nbr = 1
820 linecount = buff.get_line_count()843 linecount = buff.get_line_count()
821844
822 # Apply the title tag on the first line845 # Apply the title tag on the first line
@@ -828,14 +851,14 @@
828 # Applying title on the first line851 # Applying title on the first line
829 title_end = buff.get_iter_at_line(line_nbr-1)852 title_end = buff.get_iter_at_line(line_nbr-1)
830 title_end.forward_to_line_end()853 title_end.forward_to_line_end()
831 stripped = buff.get_text(title_start, title_end).strip('\n\t ')854 stripped = buff.get_text(title_start, title_end).strip('\n\t ')
832 # Here we ignore lines that are blank855 # Here we ignore lines that are blank
833 # Title is the first written line856 # Title is the first written line
834 while line_nbr <= linecount and not stripped:857 while line_nbr <= linecount and not stripped:
835 line_nbr += 1858 line_nbr += 1
836 title_end = buff.get_iter_at_line(line_nbr-1)859 title_end = buff.get_iter_at_line(line_nbr-1)
837 title_end.forward_to_line_end()860 title_end.forward_to_line_end()
838 stripped = buff.get_text(title_start, title_end).strip('\n\t ')861 stripped = buff.get_text(title_start, title_end).strip('\n\t ')
839 # Or to all the buffer if there is only one line862 # Or to all the buffer if there is only one line
840 else:863 else:
841 title_end = end.copy()864 title_end = end.copy()
@@ -846,8 +869,6 @@
846 self.refresh(buff.get_text(title_start, title_end).strip('\n\t'))869 self.refresh(buff.get_text(title_start, title_end).strip('\n\t'))
847 return title_end870 return title_end
848871
849
850
851 def __newsubtask(self, buff, title, line_nbr, level=1):872 def __newsubtask(self, buff, title, line_nbr, level=1):
852 anchor = self.new_subtask_callback(title)873 anchor = self.new_subtask_callback(title)
853 end_i = self.write_subtask(buff, line_nbr, anchor, level=level)874 end_i = self.write_subtask(buff, line_nbr, anchor, level=level)
@@ -875,10 +896,10 @@
875 #be in the subtask title896 #be in the subtask title
876 start_i = buff.get_iter_at_line(line_nbr)897 start_i = buff.get_iter_at_line(line_nbr)
877 start_i.forward_to_line_end()898 start_i.forward_to_line_end()
878 buff.insert(start_i,"\n")899 buff.insert(start_i, "\n")
879 #Ok, now we can start working900 #Ok, now we can start working
880 start_i = buff.get_iter_at_line(line_nbr)901 start_i = buff.get_iter_at_line(line_nbr)
881 end_i = start_i.copy()902 end_i = start_i.copy()
882 #We go back at the end of the previous line903 #We go back at the end of the previous line
883# start_i.backward_char()904# start_i.backward_char()
884# #But only if this is not the title.905# #But only if this is not the title.
@@ -886,9 +907,9 @@
886# if start_i.has_tag(self.title_tag):907# if start_i.has_tag(self.title_tag):
887# start_i.forward_char()908# start_i.forward_char()
888# insert_enter = False909# insert_enter = False
889 start = buff.create_mark("start", start_i, True)910 start = buff.create_mark("start", start_i, True)
890 end_i.forward_line()911 end_i.forward_line()
891 end = buff.create_mark("end", end_i, False)912 end = buff.create_mark("end", end_i, False)
892 buff.delete(start_i, end_i)913 buff.delete(start_i, end_i)
893 start_i = buff.get_iter_at_mark(start)914 start_i = buff.get_iter_at_mark(start)
894 self.insert_indent(buff, start_i, level, enter=insert_enter)915 self.insert_indent(buff, start_i, level, enter=insert_enter)
@@ -905,7 +926,8 @@
905 #buff.delete_mark(end)926 #buff.delete_mark(end)
906927
907 if reconnect_insert:928 if reconnect_insert:
908 self.insert_sigid = self.buff.connect('insert-text', self._insert_at_cursor)929 self.insert_sigid = self.buff.connect('insert-text',
930 self._insert_at_cursor)
909 if reconnect_modified:931 if reconnect_modified:
910 self.modified_sigid = self.buff.connect("changed", self.modified)932 self.modified_sigid = self.buff.connect("changed", self.modified)
911 return end_i933 return end_i
@@ -936,7 +958,7 @@
936 if line == self.buff.get_line_count():958 if line == self.buff.get_line_count():
937 itera.forward_to_line_end()959 itera.forward_to_line_end()
938 mark = self.buff.create_mark(None, itera, True)960 mark = self.buff.create_mark(None, itera, True)
939 self.buff.insert(itera,"\n")961 self.buff.insert(itera, "\n")
940 itera = self.buff.get_iter_at_mark(mark)962 itera = self.buff.get_iter_at_mark(mark)
941 self.buff.delete_mark(mark)963 self.buff.delete_mark(mark)
942964
@@ -946,7 +968,7 @@
946 enter = True968 enter = True
947 if itera.starts_line():969 if itera.starts_line():
948 mark = self.buff.create_mark(None, itera, True)970 mark = self.buff.create_mark(None, itera, True)
949 self.buff.insert(itera,"\n")971 self.buff.insert(itera, "\n")
950 itera = self.buff.get_iter_at_mark(mark)972 itera = self.buff.get_iter_at_mark(mark)
951 self.buff.delete_mark(mark)973 self.buff.delete_mark(mark)
952 enter = False974 enter = False
@@ -977,9 +999,9 @@
977 #It will be later replaced by the good one with right gravity999 #It will be later replaced by the good one with right gravity
978 temp_mark = self.buff.create_mark("temp", start_i, True)1000 temp_mark = self.buff.create_mark("temp", start_i, True)
9791001
980 end = buff.create_mark("end", start_i, False)1002 end = buff.create_mark("end", start_i, False)
981 if enter:1003 if enter:
982 buff.insert(start_i,"\n")1004 buff.insert(start_i, "\n")
9831005
984 #Moving the end of subtask mark to the position of the temp mark1006 #Moving the end of subtask mark to the position of the temp mark
985 if stag:1007 if stag:
@@ -994,7 +1016,7 @@
994 #This is normally not needed and purely defensive1016 #This is normally not needed and purely defensive
995 if itera.get_line() <= 0:1017 if itera.get_line() <= 0:
996 itera = buff.get_iter_at_line(1)1018 itera = buff.get_iter_at_line(1)
997 start = buff.create_mark("start", itera, True)1019 start = buff.create_mark("start", itera, True)
998 indentation = ""1020 indentation = ""
999 #adding two spaces by level1021 #adding two spaces by level
1000 spaces = " "1022 spaces = " "
@@ -1007,7 +1029,6 @@
1007 self.__apply_tag_to_mark(start, end, tag=indenttag)1029 self.__apply_tag_to_mark(start, end, tag=indenttag)
1008 return end1030 return end
10091031
1010
1011 def __apply_tag_to_mark(self, start, end, tag=None, name=None):1032 def __apply_tag_to_mark(self, start, end, tag=None, name=None):
1012 start_i = self.buff.get_iter_at_mark(start)1033 start_i = self.buff.get_iter_at_mark(start)
1013 end_i = self.buff.get_iter_at_mark(end)1034 end_i = self.buff.get_iter_at_mark(end)
@@ -1027,9 +1048,8 @@
1027 else:1048 else:
1028 buff.insert(ite, text)1049 buff.insert(ite, text)
10291050
1030
1031 def _get_indent_level(self, itera):1051 def _get_indent_level(self, itera):
1032 line_nbr = itera.get_line()1052 line_nbr = itera.get_line()
1033 start_line = itera.copy()1053 start_line = itera.copy()
1034 start_line.set_line(line_nbr)1054 start_line.set_line(line_nbr)
1035 tags = start_line.get_tags()1055 tags = start_line.get_tags()
@@ -1046,10 +1066,10 @@
10461066
1047 #First, we analyse the selection to put in our own1067 #First, we analyse the selection to put in our own
1048 #GTG clipboard a selection with description of subtasks1068 #GTG clipboard a selection with description of subtasks
1049 bounds = self.buff.get_selection_bounds()1069 bounds = self.buff.get_selection_bounds()
1050 if not bounds:1070 if not bounds:
1051 return1071 return
1052 start, stop = self.buff.get_selection_bounds()1072 start, stop = self.buff.get_selection_bounds()
10531073
1054 self.clipboard.copy(start, stop, bullet=self.bullet1)1074 self.clipboard.copy(start, stop, bullet=self.bullet1)
10551075
@@ -1105,10 +1125,10 @@
11051125
1106 #First, we will get the actual indentation value1126 #First, we will get the actual indentation value
1107 #The nbr just before the \n1127 #The nbr just before the \n
1108 line_nbr = itera.get_line()1128 line_nbr = itera.get_line()
1109 start_line = itera.copy()1129 start_line = itera.copy()
1110 start_line.set_line(line_nbr)1130 start_line.set_line(line_nbr)
1111 end_line = itera.copy()1131 end_line = itera.copy()
1112 tags = start_line.get_tags()1132 tags = start_line.get_tags()
1113 subtask_nbr = None1133 subtask_nbr = None
1114 current_indent = self._get_indent_level(itera)1134 current_indent = self._get_indent_level(itera)
@@ -1157,24 +1177,28 @@
1157 #the "-" might be after a space1177 #the "-" might be after a space
1158 #Python 2.5 should allow both tests in one1178 #Python 2.5 should allow both tests in one
1159 if current_indent == 0:1179 if current_indent == 0:
1160 if (line.startswith('-') or line.startswith(' -')) and line.lstrip(' -').strip() != "":1180 if (line.startswith('-') or line.startswith(' -')) \
1181 and line.lstrip(' -').strip() != "":
1161 line = line.lstrip(' -')1182 line = line.lstrip(' -')
1162 end_i = self.__newsubtask(self.buff, line, line_nbr)1183 end_i = self.__newsubtask(self.buff, line,
1184 line_nbr)
1163 #Here, we should increment indent level1185 #Here, we should increment indent level
1164 #If we inserted enter in the middle of a line1186 #If we inserted enter in the middle of a line
1165 if restofline and restofline.strip() != "":1187 if restofline and restofline.strip() != "":
1166 #it means we have two subtask to create1188 #it means we have two subtask to create
1167 if self.buff.get_line_count() > line_nbr+1:1189 if self.buff.get_line_count() > line_nbr+1:
1168 #but don't merge with the next line1190 #but don't merge with the next line
1169 itera = self.buff.get_iter_at_line(line_nbr+1)1191 itera = self.buff.get_iter_at_line(
1170 self.buff.insert(itera,"\n\n")1192 line_nbr + 1)
1171 self.__newsubtask(self.buff, restofline,\1193 self.buff.insert(itera, "\n\n")
1194 self.__newsubtask(self.buff, restofline,
1172 line_nbr+1)1195 line_nbr+1)
1173 else:1196 else:
1174 self.insert_indent(self.buff, end_i, 1, enter=True)1197 self.insert_indent(self.buff, end_i, 1,
1198 enter=True)
1175 tv.emit_stop_by_name('insert-text')1199 tv.emit_stop_by_name('insert-text')
1176 else:1200 else:
1177 self.buff.insert(itera,"\n")1201 self.buff.insert(itera, "\n")
1178 tv.emit_stop_by_name('insert-text')1202 tv.emit_stop_by_name('insert-text')
11791203
1180 #Then, if indent > 0, we increment it1204 #Then, if indent > 0, we increment it
@@ -1191,22 +1215,26 @@
1191 else:1215 else:
1192 #we first put the subtask one line below1216 #we first put the subtask one line below
1193 itera2 = self.buff.get_iter_at_line(line_nbr)1217 itera2 = self.buff.get_iter_at_line(line_nbr)
1194 self.buff.insert(itera2,"\n")1218 self.buff.insert(itera2, "\n")
1195 #and increment the new white line1219 #and increment the new white line
1196 itera2 = self.buff.get_iter_at_line(line_nbr)1220 itera2 = self.buff.get_iter_at_line(line_nbr)
1197 self.insert_indent(self.buff, itera2, current_indent, enter=False)1221 self.insert_indent(self.buff, itera2,
1222 current_indent, enter=False)
1198 elif current_indent == 1:1223 elif current_indent == 1:
1199 self.insert_indent(self.buff, itera, current_indent)1224 self.insert_indent(self.buff, itera,
1225 current_indent)
1200 #we stop the signal in all cases1226 #we stop the signal in all cases
1201 tv.emit_stop_by_name('insert-text')1227 tv.emit_stop_by_name('insert-text')
1202 #Then we close the tag tag1228 #Then we close the tag tag
1203 if closed_tag:1229 if closed_tag:
1204 insert_mark = self.buff.get_mark("insert_point")1230 insert_mark = self.buff.get_mark("insert_point")
1205 insert_iter = self.buff.get_iter_at_mark(insert_mark)1231 insert_iter = self.buff.get_iter_at_mark(insert_mark)
1206 self.buff.move_mark_by_name("/%s"%closed_tag, insert_iter)1232 self.buff.move_mark_by_name("/%s" % closed_tag,
1233 insert_iter)
1207 self.buff.delete_mark(insert_mark)1234 self.buff.delete_mark(insert_mark)
1208 if cutting_subtask:1235 if cutting_subtask:
1209 cursor = self.buff.get_iter_at_mark(self.buff.get_insert())1236 cursor = self.buff.get_iter_at_mark(
1237 self.buff.get_insert())
1210 endl = cursor.copy()1238 endl = cursor.copy()
1211 if not endl.ends_line():1239 if not endl.ends_line():
1212 endl.forward_to_line_end()1240 endl.forward_to_line_end()
@@ -1222,7 +1250,7 @@
1222 if itera.starts_line():1250 if itera.starts_line():
1223 #we are at the start of an existing subtask1251 #we are at the start of an existing subtask
1224 #we simply move that subtask down1252 #we simply move that subtask down
1225 self.buff.insert(itera,"\n")1253 self.buff.insert(itera, "\n")
1226 itera2 = self.buff.get_iter_at_line(line_nbr)1254 itera2 = self.buff.get_iter_at_line(line_nbr)
1227 self.buff.insert(itera2, tex)1255 self.buff.insert(itera2, tex)
1228 itera3 = self.buff.get_iter_at_line(line_nbr)1256 itera3 = self.buff.get_iter_at_line(line_nbr)
@@ -1230,25 +1258,28 @@
1230 self.buff.place_cursor(itera3)1258 self.buff.place_cursor(itera3)
1231 tv.emit_stop_by_name('insert-text')1259 tv.emit_stop_by_name('insert-text')
1232 else:1260 else:
1233 #self.__newsubtask(self.buff, tex, line_nbr, level=current_indent)1261 #self.__newsubtask(self.buff, tex, line_nbr,
1262 # level=current_indent)
1234 anchor = self.new_subtask_callback(tex)1263 anchor = self.new_subtask_callback(tex)
1235 self.buff.create_mark(anchor, itera, True)1264 self.buff.create_mark(anchor, itera, True)
1236 self.buff.create_mark("/%s"%anchor, itera, False)1265 self.buff.create_mark("/%s"%anchor, itera, False)
1237 self.insert_sigid = self.buff.connect('insert-text', self._insert_at_cursor)1266 self.insert_sigid = self.buff.connect('insert-text',
1267 self._insert_at_cursor)
1238 self.connect('key_press_event', self._keypress)1268 self.connect('key_press_event', self._keypress)
1239 self.modified_sigid = self.buff.connect("changed", self.modified)1269 self.modified_sigid = self.buff.connect("changed", self.modified)
12401270
1241 def _keypress(self, widget, event):1271 def _keypress(self, widget, event):
1242 # Check for Ctrl-Return/Enter1272 # Check for Ctrl-Return/Enter
1243 if event.state & gtk.gdk.CONTROL_MASK and event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter):1273 if event.state & gtk.gdk.CONTROL_MASK and \
1274 event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter):
1244 buff = self.buff1275 buff = self.buff
1245 cursor_mark = buff.get_insert()1276 cursor_mark = buff.get_insert()
1246 cursor_iter = buff.get_iter_at_mark(cursor_mark)1277 cursor_iter = buff.get_iter_at_mark(cursor_mark)
1247 local_start = cursor_iter.copy()1278 local_start = cursor_iter.copy()
12481279
1249 for tag in local_start.get_tags():1280 for tag in local_start.get_tags():
1250 anchor = tag.get_data('link')1281 anchor = tag.get_data('link')
1251 typ = tag.get_data('type')1282 typ = tag.get_data('type')
1252 if(anchor):1283 if(anchor):
1253 if typ == "subtask":1284 if typ == "subtask":
1254 self.open_task(anchor)1285 self.open_task(anchor)
@@ -1278,12 +1309,12 @@
1278 self.buff.disconnect(self.delete_sigid)1309 self.buff.disconnect(self.delete_sigid)
1279 #print "deintdent-delete: %s" %self.buff.get_text(startline, itera)1310 #print "deintdent-delete: %s" %self.buff.get_text(startline, itera)
1280 self.buff.delete(startline, itera)1311 self.buff.delete(startline, itera)
1281 self.delete_sigid = self.buff.connect("delete-range", \
1282 self._delete_range)
1283 #For the day when we will have different indent levels1312 #For the day when we will have different indent levels
1284 #newiter = self.buff.get_iter_at_mark(tempm)1313 #newiter = self.buff.get_iter_at_mark(tempm)
1285 #self.buff.delete_mark(tempm)1314 #self.buff.delete_mark(tempm)
1286 #self.insert_indent(self.buff, newiter, newlevel, enter=False)1315 #self.insert_indent(self.buff, newiter, newlevel, enter=False)
1316 self.delete_sigid = self.buff.connect("delete-range",
1317 self._delete_range)
12871318
1288 def backspace(self, tv):1319 def backspace(self, tv):
1289 self.buff.disconnect(self.insert_sigid)1320 self.buff.disconnect(self.insert_sigid)
@@ -1298,7 +1329,7 @@
1298 #we stopped the signal, don't forget to erase1329 #we stopped the signal, don't forget to erase
1299 #the selection if one1330 #the selection if one
1300 self.buff.delete_selection(True, True)1331 self.buff.delete_selection(True, True)
1301 self.insert_sigid = self.buff.connect('insert-text', \1332 self.insert_sigid = self.buff.connect('insert-text',
1302 self._insert_at_cursor)1333 self._insert_at_cursor)
13031334
1304 #The mouse is moving. We must change it to a hand when hovering over a link1335 #The mouse is moving. We must change it to a hand when hovering over a link
@@ -1318,8 +1349,11 @@
1318 tag_table = self.buff.get_tag_table()1349 tag_table = self.buff.get_tag_table()
1319 tag_table.foreach(self.__tag_reset, window)1350 tag_table.foreach(self.__tag_reset, window)
13201351
1321 #We clicked on a link1352 def _tag_event(self, tag, view, ev, _iter, text, anchor, typ):
1322 def _tag_event(self, tag, view, ev, _iter, text, anchor, typ): #pylint: disable-msg=W06131353 """
1354 We clicked on a link
1355 """
1356 #pylint: disable-msg=W0613
1323 _type = ev.type1357 _type = ev.type
1324 if _type == gtk.gdk.MOTION_NOTIFY:1358 if _type == gtk.gdk.MOTION_NOTIFY:
1325 return1359 return
@@ -1330,14 +1364,17 @@
1330 if typ == "subtask":1364 if typ == "subtask":
1331 self.open_task(anchor)1365 self.open_task(anchor)
1332 elif typ == "http":1366 elif typ == "http":
1333 if button == 1 and self.check_link(anchor) and self.buff.get_has_selection() == False:1367 if button == 1 and self.check_link(anchor) and \
1368 not self.buff.get_has_selection():
1334 openurl(anchor)1369 openurl(anchor)
1335 else:1370 else:
1336 print "Unknown link type for %s" %anchor1371 print "Unknown link type for %s" %anchor
1337 self.emit('anchor-clicked', text, anchor, button)1372 self.emit('anchor-clicked', text, anchor, button)
1338 self.__set_anchor(ev.window, tag, cursor, self.get_property('hover'))1373 self.__set_anchor(ev.window, tag, cursor,
1374 self.get_property('hover'))
1339 elif button in [1, 2]:1375 elif button in [1, 2]:
1340 self.__set_anchor(ev.window, tag, cursor, self.get_property('active'))1376 self.__set_anchor(ev.window, tag, cursor,
1377 self.get_property('active'))
13411378
1342 def __tag_reset(self, tag, window):1379 def __tag_reset(self, tag, window):
1343 if tag.get_data('is_anchor'):1380 if tag.get_data('is_anchor'):
@@ -1351,7 +1388,8 @@
1351 linktype = 'link'1388 linktype = 'link'
1352 else:1389 else:
1353 linktype = 'failedlink'1390 linktype = 'failedlink'
1354 self.__set_anchor(window, tag, editing_cursor, self.get_property(linktype))1391 self.__set_anchor(window, tag, editing_cursor,
1392 self.get_property(linktype))
13551393
1356 def __set_anchor(self, window, tag, cursor, prop):1394 def __set_anchor(self, window, tag, cursor, prop):
1357 window.set_cursor(cursor)1395 window.set_cursor(cursor)
13581396
=== modified file 'GTG/gtk/editor/taskviewserial.py'
--- GTG/gtk/editor/taskviewserial.py 2012-05-23 08:55:31 +0000
+++ GTG/gtk/editor/taskviewserial.py 2012-11-25 21:29:25 +0000
@@ -107,8 +107,8 @@
107 elif ta.get_data('is_subtask'):107 elif ta.get_data('is_subtask'):
108 #The current gtkTextTag is a subtask108 #The current gtkTextTag is a subtask
109 tagname = "subtask"109 tagname = "subtask"
110 subt = doc.createElement(tagname)110 subt = doc.createElement(tagname)
111 target = ta.get_data('child')111 target = ta.get_data('child')
112 subt.appendChild(doc.createTextNode(target))112 subt.appendChild(doc.createTextNode(target))
113 parent.appendChild(subt)113 parent.appendChild(subt)
114 parent.appendChild(doc.createTextNode("\n"))114 parent.appendChild(doc.createTextNode("\n"))
@@ -187,7 +187,7 @@
187 #parse the XML and put the content in the buffer187 #parse the XML and put the content in the buffer
188 def parsexml(self, buf, ite, element):188 def parsexml(self, buf, ite, element):
189 start = buf.create_mark(None, ite, True)189 start = buf.create_mark(None, ite, True)
190 end = buf.create_mark(None, ite, False)190 end = buf.create_mark(None, ite, False)
191 subtasks = self.tv.get_subtasks()191 subtasks = self.tv.get_subtasks()
192 taglist2 = []192 taglist2 = []
193 if element:193 if element:

Subscribers

People subscribed via source and target branches

to status/vote changes: