root / pykoticon / trunk / bin / pykoticon @ 60

Revision 60, 9.9 kB (checked in by jerome, 19 years ago)

Cleaned the code a bit

  • 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 urllib
27import urllib2
28
29try :
30    import win32api
31    import win32net
32    import win32netcon
33    hasWindowsExtensions = 1
34except ImportError :   
35    hasWindowsExtensions = 0
36    raise ImportError, "Mark Hammond's Win32 Extensions are missing. Please install them."
37   
38try :   
39    import wxPython.wx
40    import wx
41    hasWxPython = 1
42except ImportError :   
43    hasWxPython = 0
44    raise ImportError, "wxPython for Windows is missing. Please install it."
45   
46DUMPYKOTA_URL = "http://cgi.librelogiciel.com/cgi-bin/dumpykota.cgi"
47
48class UserQuota :
49    """A class for PyKota User Print Quota entries."""
50    def __init__(self, printername, pagecount, softlimit, hardlimit, datelimit):
51        """Initialize user print quota datas."""
52        self.PrinterName = printername
53        try :
54            self.PageCounter = int(pagecount)
55        except (ValueError, TypeError) :
56            self.PageCounter = 0
57        try :
58            self.SoftLimit = int(softlimit)
59        except (ValueError, TypeError) :
60            self.SoftLimit = None
61        try :
62            self.HardLimit = int(hardlimit)
63        except (ValueError, TypeError) :
64            self.HardLimit = None
65        self.DateLimit = datelimit
66       
67class User :
68    """A class for PyKota users."""
69    def __init__(self, username, userinfo, userquotas) :
70        """Initialize user datas."""
71        self.Name = username
72        self.LimitBy = userinfo["limitby"][0].lower()
73        try :
74            self.Balance = float(userinfo["balance"][0])
75        except (ValueError, TypeError) :
76            self.Balance = 0.0
77        try :
78            self.LifeTimePaid = float(userinfo["lifetimepaid"][0])
79        except (ValueError, TypeError) :
80            self.LifeTimePaid = 0.0
81        self.Quotas = []
82        for i in range(len(userquotas["printername"])) :
83            printername = userquotas["printername"][i]
84            pagecounter = userquotas["pagecounter"][i]
85            softlimit = userquotas["softlimit"][i]
86            hardlimit = userquotas["hardlimit"][i]
87            datelimit = userquotas["datelimit"][i]
88            self.Quotas.append(UserQuota(printername, pagecounter, softlimit, \
89                                         hardlimit, datelimit))
90           
91class CGINetworkInterface :
92    """A class for all network interactions."""
93    def __init__(self, cgiurl, authname=None, authpw=None) :
94        """Initialize CGI connection datas."""
95        self.cgiurl = cgiurl
96        self.authname = authname
97        self.authpw = authpw
98       
99    def retrieveDatas(self, arguments, fieldnames) :
100        """Retrieve datas from the CGI script."""
101        args = { "report" : 1,
102                 "format" : "csv",
103               } 
104        args.update(arguments)           
105        answer = {}
106        try :           
107            url = "%s?%s" % (self.cgiurl, urllib.urlencode(args))
108            u = urllib2.urlopen(url)
109            lines = u.readlines()
110        except IOError, msg :   
111            raise IOError, "Unable to retrieve %s : %s" % (url, msg)
112        else :   
113            u.close()
114            try :
115                lines = [ line.strip().split(",") for line in lines ]
116                fields = [field[1:-1] for field in lines[0]]
117                indices = [fields.index(fname) for fname in fieldnames]
118                answer = dict([ (fieldname, \
119                                  [ line[fields.index(fieldname)][1:-1] \
120                                    for line in lines[1:] ]) \
121                                for fieldname in fieldnames ])
122            except :   
123                raise ValueError, "Invalid datas retrieved from %s" % url
124        return answer
125       
126    def getPrinterNames(self) :
127        """Retrieve the printer's names."""
128        arguments = { "report" : 1,
129                      "format" : "csv",
130                      "datatype" : "printers",
131                    } 
132        return self.retrieveDatas(arguments, ["printername"])["printername"]
133       
134    def getUserInfo(self, username) :
135        """Retrieve the user's information."""
136        arguments = { "datatype" : "users",
137                      "filter" : "username=%s" % username,
138                    } 
139        return self.retrieveDatas(arguments, ("limitby", "balance", \
140                                                         "lifetimepaid"))
141       
142    def getUserPQuotas(self, username) :
143        """Retrieve the user's print quota information."""
144        arguments = { "datatype" : "upquotas",
145                      "filter" : "username=%s" % username,
146                    } 
147        return self.retrieveDatas(arguments, ("printername", "pagecounter", \
148                                              "softlimit", "hardlimit", \
149                                              "datelimit"))
150                                             
151    def getUser(self, username) :
152        """Retrieves the user account and quota information."""
153        info = self.getUserInfo(username)
154        if info :
155            quotas = self.getUserPQuotas(username)
156            return User(username, info, quotas)
157   
158class PyKotIcon(wxPython.wx.wxFrame):
159    def __init__(self, parent, id, title):
160        wxPython.wx.wxFrame.__init__(self, parent, -1, title, size=(800, 600), \
161                   style = wxPython.wx.wxDEFAULT_FRAME_STYLE | wxPython.wx.wxNO_FULL_REPAINT_ON_RESIZE)
162        icon = wxPython.wx.wxIcon('pykoticon.ico', \
163                                  wxPython.wx.wxBITMAP_TYPE_ICO)
164        self.SetIcon(icon)
165       
166        self.tbicon = wxPython.wx.wxTaskBarIcon()
167        self.tbicon.SetIcon(icon, "PyKotIcon")
168        wxPython.wx.EVT_TASKBAR_LEFT_DCLICK(self.tbicon, self.OnTaskBarActivate)
169        wxPython.wx.EVT_TASKBAR_RIGHT_UP(self.tbicon, self.OnTaskBarMenu)
170        wxPython.wx.EVT_ICONIZE(self, self.OnIconify)
171       
172        self.TBMENU_RESTORE = wx.NewId()
173        self.TBMENU_CLOSE = wx.NewId()
174        wxPython.wx.EVT_MENU(self.tbicon, self.TBMENU_RESTORE, \
175                                          self.OnTaskBarActivate)
176        wxPython.wx.EVT_MENU(self.tbicon, self.TBMENU_CLOSE, \
177                                          self.OnTaskBarClose)
178        self.menu = wxPython.wx.wxMenu()
179        self.menu.Append(self.TBMENU_RESTORE, "Show Print Quota")
180        self.menu.Append(self.TBMENU_CLOSE, "Quit")
181       
182        self.TBTIMER = wx.NewId()
183        self.chrono = wx.wxTimer(self, self.TBTIMER)
184        EVT_TIMER(self, self.TBTIMER, self.OnChronoTimer)
185       
186        self.User = None
187        self.networkInterface = CGINetworkInterface(DUMPYKOTA_URL)
188        self.inTimer = 0
189        self.chrono.Start(1000 * 60 * 3) # every 3 minutes
190
191    def getCurrentUserName(self) :
192        """Returns the name of the current user."""
193        return win32api.GetUserName()
194       
195    def OnChronoTimer(self, event) :
196        """Retrieves user's data quota information."""
197        if not self.inTimer : # avoids re-entrance
198            self.inTimer = 1
199            self.User = self.networkInterface.getUser(self.getCurrentUserName())
200            self.inTimer = 0
201   
202    def OnIconify(self, event) :
203        self.Hide()
204
205    def OnTaskBarActivate(self, event) :
206        if self.IsIconized() :
207            self.Iconize(False)
208        if not self.IsShown() :
209            self.Show(True)
210        self.Raise()
211
212    def OnCloseWindow(self, event) :
213        if hasattr(self, "chrono") :
214            self.chrono.Stop()
215            del self.chrono
216        if hasattr(self, "menu") :
217            menu.Destroy()
218            del self.menu
219        if hasattr(self, "tbicon") :
220            self.tbicon.Destroy()
221            del self.tbicon
222        self.Destroy()
223
224    def OnTaskBarMenu(self, evt) :
225        self.tbicon.PopupMenu(self.menu)
226
227    def OnTaskBarClose(self, evt) :
228        self.Close()
229        wxPython.wx.wxGetApp().ProcessIdle()
230
231class PyKotIconApp(wxPython.wx.wxApp):
232    def OnInit(self) :
233        frame = PyKotIcon(None, -1, "PyKota Print Quota Manager")
234        frame.Show(True)
235        return True
236       
237def crashed() :   
238    """Minimal crash method."""
239    import traceback
240    lines = []
241    for line in traceback.format_exception(*sys.exc_info()) :
242        lines.extend([l for l in line.split("\n") if l])
243    msg = "ERROR: ".join(["%s\n" % l for l in (["ERROR: PyKotIcon"] + lines)])
244    sys.stderr.write(msg)
245    sys.stderr.flush()
246   
247def main():
248    """Program's entry point."""
249    app = PyKotIconApp()
250    app.MainLoop()
251   
252def test() :
253    """Runs in test mode (console)."""
254    if len(sys.argv) >= 3 :
255        username = sys.argv[2] 
256    else :   
257        username = win32api.GetUserName()
258    net = CGINetworkInterface(DUMPYKOTA_URL)
259    user = net.getUser(username)
260    print "UserName : ", user.Name
261    print "LimitBy : ", user.LimitBy
262    print "Balance : ", user.Balance
263    for q in user.Quotas :
264        print "\tPrinterName : ", q.PrinterName
265        print "\tPageCounter : ", q.PageCounter
266        print "\tSoftLimit : ", q.SoftLimit
267        print "\tHardLimit : ", q.HardLimit
268        print "\tDateLimit : ", q.DateLimit
269        print
270
271if __name__ == '__main__':
272    if (len(sys.argv) >= 2) and (sys.argv[1] == "--test") :
273        test()
274    else :   
275        main()
276   
Note: See TracBrowser for help on using the browser.