24
24
import xml.dom.minidom
27
28
import xml.sax.saxutils as saxutils
30
33
from GTG.tools.dates import date_today, no_date, Date
31
34
from datetime import datetime
32
from GTG.core.tree import TreeNode
35
from GTG.tools.liblarch.tree import TreeNode
33
36
from GTG.tools.logger import Log
37
from GTG.tools.dates import no_date,\
36
42
class Task(TreeNode):
76
83
#avoid doing it multiple times
77
84
if not self.loaded:
80
self.req._task_loaded(self.tid)
81
#self.req._task_modified(self.tid)
86
for t in self.get_tags():
89
# self.req._task_loaded(self.tid)
83
91
def set_to_keep(self):
84
92
self.can_be_deleted = False
151
#TODO : should we merge this function with set_title ?
152
def set_complex_title(self,text,tags=[]):
157
# Get tags in the title
158
#NOTE: the ?: tells regexp that the first one is
159
# a non-capturing group, so it must not be returned
160
# to findall. http://www.amk.ca/python/howto/regex/regex.html
162
for match in re.findall(r'(?:^|[\s])(@\w+)', text):
163
tags.append(GTG.core.tagstore.Tag(match, self.req))
165
#text =text.replace(match,match[1:],1)
167
regexp = r'([\s]*)([\w-]+):([^\s]+)'
168
for spaces, attribute, args in re.findall(regexp, text):
169
valid_attribute = True
170
if attribute.lower() in ["tags", "tag"] or \
171
attribute.lower() in [_("tags"), _("tag")]:
172
for tag in args.split(","):
173
if not tag.startswith("@") :
175
tags.append(GTG.core.tagstore.Tag(tag, self.req))
176
elif attribute.lower() == "defer" or \
177
attribute.lower() == _("defer"):
178
defer_date = get_canonical_date(args)
180
valid_attribute = False
181
elif attribute.lower() == "due" or \
182
attribute.lower() == _("due"):
183
due_date = get_canonical_date(args)
185
valid_attribute = False
187
# attribute is unknown
188
valid_attribute = False
190
# if the command is valid we have to remove it
191
# from the task title
193
text.replace("%s%s:%s" % (spaces, attribute, args), "")
194
# # Create the new task
195
# task = self.req.new_task(tags=[t.get_name() for t in tags], newtask=True)
197
self.add_tag(t.get_name())
199
self.set_title(text.strip())
201
self.set_due_date(due_date)
202
self.set_start_date(defer_date)
143
204
def set_status(self, status, donedate=None):
144
205
old_status = self.status
181
242
return self.status
183
244
def get_modified(self):
245
return self.last_modified
186
247
def get_modified_string(self):
187
return self.modified.strftime("%Y-%m-%dT%H:%M:%S")
248
return self.last_modified.strftime("%Y-%m-%dT%H:%M:%S")
189
250
def set_modified(self, modified):
190
self.modified = modified
251
self.last_modified = modified
192
253
def set_due_date(self, fulldate):
193
254
assert(isinstance(fulldate, Date))
391
450
### PARENTS ##############################################################
393
#Take a tid object as parameter
394
def add_parent(self, parent_tid):
395
#FIXME : the sync should be automatically done
396
#at the tree level. remove this function
397
Log.debug("adding parent %s to task %s" %(parent_tid, self.get_id()))
398
added = TreeNode.add_parent(self, parent_tid)
401
#the parent is handled by the sync
402
# self.req.get_task(parent_tid).sync()
452
# Not necessary anymore with liblarch
453
# #Take a tid object as parameter
454
# def add_parent(self, parent_tid):
455
# #FIXME : the sync should be automatically done
456
# #at the tree level. remove this function
457
# Log.debug("adding parent %s to task %s" %(parent_tid, self.get_id()))
458
# added = TreeNode.add_parent(self, parent_tid)
461
# #the parent is handled by the sync
462
## self.req.get_task(parent_tid).sync()
407
#Take a tid as parameter
408
def remove_parent(self, tid):
409
#FIXME : the sync should be automatically done
410
#at the tree level. remove this function
411
TreeNode.remove_parent(self,tid)
413
parent = self.req.get_task(tid)
467
# #Take a tid as parameter
468
# def remove_parent(self, tid):
469
# #FIXME : the sync should be automatically done
470
# #at the tree level. remove this function
471
# TreeNode.remove_parent(self,tid)
473
# parent = self.req.get_task(tid)
417
477
#Return true is the task has parent
418
478
#If tag is provided, return True only
419
479
#if the parent has this particular tag
420
#FIXME : this function should be removed. Use the tree instead !
480
#FIXME : this function should be removed. Use the liblarch instead !
421
481
def has_parents(self, tag=None):
422
482
has_par = TreeNode.has_parent(self)
423
483
#The "all tag" argument
450
510
return self.attributes.get((namespace, att_name), None)
452
#Method called before the task is deleted
453
#This method is called by the datastore and should not be called directly
456
#we issue a delete for all the children
457
for task in self.get_subtasks():
458
#I think it's superfluous (invernizzi)
459
#task.remove_parent(self.get_id())
461
#we tell the parents we have to go
462
for i in self.get_parents():
463
task = self.req.get_task(i)
464
task.remove_child(self.get_id())
465
#we tell the tags about the deletion
466
for tagname in self.tags:
467
tag = self.req.get_tag(tagname)
468
tag.remove_task(self.get_id())
469
#then we signal the we are ready to be removed
470
self.req._task_deleted(self.get_id())
473
513
self._modified_update()
474
514
if self.is_loaded():
515
#This is a liblarch call to the TreeNode ancestor
516
gobject.idle_add(self.modified)
517
for t in self.get_tags():
518
gobject.idle_add(t.modified)
480
#This function send the modified signals for the tasks,
481
#parents and children
482
def call_modified(self):
483
#we first modify children
484
for s in self.get_children():
485
self.req._task_modified(s)
487
self.req._task_modified(self.tid)
489
for p in self.get_parents():
490
self.req._task_modified(p)
492
523
def _modified_update(self):
494
525
Updates the modified timestamp
496
self.modified = datetime.now()
527
self.last_modified = datetime.now()
498
529
### TAG FUNCTIONS ############################################################
513
547
enew = saxutils.escape(saxutils.unescape(new))
514
548
self.content = self.content.replace(eold, enew)
515
549
self.remove_tag(old)
516
self.req._tag_modified(old)
550
self.req.get_tag(old).modified()
517
551
self.tag_added(new)
518
self.req._tag_modified(new)
552
self.req.get_tag(new).modifiel()
521
555
def tag_added(self, tagname):
525
559
#print "tag %s added to task %s" %(tagname,self.get_id())
526
560
t = tagname.encode("UTF-8")
527
tag = self.req.get_tag(t)
529
tag = self.req.new_tag(t)
530
tag.add_task(self.get_id())
531
561
#Do not add the same tag twice
532
562
if not t in self.tags:
533
563
self.tags.append(t)
536
566
for child in self.get_subtasks():
537
567
if child.can_be_deleted:
539
self.req._tag_modified(t)
570
tag = self.req.get_tag(t)
572
tag = self.req.new_tag(t)
542
576
def add_tag(self, tagname):
580
610
child.remove_tag(tagname)
581
611
self.content = self._strip_tag(self.content, tagname)
583
self.req._tag_modified(tagname)
613
tag = self.req.get_tag(tagname)
585
616
def set_only_these_tags(self, tags_list):