root / pykoticon / trunk / bin / pykoticon @ 58

Revision 58, 9.1 kB (checked in by jerome, 19 years ago)

Preliminary windows taskbar functionnality working

  • 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    def OnIconify(self, evt):
186        self.Hide()
187
188    def OnTaskBarActivate(self, event):
189        if self.IsIconized():
190            self.Iconize(False)
191        if not self.IsShown():
192            self.Show(True)
193        self.Raise()
194
195    def OnCloseWindow(self, event):
196        if hasattr(self, "menu") :
197            menu.Destroy()
198            del self.menu
199        if hasattr(self, "tbicon"):
200            self.tbicon.Destroy()
201            del self.tbicon
202        self.Destroy()
203
204    def OnTaskBarMenu(self, evt):
205        self.tbicon.PopupMenu(self.menu)
206
207    def OnTaskBarClose(self, evt):
208        self.Close()
209        wxPython.wx.wxGetApp().ProcessIdle()
210
211class PyKotIconApp(wxPython.wx.wxApp):
212    def OnInit(self) :
213        frame = PyKotIcon(None, -1, "PyKota Print Quota Manager")
214        frame.Show(True)
215        return True
216       
217def crashed() :   
218    """Minimal crash method."""
219    import traceback
220    lines = []
221    for line in traceback.format_exception(*sys.exc_info()) :
222        lines.extend([l for l in line.split("\n") if l])
223    msg = "ERROR: ".join(["%s\n" % l for l in (["ERROR: PyKotIcon"] + lines)])
224    sys.stderr.write(msg)
225    sys.stderr.flush()
226   
227def main():
228    """Program's entry point."""
229    app = PyKotIconApp()
230    app.MainLoop()
231   
232def test() :
233    """Runs in test mode (console)."""
234    username = getWindowsUserName()
235    net = CGINetworkInterface(DUMPYKOTA_URL)
236    user = net.getUser(username)
237    print "UserName : ", user.Name
238    print "LimitBy : ", user.LimitBy
239    print "Balance : ", user.Balance
240    for q in user.Quotas :
241        print "\tPrinterName : ", q.PrinterName
242        print "\tPageCounter : ", q.PageCounter
243        print "\tSoftLimit : ", q.SoftLimit
244        print "\tHardLimit : ", q.HardLimit
245        print "\tDateLimit : ", q.DateLimit
246        print
247
248if __name__ == '__main__':
249    if (len(sys.argv) == 2) and (sys.argv[1] == "--test") :
250        test()
251    else :   
252        main()
253   
Note: See TracBrowser for help on using the browser.