initial commit
[beats-applet] / src / beats-applet.py
diff --git a/src/beats-applet.py b/src/beats-applet.py
new file mode 100644 (file)
index 0000000..0dbbc7d
--- /dev/null
@@ -0,0 +1,200 @@
+'''
+Beats
+2009 (c) Paul Philippov <paul@ppds.ws>
+Swatch Internet Time applet for Hildon
+'''
+import gtk
+from gtk import gdk
+import hildondesktop
+import cairo
+import gobject
+import pango
+import time
+from datetime import timedelta, datetime, tzinfo
+from ConfigParser import *
+
+Pi = 3.14
+Beat = 86.4
+
+class BeatsApplet(hildondesktop.HomeItem):
+
+   def __init__(self):
+      hildondesktop.HomeItem.__init__(self)
+
+      self.timer = None
+
+      self.connect("settings", self._DoSettings)
+      self.connect("expose-event", self.expose)
+      self.connect("screen-changed", self.screen_changed)
+      self.connect("unrealize", self.unrealize)
+      self.connect("background", self.set_timer, False)
+      self.connect("foreground", self.set_timer, True)
+
+      self.label = gtk.Label()
+      self.label.set_use_markup(True)
+      self.label.set_markup('@---.-')
+      self.add(self.label)
+      self.set_size_request(-1, -1)
+
+      self.redraw()
+
+      self.inbackground = False
+      self.set_timer(self, True)
+      self.show_all()
+
+   def redraw(self):
+      self.set_resize_type(hildondesktop.HOME_ITEM_RESIZE_NONE)
+      self.label.modify_font(pango.FontDescription(self._prefRead('font')))
+#      self.label.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self._prefRead('background')))
+      self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self._prefRead('foreground')))
+      self.label.set_padding(15, 20)
+      self.label.set_size_request(-1, -1)
+      self.set_size_request(-1, -1)
+
+   def expose(self, widget, event):
+      width, height = self.allocation[2], self.allocation[3]
+      radius = min(15, width/2, height/2)
+      x0 = 0; x1 = x0 + width
+      y0 = 0; y1 = y0 + height
+
+      cr = widget.window.cairo_create()
+      cr.set_source_rgba(1.0, 1.0, 1.0, 0.0)
+      cr.set_operator(cairo.OPERATOR_SOURCE)
+      cr.paint()
+
+      cr.move_to(x0, y0 + radius); cr.arc(x0 + radius, y0 + radius, radius, Pi, 1.5 * Pi)
+      cr.line_to(x1 - radius, y0); cr.arc(x1 - radius, y0 + radius, radius, 1.5 * Pi, 0.0)
+      cr.line_to(x1, y1 - radius); cr.arc(x1 - radius, y1 - radius, radius, 0.0, 0.5 * Pi)
+      cr.line_to(x0 + radius, y1); cr.arc(x0 + radius, y1 - radius, radius, 0.5 * Pi, Pi)
+      cr.close_path()
+      bg_color = gtk.gdk.color_parse(self._prefRead('background'))
+      cr.set_source_rgba(
+         bg_color.red   / 65535.0,
+         bg_color.green / 65535.0,
+         bg_color.blue  / 65535.0,
+         float(self._prefRead('background_alpha')) / 65535.0
+      )
+      cr.fill()
+      return False
+
+   def screen_changed(self, widget, old_screen=None):
+      screen = self.get_screen()
+      self.set_colormap(screen.get_rgba_colormap())
+      return False
+
+   def unrealize(self, widget, date=None):
+      self._prefSave('pos_x', self.allocation[0])
+      self._prefSave('pos_y', self.allocation[1])
+      if self.timer:
+         v = gobject.source_remove(self.timer)
+         self.timer = None
+
+   def set_timer(self, widget, on):
+      if self.timer != None:
+         gobject.source_remove(self.timer)
+      if on:
+         self.timer = gobject.timeout_add(Beat * 100, self.update)
+         self.update()
+
+   def update(self):
+      btm_now = datetime.utcnow() + timedelta(hours=1)
+      delta = timedelta(
+         hours = btm_now.hour,
+         minutes = btm_now.minute,
+         seconds = btm_now.second,
+         microseconds = btm_now.microsecond
+      )
+      beats = (delta.seconds + delta.microseconds / 1000000.0) / Beat
+      self.label.set_markup("@%05.1f" % beats)
+      self.label.set_size_request(-1, -1)
+      self.set_size_request(-1, -1)
+      return not self.inbackground
+
+   def _DoSettings(self, widget, data=None):
+      menuitem = gtk.MenuItem("Beats (Swatch Internet Time)")
+      menuitem.connect_object("activate", self._ShowSettings, None)
+      return menuitem
+
+   def _ShowSettings(self, widget, data=None):
+      import gtk.glade
+      self._widgetTree = gtk.glade.XML('/usr/lib/beats-applet/prefs.glade')
+      self._window = self._widgetTree.get_widget("prefs")
+      self._widgetTree.get_widget("color_background").set_current_color(gtk.gdk.color_parse(self._prefRead('background')))
+      self._widgetTree.get_widget("color_background").set_has_opacity_control(True)
+      self._widgetTree.get_widget("color_background").set_current_alpha(int(self._prefRead('background_alpha')))
+      self._widgetTree.get_widget("color_foreground").set_current_color(gtk.gdk.color_parse(self._prefRead('foreground')))
+      self._widgetTree.get_widget("color_foreground").set_current_alpha(int(self._prefRead('foreground_alpha')))
+      self._widgetTree.get_widget("color_foreground").set_has_opacity_control(True)
+      self._widgetTree.get_widget("fontselection").set_font_name(self._prefRead('font'))
+      callbackMapping = {
+         "on_bCancel_clicked": self._cancel,
+         "on_bValidate_clicked": self._validate,
+      }
+      self._widgetTree.signal_autoconnect(callbackMapping)
+      self._window.connect("delete-event", self._closebox)
+      self._window.show()
+      return True
+
+   def _color_to_string(self, c):
+      t = "#"
+      if len(hex(c.red)[2:4])==1:
+         t = t+'0'+hex(c.red)[2:4]
+      else:
+         t = t+hex(c.red)[2:4]
+      if len(hex(c.green)[2:4])==1:
+         t = t+'0'+hex(c.green)[2:4]
+      else:
+         t = t+hex(c.green)[2:4]
+      if len(hex(c.blue)[2:4])==1:
+         t = t+'0'+hex(c.blue)[2:4]
+      else:
+         t = t+hex(c.blue)[2:4]
+      return t
+
+   def _validate(self, widget, *data):
+      self._prefSave('background', self._color_to_string(self._widgetTree.get_widget("color_background").get_current_color()))
+      self._prefSave('foreground', self._color_to_string(self._widgetTree.get_widget("color_foreground").get_current_color()))
+      self._prefSave('background_alpha', str(self._widgetTree.get_widget("color_background").get_current_alpha()))
+      self._prefSave('foreground_alpha', str(self._widgetTree.get_widget("color_foreground").get_current_alpha()))
+      self._prefSave('font', self._widgetTree.get_widget("fontselection").get_font_name())
+      self._window.destroy()
+
+   def _cancel(self, widget, *data):
+      self._window.destroy()
+
+   def _closebox(self, widget, *data):
+      self._window.destroy()
+
+   def _prefRead(self, key):
+      default = {
+         'background':'#000000',
+         'background_alpha':'32767',
+         'foreground':'#FFFFFF',
+         'foreground_alpha':'65535',
+         'font':'Sans 16',
+         'pos_x':'0',
+         'pos_y':'0'
+      }
+      c = ConfigParser(default)
+      c.read('/home/user/.beats')
+      return c.get("DEFAULT", key)
+
+   def _prefSave(self, key, value):
+      default = {
+         'background':'#000000',
+         'background_alpha':'32767',
+         'foreground':'#FFFFFF',
+         'foreground_alpha':'65535',
+         'font':'Sans 16',
+      }
+      c = ConfigParser(default)
+      c.read('/home/user/.beats')
+      c.set('DEFAULT', key, value)
+      fp = open('/home/user/.beats', 'w')
+      c.write(fp)
+      fp.close()
+      self.redraw()
+
+def hd_plugin_get_objects():
+   plugin = BeatsApplet()
+   return [plugin]