~ubuntu-branches/ubuntu/quantal/openerp-client/quantal

« back to all changes in this revision

Viewing changes to bin/widget/view/tree_gtk/date_renderer.py

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-12-07 20:17:00 UTC
  • Revision ID: james.westby@ubuntu.com-20081207201700-a875pic3sd7xkoru
Tags: upstream-5.0.0~alpha
ImportĀ upstreamĀ versionĀ 5.0.0~alpha

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- encoding: utf-8 -*-
 
2
##############################################################################
 
3
#
 
4
#    OpenERP, Open Source Management Solution   
 
5
#    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
 
6
#    $Id$
 
7
#
 
8
#    This program is free software: you can redistribute it and/or modify
 
9
#    it under the terms of the GNU General Public License as published by
 
10
#    the Free Software Foundation, either version 3 of the License, or
 
11
#    (at your option) any later version.
 
12
#
 
13
#    This program is distributed in the hope that it will be useful,
 
14
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
#    GNU General Public License for more details.
 
17
#
 
18
#    You should have received a copy of the GNU General Public License
 
19
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
#
 
21
##############################################################################
 
22
 
 
23
#!/usr/bin/env python
 
24
 
 
25
import pygtk
 
26
pygtk.require('2.0')
 
27
import gtk
 
28
import gobject
 
29
import pango
 
30
import re
 
31
 
 
32
import tools
 
33
import tools.datetime_util
 
34
import time
 
35
from mx.DateTime import DateTime
 
36
 
 
37
 
 
38
class DecoratorRenderer(gtk.GenericCellRenderer):
 
39
    def __init__(self, renderer1, callback, format):
 
40
        self.__gobject_init__()
 
41
        self.renderer1 = renderer1
 
42
        self.set_property("mode", renderer1.get_property("mode"))
 
43
        self.callback = callback
 
44
        self.format = format
 
45
        self.regex = self.initial_value = self.format
 
46
        for key,val in tools.datetime_util.date_mapping.items():
 
47
            self.regex = self.regex.replace(key, val[1])
 
48
            self.initial_value = self.initial_value.replace(key, val[0])
 
49
        self.regex = '^'+self.regex+'$'
 
50
 
 
51
    def _is_not_generic_property(self, name):
 
52
        return name in ('editable', 'text', 'foreground', 'background')
 
53
    
 
54
    def set_property(self, name, value):
 
55
        if not self._is_not_generic_property(name):
 
56
            return super(DecoratorRenderer, self).set_property(name, value)
 
57
        else:
 
58
            return self.renderer1.set_property(name, value)
 
59
 
 
60
    def get_property(self, name):
 
61
        if self._is_not_generic_property(name):
 
62
            return self.renderer1.get_property(name)
 
63
        else:
 
64
            return super(DecoratorRenderer, self).get_property(name)
 
65
 
 
66
    def on_get_size(self, widget, cell_area=None):
 
67
        return self.renderer1.get_size(widget, cell_area)
 
68
 
 
69
    def on_render(self, window, widget, background_area, cell_area, expose_area, flags):
 
70
        return self.renderer1.render(window, widget, background_area, cell_area, expose_area, flags)
 
71
 
 
72
    def on_activate(self, event, widget, path, background_area, cell_area, flags):
 
73
        return self.renderer1.activate(event, widget, path, background_area, cell_area, flags)
 
74
 
 
75
    def on_start_editing(self, event, widget, path, background_area, cell_area, flags):
 
76
        if not self.get_property('editable'):
 
77
            return None
 
78
        if not event:
 
79
            event = gtk.gdk.Event(gtk.keysyms.Tab)
 
80
 
 
81
        editable = self.renderer1.start_editing(event, widget, path, background_area, cell_area, flags)
 
82
        self.editable = editable
 
83
        self.callback.display(editable)
 
84
 
 
85
        if not editable.get_text():
 
86
            editable.set_text(self.initial_value)
 
87
        self.regex = re.compile(self.regex)
 
88
 
 
89
        assert self.regex.match(self.initial_value), 'Error, the initial value should be validated by regex'
 
90
        editable.set_width_chars(len(self.initial_value))
 
91
        editable.set_max_length(len(self.initial_value))
 
92
 
 
93
        editable.connect('key-press-event', self._on_key_press)
 
94
 
 
95
 
 
96
        self._interactive_input = True
 
97
        self.mode_cmd = False
 
98
        gobject.idle_add(editable.set_position, 0)
 
99
        return editable
 
100
 
 
101
    def _on_delete_text(self, editable, start, end):
 
102
        while (start>0) and (self.initial_value[start] not in ['_','0','X']):
 
103
            start -= 1
 
