~kklimonda/ubuntu/natty/hamster-applet/lp.697667

« back to all changes in this revision

Viewing changes to src/hamster/widgets/dateinput.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-02-10 02:52:31 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20100210025231-x0q5h4q7nlvihl09
Tags: 2.29.90-0ubuntu1
* New upstream version
  - workspace tracking - switch activity, when switching desktops
  - chart improvements - theme friendly and less noisier
  - for those without GNOME panel there is now a standalone version, 
    accessible via Applications -> Accessories -> Time Tracker
  - overview window remembers position
  - maintaining cursor on the selected row after edits / refreshes
  - descriptions once again in the main input field, delimited by comma
  - activity suggestion box now sorts items by recency (Patryk Zawadzki)
  - searching
  - simplified save report dialog, thanks to the what you see is what you 
    report revamp
  - overview/stats replaced with activities / totals and stats accessible 
    from totals
  - interactive graphs to drill down in totals
  - miscellaneous performance improvements
  - pixel-perfect graphs
* Updated 01_startup-fix.patch to apply to new source layout
* debian/control:
  - Add build-depend on gnome-doc-utils

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 DateInput(gtk.Entry):
 
28
    """ a text entry widget with calendar popup"""
 
29
    __gsignals__ = {
 
30
        'date-entered': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
 
31
    }
 
32
 
 
33
 
 
34
    def __init__(self, date = None):
 
35
        gtk.Entry.__init__(self)
 
36
 
 
37
        self.set_width_chars(12) #12 is enough for 12-oct-2009, which is verbose
 
38
        self.date = date
 
39
        if date:
 
40
            self.set_date(date)
 
41
 
 
42
        self.news = False
 
43
        self.prev_cal_day = None #workaround
 
44
        self.popup = gtk.Window(type = gtk.WINDOW_POPUP)
 
45
        calendar_box = gtk.HBox()
 
46
 
 
47
        self.date_calendar = gtk.Calendar()
 
48
        self.date_calendar.mark_day(dt.datetime.today().day)
 
49
        self.date_calendar.connect("day-selected", self._on_day_selected)
 
50
        self.date_calendar.connect("day-selected-double-click",
 
51
                                   self.__on_day_selected_double_click)
 
52
        self.date_calendar.connect("button-press-event",
 
53
                                   self._on_cal_button_press_event)
 
54
        calendar_box.add(self.date_calendar)
 
55
        self.popup.add(calendar_box)
 
56
 
 
57
        self.connect("button-press-event", self._on_button_press_event)
 
58
        self.connect("key-press-event", self._on_key_press_event)
 
59
        self.connect("focus-in-event", self._on_focus_in_event)
 
60
        self.connect("focus-out-event", self._on_focus_out_event)
 
61
        self.connect("changed", self._on_text_changed)
 
62
        self.show()
 
63
 
 
64
    def set_date(self, date):
 
65
        """sets date to specified, using default format"""
 
66
        self.date = date
 
67
        self.set_text(self._format_date(self.date))
 
68
 
 
69
    def get_date(self):
 
70
        """sets date to specified, using default format"""
 
71
        self.date = self._figure_date(self.get_text())
 
72
        self.set_text(self._format_date(self.date))
 
73
        return self.date
 
74
 
 
75
    def _figure_date(self, date_str):
 
76
        try:
 
77
            return dt.datetime.strptime(date_str, "%x")
 
78
        except:
 
79
            return self.date
 
80
 
 
81
    def _format_date(self, date):
 
82
        if not date:
 
83
            return ""
 
84
        else:
 
85
            return date.strftime("%x")
 
86
 
 
87
    def _on_text_changed(self, widget):
 
88
        self.news = True
 
89
 
 
90
    def __on_day_selected_double_click(self, calendar):
 
91
        self.prev_cal_day = None
 
92
        self._on_day_selected(calendar) #forward
 
93
 
 
94
    def _on_cal_button_press_event(self, calendar, event):
 
95
        self.prev_cal_day = calendar.get_date()[2]
 
96
 
 
97
    def _on_day_selected(self, calendar):
 
98
        if self.popup.get_property("visible") == False:
 
99
            return
 
100
 
 
101
        if self.prev_cal_day == calendar.get_date()[2]:
 
102
            return
 
103
 
 
104
        cal_date = calendar.get_date()
 
105
 
 
106
        self.date = dt.date(cal_date[0], cal_date[1] + 1, cal_date[2])
 
107
        self.set_text(self._format_date(self.date))
 
108
 
 
109
        self.popup.hide()
 
110
        if self.news:
 
111
            self.emit("date-entered")
 
112
            self.news = False
 
113
 
 
114
 
 
115
    def show_popup(self):
 
116
        window = self.get_parent_window()
 
117
        x, y= window.get_origin()
 
118
 
 
119
        alloc = self.get_allocation()
 
120
 
 
121
        date = self._figure_date(self.get_text())
 
122
        if date:
 
123
            self.prev_cal_day = date.day #avoid
 
124
            self.date_calendar.select_month(date.month - 1, date.year)
 
125
            self.date_calendar.select_day(date.day)
 
126
 
 
127
        self.popup.move(x + alloc.x,y + alloc.y + alloc.height)
 
128
        self.popup.show_all()
 
129
 
 
130
    def _on_focus_in_event(self, entry, event):
 
131
        self.show_popup()
 
132
 
 
133
    def _on_button_press_event(self, button, event):
 
134
        self.show_popup()
 
135
 
 
136
 
 
137
    def _on_focus_out_event(self, event, something):
 
138
        self.popup.hide()
 
139
        if self.news:
 
140
            self.emit("date-entered")
 
141
            self.news = False
 
142
 
 
143
    def _on_key_press_event(self, entry, event):
 
144
        if self.popup.get_property("visible"):
 
145
            cal_date = self.date_calendar.get_date()
 
146
            date = dt.date(cal_date[0], cal_date[1] + 1, cal_date[2])
 
147
        else:
 
148
            date = self._figure_date(entry.get_text())
 
149
            if not date:
 
150
                return
 
151
 
 
152
        enter_pressed = False
 
153
 
 
154
        if event.keyval == gtk.keysyms.Up:
 
155
            date = date - dt.timedelta(days=1)
 
156
        elif event.keyval == gtk.keysyms.Down:
 
157
            date = date + dt.timedelta(days=1)
 
158
        elif (event.keyval == gtk.keysyms.Return or
 
159
              event.keyval == gtk.keysyms.KP_Enter):
 
160
            enter_pressed = True
 
161
        elif (event.keyval == gtk.keysyms.Escape):
 
162
            self.popup.hide()
 
163
        elif event.keyval in (gtk.keysyms.Left, gtk.keysyms.Right):
 
164
            return False #keep calendar open and allow user to walk in text
 
165
        else:
 
166
            self.popup.hide()
 
167
            return False
 
168
 
 
169
        if enter_pressed:
 
170
            self.prev_cal_day = "borken"
 
171
        else:
 
172
            #prev_cal_day is our only way of checking that date is right
 
173
            self.prev_cal_day = date.day
 
174
 
 
175
        self.date_calendar.select_month(date.month - 1, date.year)
 
176
        self.date_calendar.select_day(date.day)
 
177
        return True