Advertisement
jcomeau_ictx

xacpi.py

Jan 29th, 2014
530
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.06 KB | None | 0 0
  1. #!/usr/bin/python -OO
  2. '''
  3. tray icon battery indicator
  4.  
  5. adapted from http://ubuntuforums.org/showthread.php?t=1153951 and
  6. http://code.activestate.com/recipes/475155-dynamic-system-tray-icon-wxpython/
  7. any original code Copyright (c) 2013 jc.unternet.net
  8. licensing GPL3 or later
  9. '''
  10. import sys, os, wx, subprocess, re, time
  11. ACPI_PATTERN = '^Battery 0:\s+(\w+), (\d+)%'
  12. COLORS = {
  13.  'Full': 'green',
  14.  'Charging': 'green',
  15.  'Discharging': 'yellow',
  16. }
  17. UPDATE_TIME = 5  # seconds
  18. MILLISECONDS = 1000  # multiplier for seconds
  19. UPDATER = wx.NewEventType()  # returns unique (to this app) ID
  20. WIDTH, HEIGHT = 16, 16  # must be multiples of 5 + 1; only 16 works right
  21. BORDER_WIDTH = BORDER_HEIGHT = 1  # black border -- width and height the same
  22. PADDING_WIDTH = 3  # transparent pixels
  23. BATTERY_WIDTH = WIDTH - (PADDING_WIDTH * 2) - (BORDER_WIDTH * 2)
  24. TRANSPARENT = 'white'
  25. WARNING_LEVEL = 3  # show red when this many lines
  26. class Icon(wx.Frame):
  27.  def __init__(self, parent, ID, title):
  28.   wx.Frame.__init__(self, parent, ID, title, wx.DefaultPosition, wx.DefaultSize)
  29.   self.updateIcon()
  30.   # bind frame onQuit to window close
  31.   self.Bind(wx.EVT_CLOSE, self.onQuit)
  32.   # bind frame onUp to mouseup on taskbar icon
  33.   self.icon.Bind(wx.EVT_TASKBAR_LEFT_UP, self.onUp)
  34.   width, height = self.GetSize()
  35.   debug('frame size: (%d, %d)' % (width, height))
  36.   self.timer = wx.Timer(self, UPDATER)
  37.   self.timer.Start(UPDATE_TIME * MILLISECONDS)
  38.   wx.EVT_TIMER(self, UPDATER, self.updateIcon)
  39.   debug('initialization complete')
  40.  def onQuit(self, event):
  41.   self.timer.Stop()  # maybe not necessary but can't hurt
  42.   self.icon.Destroy()
  43.   self.Destroy()
  44.  def onUp(self, event):
  45.   iconized = self.IsIconized()
  46.   if not iconized:
  47.    self.Iconize()
  48.    self.Hide()
  49.   else:
  50.    self.Restore()
  51.    self.Show()
  52.  def updateIcon(self, event = None):
  53.   acpistring = acpi()
  54.   debug('acpi: %s' % acpistring)
  55.   status = re.compile(ACPI_PATTERN).match(acpistring)
  56.   debug('status: %s' % status)
  57.   color, charge = icon_data(*status.groups()) if status else ('red', 5)
  58.   pixels = build_image(color, charge)
  59.   image = wx.EmptyImage(WIDTH, HEIGHT)
  60.   image.SetData(pixels)
  61.   bitmap = image.ConvertToBitmap()
  62.   bitmap.SetMask(wx.Mask(bitmap, color_tuple(TRANSPARENT)))
  63.   icon_image = wx.EmptyIcon()
  64.   icon_image.CopyFromBitmap(bitmap)
  65.   if not hasattr(self, 'icon'):
  66.    self.icon = wx.TaskBarIcon()
  67.   self.icon.SetIcon(icon = icon_image, tooltip = "Battery 0 State")
  68.   # put text of acpi string in frame
  69.   if not hasattr(self, 'statusline'):
  70.    self.statusline = wx.StaticText(self, label = acpistring)
  71.   else:
  72.    self.statusline.SetLabel(acpistring)
  73. class IconApp(wx.App):
  74.  def OnInit(self):
  75.   frame = Icon(None, -1, "Battery 0 State")
  76.   frame.Show()  # shows just momentarily before we iconize it
  77.   self.SetTopWindow(frame)
  78.   frame.Iconize()
  79.   return True
  80. def build_image(color, charge):
  81.  battery_height = HEIGHT - (2 * BORDER_HEIGHT)
  82.  charge_height = int((float(charge) / 100) * battery_height)
  83.  if color == 'yellow' and charge_height <= WARNING_LEVEL:
  84.   color = 'red'
  85.  padding_left = (pixel(TRANSPARENT) * PADDING_WIDTH) + pixel('black')
  86.  padding_right = pixel('black') + (pixel(TRANSPARENT) * PADDING_WIDTH)
  87.  pixels = padding_left + (pixel('black') * BATTERY_WIDTH) + padding_right
  88.  for i in range(battery_height):
  89.   rowcolor = color
  90.   if (battery_height - 1 - i) > charge_height:
  91.    rowcolor = TRANSPARENT
  92.   pixels += padding_left + (pixel(rowcolor) * BATTERY_WIDTH) + padding_right
  93.  pixels += padding_left + (pixel('black') * BATTERY_WIDTH) + padding_right
  94.  return pixels
  95. def color_tuple(color):
  96.  if type(color) == str:
  97.   return wx.NamedColour(color).asTuple()
  98.  else:
  99.   return tuple(color)
  100. def pixel(color):
  101.  return ''.join(map(chr, color_tuple(color)))
  102. def debug(message = None):
  103.  if __debug__:
  104.   if message:
  105.    print >>sys.stderr, message
  106.   return True
  107. def acpi():
  108.  output = subprocess.Popen(['acpi'], stdout = subprocess.PIPE).communicate()[0]
  109.  return output
  110. def icon_data(word, number):
  111.  return COLORS.get(word, 'yellow'), int(number)
  112. if __name__ == '__main__':
  113.  IconApp(0).MainLoop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement