~parinporecha/gtg/config_parser_bug

« back to all changes in this revision

Viewing changes to GTG/gtk/editor/taskview.py

  • Committer: Izidor Matušov
  • Date: 2013-02-25 07:35:07 UTC
  • Revision ID: izidor.matusov@gmail.com-20130225073507-vgts69uthx7z2run
PEP8ification by Nimit

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
from webbrowser import open as openurl
37
37
 
38
38
from GTG.gtk.editor import taskviewserial
39
 
from GTG.tools      import urlregex
 
39
from GTG.tools import urlregex
40
40
 
41
41
separators = [' ', ',', '\n', '\t', '!', '?', ';', '\0', '(', ')']
42
 
#those separators are only separators if followed by a space. Else, they
43
 
#are part of the word
 
42
# those separators are only separators if followed by a space. Else, they
 
43
# are part of the word
44
44
specials_separators = ['.', '/']
45
45
 
46
46
bullet1_ltr = '→'
50
50
class TaskView(gtk.TextView):
51
51
    __gtype_name__ = 'HyperTextView'
52
52
    __gsignals__ = {'anchor-clicked': (gobject.SIGNAL_RUN_LAST,
53
 
                     None, (str, str, int))}
 
53
                                       None, (str, str, int))}
54
54
    __gproperties__ = {
55
55
        'link': (gobject.TYPE_PYOBJECT, 'link color',
56
 
                  'link color of TextView', gobject.PARAM_READWRITE),
 
56
                 'link color of TextView', gobject.PARAM_READWRITE),
57
57
        'failedlink': (gobject.TYPE_PYOBJECT, 'failed link color',
58
 
                  'failed link color of TextView', gobject.PARAM_READWRITE),
 
58
                       'failed link color of TextView',
 
59
                       gobject.PARAM_READWRITE),
59
60
        'active': (gobject.TYPE_PYOBJECT, 'active color',
60
 
                  'active color of TextView', gobject.PARAM_READWRITE),
 
61
                   'active color of TextView', gobject.PARAM_READWRITE),
61
62
        'hover': (gobject.TYPE_PYOBJECT, 'link:hover color',
62
63
                  'link:hover color of TextView', gobject.PARAM_READWRITE),
63
64
        'tag': (gobject.TYPE_PYOBJECT, 'tag color',
64
 
                  'tag color of TextView', gobject.PARAM_READWRITE),
 
65
                'tag color of TextView', gobject.PARAM_READWRITE),
65
66
        'done': (gobject.TYPE_PYOBJECT, 'link color',
66
 
                  'link color of TextView', gobject.PARAM_READWRITE),
 
67
                 'link color of TextView', gobject.PARAM_READWRITE),
67
68
        'indent': (gobject.TYPE_PYOBJECT, 'indent color',
68
 
                  'indent color of TextView', gobject.PARAM_READWRITE),
69
 
        }
 
69
                   'indent color of TextView', gobject.PARAM_READWRITE),
 
70
    }
70
71
 
71
72
    def do_get_property(self, prop):
72
73
        try:
80
81
        else:
81
82
            raise AttributeError('unknown property %s' % prop.name)
82
83
 
83
 
    #Yes, we want to redefine the buffer. Disabling pylint on that error.
 
84
    # Yes, we want to redefine the buffer. Disabling pylint on that error.
84
85
    def __init__(self, requester, clipboard, buffer=None):
85
 
        #pylint: disable-msg=W0622
 
86
        # pylint: disable-msg=W0622
86
87
        gtk.TextView.__init__(self, buffer)
87
88
        self.buff = self.get_buffer()
88
89
        self.req = requester
89
 
        #Buffer init
 
90
        # Buffer init
90
91
        self.link = {'background': 'white', 'foreground': '#007bff',
91
 
                      'underline': pango.UNDERLINE_SINGLE,
92
 
                      'strikethrough': False}
 
92
                     'underline': pango.UNDERLINE_SINGLE,
 
93
                     'strikethrough': False}
93
94
        self.failedlink = {'background': 'white', 'foreground': '#ff5454',
94
 
                      'underline': pango.UNDERLINE_NONE,
95
 
                      'strikethrough': False}
 
95
                           'underline': pango.UNDERLINE_NONE,
 
96
                           'strikethrough': False}
96
97
        self.done = {'background': 'white', 'foreground': 'gray',
97
 
                                    'strikethrough': True}
 
98
                     'strikethrough': True}
98
99
        self.active = {'background': 'light gray', 'foreground': '#ff1e00',
99
 
                                    'underline': pango.UNDERLINE_SINGLE}
 
100
                       'underline': pango.UNDERLINE_SINGLE}
100
101
        self.hover = {'background': 'light gray'}
101
102
        self.tag = {'background': "#FFea00", 'foreground': 'black'}
102
103
        self.indent = {'scale': 1.4, 'editable': False, 'left-margin': 10,
103
 
                                 "accumulative-margin": True}
 
104
                       "accumulative-margin": True}
104
105
 
105
106
        ###### Tag we will use ######
106
107
        # We use the tag table (tag are defined here
108
109
        self.table = self.buff.get_tag_table()
109
110
        # Tag for title
110
111
        self.title_tag = self.buff.create_tag("title", foreground="#007bff",
111
 
                            scale=1.6, underline=1)
 
112
                                              scale=1.6, underline=1)
112
113
        self.title_tag.set_property("pixels-above-lines", 10)
113
114
        self.title_tag.set_property("pixels-below-lines", 10)
114
115
        # Tag for highlight (tags are automatically added to the tag table)
115
116
        self.buff.create_tag("fluo", background="#F0F")
116
117
        # Tag for bullets
117
118
        self.buff.create_tag("bullet", scale=1.6)
118
 
        #end = self.buff.get_end_iter()
 
119
        # end = self.buff.get_end_iter()
119
120
 
120
 
        #This is the list of all the links in our task
 
121
        # This is the list of all the links in our task
121
122
        self.__tags = []
122
 
        #This is a simple stack used by the serialization
 
123
        # This is a simple stack used by the serialization
123
124
        self.__tag_stack = {}
124
125
 
125
 
        #Signals
 
126
        # Signals
126
127
        self.connect('motion-notify-event', self._motion)
127
128
        self.connect('focus-out-event',
128
 
            lambda w, e: self.table.foreach(self.__tag_reset, e.window))
 
129
                     lambda w, e: self.table.foreach(self.__tag_reset,
 
130
                                                     e.window))
129
131
        self.insert_sigid = self.buff.connect('insert-text',
130
132
                                              self._insert_at_cursor)
131
133
        self.delete_sigid = self.buff.connect("delete-range",
132
 
            self._delete_range)
 
134
                                              self._delete_range)
133
135
        self.connect('copy-clipboard', self.copy_clipboard, "copy")
134
136
        self.connect('cut-clipboard', self.copy_clipboard, "cut")
135
137
        self.connect('paste-clipboard', self.paste_clipboard)
136
138
 
137
139
        self.connect('drag-data-received', self.drag_receive)
138
140
 
139
 
        #All the typical properties of our textview
 
141
        # All the typical properties of our textview
140
142
        self.set_wrap_mode(gtk.WRAP_WORD)
141
143
        self.set_editable(True)
142
144
        self.set_cursor_visible(True)
143
145
        self.buff.set_modified(False)
144
146
 
145
 
        #Let's try with serializing
 
147
        # Let's try with serializing
146
148
        self.mime_type = 'application/x-gtg-task'
147
149
        serializer = taskviewserial.Serializer()
148
150
        unserializer = taskviewserial.Unserializer(self)
149
151
        self.buff.register_serialize_format(self.mime_type,
150
 
            serializer.serialize, None)
 
152
                                            serializer.serialize, None)
151
153
        self.buff.register_deserialize_format(self.mime_type,
152
 
            unserializer.unserialize, None)
 
154
                                              unserializer.unserialize, None)
153
155
 
154
 
        #The list of callbacks we have to set
 
156
        # The list of callbacks we have to set
155
157
        self.remove_tag_callback = None
156
158
        self.add_tag_callback = None
157
159
        self.get_tagslist = None
158
160
        self.get_subtasks = None
159
 
        self.remove_subtask =None
 
