use time.strptime
[openerp-client.git] / bin / widget / view / tree_gtk / date_renderer.py
blobd930863bedf8df5ee5378f84cfc952cb5f729db9
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
6 # $Id$
8 # WARNING: This program as such is intended to be used by professional
9 # programmers who take the whole responsability of assessing all potential
10 # consequences resulting from its eventual inadequacies and bugs
11 # End users who are looking for a ready-to-use solution with commercial
12 # garantees and support are strongly adviced to contract a Free Software
13 # Service Company
15 # This program is Free Software; you can redistribute it and/or
16 # modify it under the terms of the GNU General Public License
17 # as published by the Free Software Foundation; either version 2
18 # of the License, or (at your option) any later version.
20 # This program is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 ##############################################################################
31 #!/usr/bin/env python
33 import pygtk
34 pygtk.require('2.0')
35 import gtk
36 import gobject
37 import pango
38 import re
40 import tools
41 from tools import date_mapping
43 import time
44 from mx.DateTime import DateTime
47 class DecoratorRenderer(gtk.GenericCellRenderer):
48 def __init__(self, renderer1, callback, format):
49 self.__gobject_init__()
50 self.renderer1 = renderer1
51 self.set_property("mode", renderer1.get_property("mode"))
52 self.callback = callback
53 self.format = format
54 self.regex = self.initial_value = self.format
55 for key,val in date_mapping.items():
56 self.regex = self.regex.replace(key, val[1])
57 self.initial_value = self.initial_value.replace(key, val[0])
58 self.regex = '^'+self.regex+'$'
60 def set_property(self, name, value):
61 if name not in ('editable', ):
62 return super(DecoratorRenderer, self).set_property(name, value)
63 else:
64 return self.renderer1.set_property(name, value)
66 def get_property(self, name):
67 if name in ('editable', ):
68 return self.renderer1.get_property(name)
69 else:
70 return super(DecoratorRenderer, self).get_property(name)
72 def on_get_size(self, widget, cell_area=None):
73 return self.renderer1.get_size(widget, cell_area)
75 def on_render(self, window, widget, background_area, cell_area, expose_area, flags):
76 return self.renderer1.render(window, widget, background_area, cell_area, expose_area, flags)
78 def on_activate(self, event, widget, path, background_area, cell_area, flags):
79 return self.renderer1.activate(event, widget, path, background_area, cell_area, flags)
81 def on_start_editing(self, event, widget, path, background_area, cell_area, flags):
82 if not event:
83 event = gtk.gdk.Event(gtk.keysyms.Tab)
85 editable = self.renderer1.start_editing(event, widget, path, background_area, cell_area, flags)
86 self.editable = editable
87 self.callback.display(editable)
89 if not editable.get_text():
90 editable.set_text(self.initial_value)
91 self.regex = re.compile(self.regex)
93 assert self.regex.match(self.initial_value), 'Error, the initial value should be validated by regex'
94 editable.set_width_chars(len(self.initial_value))
95 editable.set_max_length(len(self.initial_value))
97 editable.connect('key-press-event', self._on_key_press)
100 self._interactive_input = True
101 self.mode_cmd = False
102 gobject.idle_add(editable.set_position, 0)
103 return editable
105 def _on_delete_text(self, editable, start, end):
106 while (start>0) and (self.initial_value[start] not in ['_','0','X']):
107 start -= 1
108 text = editable.get_text()
109 text = text[:start] + self.initial_value[start:end] + text[end:]
110 editable.set_text(text)
111 gobject.idle_add(editable.set_position, start)
112 return
114 def date_get(self, editable):
115 tt = time.strftime(self.format, time.localtime())
116 tc = editable.get_text()
117 if tc==self.initial_value:
118 return False
119 for a in range(len(self.initial_value)):
120 if self.initial_value[a] == tc[a]:
121 tc = tc[:a] + tt[a] + tc[a+1:]
122 try:
123 editable.set_text(tc)
124 return time.strptime(tc, self.format)
125 except:
126 tc = tt
127 editable.set_text(tc)
128 return time.strptime(tc, self.format)
130 def _on_key_press(self, editable, event):
131 if event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Escape, gtk.keysyms.Return):
132 if self.mode_cmd:
133 self.mode_cmd = False
134 if self.callback: self.callback.process(self, event)
135 #self.stop_emission("key-press-event")
136 return True
137 else:
138 return False
139 elif event.keyval in (ord('+'),ord('-'),ord('=')):
140 self.mode_cmd = True
141 self.date_get(editable)
142 if self.callback: self.callback.event(self, event)
143 return True
144 elif self.mode_cmd:
145 if self.callback: self.callback.event(self, event)
146 return True
148 if event.keyval in (gtk.keysyms.BackSpace,):
149 pos = editable.get_position()
150 self._on_delete_text(editable, max(0,pos-1), pos)
151 return True
152 if event.keyval in (gtk.keysyms.Delete,):
153 pos = editable.get_position()
154 text = editable.get_text()
155 self._on_delete_text(editable, pos, len(text))
156 return True
158 if event.keyval>=ord('0') and event.keyval<=ord('9'):
159 pos = editable.get_position()
160 text = editable.get_text()
161 text = text[:pos] + chr(event.keyval) + text[pos + 1:]
162 if self.regex.match(text):
163 pos += 1
164 while (pos<len(self.initial_value)) and (self.initial_value[pos] not in ['_','0','X']):
165 pos += 1
166 editable.set_text(text)
167 editable.show()
168 gobject.idle_add(editable.set_position, pos)
170 if not event.string:
171 return False
172 return True
174 def date_set(self, dt):
175 if dt:
176 self.editable.set_text( dt.strftime(self.format) )
177 else:
178 self.editable.set_text(self.initial_value)
181 class date_callback(object):
182 def __init__(self, treeview=None):
183 self.value = ''
184 self.treeview = treeview
186 def event(self, widget, event):
187 if event.keyval in (gtk.keysyms.BackSpace,):
188 self.value = self.value[:-1]
189 if event.keyval<250:
190 self.value = self.value+chr(event.keyval)
191 self.display(widget)
192 return True
194 def display(self, widget):
195 if self.treeview:
196 if self.value:
197 self.treeview.warn('misc-message', '<b>' + str(tools.to_xml(self.value))+"</b>")
198 else:
199 self.treeview.warn('misc-message', _("Press <i>'+'</i>, <i>'-'</i> or <i>'='</i> for special date operations."))
201 def process(self, widget, event):
202 if (not event.keyval == gtk.keysyms.Escape) or not event:
203 cmd = self.value
204 for r,f in tools.date_operation.items():
205 groups = re.match(r, cmd)
206 if groups:
207 dt = widget.date_get(widget.editable)
208 if not dt:
209 dt = time.strftime(widget.format, time.localtime())
210 dt = time.strptime(dt, widget.format)
211 widget.date_set(f(dt,groups))
212 break
213 self.value = ''
214 self.display(widget)