~ubuntu-branches/ubuntu/vivid/hamster-applet/vivid

« back to all changes in this revision

Viewing changes to hamster/widgets/timeinput.py

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Starr-Bochicchio, Robert Ancell, Andrew Starr-Bochicchio
  • Date: 2009-12-22 17:52:52 UTC
  • mfrom: (1.1.13 upstream) (5.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091222175252-2r447ri9x56hi4kl
Tags: 2.29.4-0ubuntu1
[ Robert Ancell ]
* debian/control.in:
  - Remove old debian VCS links

[ Andrew Starr-Bochicchio ]
* New upstream release. (LP: #488783)
 - Fixed problems with hamster interfering with 
   screensaver hibernation code. (LP: #448438)
 - Fixes to the dropdown in compiz (not spanning
   over virtual desktops anymore). (LP: #303572)

* Merge with Debian testing, remaining Ubuntu changes:
 - Adapt debian/watch to take unstable version.
 - Point Vcs field at lp:~ubuntu-desktop/hamster-applet/ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# - coding: utf-8 -
 
2
 
 
3
# Copyright (C) 2008-2009 Toms Bauģis <toms.baugis at gmail.com>
 
4
 
 
5
# This file is part of Project Hamster.
 
6
 
 
7
# Project Hamster is free software: you can redistribute it and/or modify
 
8
# it under the terms of the GNU General Public License as published by
 
9
# the Free Software Foundation, either version 3 of the License, or
 
10
# (at your option) any later version.
 
11
 
 
12
# Project Hamster 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 General Public License for more details.
 
16
 
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with Project Hamster.  If not, see <http://www.gnu.org/licenses/>.
 
19
 
 
20
from .hamster.stuff import format_duration
 
21
import gtk
 
22
import datetime as dt
 
23
import calendar
 
24
import gobject
 
25
import re
 
26
 
 
27
class TimeInput(gtk.Entry):
 
28
    __gsignals__ = {
 
29
        'time-entered': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
 
30
    }
 
31
 
 
32
 
 
33
    def __init__(self, time = None, start_time = None):
 
34
        gtk.Entry.__init__(self)
 
35
 
 
36
        self.start_time = start_time
 
37
        self.news = False
 
38
 
 
39
        self.set_width_chars(7) #7 is like 11:24pm
 
40
        self.time = time
 
41
        if time:
 
42
            self.set_time(time)
 
43
 
 
44
 
 
45
        self.popup = gtk.Window(type = gtk.WINDOW_POPUP)
 
46
        time_box = gtk.ScrolledWindow()
 
47
        time_box.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
 
48
        time_box.set_shadow_type(gtk.SHADOW_IN)
 
49
 
 
50
        self.time_tree = gtk.TreeView()
 
51
        self.time_tree.set_headers_visible(False)
 
52
        self.time_tree.set_hover_selection(True)
 
53
 
 
54
        self.time_tree.append_column(gtk.TreeViewColumn("Time",
 
55
                                                        gtk.CellRendererText(),
 
56
                                                        text=0))
 
57
        self.time_tree.connect("button-press-event",
 
58
                               self._on_time_tree_button_press_event)
 
59
 
 
60
        time_box.add(self.time_tree)
 
61
        self.popup.add(time_box)
 
62
 
 
63
        self.connect("button-press-event", self._on_button_press_event)
 
64
        self.connect("key-press-event", self._on_key_press_event)
 
65
        self.connect("focus-in-event", self._on_focus_in_event)
 
66
        self.connect("focus-out-event", self._on_focus_out_event)
 
67
        self.connect("changed", self._on_text_changed)
 
68
        self.show()
 
69
 
 
70
 
 
71
    def set_start_time(self, start_time):
 
72
        """ set the start time. when start time is set, drop down list
 
73
            will start from start time and duration will be displayed in
 
74
            brackets
 
75
        """
 
76
        self.start_time = start_time
 
77
 
 
78
    def set_time(self, time):
 
79
        self.time = time
 
80
        self.set_text(self._format_time(time))
 
81
        
 
82
    def _on_text_changed(self, widget):
 
83
        self.news = True
 
84
        
 
85
    def figure_time(self, str_time):
 
86
        if not str_time:
 
87
            return self.time
 
88
        
 
89
        # strip everything non-numeric and consider hours to be first number
 
90
        # and minutes - second number
 
91
        numbers = re.split("\D", str_time)
 
92
        numbers = filter(lambda x: x!="", numbers)
 
93
        
 
94
        hours, minutes = None, None
 
95
        
 
96
        if len(numbers) == 1 and len(numbers[0]) == 4:
 
97
            hours, minutes = int(numbers[0][:2]), int(numbers[0][2:])
 
98
        else:
 
99
            if len(numbers) >= 1:
 
100
                hours = int(numbers[0])
 
101
            if len(numbers) >= 2:
 
102
                minutes = int(numbers[1])
 
103
            
 
104
        if (hours is None or minutes is None) or hours > 24 or minutes > 60:
 
105
            return self.time #no can do
 
106
    
 
107
        return dt.datetime.now().replace(hour = hours, minute = minutes,
 
108
                                         second = 0, microsecond = 0)
 
109
 
 
110
 
 
111
    def _select_time(self, time_text):
 
112
        #convert forth and back so we have text formated as we want
 
113
        time = self.figure_time(time_text)
 
114
        time_text = self._format_time(time) 
 
115
        
 
116
        self.set_text(time_text)
 
117
        self.set_position(len(time_text))
 
118
        self.popup.hide()
 
119
        if self.news:
 
120
            self.emit("time-entered")
 
121
            self.news = False
 
122
    
 
123
    def get_time(self):
 
124
        self.time = self.figure_time(self.get_text())
 
125
        self.set_text(self._format_time(self.time))
 
126
        return self.time
 
127
 
 
128
    def _format_time(self, time):
 
129
        if time is None:
 
130
            return None
 
131
        
 
132
        #return time.strftime("%I:%M%p").lstrip("0").lower()
 
133
        return time.strftime("%H:%M").lower()
 
134
    
 
135
 
 
136
    def _on_focus_in_event(self, entry, event):
 
137
        self.show_popup()
 
138
 
 
139
    def _on_button_press_event(self, button, event):
 
140
        self.show_popup()
 
141
 
 
142
    def _on_focus_out_event(self, event, something):
 
143
        self.popup.hide()
 
144
        if self.news:
 
145
            self.emit("time-entered")
 
146
            self.news = False
 
147
        
 
148
 
 
149
    def show_popup(self):
 
150
        focus_time = self.figure_time(self.get_text())
 
151
        
 
152
        hours = gtk.ListStore(gobject.TYPE_STRING)
 
153
        
 
154
        # populate times
 
155
        i_time = self.start_time or dt.datetime(1900, 1, 1, 0, 0)
 
156
        
 
157
        if focus_time and focus_time < i_time:
 
158
            focus_time += dt.timedelta(days = 1)
 
159
        
 
160
        if self.start_time:
 
161
            end_time = i_time + dt.timedelta(hours = 12)
 
162
            i_time += dt.timedelta(minutes = 15)
 
163
        else:
 
164
            end_time = i_time + dt.timedelta(hours = 24)
 
165
        
 
166
        i, focus_row = 0, None
 
167
        
 
168
        while i_time < end_time:
 
169
            row_text = self._format_time(i_time)
 
170
            if self.start_time:
 
171
                delta = (i_time - self.start_time).seconds / 60
 
172
                delta_text = format_duration(delta)
 
173
                
 
174
                row_text += " (%s)" % delta_text
 
175
 
 
176
            hours.append([row_text])
 
177
            
 
178
            if focus_time and i_time <= focus_time <= i_time + \
 
179
                                                     dt.timedelta(minutes = 30):
 
180
                focus_row = i
 
181
            
 
182
            if self.start_time:
 
183
                i_time += dt.timedelta(minutes = 15)
 
184
            else:
 
185
                i_time += dt.timedelta(minutes = 30)
 
186
 
 
187
            i += 1
 
188
 
 
189
        self.time_tree.set_model(hours)        
 
190
 
 
191
        #focus on row
 
192
        if focus_row != None:
 
193
            self.time_tree.set_cursor(focus_row)
 
194
            self.time_tree.scroll_to_cell(focus_row, use_align = True, row_align = 0.4)
 
195
        
 
196
        #move popup under the widget
 
197
        alloc = self.get_allocation()
 
198
        w = alloc.width
 
199
        if self.start_time:
 
200
            w = w * 2
 
201
        self.time_tree.set_size_request(w, alloc.height * 5)
 
202
 
 
203
        window = self.get_parent_window()
 
204
        x, y= window.get_origin()
 
205
 
 
206
        self.popup.move(x + alloc.x,y + alloc.y + alloc.height)
 
207
        self.popup.show_all()
 
208
 
 
209
    
 
210
    def _on_time_tree_button_press_event(self, tree, event):
 
211
        model, iter = tree.get_selection().get_selected()
 
212
        time = model.get_value(iter, 0)
 
213
        self._select_time(time)
 
214
        
 
215
        
 
216
    def _on_key_press_event(self, entry, event):
 
217
        cursor = self.time_tree.get_cursor()
 
218
 
 
219
        if not cursor or not cursor[0]:
 
220
            return
 
221
        
 
222
        i = cursor[0][0]
 
223
 
 
224
        if event.keyval == gtk.keysyms.Up:
 
225
            i-=1
 
226
        elif event.keyval == gtk.keysyms.Down:
 
227
            i+=1
 
228
        elif (event.keyval == gtk.keysyms.Return or
 
229
              event.keyval == gtk.keysyms.KP_Enter):
 
230
            
 
231
            if self.popup.get_property("visible"):
 
232
                self._select_time(self.time_tree.get_model()[i][0])
 
233
            else:
 
234
                self._select_time(entry.get_text())
 
235
        elif (event.keyval == gtk.keysyms.Escape):
 
236
            self.popup.hide()
 
237
        else:
 
238
            #any kind of other input
 
239
            self.popup.hide()
 
240
            return False
 
241
        
 
242
        # keep it in the sane borders
 
243
        i = min(max(i, 0), len(self.time_tree.get_model()) - 1)
 
244
        
 
245
        self.time_tree.set_cursor(i)
 
246
        self.time_tree.scroll_to_cell(i, use_align = True, row_align = 0.4)
 
247
        return True
 
248
 
 
249
 
 
250