161
        self.remove_subtask = None
160
162
        self.__refresh_cb = None  # refresh the editor window
161
 
        self.open_task = None # open another task
162
 
        self.new_subtask_callback = None # create a subtask
163
 
        self.save_task = None #This will save the task without refreshing all
 
163
        self.open_task = None  # open another task
 
164
        self.new_subtask_callback = None  # create a subtask
 
165
        self.save_task = None  # This will save the task without refreshing all
164
166
 
165
 
        #The signal emitted each time the buffer is modified
166
 
        #Putting it at the end to avoid doing it too much when starting
 
167
        # The signal emitted each time the buffer is modified
 
168
        # Putting it at the end to avoid doing it too much when starting
167
169
        self.modified_sigid = self.buff.connect("changed", self.modified)
168
170
        self.backspace_sigid = self.connect("backspace", self.backspace)
169
171
        self.tobe_refreshed = False
183
185
        self.modified(full=True)
184
186
        self.stop_emission('drag-data-received')
185
187
 
186
 
 
187
 
    #editable means that the user can edit the taskview
188
 
    #this is initially set at False and then to True once the editor window
189
 
    #is displayed.
190
 
    #this is used to avoid saving the task when the window is still
191
 
    #not displayed
 
188
    # editable means that the user can edit the taskview
 
189
    # this is initially set at False and then to True once the editor window
 
190
    # is displayed.
 
191
    # this is used to avoid saving the task when the window is still
 
192
    # not displayed
192
193
    def set_editable(self, boule):
193
194
        self.editable = boule
194
195
 
195
196
    def get_editable(self):
196
197
        return self.editable
197
198
 
198
 
    #This function is called to refresh the editor
199
 
    #Specially when we change the title
 
199
    # This function is called to refresh the editor
 
200
    # Specially when we change the title
200
201
    def refresh(self, title):
201
202
        if self.__refresh_cb:
202
203
            self.__refresh_cb(title)
204
205
    def refresh_callback(self, funct):
205
206
        self.__refresh_cb = funct
206
207
 
207
 
    #This callback is called to add a new tag
 
208
    # This callback is called to add a new tag
208
209
    def set_add_tag_callback(self, funct):
209
210
        self.add_tag_callback = funct
210
211
 
211
 
    #This callback is called to add a new tag
 
212
    # This callback is called to add a new tag
212
213
    def set_remove_tag_callback(self, funct):
213
214
        self.remove_tag_callback = funct
214
215
 
215
 
    #This callback is called to have the list of tags of a task
 
216
    # This callback is called to have the list of tags of a task
216
217
    def set_get_tagslist_callback(self, funct):
217
218
        self.get_tagslist = funct
218
219
 
219
 
    #This callback is called to create a new subtask
 
220
    # This callback is called to create a new subtask
220
221
    def set_subtask_callback(self, funct):
221
222
        self.new_subtask_callback = funct
222
223
 
223
 
    #This callback is called to open another task
 
224
    # This callback is called to open another task
224
225
    def open_task_callback(self, funct):
225
226
        self.open_task = funct
226
227
 
227
 
    #This was historically a callback but it returns the title
 
228
    # This was historically a callback but it returns the title
228
229
    def get_subtasktitle(self, tid):
229
230
        task = self.req.get_task(tid)
230
231
        if task:
232
233
        else:
233
234
            return None
234
235
 
235
 
    #This callback is called to get the list of tid of subtasks
 
236
    # This callback is called to get the list of tid of subtasks
236
237
    def subtasks_callback(self, funct):
237
238
        self.get_subtasks = funct
238
239
 
239
 
    #This callback is called to remove a subtask by its pid
 
240
    # This callback is called to remove a subtask by its pid
240
241
    def removesubtask_callback(self, funct):
241
242
        self.remove_subtask = funct
242
243
 
243
244
    def save_task_callback(self, funct):
244
245
        self.save_task = funct
245
246
 
246
 
    #Buffer related functions
247
 
    #Those functions are higly related and should always be symetrical
248
 
    #See also the serializing functions
 
247
    # Buffer related functions
 
248
    # Those functions are higly related and should always be symetrical
 
249
    # See also the serializing functions
249
250
 #### The "Set text" group ########
250
 
    #This set the text of the buffer (and replace any existing one)
251
 
    #without deserializing (used for the title)
 
251
    # This set the text of the buffer (and replace any existing one)
 
252
    # without deserializing (used for the title)
252
253
    def set_text(self, stri):
253
254
        self.buff.set_text(stri)
254
 
    #This append text at the end of the buffer after deserializing it
 
255
    # This append text at the end of the buffer after deserializing it
 
256
 
255
257
    def insert(self, text, _iter=None):
256
258
        if _iter is None:
257
259
            _iter = self.buff.get_end_iter()
258
 
        #Ok, this line require an integer at some place !
259
 
        #disable the insert and modified signals
 
260
        # Ok, this line require an integer at some place !
 
261
        # disable the insert and modified signals
260
262
        reconnect_insert = False
261
263
        reconnect_modified = False
262
264
        if self.insert_sigid:
268
270
            self.modified_sigid = False
269
271
            reconnect_modified = True
270
272
 
271
 
        #deserialize
 
273
        # deserialize
272
274
        self.buff.deserialize(self.buff, self.mime_type, _iter, text)
273
275
 
274
 
        #reconnect
 
276
        # reconnect
275
277
        if reconnect_insert:
276
278
            self.insert_sigid = self.buff.connect('insert-text',
277
 
                self._insert_at_cursor)
 
279
                                                  self._insert_at_cursor)
278
280
        if reconnect_modified:
279
281
            self.modified_sigid = self.buff.connect("changed", self.modified)
280
282
 
281
 
    #This insert raw text without deserializing
 
283
    # This insert raw text without deserializing
282
284
    def insert_text(self, text, _iter=None):
283
285
        if _iter is None:
284
286
            _iter = self.buff.get_end_iter()
285
287
        self.buff.insert(_iter, text)
286
288
 
287
 
    #We cannot get an insert in the title
 
289
    # We cannot get an insert in the title
288
290
    def get_insert(self):
289
291
        mark = self.buff.get_insert()
290
292
        itera = self.buff.get_iter_at_mark(mark)
313
315
            return True
314
316
 
315
317
    def create_anchor_tag(self, b, anchor, text=None, typ=None):
316
 
        #We cannot have two tags with the same name
317
 
        #That's why the link tag has no name
318
 
        #but it has a "is_anchor" property
 
318
        # We cannot have two tags with the same name
 
319
        # That's why the link tag has no name
 
320
        # but it has a "is_anchor" property
319
321
        if typ == "http":
320
322
            linktype = 'link'
321
 
        #By default, the type is a subtask
 
323
        # By default, the type is a subtask
322
324
        else:
323
325
            task = self.req.get_task(anchor)
324
326
            if task and task.get_status() == "Active":
329
331
        if linktype == 'link' and not self.check_link(anchor):
330
332
            linktype = 'failedlink'
331
333
 
332
 
        #pylint: disable-msg=W0142
 
334
        # pylint: disable-msg=W0142
333
335
        tag = b.create_tag(None, **self.get_property(linktype))
334
336
        tag.set_data('is_anchor', True)
335
337
        tag.set_data('link', anchor)
339
341
        self.__tags.append(tag)
340
342
        return tag
341
343
 
342
 
    #Apply the tag tag to a set of TextMarks (not Iter)
 
344
    # Apply the tag tag to a set of TextMarks (not Iter)
343
345
    def apply_tag_tag(self, buff, tag, s, e):
344
346
        ss = buff.get_iter_at_mark(s)
345
347
        ee = buff.get_iter_at_mark(e)
346
 
        #If the tag is already applied, we do nothing
 
348
        # If the tag is already applied, we do nothing
347
349
        t_list = ss.get_tags()
348
350
        texttag = None
349
351
        already = False
353
355
                if ss.begins_tag(t) and ee.ends_tag(t):
354
356
                    already = True
355
357
        if not texttag:
356
 
            #pylint: disable-msg=W0142
 
358
            # pylint: disable-msg=W0142
357
359
            texttag = buff.create_tag(None, **self.get_property('tag'))
358
360
            texttag.set_data('is_tag', True)
