1
# -*- coding: utf-8 -*-
2
# -----------------------------------------------------------------------------
3
# Gettings Things Gnome! - a personal organizer for the GNOME desktop
4
# Copyright (c) 2008-2009 - Lionel Dricot & Bertrand Rousseau
6
# This program is free software: you can redistribute it and/or modify it under
7
# the terms of the GNU General Public License as published by the Free Software
8
# Foundation, either version 3 of the License, or (at your option) any later
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16
# 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/>.
18
# -----------------------------------------------------------------------------
20
from datetime import datetime
22
from GTG.tools.dates import date_today, no_date, Date
25
from GTG.tools.liblarch import Tree
26
from GTG.core.task import Task
27
from GTG.core.tagstore import Tag
28
from GTG.core import CoreConfig
33
#Keep the tree in memory jus in case we have to use it for filters.
37
def get_tasks_tree(self):
38
'''This create a liblarch tree suitable for tasks,
39
including default filters
40
For tags, filter are dynamically created at Tag insertion.
44
'workview': [self.workview],
45
'active': [self.active],
46
'closed': [self.closed, {'flat': True}],
47
'notag': [self.notag, {'transparent': True}],
48
'workable': [self.is_workable],
49
'started': [self.is_started],
50
'workdue': [self.workdue],
51
'workstarted': [self.workstarted],
52
'worktostart': [self.worktostart],
53
'worklate': [self.worklate],
54
'no_disabled_tag': [self.no_disabled_tag,{'transparent': True}],
63
tasktree.add_filter(f,filt[0],param)
64
self.tasktree = tasktree
68
def get_tags_tree(self,req):
69
'''This create a liblarch tree suitable for tags,
70
including the all_tags_tag and notag_tag.
74
### building the initial tags
75
# Build the "all tasks tag"
76
alltag = Tag(CoreConfig.ALLTASKS_TAG, req=req)
77
alltag.set_attribute("special","all")
78
alltag.set_attribute("label","<span weight='bold'>%s</span>"\
80
alltag.set_attribute("icon","gtg-tags-all")
81
alltag.set_attribute("order",0)
82
tagtree.add_node(alltag)
83
p = {'transparent':True}
84
self.tasktree.add_filter(CoreConfig.ALLTASKS_TAG,\
85
self.alltag,parameters=p)
86
# Build the "without tag tag"
87
notag_tag = Tag(CoreConfig.NOTAG_TAG,req=req)
88
notag_tag.set_attribute("special","notag")
89
notag_tag.set_attribute("label","<span weight='bold'>%s</span>"\
90
% _("Tasks with no tags"))
91
notag_tag.set_attribute("icon","gtg-tags-none")
92
notag_tag.set_attribute("order",1)
93
tagtree.add_node(notag_tag)
94
p = {'transparent':True}
95
self.tasktree.add_filter(CoreConfig.NOTAG_TAG,\
96
self.notag,parameters=p)
98
sep_tag = Tag(CoreConfig.SEP_TAG,req=req)
99
sep_tag.set_attribute("special","sep")
100
sep_tag.set_attribute("order",2)
101
tagtree.add_node(sep_tag)
105
tagtree.add_filter('active',self.actively_used_tag)
106
tagtree.add_filter('used',self.used_tag)
108
activeview = tagtree.get_viewtree(name='active',refresh=False)
109
activeview.apply_filter('active')
111
usedview = tagtree.get_viewtree(name='used',refresh=False)
112
usedview.apply_filter('used')
114
self.tagtree = tagtree
115
self.tagtree_loaded = True
118
################# Tag Filters ##########################################
120
#filter to display only tags with active tasks
121
def actively_used_tag(self,node,parameters=None):
122
toreturn = node.is_actively_used()
125
def used_tag(self,node,parameters=None):
126
return node.is_used()
129
################# Task Filters #########################################
130
#That one is used to filters tag. Is it built dynamically each times
131
#a tag is added to the tagstore
132
def tag_filter(self,node,parameters=None):
133
#FIXME: we should take tag children into account
134
#Bryce : use self.tagtree to find children/parents of tags
135
tname = parameters['tag']
136
return node.has_tags([tname])
138
def alltag(self,task,parameters=None):
141
def notag(self,task,parameters=None):
142
""" Filter of tasks without tags """
143
return task.has_tags(notag_only=True)
145
def is_leaf(self,task,parameters=None):
146
""" Filter of tasks which have no children """
147
return not task.has_child()
149
def is_workable(self,task,parameters=None):
150
""" Filter of tasks that can be worked """
152
for c in task.get_subtasks():
153
if c and c.get_status() == Task.STA_ACTIVE:
157
def is_started(self,task,parameters=None):
158
'''Filter for tasks that are already started'''
159
start_date = task.get_start_date()
161
#Seems like pylint falsely assumes that subtraction always results
162
#in an object of the same type. The subtraction of dates
163
#results in a datetime.timedelta object
164
#that does have a 'days' member.
165
difference = date_today() - start_date
166
if difference.days == 0:
167
# Don't count today's tasks started until morning
168
return datetime.now().hour > 4
170
return difference.days > 0 #pylint: disable-msg=E1101
174
def workview(self,task,parameters=None):
175
wv = self.active(task) and\
176
self.is_started(task) and\
177
self.is_workable(task)
180
def workdue(self,task):
181
''' Filter for tasks due within the next day '''
182
wv = self.workview(task) and \
183
task.get_due_date() != no_date and \
184
task.get_days_left() < 2
187
def worklate(self,task):
188
''' Filter for tasks due within the next day '''
189
wv = self.workview(task) and \
190
task.get_due_date() != no_date and \
191
task.get_days_late() > 0
194
def workstarted(self,task):
195
''' Filter for workable tasks with a start date specified '''
196
wv = self.workview(task) and \
200
def worktostart(self,task):
201
''' Filter for workable tasks without a start date specified '''
202
wv = self.workview(task) and \
206
def active(self,task,parameters=None):
207
""" Filter of tasks which are active """
208
#FIXME: we should also handle unactive tags
209
return task.get_status() == Task.STA_ACTIVE
211
def closed(self,task,parameters=None):
212
""" Filter of tasks which are closed """
213
ret = task.get_status() in [Task.STA_DISMISSED, Task.STA_DONE]
216
def no_disabled_tag(self,task,parameters=None):
217
"""Filter of task that don't have any disabled/nonworkview tag"""
219
for t in task.get_tags():
220
if t.get_attribute("nonworkview") == "True":