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

Reply via email to