359
361
            texttag.set_data('tagname', tag)
360
 
            #This one is for marks
 
362
            # This one is for marks
361
363
        if not already:
362
364
            self.__apply_tag_to_mark(s, e, tag=texttag)
363
365
 
364
 
    #Apply the tag tag to a set of TextMarks (not Iter)
365
 
    #Also change the subtask title if needed
 
366
    # Apply the tag tag to a set of TextMarks (not Iter)
 
367
    # Also change the subtask title if needed
366
368
    def apply_subtask_tag(self, buff, subtask, s, e):
367
369
        i_s = buff.get_iter_at_mark(s)
368
370
        i_e = buff.get_iter_at_mark(e)
369
371
        tex = buff.get_text(i_s, i_e)
370
 
        #we don't accept \n in a subtask title
 
372
        # we don't accept \n in a subtask title
371
373
        if "\n" in tex:
372
374
            i_e = i_s.copy()
373
375
            while i_e.get_char() != "\n":
377
379
        if len(tex) > 0:
378
380
            self.req.get_task(subtask).set_title(tex)
379
381
            texttag = self.create_anchor_tag(buff, subtask, text=tex,
380
 
                typ="subtask")
 
382
                                             typ="subtask")
381
383
            texttag.set_data('is_subtask', True)
382
384
            texttag.set_data('child', subtask)
383
 
            #This one is for marks
 
385
            # This one is for marks
384
386
            self.__apply_tag_to_mark(s, e, tag=texttag)
385
387
        else:
386
388
            self.remove_subtask(subtask)
388
390
            buff.delete_mark(e)
389
391
 
390
392
    def create_indent_tag(self, buff, level):
391
 
        #pylint: disable-msg=W0142
 
393
        # pylint: disable-msg=W0142
392
394
        tag = buff.create_tag(None, **self.get_property('indent'))
393
395
        tag.set_data('is_indent', True)
394
396
        tag.set_data('indent_level', level)
395
397
        return tag
396
398
 
397
 
    #Insert a list of subtasks at the end of the buffer
 
399
    # Insert a list of subtasks at the end of the buffer
398
400
    def insert_subtasks(self, st_list):
399
401
        for tid in st_list:
400
402
            line_nbr = self.buff.get_end_iter().get_line()
401
 
            #Warning, we have to take the next line !
402
 
            self.write_subtask(self.buff, line_nbr+1, tid)
 
403
            # Warning, we have to take the next line !
 
404
            self.write_subtask(self.buff, line_nbr + 1, tid)
403
405
 
404
 
    #Insert a list of tag in the first line of the buffer
 
406
    # Insert a list of tag in the first line of the buffer
405
407
    def insert_tags(self, tag_list):
406
 
        #First, we don't insert tags that are already present
 
408
        # First, we don't insert tags that are already present
407
409
        for t in self.get_tagslist():
408
410
            if t in tag_list:
409
411
                tag_list.remove(t)
410
412
        if len(tag_list) > 0:
411
 
            #We insert them just after the title
412
 
            #We use the current first line if it begins with a tag
 
413
            # We insert them just after the title
 
414
            # We use the current first line if it begins with a tag
413
415
            firstline = self.buff.get_iter_at_line(1)
414
416
            newline = True
415
417
            for tt in firstline.get_tags():
430
432
    #            if not text.strip(", "):
431
433
    #                newline = False
432
434
    #                firstline.forward_to_line_end()
433
 
            #Now we can process
 
435
            # Now we can process
434
436
            if newline:
435
437
                firstline = self.buff.get_iter_at_line(0)
436
438
                firstline.forward_to_line_end()
437
439
                self.insert_text("\n", firstline)
438
440
                firstline = self.buff.get_iter_at_line(1)
439
441
            line_mark = self.buff.create_mark("firstline", firstline, False)
440
 
            #self.tv.insert_at_mark(buf, line_mark, "\n")
 
442
            # self.tv.insert_at_mark(buf, line_mark, "\n")
441
443
            ntags = len(tag_list)
442
444
            for t in tag_list:
443
445
                ntags = ntags - 1
456
458
        line_mark = self.buff.create_mark("lastline", lastline, False)
457
459
        self.insert_at_mark(self.buff, line_mark, tag)
458
460
 
459
 
    #this function select and highligth the title (first line)
 
461
    # this function select and highligth the title (first line)
460
462
    def select_title(self):
461
463
        start = self.buff.get_start_iter()
462
464
        stop = start.copy()
464
466
        self.buff.select_range(start, stop)
465
467
 
466
468
 ##### The "Get text" group #########
467
 
    #Get the complete serialized text
468
 
    #But without the title
 
469
    # Get the complete serialized text
 
470
    # But without the title
469
471
    def get_text(self):
470
 
        #we get the text
 
472
        # we get the text
471
473
        start = self.buff.get_start_iter()
472
474
        start.forward_to_line_end()
473
475
        conti = True
475
477
            conti = start.forward_line()
476
478
            if conti:
477
479
                conti = start.forward_to_line_end()
478
 
        #we go to the next line, just after the title
 
480
        # we go to the next line, just after the title
479
481
        start.forward_line()
480
482
        end = self.buff.get_end_iter()
481
483
        texte = self.buff.serialize(self.buff, self.mime_type, start, end)
482
484
 
483
485
        return texte
484
 
    #Get the title of the task (aka the first line of the buffer)
 
486
    # Get the title of the task (aka the first line of the buffer)
 
487
 
485
488
    def get_title(self):
486
489
        start = self.buff.get_start_iter()
487
490
        end = self.buff.get_start_iter()
488
491
        end.forward_to_line_end()
489
 
        #The boolean stays True as long as we are in the buffer
 
492
        # The boolean stays True as long as we are in the buffer
490
493
        conti = True
491
494
        while conti and not end.ends_tag(self.table.lookup("title")):
492
495
            conti = end.forward_line()
493
496
            if conti:
494
497
                conti = end.forward_to_line_end()
495
 
        #We don't want to deserialize the title
496
 
        #Let's get the pure text directly
 
498
        # We don't want to deserialize the title
 
499
        # Let's get the pure text directly
497
500
        title = unicode(self.buff.get_text(start, end))
498
 
        #Let's strip blank lines
 
501
        # Let's strip blank lines
499
502
        stripped = title.strip(' \n\t')
500
503
        return stripped
501
504
 
502
505
    ### PRIVATE FUNCTIONS #####################################################
503
 
    #This function is called so frequently that we should optimize it more.
 
506
    # This function is called so frequently that we should optimize it more.
504
507
    def modified(self, buff=None, full=False, refresheditor=True):
