1 | #! /usr/bin/env python |
---|
2 | # -*- coding: utf-8 -*- |
---|
3 | # |
---|
4 | # PyKota : Print Quotas for CUPS |
---|
5 | # |
---|
6 | # (c) 2003-2009 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 3 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, see <http://www.gnu.org/licenses/>. |
---|
19 | # |
---|
20 | # $Id$ |
---|
21 | # |
---|
22 | # |
---|
23 | |
---|
24 | """An On Screen Display (OSD) monitor for PyKota's end users.""" |
---|
25 | |
---|
26 | import sys |
---|
27 | import os |
---|
28 | import pwd |
---|
29 | import time |
---|
30 | |
---|
31 | try : |
---|
32 | import pyosd |
---|
33 | except ImportError : |
---|
34 | sys.stderr.write("Sorry ! You need both xosd and the Python OSD library (pyosd) for this software to work.\n") |
---|
35 | sys.exit(-1) |
---|
36 | |
---|
37 | import pykota.appinit |
---|
38 | from pykota.utils import run, loginvalidparam |
---|
39 | from pykota.commandline import PyKotaOptionParser |
---|
40 | from pykota.errors import PyKotaToolError, PyKotaCommandLineError |
---|
41 | from pykota.tool import PyKotaTool |
---|
42 | |
---|
43 | class PyKOSD(PyKotaTool) : |
---|
44 | """A class for an On Screen Display print quota monitor.""" |
---|
45 | def main(self, args, options) : |
---|
46 | """Main function starts here.""" |
---|
47 | savecolor = options.color |
---|
48 | loop = options.loop |
---|
49 | username = pwd.getpwuid(os.getuid())[0] |
---|
50 | while True : |
---|
51 | color = savecolor |
---|
52 | user = self.storage.getUserFromBackend(username) # don't use cache |
---|
53 | if not user.Exists : |
---|
54 | raise PyKotaCommandLineError, _("You %(username)s don't have a PyKota printing account. Please contact your administrator.") % locals() |
---|
55 | if user.LimitBy == "quota" : |
---|
56 | printers = self.storage.getMatchingPrinters("*") |
---|
57 | upquotas = [ self.storage.getUserPQuotaFromBackend(user, p) for p in printers ] # don't use cache |
---|
58 | nblines = len(upquotas) |
---|
59 | display = pyosd.osd(font=options.font, |
---|
60 | colour=color, |
---|
61 | timeout=options.duration, |
---|
62 | shadow=2, |
---|
63 | lines=nblines) |
---|
64 | for line in range(nblines) : |
---|
65 | upq = upquotas[line] |
---|
66 | if upq.HardLimit is None : |
---|
67 | if upq.SoftLimit is None : |
---|
68 | percent = "%i" % upq.PageCounter |
---|
69 | else : |
---|
70 | percent = "%i%%" % min((upq.PageCounter * 100) / upq.SoftLimit, 100) |
---|
71 | else : |
---|
72 | percent = "%i%%" % min((upq.PageCounter * 100) / upq.HardLimit, 100) |
---|
73 | printername = upq.Printer.Name |
---|
74 | msg = _("Pages used on %(printername)s : %(percent)s") % locals() |
---|
75 | display.display(msg.encode(self.charset, "replace"), |
---|
76 | type=pyosd.TYPE_STRING, |
---|
77 | line=line) |
---|
78 | elif user.LimitBy == "balance" : |
---|
79 | if user.AccountBalance <= self.config.getBalanceZero() : |
---|
80 | color = "#FF0000" |
---|
81 | display = pyosd.osd(font=options.font, |
---|
82 | colour=color, |
---|
83 | timeout=options.duration, |
---|
84 | shadow=2) |
---|
85 | balance = user.AccountBalance |
---|
86 | msg = _("PyKota Units left : %(balance).2f") % locals() |
---|
87 | display.display(msg.encode(self.charset, "replace"), |
---|
88 | type=pyosd.TYPE_STRING) |
---|
89 | elif user.LimitBy == "noprint" : |
---|
90 | display = pyosd.osd(font=options.font, |
---|
91 | colour="#FF0000", |
---|
92 | timeout=options.duration, |
---|
93 | shadow=2) |
---|
94 | msg = _("Printing denied.") |
---|
95 | display.display(msg.encode(self.charset, "replace"), |
---|
96 | type=pyosd.TYPE_STRING) |
---|
97 | elif user.LimitBy == "noquota" : |
---|
98 | display = pyosd.osd(font=options.font, |
---|
99 | colour=savecolor, |
---|
100 | timeout=options.duration, |
---|
101 | shadow=2) |
---|
102 | msg = _("Printing not limited.") |
---|
103 | display.display(msg.encode(self.charset, "replace"), |
---|
104 | type=pyosd.TYPE_STRING) |
---|
105 | elif user.LimitBy == "nochange" : |
---|
106 | display = pyosd.osd(font=options.font, |
---|
107 | colour=savecolor, |
---|
108 | timeout=options.duration, |
---|
109 | shadow=2) |
---|
110 | msg = _("Printing not limited, no accounting.") |
---|
111 | display.display(msg.encode(self.charset, "replace"), |
---|
112 | type=pyosd.TYPE_STRING) |
---|
113 | else : |
---|
114 | limitby = repr(user.LimitBy) |
---|
115 | raise PyKotaToolError, "Incorrect limitation factor %(limitby)s for user %(username)s" % locals() |
---|
116 | |
---|
117 | time.sleep(options.duration + 1) |
---|
118 | if loop : |
---|
119 | loop -= 1 |
---|
120 | if not loop : |
---|
121 | break |
---|
122 | time.sleep(options.sleep) |
---|
123 | |
---|
124 | return 0 |
---|
125 | |
---|
126 | if __name__ == "__main__" : |
---|
127 | def checkandset_positiveint(option, opt, value, optionparser) : |
---|
128 | """Checks and sets positive integer values.""" |
---|
129 | if value < 0 : |
---|
130 | loginvalidparam(opt, value, option.default) |
---|
131 | setattr(optionparser.values, option.dest, option.default) |
---|
132 | else : |
---|
133 | setattr(optionparser.values, option.dest, value) |
---|
134 | |
---|
135 | def checkandset_color(option, opt, value, optionparser) : |
---|
136 | """Checks and sets the color value.""" |
---|
137 | if not value.startswith("#") : |
---|
138 | value = "#%s" % value |
---|
139 | try : |
---|
140 | int(value[1:], 16) |
---|
141 | except (ValueError, TypeError) : |
---|
142 | error = True |
---|
143 | else : |
---|
144 | error = False |
---|
145 | if (len(value) != 7) or error : |
---|
146 | loginvalidparam(opt, value, option.default) |
---|
147 | setattr(optionparser.values, option.dest, option.default) |
---|
148 | else : |
---|
149 | setattr(optionparser.values, option.dest, value) |
---|
150 | |
---|
151 | parser = PyKotaOptionParser(description=_("An On Screen Display (OSD) monitor for PyKota's end users.")) |
---|
152 | parser.add_option("-c", "--color", "--colour", |
---|
153 | type="string", |
---|
154 | action="callback", |
---|
155 | callback=checkandset_color, |
---|
156 | dest="color", |
---|
157 | default="#00FF00", |
---|
158 | help=_("Set the color that will be used for display, as an hexadecimal triplet. For example #FF0000 is 100% red. The default is 100% green (%default).")) |
---|
159 | parser.add_option("-d", "--duration", |
---|
160 | type="int", |
---|
161 | action="callback", |
---|
162 | callback=checkandset_positiveint, |
---|
163 | dest="duration", |
---|
164 | default=3, |
---|
165 | help=_("Set the time in seconds during which the message will be displayed. Defaults to %default seconds.")) |
---|
166 | parser.add_option("-f", "--font", |
---|
167 | dest="font", |
---|
168 | default=pyosd.default_font, |
---|
169 | help=_("Set the font to use. Defaults to %default.")) |
---|
170 | parser.add_option("-l", "--loop", |
---|
171 | type="int", |
---|
172 | action="callback", |
---|
173 | callback=checkandset_positiveint, |
---|
174 | dest="loop", |
---|
175 | default=0, |
---|
176 | help=_("Set the number of times the info will be displayed. Defaults to %default, which means loop forever.")) |
---|
177 | parser.add_option("-s", "--sleep", |
---|
178 | type="int", |
---|
179 | action="callback", |
---|
180 | callback=checkandset_positiveint, |
---|
181 | dest="sleep", |
---|
182 | default=180, |
---|
183 | help=_("Set the sleeping time in seconds between two refreshes. Defaults to %default seconds.")) |
---|
184 | |
---|
185 | parser.add_example('-s 60 --loop 5', |
---|
186 | _("This would tell pykosd to display the current user's status for 3 seconds (the default) every 60 seconds, and exit after 5 iterations.")) |
---|
187 | |
---|
188 | run(parser, PyKOSD) |
---|