Added documentation to action.py and project.py
[matthijs/upstream/mobilegtd.git] / src / model / action.py
1 import re
2 from model import *
3 import config.config as config
4
5 class ActionStatus(Status):
6     pass
7
8 class UnprocessedStatus(Status):
9     def __init__(self):
10         super(UnprocessedStatus,self).__init__(u'unprocessed',0)
11     def update(self,owner):
12         return active
13
14
15
16 unprocessed = UnprocessedStatus()
17 active = ActionStatus(u'active',1,u'-')
18 done = ActionStatus(u'done',2,u'+')
19 tickled = ActionStatus(u'tickled',3,u'/')
20 inactive = ActionStatus(u'inactive',4,u'!')
21 someday = ActionStatus(u'someday',5,u'~')
22 info = ActionStatus(u'info',0)
23
24 action_regexp = re.compile('(?P<status>[+-/!])?\s*(?P<context>\S*)\s*(?P<description>[^\(]*)(\((?P<info>[^\)]*))?',re.U)
25 context_regexp = re.compile('(?P<numbers>\d*)(?P<text>\D?.*)',re.U)
26
27
28 def parse_action_line(string):
29     matching = action_regexp.match(string)
30     description = matching.group('description').rstrip(u' \r\n')
31     status_symbol = matching.group('status')
32     if (status_symbol == None):
33         status_symbol = u''
34     status = ActionStatus.get_status(status_symbol)
35     info = matching.group('info')
36     context = parse_context(matching.group('context'))
37     if(info==None):
38         info=u''
39     return context,description,info,status    
40
41
42 def parse_context(context):
43     context_matching = context_regexp.match(context)
44     context_numbers = context_matching.group('numbers')
45     context_text = context_matching.group('text')
46     if(context_numbers in config.ABBREVIATIONS):
47         context=(unicode(config.ABBREVIATIONS[context_numbers])+context_text).rstrip(u'/')
48     else:
49         context=context_text
50     if (len(context)<2):
51         context = u'None'
52     return context
53
54
55
56
57 class Action(ObservableItem,ItemWithStatus):
58     """Actions in the GTD terminology are physical, visible activities.
59     In MobileGTD, an action consists of a description (e.g. "Google for Python"),
60     a context ("@Computer") and optionally a project which it belongs to and
61     additional information.
62     An Action also has a state. This can be one of the following:
63     - unprocessed: New, has not yet been processed in any way by MobileGTD
64     - active: The action is among the next actions
65     - done: The action has been performed
66     - tickled: The action has been postponed to a certain date
67     - inactive: The action has been paused
68     """
69     def parse(string):
70         assert type(string) == unicode
71         context,description,info,status  = parse_action_line(string)
72         return Action(description,context,info=info,status=status)
73     
74     parse = staticmethod(parse)
75     
76     def __init__(self,description,context,project=None,info=u'',status=unprocessed):
77         super(Action, self).__init__()
78         self.project = project
79         assert type(description) == unicode
80         assert type(context) == unicode
81         assert type(info) == unicode
82         
83         self.description = description
84         self.context = context
85         self.info = info
86         self.status = status
87         
88     def is_active(self):
89         return self.status in [active,unprocessed]
90     
91     def is_reviewable(self):
92         return self.status in [unprocessed,inactive]
93     
94     def is_not_done(self):
95         return self.status in [active,unprocessed,inactive]
96         
97     def __repr__(self):
98         advanced_info = u''
99         if self.project:
100             advanced_info = advanced_info+' Project: '+str(self.project)
101         if len(self.info) > 0:
102             advanced_info = advanced_info +' Info: '+self.info
103         if len(advanced_info) > 0:
104             advanced_info = '   ('+advanced_info+' )'
105         return repr(self.description)+' @'+repr(self.context)+repr(advanced_info)
106     
107     def project_file_string(self,entry_separator=' '):
108         return (u'%s%s'%(self.status_symbol(),self.context_description_info())).strip()
109     
110     def context_description_info(self,entry_separator=' '):
111         return u'%s%s%s%s%s'%(\
112                 self.context,entry_separator,\
113                 self.description,entry_separator,\
114                 self.info_string())
115
116     def info_string(self,entry_separator=''):
117         info_string = u''
118         if (len(self.info) > 1):
119             info_string = u'%s(%s)'%(entry_separator,self.info)
120         return info_string
121
122     def __str__(self):
123         return self.project_file_string()
124     def __cmp__(self,other):
125         return self.status.__cmp__(other.status)
126
127     def summary(self):
128         return self.description
129 __all__ = ["Action","ActionStatus","active","done","tickled","inactive","someday","info","unprocessed","parse_action_line","parse_context"]