505
508
        """Called when the buffer has been modified.
506
509
 
515
518
        cursor_mark = buff.get_insert()
516
519
        cursor_iter = buff.get_iter_at_mark(cursor_mark)
517
520
        table = buff.get_tag_table()
518
 
        #This should be called only if we are on the title line
519
 
        #As an optimisation
520
 
        #But we should still get the title_end iter
 
521
        # This should be called only if we are on the title line
 
522
        # As an optimisation
 
523
        # But we should still get the title_end iter
521
524
        if full or self.is_at_title(buff, cursor_iter):
522
 
            #The apply title is very expensive because
523
 
            #It involves refreshing the whole task tree
 
525
            # The apply title is very expensive because
 
526
            # It involves refreshing the whole task tree
524
527
            title_end = self._apply_title(buff, refresheditor)
525
528
 
526
529
        if full:
527
530
            local_start = title_end.copy()
528
531
            local_end = buff.get_end_iter()
529
532
        else:
530
 
            #We analyse only the current line
 
533
            # We analyse only the current line
531
534
            local_start = cursor_iter.copy()
532
535
            local_start.set_line(local_start.get_line())
533
536
            local_end = cursor_iter.copy()
534
537
            local_end.forward_lines(2)
535
 
        #if full=False we detect tag only on the current line
 
538
        # if full=False we detect tag only on the current line
536
539
 
537
 
        #The following 3 lines are a quick ugly fix for bug #359469
 
540
        # The following 3 lines are a quick ugly fix for bug #359469
538
541
#        temp = buff.get_iter_at_line(1)
539
542
#        temp.backward_char()
540
543
#        self._detect_tag(buff, temp, buff.get_end_iter())
541
 
        #This should be the good line
 
544
        # This should be the good line
542
545
        self._detect_tag(buff, local_start, local_end)
543
546
        self._detect_url(buff, local_start, local_end)
544
547
 
545
 
        #subt_list = self.get_subtasks()
546
 
        #First, we remove the olds tags
 
548
        # subt_list = self.get_subtasks()
 
549
        # First, we remove the olds tags
547
550
        tag_list = []
548
551
 
549
 
        def subfunc(texttag, data=None): #pylint: disable-msg=W0613
 
552
        def subfunc(texttag, data=None):  # pylint: disable-msg=W0613
550
553
            if texttag.get_data('is_subtask'):
551
554
                tag_list.append(texttag)
552
555
 
556
559
            buff.remove_tag(t, start, end)
557
560
            table.remove(t)
558
561
 
559
 
        #We apply the hyperlink tag to subtask
 
562
        # We apply the hyperlink tag to subtask
560
563
        for s in self.get_subtasks():
561
564
            start_mark = buff.get_mark(s)
562
565
            # "applying %s to %s - %s"%(s, start_mark, end_mark)
563
566
            if start_mark:
564
 
                #In fact, the subtask mark always go to the end of line.
 
567
                # In fact, the subtask mark always go to the end of line.
565
568
                start_i = buff.get_iter_at_mark(start_mark)
566
569
                if self._get_indent_level(start_i) > 0:
567
570
                    start_i.forward_to_line_end()
568
 
                    end_mark = buff.create_mark("/%s"%s, start_i, False)
 
571
                    end_mark = buff.create_mark("/%s" % s, start_i, False)
569
572
                    self.apply_subtask_tag(buff, s, start_mark, end_mark)
570
573
                else:
571
574
                    self.remove_subtask(s)
572
575
 
573
 
 
574
 
        #Now we apply the tag tag to the marks
 
576
        # Now we apply the tag tag to the marks
575
577
        for t in self.get_tagslist():
576
578
            start_mark = buff.get_mark(t)
577
 
            end_mark = buff.get_mark("/%s"%t)
 
579
            end_mark = buff.get_mark("/%s" % t)
578
580
            # "applying %s to %s - %s"%(t, start_mark, end_mark)
579
581
            if start_mark and end_mark:
580
582
                self.apply_tag_tag(buff, t, start_mark, end_mark)
581
583
 
582
 
        #Ok, we took care of the modification
 
584
        # Ok, we took care of the modification
583
585
        self.buff.set_modified(False)
584
 
        #Else we save the task anyway (but without refreshing all)
 
586
        # Else we save the task anyway (but without refreshing all)
585
587
        if self.save_task:
586
588
            self.save_task()
587
589
 
588
 
    #Detect URL in the tasks
589
 
    #It's ugly...
 
590
    # Detect URL in the tasks
 
591
    # It's ugly...
590
592
    def _detect_url(self, buff, start, end):
591
 
        #subt_list = self.get_subtasks()
592
 
        #First, we remove the olds tags
 
593
        # subt_list = self.get_subtasks()
 
594
        # First, we remove the olds tags
593
595
        tag_list = []
594
596
        table = buff.get_tag_table()
595
597
 
600
602
        table.foreach(subfunc)
601
603
        for t in tag_list:
602
604
            buff.remove_tag(t, start, end)
603
 
        #Now we add the tag URL
 
605
        # Now we add the tag URL
604
606
        it = start.copy()
605
607
        prev = start.copy()
606
608
        while (it.get_offset() < end.get_offset()) and (it.get_char() != '\0'):
618
620
                    if text == "www":
619
621
                        url = "http://" + url
620
622
                    texttag = self.create_anchor_tag(buff, url, text=None,
621
 
                        typ="http")
 
623
                                                     typ="http")
622
624
                    it = prev.copy()
623
625
                    it.forward_chars(m.end())
624
626
                    buff.apply_tag(texttag, prev, it)
646
648
                            "show_bug.cgi?id=%s" % nbr
647
649
                    if topoint:
648
650
                        texttag = self.create_anchor_tag(buff,
649
 
                                                topoint, text=None, typ="http")
 
651
                                                         topoint, text=None,
 
652
                                                         typ="http")
650
653
                        buff.apply_tag(texttag, prev, it)
651
654
 
652
 
 
653
 
    #Detect tags in buff in the region between start iter and end iter
 
655
    # Detect tags in buff in the region between start iter and end iter
654
656
    def _detect_tag(self, buff, start, end):
655
657
        # Removing already existing tag in the current selection
656
658
        # out of the tag table
658
660
        table = buff.get_tag_table()
659
661
        old_tags = []
660
662
        new_tags = []
661
 
        #We must be strictly < than the end_offset. If not, we might
662
 
        #find the beginning of a tag on the nextline
 
663
        # We must be strictly < than the end_offset. If not, we might
 
664
        # find the beginning of a tag on the nextline
663
665
        while (it.get_offset() < end.get_offset()) and (it.get_char() != '\0'):
664
666
            if it.begins_tag():
665
667
                tags = it.get_toggled_tags(True)
666
668
                for ta in tags:
667
 
                    #removing deleted tags
 
669
                    # removing deleted tags
668
670
                    if ta.get_data('is_tag'):
669
671
                        tagname = ta.get_data('tagname')
670
672
                        old_tags.append(tagname)
671
673
                        buff.remove_tag(ta, start, end)
672
674
                        table.remove(ta)
673
 
                        #Removing the marks if they exist
 
675
                        # Removing the marks if they exist
674
676
                        mark1 = buff.get_mark(tagname)
675
677
                        if mark1:
676
678
                            offset1 = buff.get_iter_at_mark(mark1).get_offset()
677
679
                            if start.get_offset() <= offset1 <= \
678
 
                                end.get_offset():
 
680
                                    end.get_offset():
679
681
                                buff.delete_mark_by_name(tagname)
680
 
                        mark2 = buff.get_mark("/%s"%tagname)
 
682
                        mark2 = buff.get_mark("/%s" % tagname)
681
683
                        if mark2:
682
684
                            offset2 = buff.get_iter_at_mark(mark2).get_offset()
683
685
                            if start.get_offset() <= offset2 <= \
684
 
                                end.get_offset():
685
 
                                buff.delete_mark_by_name("/%s"%tagname)
 
686
                                    end.get_offset():
 
687
                                buff.delete_mark_by_name("/%s" % tagname)
686
688
            it.forward_char()
687
689
 
688
690
        # Set iterators for word
702
704
            if my_char not in separators:
703
705
                last_char = my_char
704
706
                word_end = char_end.copy()
705
 
                #If a special case is at the end of the document
706
 
                #we don't include it in the tag
 
707
                # If a special case is at the end of the document
 
708
                # we don't include it in the tag
707
709
                if word_end.is_end() and last_char in specials_separators:
708
710
                    word_end.backward_char()
709
711
            else:
710
 
                #We remove the special case followed by a separator
 
712
                # We remove the special case followed by a separator
711
713
                if last_char in specials_separators:
712
714
                    word_end.backward_char()
713
715
                do_word_check = True
720
722
                if (word_end.compare(word_start) > 0):
721
723
                    my_word = buff.get_text(word_start, word_end)
722
724
                    # We do something about it
723
 
                    #We want a tag bigger than the simple "@"
724
 
                    #and it shouldn't start with @@ (bug 531553)
 
725
                    # We want a tag bigger than the simple "@"
 
726
                    # and it shouldn't start with @@ (bug 531553)
725
727
                    if len(my_word) > 1 and my_word[0] == '@' \
726
 
                       and not my_word[1] == '@':
727
 
                        #self.apply_tag_tag(buff, my_word, word_start,
 
728
                            and not my_word[1] == '@':
 
729
                        # self.apply_tag_tag(buff, my_word, word_start,
728
730
                        #   word_end)
729
 
                        #We will add mark where tag should be applied
 
731
                        # We will add mark where tag should be applied
730
732
                        buff.create_mark(my_word, word_start, True)
731
 
                        buff.create_mark("/%s"%my_word, word_end, False)
732
 
                        #adding tag to a local list
 
733
                        buff.create_mark("/%s" % my_word, word_end, False)
 
734
                        # adding tag to a local list
733
735
                        new_tags.append(my_word)
734
 
                        #adding tag to the model
 
736
                        # adding tag to the model
735
737
                        self.add_tag_callback(my_word)
736
738
 
737
739
                # We set new word boundaries
757
759
 
758
760
        if itera.get_line() == 0:
759
761
            to_return = True
760
 
        #We are at a line with the title tag applied
 
762
        # We are at a line with the title tag applied
761
763
        elif self.title_tag in itera.get_tags():
762
764
            to_return = True
763
 
        #else, we look if there's something between us and buffer start
 
765
        # else, we look if there's something between us and buffer start
764
766
        elif not buff.get_text(buff.get_start_iter(), itera).strip('\n\t '):
765
767
            to_return = True
766
768
 
767
769
        return to_return
768
770
 
769
 
    #When the user removes a selection, we remove subtasks and @tags
770
 
    #from this selection
 
771
    # When the user removes a selection, we remove subtasks and @tags
 
772
    # from this selection
771
773
    def _delete_range(self, buff, start, end):
772
774
#        #If we are at the beginning of a mark, put this mark at the end
773
775
#        marks = start.get_marks()
774
776
#        for m in marks:
775
777
#            print m.get_name()
776
778
#            buff.move_mark(m, end)
777
 
        #If the begining of the selection is in the middle of an indent
778
 
        #We want to start at the begining
779
 
        tags = start.get_tags()+start.get_toggled_tags(False)
 
779
        # If the begining of the selection is in the middle of an indent
 
780
        # We want to start at the begining
 
781
        tags = start.get_tags() + start.get_toggled_tags(False)
780
782
        for ta in tags:
781
783
            if (ta.get_data('is_indent')):
782
784
                line = start.get_line()
786
788
#                endindent = start.copy()
787
789
#                endindent.forward_to_tag_toggle(ta)
788
790
#                buff.remove_tag(ta, start, endindent)
789
 
        #Now we delete all, char after char
 
791
        # Now we delete all, char after char
790
792
        it = start.copy()
791
793
        while it.get_offset() <= end.get_offset() and it.get_char() != '\0':
792
794
            if it.begins_tag():
793
795
                tags = it.get_tags()
794
796
                for ta in tags:
795
 
                    #removing deleted subtasks
 
797
                    # removing deleted subtasks
796
798
                    if ta.get_data('is_subtask') and it.begins_tag(ta):
797
799
                        target = ta.get_data('child')
798
 
                        #print "removing task %s" %target
 
800
                        # print "removing task %s" %target
799
801
                        self.remove_subtask(target)
800
 
                    #removing deleted tags
 
802
                    # removing deleted tags
801
803
                    if ta.get_data('is_tag') and it.begins_tag(ta):
802
804
                        tagname = ta.get_data('tagname')
803
805
                        self.remove_tag_callback(tagname)
804
806
                        if buff.get_mark(tagname):
805
807
                            buff.delete_mark_by_name(tagname)
806
 
                        if buff.get_mark("/%s"%tagname):
807
 
                            buff.delete_mark_by_name("/%s"%tagname)
 
808
                        if buff.get_mark("/%s" % tagname):
 
809
                            buff.delete_mark_by_name("/%s" % tagname)
808
810
                    if ta.get_data('is_indent'):
809
 
                        #Because the indent tag is read only
810
 
                        #we will remove it
 
811
                        # Because the indent tag is read only
 
812
                        # we will remove it
811
813
                        endtag = it.copy()
812
814
                        endtag.forward_to_tag_toggle(ta)
813
815
                        buff.remove_tag(ta, it, endtag)
814
 
                        #Also, we want to delete the indent completely,
815
 
                        #Even if the selection was in the middle of an indent
 
816
                        # Also, we want to delete the indent completely,
 
817
                        # Even if the selection was in the middle of an indent
816
818
 
817
819
            it.forward_char()
818
 
        #now we really delete the selected stuffs
 
820
        # now we really delete the selected stuffs
819
821
        selec = self.buff.get_selection_bounds()
820
822
#        if selec:
821
823
#            print "deleted text is ##%s##" %self.buff.get_text(selec[0],
831
833
#        self.delete_sigid = self.buff.connect("delete-range",
832
834
#            self._delete_range)
833
835
#        self.backspace_sigid = self.connect("backspace", self.backspace)
834
 
        #We return false so the parent still get the signal
 
836
        # We return false so the parent still get the signal
835
837
        return False
836
838
 
837
839
    def _apply_title(self, buff, refresheditor=True):
851
853
        title_start = start.copy()
852
854
        if linecount > line_nbr:
853
855
            # Applying title on the first line
854
 
            title_end = buff.get_iter_at_line(line_nbr-1)
 
856
            title_end = buff.get_iter_at_line(line_nbr - 1)
855
857
            title_end.forward_to_line_end()
856
858
            stripped = buff.get_text(title_start, title_end).strip('\n\t ')
857
859
            # Here we ignore lines that are blank
858
860
            # Title is the first written line
859
861
            while line_nbr <= linecount and not stripped:
860
862
                line_nbr += 1
861
 
                title_end = buff.get_iter_at_line(line_nbr-1)
 
863
                title_end = buff.get_iter_at_line(line_nbr - 1)
862
864
                title_end.forward_to_line_end()
863
865
                stripped = buff.get_text(title_start, title_end).strip('\n\t ')
864
866
        # Or to all the buffer if there is only one line
876
878
        end_i = self.write_subtask(buff, line_nbr, anchor, level=level)
877
879
        return end_i
878
880
 
879
 
    #Write the subtask then return the iterator at the end of the line
 
881
    # Write the subtask then return the iterator at the end of the line
880
882
    def write_subtask(self, buff, line_nbr, anchor, level=1):
881
 
        #disable the insert signal to avoid recursion
882
 
        #firstly, we check that the subtask exists !
 
883
        # disable the insert signal to avoid recursion
 
884
        # firstly, we check that the subtask exists !
883
885
        if not self.req.has_task(anchor):
884
886
            return False
885
887
        reconnect_insert = False
893
895
            self.modified_sigid = False
894
896
            reconnect_modified = True
895
897
 
896
 
        #First, we insert the request \n
897
 
        #If we don't do this, the content of next line will automatically
898
 
        #be in the subtask title
 
898
        # First, we insert the request \n
 
899
        # If we don't do this, the content of next line will automatically
 
900
        # be in the subtask title
899
901
        start_i = buff.get_iter_at_line(line_nbr)
900
902
        start_i.forward_to_line_end()
901
903
        buff.insert(start_i, "\n")
902
 
        #Ok, now we can start working
 
904
        # Ok, now we can start working
903
905
        start_i = buff.get_iter_at_line(line_nbr)
904
906
        end_i = start_i.copy()
905
 
        #We go back at the end of the previous line
 
907
        # We go back at the end of the previous line
906
908
#        start_i.backward_char()
907
909
#        #But only if this is not the title.
908
910
        insert_enter = False
918
920
        newline = self.get_subtasktitle(anchor)
919
921
        end_i = buff.get_iter_at_mark(end)
920
922
        startm = buff.create_mark(anchor, end_i, True)
921
 
        #Putting the subtask marks around the title
 
923
        # Putting the subtask marks around the title
922
924
        self.insert_at_mark(buff, end, newline)
923
925
        end_i = buff.get_iter_at_mark(end)
924
 
        endm = buff.create_mark("/%s"%anchor, end_i, False)
925
 
        #put the tag on the marks
 
926
        endm = buff.create_mark("/%s" % anchor, end_i, False)
 
927
        # put the tag on the marks
926
928
        self.apply_subtask_tag(buff, anchor, startm, endm)
927
 
        #buff.delete_mark(start)
928
 
        #buff.delete_mark(end)
 
929
        # buff.delete_mark(start)
 
930
        # buff.delete_mark(end)
929
931
 
930
932
        if reconnect_insert:
931
933
            self.insert_sigid = self.buff.connect('insert-text',
932
 
                self._insert_at_cursor)
 
934
                                                  self._insert_at_cursor)
933
935
        if reconnect_modified:
934
936
            self.modified_sigid = self.buff.connect("changed", self.modified)
935
937
        return end_i
937
939
    def insert_newtask(self, fitera=None):
938
940
        if not fitera:
939
941
            fitera = self.get_insert()
940
 
        #First, find a line without subtask
 
942
        # First, find a line without subtask
941
943
        line = fitera.get_line()
942
 
        #Avoid the title at all cost
 
944
        # Avoid the title at all cost
943
945
        if line <= 0:
944
946
            line = 1
945
947
        startl = self.buff.get_iter_at_line(line)
955
957
            if found:
956
958
                itera = startl
957
959
 
958
 
        #if the last line is indented, then insert a new line
959
 
        #at the end
 
960
        # if the last line is indented, then insert a new line
 
961
        # at the end
960
962
        if line == self.buff.get_line_count():
961
963
            itera.forward_to_line_end()
962
964
            mark = self.buff.create_mark(None, itera, True)
964
966
            itera = self.buff.get_iter_at_mark(mark)
965
967
            self.buff.delete_mark(mark)
966
968
 
967
 
        #If we are not on the end of line, go there
968
 
        #but if we are at the start of line, then create the subtask
969
 
        #before the current line
 
969
        # If we are not on the end of line, go there
 
970
        # but if we are at the start of line, then create the subtask
 
971
        # before the current line
970
972
        enter = True
971
973
        if itera.starts_line():
972
974
            mark = self.buff.create_mark(None, itera, True)
981
983
        self.buff.place_cursor(end)
982
984
 
983
985
    def insert_indent(self, buff, start_i, level, enter=True):
984
 
        #We will close the current subtask tag
 
986
        # We will close the current subtask tag
985
987
        list_stag = start_i.get_toggled_tags(False)
986
988
        stag = None
987
989
        for t in list_stag:
988
990
            if t.get_data('is_subtask'):
989
991
                stag = t
990
 
        #maybe the tag was not toggled off here but we were in the middle
 
992
        # maybe the tag was not toggled off here but we were in the middle
991
993
        if not stag:
992
994
            list_stag = start_i.get_tags()
993
995
            for t in list_stag:
994
996
                if t.get_data('is_subtask'):
995
997
                    stag = t
996
998
        if stag:
997
 
            #We will remove the tag from the whole text
 
999
            # We will remove the tag from the whole text
998
1000
            subtid = stag.get_data('child')
999
 
        #We move the end_subtask mark to here
1000
 
        #We have to create a temporary mark with left gravity
1001
 
        #It will be later replaced by the good one with right gravity
 
1001
        # We move the end_subtask mark to here
 
1002
        # We have to create a temporary mark with left gravity
 
1003
        # It will be later replaced by the good one with right gravity
1002
1004
        temp_mark = self.buff.create_mark("temp", start_i, True)
1003
1005
 
1004
1006
        end = buff.create_mark("end", start_i, False)
1005
1007
        if enter:
1006
1008
            buff.insert(start_i, "\n")
1007
1009
 
1008
 
        #Moving the end of subtask mark to the position of the temp mark
 
1010
        # Moving the end of subtask mark to the position of the temp mark
1009
1011
        if stag:
1010
1012
            itera = buff.get_iter_at_mark(temp_mark)
1011
 
            buff.move_mark_by_name("/%s"%subtid, itera)
 
1013
            buff.move_mark_by_name("/%s" % subtid, itera)
1012
1014
        buff.delete_mark(temp_mark)
1013
 
        #The mark has right gravity but because we put it on the left
1014
 
        #of the newly inserted \n, it will not move anymore.
 
1015
        # The mark has right gravity but because we put it on the left
 
1016
        # of the newly inserted \n, it will not move anymore.
1015
1017
 
1016
1018
        itera = buff.get_iter_at_mark(end)
1017
 
        #We should never have an indentation at 0.
1018
 
        #This is normally not needed and purely defensive
 
1019
        # We should never have an indentation at 0.
 
1020
        # This is normally not needed and purely defensive
1019
1021
        if itera.get_line() <= 0:
1020
1022
            itera = buff.get_iter_at_line(1)
1021
1023
        start = buff.create_mark("start", itera, True)
1022
1024
        indentation = ""
1023
 
        #adding two spaces by level
 
1025
        # adding two spaces by level
1024
1026
        spaces = "  "
1025
 
        indentation = indentation + (level-1)*spaces
1026
 
        #adding the symbol
 
1027
        indentation = indentation + (level - 1) * spaces
 
1028
        # adding the symbol
1027
1029
        if level == 1:
1028
 
            indentation = "%s%s "%(indentation, self.bullet1)
 
1030
            indentation = "%s%s " % (indentation, self.bullet1)
1029
1031
        buff.insert(itera, indentation)
1030
1032
        indenttag = self.create_indent_tag(buff, level)
1031
1033
        self.__apply_tag_to_mark(start, end, tag=indenttag)
1034
1036
    def __apply_tag_to_mark(self, start, end, tag=None, name=None):
1035
1037
        start_i = self.buff.get_iter_at_mark(start)
1036
1038
        end_i = self.buff.get_iter_at_mark(end)
1037
 
        #we should apply the tag only if the mark are separated
 
1039
        # we should apply the tag only if the mark are separated
1038
1040
        if end_i.get_offset() - start_i.get_offset() > 0:
1039
1041
            if tag:
1040
1042
                self.buff.apply_tag(tag, start_i, end_i)
1061
1063
                current_indent = ta.get_data('indent_level')
1062
1064
        return current_indent
1063
1065
 
1064
 
    #Method called on copy and cut actions
1065
 
    #param is either "cut" or "copy"
 
1066
    # Method called on copy and cut actions
 
1067
    # param is either "cut" or "copy"
1066
1068
    def copy_clipboard(self, widget, param=None):
1067
1069
        clip = gtk.clipboard_get(gdk.SELECTION_CLIPBOARD)
1068
1070
 
1069
 
        #First, we analyse the selection to put in our own
1070
 
        #GTG clipboard a selection with description of subtasks
 
1071
        # First, we analyse the selection to put in our own
 
1072
        # GTG clipboard a selection with description of subtasks
1071
1073
        bounds = self.buff.get_selection_bounds()
1072
1074
        if not bounds:
1073
1075
            return
1084
1086
        else:
1085
1087
            self.stop_emission("copy_clipboard")
1086
1088
 
1087
 
    #Called on paste.
 
1089
    # Called on paste.
1088
1090
    def paste_clipboard(self, widget, param=None):
1089
1091
        clip = gtk.clipboard_get(gdk.SELECTION_CLIPBOARD)
1090
 
        #if the clipboard text is the same are our own internal
1091
 
        #clipboard text, it means that we can paste from our own clipboard
1092
 
        #else, that we can empty it.
 
1092
        # if the clipboard text is the same are our own internal
 
1093
        # clipboard text, it means that we can paste from our own clipboard
 
1094
        # else, that we can empty it.
1093
1095
        our_paste = self.clipboard.paste_text()
1094
 
        if our_paste != None and clip.wait_for_text() == our_paste:
1095
 
            #first, we delete the current selection
 
1096
        if our_paste is not None and clip.wait_for_text() == our_paste:
 
1097
            # first, we delete the current selection
1096
1098
            self.buff.delete_selection(False, True)
1097
1099
            for line in self.clipboard.paste():
1098
1100
                if line[0] == 'text':
1099
1101
                    self.buff.insert_at_cursor(line[1])
1100
1102
                if line[0] == 'subtask':
1101
 
                    tid=line[1]
 
1103
                    tid = line[1]
1102
1104
                    self.new_subtask_callback(tid=tid)
1103
1105
                    mark = self.buff.get_insert()
1104
1106
                    line_nbr = self.buff.get_iter_at_mark(mark).get_line()
1105
 
                    #we must paste the \n before inserting the subtask
1106
 
                    #else, we will start another subtask
 
1107
                    # we must paste the \n before inserting the subtask
 
1108
                    # else, we will start another subtask
1107
1109
                    self.buff.insert_at_cursor("\n")
1108
1110
                    self.write_subtask(self.buff, line_nbr, tid)
1109
1111
 
1110
 
            #we handle ourselves the pasting
 
1112
            # we handle ourselves the pasting
1111
1113
            self.stop_emission("paste_clipboard")
1112
1114
 
1113
1115
        else:
1114
 
            #we keep the normal pasting by not interupting the signal
 
1116
            # we keep the normal pasting by not interupting the signal
1115
1117
            self.clipboard.clear()
1116
1118
 
1117
 
    #Function called each time the user inputs a letter
 
1119
    # Function called each time the user inputs a letter
1118
1120
    def _insert_at_cursor(self, tv, itera, tex, leng):
1119
 
        #We don't paste the bullet
 
1121
        # We don't paste the bullet
1120
1122
        if tex.strip() != self.bullet1:
1121
 
            #print "text ###%s### inserted length = %s" %(tex, leng)
1122
 
            #disable the insert signal to avoid recursion
 
1123
            # print "text ###%s### inserted length = %s" %(tex, leng)
 
1124
            # disable the insert signal to avoid recursion
1123
1125
            self.buff.disconnect(self.insert_sigid)
1124
1126
            self.insert_sigid = False
1125
1127
            self.buff.disconnect(self.modified_sigid)
1126
1128
            self.modified_sigid = False
1127
1129
 
1128
 
            #First, we will get the actual indentation value
1129
 
            #The nbr just before the \n
 
1130
            # First, we will get the actual indentation value
 
1131
            # The nbr just before the \n
1130
1132
            line_nbr = itera.get_line()
1131
1133
            start_line = itera.copy()
1132
1134
            start_line.set_line(line_nbr)
1138
1140
            for ta in tags:
1139
1141
                if ta.get_data('is_subtask'):
1140
1142
                    subtask_nbr = ta.get_data('child')
1141
 
            #Maybe we are simply at the end of the tag
 
1143
            # Maybe we are simply at the end of the tag
1142
1144
            if not subtask_nbr and itera.ends_tag():
1143
1145
                for ta in itera.get_toggled_tags(False):
1144
1146
                    if ta.get_data('is_subtask'):
1145
1147
                        subtask_nbr = ta.get_data('child')
1146
1148
 
1147
 
            #New line: the user pressed enter !
1148
 
            #If the line begins with "-", it's a new subtask !
 
1149
            # New line: the user pressed enter !
 
1150
            # If the line begins with "-", it's a new subtask !
1149
1151
            if tex == '\n':
1150
1152
                self.buff.create_mark("insert_point", itera, True)
1151
 
                #First, we close tag tags.
1152
 
                #If we are at the end of a tag, we look for closed tags
 
1153
                # First, we close tag tags.
 
1154
                # If we are at the end of a tag, we look for closed tags
1153
1155
                closed_tag = None
1154
1156
                cutting_subtask = False
1155
1157
                if itera.ends_tag():
1156
1158
                    list_stag = itera.get_toggled_tags(False)
1157
 
                #Or maybe we are in the middle of a tag
 
1159
                # Or maybe we are in the middle of a tag
1158
1160
                else:
1159
1161
                    list_stag = itera.get_tags()
1160
1162
                for t in list_stag:
1163
1165
                    elif t.get_data('is_subtask'):
1164
1166
                        cutting_subtask = True
1165
1167
                        closed_tag = t.get_data('child')
1166
 
                #We add a bullet list but not on the first line
1167
 
                #Because it's the title
 
1168
                # We add a bullet list but not on the first line
 
1169
                # Because it's the title
1168
1170
                if line_nbr > 0:
1169
1171
                    line = start_line.get_slice(end_line)
1170
 
                    #the part after the enter
 
1172
                    # the part after the enter
1171
1173
                    realend = end_line.copy()
1172
1174
                    restofline = None
1173
1175
                    if not realend.ends_line():
1175
1177
                        restofline = end_line.get_slice(realend)
1176
1178
                        restofline.strip()
1177
1179
 
1178
 
                    #If indent is 0, We check if we created a new task
1179
 
                    #the "-" might be after a space
1180
 
                    #Python 2.5 should allow both tests in one
 
1180
                    # If indent is 0, We check if we created a new task
 
1181
                    # the "-" might be after a space
 
1182
                    # Python 2.5 should allow both tests in one
1181
1183
                    if current_indent == 0:
1182
1184
                        if (line.startswith('-') or line.startswith(' -')) \
1183
 
                            and line.lstrip(' -').strip() != "":
 
1185
                                and line.lstrip(' -').strip() != "":
1184
1186
                            line = line.lstrip(' -')
1185
1187
                            end_i = self.__newsubtask(self.buff, line,
1186
 
                                line_nbr)
1187
 
                            #Here, we should increment indent level
1188
 
                            #If we inserted enter in the middle of a line
 
1188
                                                      line_nbr)
 
1189
                            # Here, we should increment indent level
 
1190
                            # If we inserted enter in the middle of a line
1189
1191
                            if restofline and restofline.strip() != "":
1190
 
                                #it means we have two subtask to create
1191
 
                                if self.buff.get_line_count() > line_nbr+1:
1192
 
                                    #but don't merge with the next line
 
1192
                                # it means we have two subtask to create
 
1193
                                if self.buff.get_line_count() > line_nbr + 1:
 
1194
                                    # but don't merge with the next line
1193
1195
                                    itera = self.buff.get_iter_at_line(
1194
1196
                                        line_nbr + 1)
1195
1197
                                    self.buff.insert(itera, "\n\n")
1196
1198
                                self.__newsubtask(self.buff, restofline,
1197
 
                                                            line_nbr+1)
 
1199
                                                  line_nbr + 1)
1198
1200
                            else:
1199
1201
                                self.insert_indent(self.buff, end_i, 1,
1200
 
                                    enter=True)
 
1202
                                                   enter=True)
1201
1203
                            tv.emit_stop_by_name('insert-text')
1202
1204
                        else:
1203
1205
                            self.buff.insert(itera, "\n")
1204
1206
                            tv.emit_stop_by_name('insert-text')
1205
1207
 
1206
 
                    #Then, if indent > 0, we increment it
1207
 
                    #First step: we preserve it.
 
1208
                    # Then, if indent > 0, we increment it
 
1209
                    # First step: we preserve it.
1208
1210
                    else:
1209
 
                        if not line.lstrip("%s "%self.bullet1):
1210
 
                            #if we didn't write a task, we remove the indent
1211
 
                            #we check if the iterator is well at the end of
1212
 
                            #the line
 
1211
                        if not line.lstrip("%s " % self.bullet1):
 
1212
                            # if we didn't write a task, we remove the indent
 
1213
                            # we check if the iterator is well at the end of
 
1214
                            # the line
1213
1215
                            if end_line.ends_line():
1214
1216
                                self.deindent(itera, newlevel=0)
1215
 
                            #else, it means that we pressed enter before
1216
 
                            #a subtask title
 
1217
                            # else, it means that we pressed enter before
 
1218
                            # a subtask title
1217
1219
                            else:
1218
 
                                #we first put the subtask one line below
 
1220
                                # we first put the subtask one line below
1219
1221
                                itera2 = self.buff.get_iter_at_line(line_nbr)
1220
1222
                                self.buff.insert(itera2, "\n")
1221
 
                                #and increment the new white line
 
1223
                                # and increment the new white line
1222
1224
                                itera2 = self.buff.get_iter_at_line(line_nbr)
1223
1225
                                self.insert_indent(self.buff, itera2,
1224
 
                                    current_indent, enter=False)
 
1226
                                                   current_indent, enter=False)
1225
1227
                        elif current_indent == 1:
1226
1228
                            self.insert_indent(self.buff, itera,
1227
 
                                current_indent)
1228
 
                        #we stop the signal in all cases
 
1229
                                               current_indent)
 
1230
                        # we stop the signal in all cases
1229
1231
                        tv.emit_stop_by_name('insert-text')
1230
 
                    #Then we close the tag tag
 
1232
                    # Then we close the tag tag
1231
1233
                    if closed_tag:
1232
1234
                        insert_mark = self.buff.get_mark("insert_point")
1233
1235
                        insert_iter = self.buff.get_iter_at_mark(insert_mark)
1234
1236
                        self.buff.move_mark_by_name("/%s" % closed_tag,
1235
 
                            insert_iter)
 
1237
                                                    insert_iter)
1236
1238
                        self.buff.delete_mark(insert_mark)
1237
1239
                        if cutting_subtask:
1238
1240
                            cursor = self.buff.get_iter_at_mark(
1243
1245
                            text = self.buff.get_text(cursor, endl)
1244
1246
                            anchor = self.new_subtask_callback(text)
1245
1247
                            self.buff.create_mark(anchor, cursor, True)
1246
 
                            self.buff.create_mark("/%s"%anchor, endl, False)
 
1248
                            self.buff.create_mark("/%s" % anchor, endl, False)
1247
1249
                        self.modified(full=True)
1248
 
            #The user entered something else than \n
 
1250
            # The user entered something else than \n
1249
1251
            elif tex:
1250
 
                #We are on an indented line without subtask ? Create it !
 
1252
                # We are on an indented line without subtask ? Create it !
1251
1253
                if current_indent > 0 and not subtask_nbr:
1252
1254
                    if itera.starts_line():
1253
 
                        #we are at the start of an existing subtask
1254
 
                        #we simply move that subtask down
 
1255
                        # we are at the start of an existing subtask
 
1256
                        # we simply move that subtask down
1255
1257
                        self.buff.insert(itera, "\n")
1256
1258
                        itera2 = self.buff.get_iter_at_line(line_nbr)
1257
1259
                        self.buff.insert(itera2, tex)
1260
1262
                        self.buff.place_cursor(itera3)
1261
1263
                        tv.emit_stop_by_name('insert-text')
1262
1264
                    else:
1263
 
                        #self.__newsubtask(self.buff, tex, line_nbr,
 
1265
                        # self.__newsubtask(self.buff, tex, line_nbr,
1264
1266
                        #   level=current_indent)
1265
1267
                        anchor = self.new_subtask_callback(tex)
1266
1268
                        self.buff.create_mark(anchor, itera, True)
1267
 
                        self.buff.create_mark("/%s"%anchor, itera, False)
 
1269
                        self.buff.create_mark("/%s" % anchor, itera, False)
1268
1270
            self.insert_sigid = self.buff.connect('insert-text',
1269
 
                self._insert_at_cursor)
 
1271
                                                  self._insert_at_cursor)
1270
1272
            self.connect('key_press_event', self._keypress)
1271
1273
            self.modified_sigid = self.buff.connect("changed", self.modified)
1272
1274
 
1273
1275
    def _keypress(self, widget, event):
1274
1276
        # Check for Ctrl-Return/Enter
1275
1277
        if event.state & gtk.gdk.CONTROL_MASK and \
1276
 
            event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter):
 
1278
                event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter):
1277
1279
            buff = self.buff
1278
1280
            cursor_mark = buff.get_insert()
1279
1281
            cursor_iter = buff.get_iter_at_mark(cursor_mark)
1290
1292
 
1291
1293
            return True
1292
1294
 
1293
 
    #Deindent the current line of one level
1294
 
    #If newlevel is set, force to go to that level
 
1295
    # Deindent the current line of one level
 
1296
    # If newlevel is set, force to go to that level
1295
1297
    def deindent(self, itera, newlevel=-1):
1296
1298
        line = itera.get_line()
1297
1299
        startline = self.buff.get_iter_at_line(line)
1302
1304
 
1303
1305
            if newlevel > 0:
1304
1306
                newlevel -= 1
1305
 
        #If it's still < 0
 
1307
        # If it's still < 0
1306
1308
        if newlevel < 0:
1307
1309
            print "bug: no is_indent tag on that line"
1308
 
        #startline.backward_char()
1309
 
        #We make a temp mark where we should insert the new indent
1310
 
        #tempm = self.buff.create_mark("temp", startline)
 
1310
        # startline.backward_char()
 
1311
        # We make a temp mark where we should insert the new indent
 
1312
        # tempm = self.buff.create_mark("temp", startline)
1311
1313
        self.buff.disconnect(self.delete_sigid)
1312
 
        #print "deintdent-delete: %s" %self.buff.get_text(startline, itera)
 
1314
        # print "deintdent-delete: %s" %self.buff.get_text(startline, itera)
1313
1315
        self.buff.delete(startline, itera)
1314
 
        #For the day when we will have different indent levels
1315
 
        #newiter = self.buff.get_iter_at_mark(tempm)
1316
 
        #self.buff.delete_mark(tempm)
1317
 
        #self.insert_indent(self.buff, newiter, newlevel, enter=False)
 
1316
        # For the day when we will have different indent levels
 
1317
        # newiter = self.buff.get_iter_at_mark(tempm)
 
1318
        # self.buff.delete_mark(tempm)
 
1319
        # self.insert_indent(self.buff, newiter, newlevel, enter=False)
1318
1320
        self.delete_sigid = self.buff.connect("delete-range",
1319
 
                                               self._delete_range)
 
1321
                                              self._delete_range)
1320
1322
 
1321
1323
    def backspace(self, tv):
1322
1324
        self.buff.disconnect(self.insert_sigid)
1323
1325
        insert_mark = self.buff.get_insert()
1324
1326
        insert_iter = self.buff.get_iter_at_mark(insert_mark)
1325
 
        #All this crap to find if we are at the end of an indent tag
 
1327
        # All this crap to find if we are at the end of an indent tag
1326
1328
        if insert_iter.ends_tag():
1327
1329
            for t in insert_iter.get_toggled_tags(False):
1328
1330
                if t.get_data('is_indent'):
1329
1331
                    self.deindent(insert_iter)
1330
1332
                    tv.emit_stop_by_name('backspace')
1331
 
                    #we stopped the signal, don't forget to erase
1332
 
                    #the selection if one
 
1333
                    # we stopped the signal, don't forget to erase
 
1334
                    # the selection if one
1333
1335
                    self.buff.delete_selection(True, True)
1334
1336
        self.insert_sigid = self.buff.connect('insert-text',
1335
 
                                               self._insert_at_cursor)
 
1337
                                              self._insert_at_cursor)
1336
1338
 
1337
 
    #The mouse is moving. We must change it to a hand when hovering over a link
 
1339
    # The mouse is moving. We must change it to a hand when hovering over a
 
1340
    # link
1338
1341
    def _motion(self, view, ev):
1339
1342
        window = ev.window
1340
1343
        x, y, _ = window.get_pointer()
1355
1358
        """
