~nmu-sscheel/gtg/rework-task-editor

« back to all changes in this revision

Viewing changes to GTG/core/treefactory.py

  • Committer: Luca Invernizzi
  • Date: 2010-09-08 14:15:11 UTC
  • mfrom: (825.1.227 liblarch_rebased)
  • Revision ID: invernizzi.l@gmail.com-20100908141511-vsctgw74dj1xp0wi
Liblarch is now in trunk.
Note that performances are still bad and it misses DnD and multi-select
support, but its state is better that the current trunk.
Backends are added in this merge too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
5
#
 
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
 
9
# version.
 
10
#
 
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
 
14
# details.
 
15
#
 
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
# -----------------------------------------------------------------------------
 
19
 
 
20
from datetime import datetime
 
21
 
 
22
from GTG.tools.dates  import date_today, no_date, Date
 
23
 
 
24
from GTG                         import _
 
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
 
29
 
 
30
class TreeFactory:
 
31
 
 
32
    def __init__(self):
 
33
        #Keep the tree in memory jus in case we have to use it for filters.
 
34
        self.tasktree = None
 
35
        self.tagtree = None
 
36
 
 
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.
 
41
        '''
 
42
        tasktree = Tree()
 
43
        f_dic = {
 
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}],
 
55
          }
 
56
          
 
57
        for f in f_dic:
 
58
            filt = f_dic[f]
 
59
            if len(filt) > 1:
 
60
                param = filt[1]
 
61
            else:
 
62
                param = None
 
63
            tasktree.add_filter(f,filt[0],param)
 
64
        self.tasktree = tasktree
 
65
        return tasktree
 
66
    
 
67
    
 
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.
 
71
        '''
 
72
        tagtree = Tree()
 
73
        
 
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>"\
 
79
                                             % _("All tasks"))
 
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)
 
97
        # Build the separator
 
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)
 
102
        
 
103
        
 
104
        #### Filters 
 
105
        tagtree.add_filter('active',self.actively_used_tag)
 
106
        tagtree.add_filter('used',self.used_tag)
 
107
        
 
108
        activeview = tagtree.get_viewtree(name='active',refresh=False)
 
109
        activeview.apply_filter('active')
 
110
        
 
111
        usedview = tagtree.get_viewtree(name='used',refresh=False)
 
112
        usedview.apply_filter('used')
 
113
        
 
114
        self.tagtree = tagtree
 
115
        self.tagtree_loaded = True
 
116
        return tagtree
 
117
    
 
118
    ################# Tag Filters ##########################################
 
119
    
 
120
    #filter to display only tags with active tasks
 
121
    def actively_used_tag(self,node,parameters=None):
 
122
        toreturn = node.is_actively_used()
 
123
        return toreturn
 
124
        
 
125
    def used_tag(self,node,parameters=None):
 
126
        return node.is_used()
 
127
        
 
128
        
 
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])
 
137
        
 
138
    def alltag(self,task,parameters=None):
 
139
        return True
 
140
    
 
141
    def notag(self,task,parameters=None):
 
142
        """ Filter of tasks without tags """
 
143
        return task.has_tags(notag_only=True)
 
144
        
 
145
    def is_leaf(self,task,parameters=None):
 
146
        """ Filter of tasks which have no children """
 
147
        return not task.has_child()
 
148
    
 
149
    def is_workable(self,task,parameters=None):
 
150
        """ Filter of tasks that can be worked """
 
151
        workable = True
 
152
        for c in task.get_subtasks():
 
153
            if c and c.get_status() == Task.STA_ACTIVE:
 
154
                workable = False
 
155
        return workable
 
156
        
 
157
    def is_started(self,task,parameters=None):
 
158
        '''Filter for tasks that are already started'''
 
159
        start_date = task.get_start_date()
 
160
        if 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
 
169
            else:
 
170
                return difference.days > 0 #pylint: disable-msg=E1101
 
171
        else:
 
172
            return True
 
173
            
 
174
    def workview(self,task,parameters=None):
 
175
        wv = self.active(task) and\
 
176
             self.is_started(task) and\
 
177
             self.is_workable(task)
 
178
        return wv
 
179
        
 
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
 
185
        return wv
 
186
 
 
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
 
192
        return wv
 
193
 
 
194
    def workstarted(self,task):
 
195
        ''' Filter for workable tasks with a start date specified '''
 
196
        wv = self.workview(task) and \
 
197
             task.start_date
 
198
        return wv
 
199
        
 
200
    def worktostart(self,task):
 
201
        ''' Filter for workable tasks without a start date specified '''
 
202
        wv = self.workview(task) and \
 
203
             not task.start_date
 
204
        return wv
 
205
        
 
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
 
210
        
 
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]
 
214
        return ret
 
215
        
 
216
    def no_disabled_tag(self,task,parameters=None):
 
217
        """Filter of task that don't have any disabled/nonworkview tag"""
 
218
        toreturn = True
 
219
        for t in task.get_tags():
 
220
            if t.get_attribute("nonworkview") == "True":
 
221
                toreturn = False
 
222
        return toreturn