correct link to project homepage
[beats-applet] / src / beats-applet.py
1 '''
2 Beats
3 2009 (c) Paul Philippov <paul@ppds.ws>
4 Swatch Internet Time applet for Hildon
5 '''
6 import gtk
7 from gtk import gdk
8 import hildondesktop
9 import cairo
10 import gobject
11 import pango
12 import time
13 from datetime import timedelta, datetime, tzinfo
14 from ConfigParser import *
15
16 Pi = 3.14
17 Beat = 86.4
18
19 class BeatsApplet(hildondesktop.HomeItem):
20
21    def __init__(self):
22       hildondesktop.HomeItem.__init__(self)
23
24       self.timer = None
25
26       self.connect("settings", self._DoSettings)
27       self.connect("expose-event", self.expose)
28       self.connect("screen-changed", self.screen_changed)
29       self.connect("unrealize", self.unrealize)
30       self.connect("background", self.set_timer, False)
31       self.connect("foreground", self.set_timer, True)
32
33       self.label = gtk.Label()
34       self.label.set_use_markup(True)
35       self.label.set_markup('@---.-')
36       self.add(self.label)
37       self.set_size_request(-1, -1)
38
39       self.redraw()
40
41       self.inbackground = False
42       self.set_timer(self, True)
43       self.show_all()
44
45    def redraw(self):
46       self.set_resize_type(hildondesktop.HOME_ITEM_RESIZE_NONE)
47       self.label.modify_font(pango.FontDescription(self._prefRead('font')))
48 #      self.label.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self._prefRead('background')))
49       self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self._prefRead('foreground')))
50       self.label.set_padding(15, 20)
51       self.label.set_size_request(-1, -1)
52       self.set_size_request(-1, -1)
53
54    def expose(self, widget, event):
55       width, height = self.allocation[2], self.allocation[3]
56       radius = min(15, width/2, height/2)
57       x0 = 0; x1 = x0 + width
58       y0 = 0; y1 = y0 + height
59
60       cr = widget.window.cairo_create()
61       cr.set_source_rgba(1.0, 1.0, 1.0, 0.0)
62       cr.set_operator(cairo.OPERATOR_SOURCE)
63       cr.paint()
64
65       cr.move_to(x0, y0 + radius); cr.arc(x0 + radius, y0 + radius, radius, Pi, 1.5 * Pi)
66       cr.line_to(x1 - radius, y0); cr.arc(x1 - radius, y0 + radius, radius, 1.5 * Pi, 0.0)
67       cr.line_to(x1, y1 - radius); cr.arc(x1 - radius, y1 - radius, radius, 0.0, 0.5 * Pi)
68       cr.line_to(x0 + radius, y1); cr.arc(x0 + radius, y1 - radius, radius, 0.5 * Pi, Pi)
69       cr.close_path()
70       bg_color = gtk.gdk.color_parse(self._prefRead('background'))
71       cr.set_source_rgba(
72          bg_color.red   / 65535.0,
73          bg_color.green / 65535.0,
74          bg_color.blue  / 65535.0,
75          float(self._prefRead('background_alpha')) / 65535.0
76       )
77       cr.fill()
78       return False
79
80    def screen_changed(self, widget, old_screen=None):
81       screen = self.get_screen()
82       self.set_colormap(screen.get_rgba_colormap())
83       return False
84
85    def unrealize(self, widget, date=None):
86       self._prefSave('pos_x', self.allocation[0])
87       self._prefSave('pos_y', self.allocation[1])
88       if self.timer:
89          v = gobject.source_remove(self.timer)
90          self.timer = None
91
92    def set_timer(self, widget, on):
93       if self.timer != None:
94          gobject.source_remove(self.timer)
95       if on:
96          self.timer = gobject.timeout_add(Beat * 100, self.update)
97          self.update()
98
99    def update(self):
100       btm_now = datetime.utcnow() + timedelta(hours=1)
101       delta = timedelta(
102          hours = btm_now.hour,
103          minutes = btm_now.minute,
104          seconds = btm_now.second,
105          microseconds = btm_now.microsecond
106       )
107       beats = (delta.seconds + delta.microseconds / 1000000.0) / Beat
108       self.label.set_markup("@%05.1f" % beats)
109       self.label.set_size_request(-1, -1)
110       self.set_size_request(-1, -1)
111       return not self.inbackground
112
113    def _DoSettings(self, widget, data=None):
114       menuitem = gtk.MenuItem("Beats (Swatch Internet Time)")
115       menuitem.connect_object("activate", self._ShowSettings, None)
116       return menuitem
117
118    def _ShowSettings(self, widget, data=None):
119       import gtk.glade
120       self._widgetTree = gtk.glade.XML('/usr/lib/beats-applet/prefs.glade')
121       self._window = self._widgetTree.get_widget("prefs")
122       self._widgetTree.get_widget("color_background").set_current_color(gtk.gdk.color_parse(self._prefRead('background')))
123       self._widgetTree.get_widget("color_background").set_has_opacity_control(True)
124       self._widgetTree.get_widget("color_background").set_current_alpha(int(self._prefRead('background_alpha')))
125       self._widgetTree.get_widget("color_foreground").set_current_color(gtk.gdk.color_parse(self._prefRead('foreground')))
126       self._widgetTree.get_widget("color_foreground").set_current_alpha(int(self._prefRead('foreground_alpha')))
127       self._widgetTree.get_widget("color_foreground").set_has_opacity_control(True)
128       self._widgetTree.get_widget("fontselection").set_font_name(self._prefRead('font'))
129       callbackMapping = {
130          "on_bCancel_clicked": self._cancel,
131          "on_bValidate_clicked": self._validate,
132       }
133       self._widgetTree.signal_autoconnect(callbackMapping)
134       self._window.connect("delete-event", self._closebox)
135       self._window.show()
136       return True
137
138    def _color_to_string(self, c):
139       t = "#"
140       if len(hex(c.red)[2:4])==1:
141          t = t+'0'+hex(c.red)[2:4]
142       else:
143          t = t+hex(c.red)[2:4]
144       if len(hex(c.green)[2:4])==1:
145          t = t+'0'+hex(c.green)[2:4]
146       else:
147          t = t+hex(c.green)[2:4]
148       if len(hex(c.blue)[2:4])==1:
149          t = t+'0'+hex(c.blue)[2:4]
150       else:
151          t = t+hex(c.blue)[2:4]
152       return t
153
154    def _validate(self, widget, *data):
155       self._prefSave('background', self._color_to_string(self._widgetTree.get_widget("color_background").get_current_color()))
156       self._prefSave('foreground', self._color_to_string(self._widgetTree.get_widget("color_foreground").get_current_color()))
157       self._prefSave('background_alpha', str(self._widgetTree.get_widget("color_background").get_current_alpha()))
158       self._prefSave('foreground_alpha', str(self._widgetTree.get_widget("color_foreground").get_current_alpha()))
159       self._prefSave('font', self._widgetTree.get_widget("fontselection").get_font_name())
160       self._window.destroy()
161
162    def _cancel(self, widget, *data):
163       self._window.destroy()
164
165    def _closebox(self, widget, *data):
166       self._window.destroy()
167
168    def _prefRead(self, key):
169       default = {
170          'background':'#000000',
171          'background_alpha':'32767',
172          'foreground':'#FFFFFF',
173          'foreground_alpha':'65535',
174          'font':'Sans 16',
175          'pos_x':'0',
176          'pos_y':'0'
177       }
178       c = ConfigParser(default)
179       c.read('/home/user/.beats')
180       return c.get("DEFAULT", key)
181
182    def _prefSave(self, key, value):
183       default = {
184          'background':'#000000',
185          'background_alpha':'32767',
186          'foreground':'#FFFFFF',
187          'foreground_alpha':'65535',
188          'font':'Sans 16',
189       }
190       c = ConfigParser(default)
191       c.read('/home/user/.beats')
192       c.set('DEFAULT', key, value)
193       fp = open('/home/user/.beats', 'w')
194       c.write(fp)
195       fp.close()
196       self.redraw()
197
198 def hd_plugin_get_objects():
199    plugin = BeatsApplet()
200    return [plugin]