[IMP] Improved views for project and project_gtd
[odoo/odoo.git] / addons / project_gtd / project_gtd.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #    
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
19 #
20 ##############################################################################
21
22 from xml import dom
23 from lxml import etree
24
25 from mx import DateTime
26 from mx.DateTime import now
27 import time
28 import tools
29 import netsvc
30 from osv import fields, osv
31 import ir
32
33 class project_gtd_context(osv.osv):
34     _name = "project.gtd.context"
35     _description = "Contexts"
36     _columns = {
37         'name': fields.char('Context', size=64, required=True, select=1),
38         'sequence': fields.integer('Sequence'),
39         'project_default_id': fields.many2one('project.project', 'Default Project', required=True),
40     }
41     _defaults = {
42         'sequence': lambda *args: 1
43     }
44     _order = "sequence, name"
45     
46 project_gtd_context()
47
48
49 class project_gtd_timebox(osv.osv):
50     _name = "project.gtd.timebox"
51     _order = "sequence"
52     _columns = {
53         'name': fields.char('Timebox', size=64, required=True, select=1),
54         'sequence': fields.integer('Sequence'),
55         'icon': fields.selection(tools.icons, 'Icon', size=64),
56     }
57     
58     def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
59         res = super(project_gtd_timebox,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
60         if (res['type']=='form') and ('record_id' in context):
61             if context['record_id']:
62                 rec = self.browse(cr, uid, int(context['record_id']), context)
63             else:
64                 iids = self.search(cr,uid, [('user_id','=',uid),('parent_id','=',False)], context=context)
65                 if len(iids):
66                     rec = self.browse(cr, uid, int(iids[0]), context=context)
67                 else:
68                     return res
69             res['arch'] = """
70     <form string="Daily Timebox">
71         <field name="name" readonly="1"/>
72         <notebook position="top">
73             """
74             for i in range(1,7):
75                 if not getattr(rec, 'context%d_id'%i):
76                     continue
77                 res['arch']+= """
78             <page string="%s">
79                 <field name="%s" colspan="4" nolabel="1">
80                     <tree editable="bottom" colors="grey:state in ('done','pending');red:state=='cancelled'" string="Tasks">
81                         <field name="name"/>
82                 """ % (getattr(rec, 'context%d_id'%(i,)).name.encode('utf-8'), 'task%d_ids'%(i,))
83                 if rec.col_project:
84                     res['arch'] += '<field name="project_id" required="1"/>\n'
85                 if rec.col_date_start:
86                     res['arch'] += '<field name="date_start"/>\n'
87                 if rec.col_priority:
88                     res['arch'] += '<field name="priority"/>\n'
89                 if rec.col_deadline:
90                     res['arch'] += '<field name="date_deadline"/>\n'
91                 if rec.col_planned_hours:
92                     res['arch'] += '<field name="planned_hours"  widget="float_time" sum="Est. Hours"/>\n'
93                 if rec.col_effective_hours:
94                     res['arch'] += '<field name="effective_hours"  widget="float_time" sum="%s"/>\n' % (_('Eff. Hours'),)
95                 res['arch'] += """
96                         <field name="state" readonly="1"/>
97                     </tree>
98                 </field>
99             </page>
100                 """
101             res['arch']+="""
102         </notebook>
103     </form>
104             """
105         doc = etree.XML(res['arch'])
106         xarch, xfields = self._view_look_dom_arch(cr, uid, doc, view_id, context=context)
107         res['arch'] = xarch
108         res['fields'] = xfields
109         return res
110
111 project_gtd_timebox()
112
113 class project_task(osv.osv):
114     _inherit = "project.task"
115     _columns = {
116         'timebox_id': fields.many2one('project.gtd.timebox', "Timebox"),
117         'context_id': fields.many2one('project.gtd.context', "Context"),
118      }
119     
120     def copy_data(self, cr, uid, id, default=None, context=None):
121         if not default:
122             default = {}
123         default['timebox_id']=False
124         default['context_id']=False
125         return super(project_task,self).copy_data(cr, uid, id, default, context)
126     
127     def _get_context(self,cr, uid, ctx):
128         ids = self.pool.get('project.gtd.context').search(cr, uid, [], context=ctx)
129         return ids and ids[0] or False
130     _defaults = {
131         'context_id': _get_context
132     }
133     
134     def next_timebox(self, cr, uid, ids, *args):
135         timebox_obj = self.pool.get('project.gtd.timebox')
136         timebox_ids = timebox_obj.search(cr,uid,[])
137         for task in self.browse(cr,uid,ids):
138             timebox = task.timebox_id.id
139             if timebox and  timebox_ids.index(timebox) != len(timebox_ids)-1 :
140                 index = timebox_ids.index(timebox)
141             else:
142                 index = -1
143             self.write(cr, uid, task.id, {'timebox_id': timebox_ids[index+1]})
144         return True
145
146     def prev_timebox(self, cr, uid, ids, *args):
147         timebox_obj = self.pool.get('project.gtd.timebox')
148         timebox_ids = timebox_obj.search(cr,uid,[])
149         for task in self.browse(cr,uid,ids):
150             timebox = task.timebox_id.id
151             if timebox and  timebox_ids.index(timebox) != 0 :
152                 index = timebox_ids.index(timebox)
153             else:
154                 index = len(timebox_ids)
155             self.write(cr, uid, task.id, {'timebox_id': timebox_ids[index - 1]})
156         return True
157     
158     def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
159         res = super(project_task,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
160         search_extended = False
161         timebox_obj = self.pool.get('project.gtd.timebox')
162         if res['type'] == 'search':
163             tt = timebox_obj.browse(cr, uid, timebox_obj.search(cr,uid,[]))
164             search_extended ='''<newline/><group col="%d">''' % (len(tt)+6,)
165             search_extended += '''<filter domain="[('timebox_id','=', 0)]" icon="gtk-new" string="Inbox"/>'''
166             search_extended += '''<separator orientation="vertical"/>'''
167             for time in tt:
168                 if time.icon:
169                     icon = time.icon
170                 else :
171                     icon=""
172                 search_extended += ''' <filter domain="[('timebox_id','=', ''' + str(time.id) + ''')]" icon="''' + icon + '''" string="''' + time.name + '''"/>'''
173             search_extended += '''
174             <separator orientation="vertical"/>
175             <field name="context_id" select="1" widget="selection"/> 
176             <field name="priority" select="1"/>
177             </group>
178             </search> '''
179         if search_extended:
180             res['arch'] = res['arch'].replace('</search>',search_extended)
181             attrs_sel = self.pool.get('project.gtd.context').name_search(cr, uid, '', [], context=context)
182             context_id_info = self.pool.get('project.task').fields_get(cr, uid, ['context_id'])
183             context_id_info['context_id']['selection'] = attrs_sel
184             res['fields'].update(context_id_info)
185         return res
186  
187     # Override read for using this method if context set !!!
188     #_order = "((55-ascii(coalesce(priority,'2')))*2 +  coalesce((date_start::date-current_date)/2,8))"
189 project_task()
190
191 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
192