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
RevLine 
[47]1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
[48]4# PyKotIcon - Windows System Tray Icon for PyKota
[47]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#
[53]21# $Id$
[47]22#
23#
24
25import sys
26import urllib
27import urllib2
28
[57]29try :
30    import win32api
31    import win32net
32    import win32netcon
33    hasWindowsExtensions = 1
34except ImportError :   
35    hasWindowsExtensions = 0
[58]36    raise ImportError, "Mark Hammond's Win32 Extensions are missing. Please install them."
[57]37   
[58]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   
[47]46DUMPYKOTA_URL = "http://cgi.librelogiciel.com/cgi-bin/dumpykota.cgi"
47
[56]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           
[55]91class CGINetworkInterface :
92    """A class for all network interactions."""
[56]93    def __init__(self, cgiurl, authname=None, authpw=None) :
[55]94        """Initialize CGI connection datas."""
[56]95        self.cgiurl = cgiurl
96        self.authname = authname
97        self.authpw = authpw
[55]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 :           
[56]107            url = "%s?%s" % (self.cgiurl, urllib.urlencode(args))
[55]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, \
[56]119                                  [ line[fields.index(fieldname)][1:-1] \
120                                    for line in lines[1:] ]) \
[55]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                    } 
[58]139        return self.retrieveDatas(arguments, ("limitby", "balance", \
140                                                         "lifetimepaid"))
[55]141       
142    def getUserPQuotas(self, username) :
143        """Retrieve the user's print quota information."""
144        arguments = { "datatype" : "upquotas",
145                      "filter" : "username=%s" % username,
146                    } 
[56]147        return self.retrieveDatas(arguments, ("printername", "pagecounter", \
[58]148                                              "softlimit", "hardlimit", \
149                                              "datelimit"))
[56]150                                             
151    def getUser(self, username) :
152        """Retrieves the user account and quota information."""
153        info = self.getUserInfo(username)
[60]154        if info :
155            quotas = self.getUserPQuotas(username)
156            return User(username, info, quotas)
[47]157   
[58]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")
[59]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
[58]190
[59]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) :
[58]203        self.Hide()
204
[59]205    def OnTaskBarActivate(self, event) :
206        if self.IsIconized() :
[58]207            self.Iconize(False)
[59]208        if not self.IsShown() :
[58]209            self.Show(True)
210        self.Raise()
211
[59]212    def OnCloseWindow(self, event) :
213        if hasattr(self, "chrono") :
214            self.chrono.Stop()
215            del self.chrono
[58]216        if hasattr(self, "menu") :
217            menu.Destroy()
218            del self.menu
[59]219        if hasattr(self, "tbicon") :
[58]220            self.tbicon.Destroy()
221            del self.tbicon
222        self.Destroy()
223
[59]224    def OnTaskBarMenu(self, evt) :
[58]225        self.tbicon.PopupMenu(self.menu)
226
[59]227    def OnTaskBarClose(self, evt) :
[58]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()
[47]246   
[58]247def main():
248    """Program's entry point."""
249    app = PyKotIconApp()
250    app.MainLoop()
[47]251   
[58]252def test() :
253    """Runs in test mode (console)."""
[60]254    if len(sys.argv) >= 3 :
255        username = sys.argv[2] 
256    else :   
257        username = win32api.GetUserName()
[58]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
[47]270
[58]271if __name__ == '__main__':
[60]272    if (len(sys.argv) >= 2) and (sys.argv[1] == "--test") :
[58]273        test()
274    else :   
275        main()
276   
Note: See TracBrowser for help on using the browser.