I know that there are other tools like this available but I had some
time last week while anxiously waiting for the new wx to roll through
the tinderbox, and I happen to know a little bit about a nice cross
platform GUI toolkit... So I whipped up the basics of this little tool
while waiting last week, and put some finishing touches on it over the
last couple days.
Have fun with it.
--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!
#!/usr/bin/env python
#----------------------------------------------------------------------
#
# A simple little app to display Chandler's tinderbox status in an
# icon on the taskbar/system tray, or as a Doc icon on OS X. On Windows
# and Linux double clicking on the icon will display a popup status
# window with more details. The popup status window is also available
# via a right-click menu on all three platforms.
#
# The color stripes in the icon corespond with the colored boxes in the
# popup status window. (Green is good.) Clicking the link at the top
# of the status window will open your default browser and take you to
# the main tinderbox page.
#
#----------------------------------------------------------------------
import wx
import wx.html
import sys
import webbrowser
import urllib
URL1 = "http://builds.osafoundation.org/tinderbox/Chandler/quickparse.html"
URL2 = "http://builds.osafoundation.org/tinderbox/Chandler/panel.html"
UPDATE = 60 # number of seconds between updates
ID_SHOWSTATUS = wx.NewId()
class StatusIcon(wx.TaskBarIcon):
def __init__(self):
wx.TaskBarIcon.__init__(self)
self.data = None
self.MakeIcon()
def CreatePopupMenu(self):
menu = wx.Menu()
if app.frame.IsShown():
menu.Append(ID_SHOWSTATUS, "Hide Status")
else:
menu.Append(ID_SHOWSTATUS, "Show Status")
# There is already a Quit item on the popup menu on wxMac
if 'wxMac' not in wx.PlatformInfo:
menu.Append(wx.ID_EXIT, "Exit")
return menu
def MakeIcon(self):
size = wx.Size(128,128)
bmp = wx.EmptyBitmap(size.width, size.height)
dc = wx.MemoryDC()
dc.SelectObject(bmp)
dc.SetBackground(wx.Brush("white"))
dc.Clear()
if self.data:
numlines = size.height / len(self.data)
y = size.height % len(self.data)
for item in self.data:
if item == 'success':
colour = 'green'
elif item == 'test_failed':
colour = wx.Colour(255,170,0)
else:
colour = 'red'
pen = wx.Pen(colour, numlines)
dc.SetPen(pen)
dc.DrawLine(numlines, y, size.width-numlines, y)
y += numlines
del dc
img = wx.ImageFromBitmap(bmp)
if "wxGTK" in wx.PlatformInfo:
img = img.Scale(22, 22)
elif "wxMSW" in wx.PlatformInfo:
img = img.Scale(16,16)
icon = wx.IconFromBitmap(img.ConvertToBitmap())
self.SetIcon(icon, "TBox Status")
def DoUpdate(self):
page = urllib.urlopen(URL1)
data = page.read()
status = []
for line in data.split('\n'):
if line.find('|') != -1:
status.append(line.split('|')[-1])
self.data = status[1:]
self.MakeIcon()
class StatusHtmlWindow(wx.html.HtmlWindow):
def __init__(self, parent):
wx.html.HtmlWindow.__init__(self, parent)
if "gtk2" in wx.PlatformInfo:
self.SetStandardFonts()
self.SetBorders(5)
def OnLinkClicked(self, linkinfo):
webbrowser.open(linkinfo.GetHref())
def LoadPage(self, URL):
# Load the data from the URL
busy = wx.BusyCursor()
page = urllib.urlopen(URL)
htext = page.read()
self.SetPage(htext)
class StatusFrame(wx.Frame):
def __init__(self, style=0):
wx.Frame.__init__(self, None, title="OSAF TBox Status",
style=wx.FRAME_NO_TASKBAR | wx.RESIZE_BORDER | style,
name="tboxstatus"
)
self.html = StatusHtmlWindow(self)
self.SetSize((150,150))
self.Bind(wx.EVT_CLOSE, self.OnClose)
# mouse events for dragging the window
self.html.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.html.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.html.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.html.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
# restore size and position
cfg = wx.Config.Get()
cfg.SetPath("/")
if cfg.Exists("Pos"):
pos = eval(cfg.Read("Pos"))
# TODO: ensure this position is on-screen
self.SetPosition(pos)
if cfg.Exists("Size"):
sz = eval(cfg.Read("Size"))
self.SetSize(sz)
self.firsttime = False
else:
self.firsttime = True
def DoUpdate(self):
self.html.LoadPage(URL2)
if self.firsttime:
self.firsttime = False
ir = self.html.GetInternalRepresentation()
self.SetClientSize((ir.GetWidth()+25, ir.GetHeight()+25))
def OnClose(self, evt):
cfg = wx.Config.Get()
cfg.SetPath("/")
cfg.Write("Pos", str(self.GetPosition().Get()))
cfg.Write("Size", str(self.GetSize().Get()))
evt.Skip()
def OnLeftDown(self, evt):
win = evt.GetEventObject()
win.CaptureMouse()
self.capture = win
pos = win.ClientToScreen(evt.GetPosition())
origin = self.GetPosition()
dx = pos.x - origin.x
dy = pos.y - origin.y
self.delta = wx.Point(dx, dy)
evt.Skip()
def OnLeftUp(self, evt):
if self.capture.HasCapture():
self.capture.ReleaseMouse()
evt.Skip()
def OnMouseMove(self, evt):
if evt.Dragging() and evt.LeftIsDown():
win = evt.GetEventObject()
pos = win.ClientToScreen(evt.GetPosition())
fp = (pos.x - self.delta.x, pos.y - self.delta.y)
self.Move(fp)
else:
evt.Skip()
def OnRightUp(self, evt):
self.Hide()
evt.Skip()
class StatusApp(wx.App):
def OnInit(self):
self.SetAppName("tboxstatus")
self.SetVendorName("Robin Dunn")
style=0
if len(sys.argv) > 1 and sys.argv[1] == 'stayontop':
style = wx.STAY_ON_TOP
self.frame = StatusFrame(style)
self.tbicon = StatusIcon()
self.Bind(wx.EVT_TIMER, self.OnUpdate)
self.timer = wx.Timer(self)
self.timer.Start(UPDATE * 1000)
wx.CallAfter(self.OnUpdate, None)
self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnShowStatus)
self.tbicon.Bind(wx.EVT_MENU, self.OnShowStatus, id=ID_SHOWSTATUS)
self.tbicon.Bind(wx.EVT_MENU, self.OnExitStatusApp, id=wx.ID_EXIT)
return True
def OnUpdate(self, evt):
if self.frame.IsShown():
self.frame.DoUpdate()
self.tbicon.DoUpdate()
def OnShowStatus(self, evt):
if self.frame.IsShown():
self.frame.Hide()
else:
self.frame.Show()
self.frame.Raise()
self.frame.DoUpdate()
def OnExitStatusApp(self, evt):
self.frame.Close()
self.timer.Stop()
self.tbicon.Destroy()
app = StatusApp()
app.MainLoop()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Open Source Applications Foundation "chandler-dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/chandler-dev