root / pykoticon / trunk / bin / pykoticon @ 59

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

Added the timer functionnality

  • 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        quotas = self.getUserPQuotas(username)
155        return User(username, info, quotas)
156   
157def getWindowsUserName() :   
158    """Retrieves the current user's name under MS Windows."""
159    return win32api.GetUserName()
160   
161class PyKotIcon(wxPython.wx.wxFrame):
162    def __init__(self, parent, id, title):
163        wxPython.wx.wxFrame.__init__(self, parent, -1, title, size=(800, 600), \
164                   style = wxPython.wx.wxDEFAULT_FRAME_STYLE | wxPython.wx.wxNO_FULL_REPAINT_ON_RESIZE)
165        icon = wxPython.wx.wxIcon('pykoticon.ico', \
166                                  wxPython.wx.wxBITMAP_TYPE_ICO)
167        self.SetIcon(icon)
168       
169        self.tbicon = wxPython.wx.wxTaskBarIcon()
170        self.tbicon.SetIcon(icon, "PyKotIcon")
171        wxPython.wx.EVT_TASKBAR_LEFT_DCLICK(self.tbicon, self.OnTaskBarActivate)
172        wxPython.wx.EVT_TASKBAR_RIGHT_UP(self.tbicon, self.OnTaskBarMenu)
173        wxPython.wx.EVT_ICONIZE(self, self.OnIconify)
174       
175        self.TBMENU_RESTORE = wx.NewId()
176        self.TBMENU_CLOSE = wx.NewId()
177        wxPython.wx.EVT_MENU(self.tbicon, self.TBMENU_RESTORE, \
178                                          self.OnTaskBarActivate)
179        wxPython.wx.EVT_MENU(self.tbicon, self.TBMENU_CLOSE, \
180                                          self.OnTaskBarClose)
181        self.menu = wxPython.wx.wxMenu()
182        self.menu.Append(self.TBMENU_RESTORE, "Show Print Quota")
183        self.menu.Append(self.TBMENU_CLOSE, "Quit")
184       
185        self.TBTIMER = wx.NewId()
186        self.chrono = wx.wxTimer(self, self.TBTIMER)
187        EVT_TIMER(self, self.TBTIMER, self.OnChronoTimer)
188       
189        self.User = None
190        self.networkInterface = CGINetworkInterface(DUMPYKOTA_URL)
191        self.inTimer = 0
192        self.chrono.Start(1000 * 60 * 3) # every 3 minutes
193
194    def getCurrentUserName(self) :
195        """Returns the name of the current user."""
196        return win32api.GetUserName()
197       
198    def OnChronoTimer(self, event) :
199        """Retrieves user's data quota information."""
200        if not self.inTimer : # avoids re-entrance
201            self.inTimer = 1
202            self.User = self.networkInterface.getUser(self.getCurrentUserName())
203            self.inTimer = 0
204   
205    def OnIconify(self, event) :
206        self.Hide()
207
208    def OnTaskBarActivate(self, event) :
209        if self.IsIconized() :
210            self.Iconize(False)
211        if not self.IsShown() :
212            self.Show(True)
213        self.Raise()
214
215    def OnCloseWindow(self, event) :
216        if hasattr(self, "chrono") :
217            self.chrono.Stop()
218            del self.chrono
219        if hasattr(self, "menu") :
220            menu.Destroy()
221            del self.menu
222        if hasattr(self, "tbicon") :
223            self.tbicon.Destroy()
224            del self.tbicon
225        self.Destroy()
226
227    def OnTaskBarMenu(self, evt) :
228        self.tbicon.PopupMenu(self.menu)
229
230    def OnTaskBarClose(self, evt) :
231        self.Close()
232        wxPython.wx.wxGetApp().ProcessIdle()
233
234class PyKotIconApp(wxPython.wx.wxApp):
235    def OnInit(self) :
236        frame = PyKotIcon(None, -1, "PyKota Print Quota Manager")
237        frame.Show(True)
238        return True
239       
240def crashed() :   
241    """Minimal crash method."""
242    import traceback
243    lines = []
244    for line in traceback.format_exception(*sys.exc_info()) :
245        lines.extend([l for l in line.split("\n") if l])
246    msg = "ERROR: ".join(["%s\n" % l for l in (["ERROR: PyKotIcon"] + lines)])
247    sys.stderr.write(msg)
248    sys.stderr.flush()
249   
250def main():
251    """Program's entry point."""
252    app = PyKotIconApp()
253    app.MainLoop()
254   
255def test() :
256    """Runs in test mode (console)."""
257    username = getWindowsUserName()
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.