104
        text = editable.get_text()
 
105
        text = text[:start] + self.initial_value[start:end] + text[end:]
 
106
        editable.set_text(text)
 
107
        gobject.idle_add(editable.set_position, start)
 
108
        return
 
109
 
 
110
    def date_get(self, editable):
 
111
        tt = time.strftime(self.format, time.localtime())
 
112
        tc = editable.get_text()
 
113
        if tc==self.initial_value:
 
114
            return False
 
115
        for a in range(len(self.initial_value)):
 
116
            if self.initial_value[a] == tc[a]:
 
117
                tc = tc[:a] + tt[a] + tc[a+1:]
 
118
        try:
 
119
            editable.set_text(tc)
 
120
            return tools.datetime_util.strptime(tc, self.format)
 
121
        except:
 
122
            tc = tt
 
123
        editable.set_text(tc)
 
124
        return tools.datetime_util.strptime(tc, self.format)
 
125
 
 
126
    def _on_key_press(self, editable, event):
 
127
        if event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Escape, gtk.keysyms.Return):
 
128
            if self.mode_cmd:
 
129
                self.mode_cmd = False
 
130
                if self.callback: self.callback.process(self, event)
 
131
                #self.stop_emission("key-press-event")
 
132
                return True
 
133
            else:
 
134
                return False
 
135
        elif event.keyval in (ord('+'),ord('-'),ord('=')):
 
136
                self.mode_cmd = True
 
137
                self.date_get(editable)
 
138
                if self.callback: self.callback.event(self, event)
 
139
                return True
 
140
        elif self.mode_cmd:
 
141
            if self.callback: self.callback.event(self, event)
 
142
            return True
 
143
 
 
144
        if event.keyval in (gtk.keysyms.BackSpace,):
 
145
            pos = editable.get_position()
 
146
            self._on_delete_text(editable, max(0,pos-1), pos)
 
147
            return True
 
148
        if event.keyval in (gtk.keysyms.Delete,):
 
149
            pos = editable.get_position()
 
150
            text = editable.get_text()
 
151
            self._on_delete_text(editable, pos, len(text))
 
152
            return True
 
153
 
 
154
        if event.keyval>=ord('0') and event.keyval<=ord('9'):
 
155
            pos = editable.get_position()
 
156
            text = editable.get_text()
 
157
            text = text[:pos] + chr(event.keyval) + text[pos + 1:]
 
158
            if self.regex.match(text):
 
159
                pos += 1
 
160
                while (pos<len(self.initial_value)) and (self.initial_value[pos] not in ['_','0','X']):
 
161
                    pos += 1
 
162
                editable.set_text(text)
 
163
                editable.show()
 
164
                gobject.idle_add(editable.set_position, pos)
 
165
 
 
166
        if not event.string:
 
167
            return False
 
168
        return True
 
169
 
 
170
    def date_set(self, dt):
 
171
        if dt:
 
172
            self.editable.set_text( dt.strftime(self.format) )
 
173
        else:
 
174
            self.editable.set_text(self.initial_value)
 
175
 
 
176
 
 
177
class date_callback(object):
 
178
    def __init__(self, treeview=None):
 
179
        self.value = ''
 
180
        self.treeview = treeview
 
181
 
 
182
    def event(self, widget, event):
 
183
        if event.keyval in (gtk.keysyms.BackSpace,):
 
184
            self.value = self.value[:-1]
 
185
        if event.keyval<250:
 
186
            self.value = self.value+chr(event.keyval)
 
187
        self.display(widget)
 
188
        return True
 
189
 
 
190
    def display(self, widget):
 
191
        if self.treeview:
 
192
            if self.value:
 
193
                self.treeview.warn('misc-message', '<b>' + str(tools.to_xml(self.value))+"</b>")
 
194
            else:
 
195
                self.treeview.warn('misc-message', _("Press <i>'+'</i>, <i>'-'</i> or <i>'='</i> for special date operations."))
 
196
 
 
197
    def process(self, widget, event):
 
198
        if (not event) or event.keyval != gtk.keysyms.Escape:
 
199
            cmd = self.value
 
200
            for r,f in tools.datetime_util.date_operation.items():
 
201
                groups = re.match(r, cmd)
 
202
                if groups:
 
203
                    dt = widget.date_get(widget.editable)
 
204
                    if not dt:
 
205
                        dt = time.strftime(widget.format, time.localtime())
 
206
                        dt = tools.datetime_util.strptime(dt, widget.format)
 
207
                    widget.date_set(f(dt,groups))
 
208
                    break
 
209
        self.value = ''
 
210
        self.display(widget)
 
211
 
 
212
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
 
213