1356
1359
        We clicked on a link
1357
1360
        """
1358
 
        #pylint: disable-msg=W0613
 
1361
        # pylint: disable-msg=W0613
1359
1362
        _type = ev.type
1360
1363
        if _type == gtk.gdk.MOTION_NOTIFY:
1361
1364
            return
1367
1370
                    self.open_task(anchor)
1368
1371
                elif typ == "http":
1369
1372
                    if button == 1 and self.check_link(anchor) and \
1370
 
                        not self.buff.get_has_selection():
 
1373
                            not self.buff.get_has_selection():
1371
1374
                        openurl(anchor)
1372
1375
                else:
1373
 
                    print "Unknown link type for %s" %anchor
 
1376
                    print "Unknown link type for %s" % anchor
1374
1377
                self.emit('anchor-clicked', text, anchor, button)
1375
1378
                self.__set_anchor(ev.window, tag, cursor,
1376
 
                    self.get_property('hover'))
 
1379
                                  self.get_property('hover'))
1377
1380
            elif button in [1, 2]:
1378
1381
                self.__set_anchor(ev.window, tag, cursor,
1379
 
                    self.get_property('active'))
 
1382
                                  self.get_property('active'))
1380
1383
 
1381
1384
    def __tag_reset(self, tag, window):
1382
1385
        if tag.get_data('is_anchor'):
1383
 
            #We need to get the normal cursor back
 
1386
            # We need to get the normal cursor back
1384
1387
            editing_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
1385
1388
            if tag.get_property('strikethrough'):
1386
1389
                linktype = 'done'
1391
1394
                else:
1392
1395
                    linktype = 'failedlink'
1393
1396
            self.__set_anchor(window, tag, editing_cursor,
1394
 
                self.get_property(linktype))
 
1397
                              self.get_property(linktype))
1395
1398
 
1396
1399
    def __set_anchor(self, window, tag, cursor, prop):
1397
1400
        window.set_cursor(cursor)