root / pykoticon / trunk / bin / pykoticon @ 87

Revision 87, 7.9 kB (checked in by jerome, 18 years ago)

Rewritten almost from scratch. Now includes an xml-rpc server

  • Property svn:keywords set to Id
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# PyKotIcon - Windows System Tray Icon for PyKota
5#
6# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20#
21# $Id$
22#
23#
24
25import sys
26import os
27import urllib
28import urllib2
29import locale
30import gettext
31import socket
32import threading
33import SimpleXMLRPCServer
34
35import time
36
37if sys.platform == "win32" :
38    isWindows = 1
39    try :
40        import win32api
41    except ImportError :   
42        raise ImportError, "Mark Hammond's Win32 Extensions are missing. Please install them."
43    else :   
44        iconsdir = os.path.split(sys.argv[0])[0]
45else :       
46    isWindows = 0
47    iconsdir = "/usr/share/pykoticon"   # TODO : change this
48    import pwd
49   
50try :   
51    import wxPython.wx
52    import wx
53    hasWxPython = 1
54except ImportError :   
55    hasWxPython = 0
56    raise ImportError, "wxPython is missing. Please install it."
57   
58def getCurrentUserName() :
59    """Retrieves the current user's name."""
60    if isWindows :
61        return win32api.GetUserName()
62    else :   
63        try :
64            return pwd.getpwuid(os.geteuid())[0]
65        except :
66            return "** Unknown **"
67       
68class MyXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer) :
69    """My own server class."""
70    def __init__(self, frame, printserver, localport) :
71        myIPAddress = socket.gethostbyaddr(socket.gethostname())[2][0]
72        SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, (myIPAddress, localport))
73        self.printServer = printserver
74        self.frame = frame
75        loop = threading.Thread(target=self.mainloop)
76        loop.start()
77       
78    def export_quitApplication(self) :   
79        """Makes the application quit."""
80        self.frame.quitEvent.set()
81        return True
82       
83    def export_openDialog(self) :   
84        """Opens a dialog to ask username, password, etc..."""
85        print "Open dialog !"
86        return ("jerome", "blah")
87       
88    def verify_request(self, request, client_address) :
89        """Ensures that requests which don't come from the print server are rejected."""
90        (client, port) = client_address
91        if socket.gethostbyname(self.printServer) == client :
92            return True
93        else :
94            # Unauthorized access !
95            return False
96       
97    def _dispatch(self, method, params) :   
98        """Ensure that only export_* methods are available."""
99        return getattr(self, "export_%s" % method)(*params)
100       
101    def mainloop(self) :
102        """XML-RPC Server's main loop."""
103        self.register_function(self.export_openDialog)
104        self.register_function(self.export_quitApplication)
105        while not self.frame.quitEvent.isSet() :
106            self.handle_request()
107        self.frame.Close() 
108        sys.exit(0)
109   
110class PyKotIcon(wx.Frame):
111    """Main class."""
112    def __init__(self, parent, id):
113        wx.Frame.__init__(self, parent, -1, \
114               _("PyKota for user %s") % getCurrentUserName(), \
115               size = (-1, -1), \
116               style = wxPython.wx.wxDEFAULT_FRAME_STYLE \
117                     | wxPython.wx.wxSIZE_AUTO_HEIGHT \
118                     | wxPython.wx.wxSIZE_AUTO_WIDTH \
119                     | wxPython.wx.wxICONIZE \
120                     | wxPython.wx.wxNO_FULL_REPAINT_ON_RESIZE)
121        try :             
122            self.tbicon = wxPython.wx.wxTaskBarIcon()
123        except AttributeError :   
124            self.tbicon = None # No taskbar icon facility, old wxWidgets maybe
125       
126        self.greenicon = wxPython.wx.wxIcon(os.path.join(iconsdir, "pykoticon-green.ico"), \
127                                  wxPython.wx.wxBITMAP_TYPE_ICO)
128        self.redicon = wxPython.wx.wxIcon(os.path.join(iconsdir, "pykoticon-red.ico"), \
129                                  wxPython.wx.wxBITMAP_TYPE_ICO)
130       
131        self.SetIcon(self.greenicon)
132        if self.tbicon is not None :
133            self.tbicon.SetIcon(self.greenicon, "PyKotIcon")
134            wxPython.wx.EVT_TASKBAR_LEFT_DCLICK(self.tbicon, self.OnTaskBarActivate)
135            wxPython.wx.EVT_TASKBAR_RIGHT_UP(self.tbicon, self.OnTaskBarMenu)
136       
137            self.TBMENU_RESTORE = wx.NewId()
138            self.TBMENU_CLOSE = wx.NewId()
139            wxPython.wx.EVT_MENU(self.tbicon, self.TBMENU_RESTORE, \
140                                              self.OnTaskBarActivate)
141            wxPython.wx.EVT_MENU(self.tbicon, self.TBMENU_CLOSE, \
142                                              self.OnTaskBarClose)
143            self.menu = wxPython.wx.wxMenu()
144            self.menu.Append(self.TBMENU_RESTORE, _("Show Print Quota"))
145            self.menu.Append(self.TBMENU_CLOSE, _("Quit"))
146       
147        wxPython.wx.EVT_ICONIZE(self, self.OnIconify)
148        wxPython.wx.EVT_CLOSE(self, self.OnClose)
149       
150    def postInit(self, printserver, localport) :   
151        """Starts the XML-RPC server."""
152        self.quitEvent = threading.Event()
153        self.server = MyXMLRPCServer(self, printserver, localport)
154   
155    def OnIconify(self, event) :
156        self.Hide()
157
158    def OnTaskBarActivate(self, event) :
159        if self.IsIconized() :
160            self.Iconize(False)
161        if not self.IsShown() :
162            self.Show(True)
163        self.Raise()
164
165    def OnClose(self, event) :
166        sys.stderr.write("Close event !\n")
167        if not self.quitEvent.isSet() :
168            self.quitEvent.set()
169        if hasattr(self, "menu") :
170            self.menu.Destroy()
171            del self.menu
172        if hasattr(self, "tbicon") and self.tbicon :
173            self.tbicon.Destroy()
174            del self.tbicon
175        self.Destroy()
176
177    def OnTaskBarMenu(self, evt) :
178        if self.tbicon :
179            self.tbicon.PopupMenu(self.menu)
180
181    def OnTaskBarClose(self, evt) :
182        self.Close()
183
184class PyKotIconApp(wx.PySimpleApp):
185    def OnInit(self) :
186        try :
187            self.frame = PyKotIcon(None, -1)
188        except :   
189            crashed()
190        return True
191       
192    def postInit(self, printserver, localport) :   
193        """Continues processing."""
194        self.frame.postInit(printserver, localport)
195        self.frame.Show(True)
196       
197def main(printserver, localport):
198    """Program's entry point."""
199    try :
200        locale.setlocale(locale.LC_ALL, "")
201    except (locale.Error, IOError) :
202        sys.stderr.write("Problem while setting locale.\n")
203    try :
204        gettext.install("pykoticon")
205    except :
206        gettext.NullTranslations().install()
207    app = PyKotIconApp()
208    try :
209        localport = int(localport)   
210    except (TypeError, ValueError) :   
211        raise ValueError, "Invalid TCP port parameter %s\n" % localport
212    app.postInit(printserver, localport)
213    app.MainLoop()
214   
215def crashed() :   
216    """Minimal crash method."""
217    import traceback
218    lines = []
219    for line in traceback.format_exception(*sys.exc_info()) :
220        lines.extend([l for l in line.split("\n") if l])
221    msg = "ERROR: ".join(["%s\n" % l for l in (["ERROR: PyKotIcon"] + lines)])
222    sys.stderr.write(msg)
223    sys.stderr.flush()
224   
225if __name__ == '__main__':
226    if len(sys.argv) >= 2 :
227        arg = sys.argv[1]
228        if arg in ("-v", "--version") :   
229            print "0.3"
230        elif arg in ("-h", "--help") :   
231            print "usage : pykoticon printserver_hostname localport"
232        else :
233            main(*sys.argv[1:3])
234    else :   
235        main("localhost", "7654")
Note: See TracBrowser for help on using the browser.