root / pykota / trunk / bin / pkbanner @ 2024

Revision 1971, 13.9 kB (checked in by jalet, 20 years ago)

Fixed the default value for the --savetoner command line option

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# A banner generator for PyKota
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.11  2004/12/03 12:34:28  jalet
27# Fixed the default value for the --savetoner command line option
28#
29# Revision 1.10  2004/11/17 13:28:19  jalet
30# Fixed some typo in the help
31#
32# Revision 1.9  2004/11/17 13:24:05  jalet
33# Improved pkbanner's help
34#
35# Revision 1.8  2004/11/17 13:12:04  jalet
36# Implemented the --savetoner command line option
37#
38# Revision 1.7  2004/11/15 22:29:01  jalet
39# Moved title and filename to the left to free some space.
40#
41# Revision 1.6  2004/11/15 22:20:27  jalet
42# Now outputs strings as-is, and not title-ized
43#
44# Revision 1.5  2004/11/15 22:01:34  jalet
45# Improved banner handling.
46# Fix for raw printing and banners.
47#
48# Revision 1.4  2004/11/15 19:59:34  jalet
49# PyKota banners now basically work !
50#
51# Revision 1.3  2004/11/12 23:46:44  jalet
52# Heavy work on pkbanner. Not finished yet though, but mostly works.
53#
54# Revision 1.2  2004/11/11 14:25:48  jalet
55# Added some TODO comments
56#
57# Revision 1.1  2004/11/10 22:48:47  jalet
58# Banner generator's skeleton added
59#
60#
61#
62
63import sys
64import os
65import time
66import cStringIO
67import popen2
68
69try :
70    from reportlab.pdfgen import canvas
71    from reportlab.lib import pagesizes
72    from reportlab.lib.units import cm
73except ImportError :   
74    hasRL = 0
75else :   
76    hasRL = 1
77   
78try :
79    import PIL.Image 
80except ImportError :   
81    hasPIL = 0
82else :   
83    hasPIL = 1
84   
85from pykota.tool import Tool, PyKotaToolError, crashed, N_
86
87__doc__ = N_("""pkbanner v%s (c) 2003-2004 C@LL - Conseil Internet & Logiciels Libres
88
89Generates banners.
90
91command line usage :
92
93  pkbanner  [options]
94
95options :
96
97  -v | --version       Prints pkbanner's version number then exits.
98  -h | --help          Prints this message then exits.
99 
100  -l | --logo img      Use the image as the banner's logo. The logo will
101                       be drawn at the center top of the page. The default
102                       logo is /usr/share/pykota/logos/pykota.jpeg
103                       
104  -p | --pagesize sz   Sets sz as the page size. Most well known
105                       page sizes are recognized, like 'A4' or 'Letter'
106                       to name a few. The default size is A4.
107 
108  -s | --savetoner s   Sets the text luminosity factor to s%%. This can be
109                       used to save toner. The default value is 0, which
110                       means that no toner saving will be done.
111 
112  -u | --url u         Uses u as an url to be written at the bottom of
113                       the banner page. The default url is :
114                       http://www.librelogiciel.com/software/
115 
116examples :                             
117
118  Using pkbanner directly from the command line is not recommended,
119  excepted for testing purposes. You should use pkbanner in the
120  'startingbanner' or 'endingbanner' directives in pykota.conf
121 
122    startingbanner: /usr/bin/pkbanner --logo="" --savetoner=75
123 
124      With such a setting in pykota.conf, all print jobs will be
125      prefixed with an A4 banner with no logo, and text luminosity will
126      be increased by 75%%. The PostScript output will be directly sent
127      to your printer.
128     
129  You'll find more examples in the sample configuration file included   
130  in PyKota.
131     
132This program is free software; you can redistribute it and/or modify
133it under the terms of the GNU General Public License as published by
134the Free Software Foundation; either version 2 of the License, or
135(at your option) any later version.
136
137This program is distributed in the hope that it will be useful,
138but WITHOUT ANY WARRANTY; without even the implied warranty of
139MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
140GNU General Public License for more details.
141
142You should have received a copy of the GNU General Public License
143along with this program; if not, write to the Free Software
144Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
145
146Please e-mail bugs to: %s""")
147       
148class PyKotaBanner(Tool) :       
149    """A class for pkbanner."""
150    def getPageSize(self, pgsize) :
151        """Returns the correct page size or None if not found."""
152        try :
153            return getattr(pagesizes, pgsize.upper())
154        except AttributeError :   
155            try :
156                return getattr(pagesizes, pgsize.lower())
157            except AttributeError :
158                pass
159               
160    def getVar(self, varname) :           
161        """Extracts a variable from the environment and returns its value or 'Unknown' in the current locale."""
162        return os.environ.get(varname) or _("Unknown")
163       
164    def printVar(self, canvas, x, y, label, value, size, savetoner) :
165        """Outputs a variable onto the PDF canvas.
166       
167           Returns the number of points to substract to current Y coordinate.
168        """   
169        canvas.saveState()
170        canvas.setFont("Helvetica-Bold", size)
171        (r, g, b) =  [ color + (savetoner * (1.0 - color)) for color in (0, 0, 0) ] # Black * savetoner
172        canvas.setFillColorRGB(r, g, b)
173        message = "%s :" % _(label)
174        canvas.drawRightString(x, y, message)
175        canvas.setFont("Courier-Bold", size)
176        (r, g, b) =  [ color + (savetoner * (1.0 - color)) for color in (1, 0, 0) ] # Red * savetoner
177        canvas.setFillColorRGB(r, g, b)
178        canvas.drawString(x + 0.5*cm, y, value)
179        canvas.restoreState()
180        return (size + 4)
181   
182    def genPDF(self, pagesize, logo, url, savetoner) :
183        """Generates the banner in PDF format, return the PDF document as a string."""
184       
185        document = cStringIO.StringIO()
186        c = canvas.Canvas(document, pagesize=pagesize, pageCompression=1)
187       
188        c.setAuthor("Jerome Alet")
189        c.setTitle("PyKota generated Banner")
190        c.setSubject("This is a print banner generated with PyKota")
191       
192        xcenter = pagesize[0] / 2.0
193        ycenter = pagesize[1] / 2.0
194                   
195        ypos = pagesize[1] - (2 * cm)           
196       
197        if logo :
198            try :   
199                imglogo = PIL.Image.open(logo)
200            except :   
201                self.printInfo("Unable to open image %s" % logo, "warn")
202            else :
203                (width, height) = imglogo.size
204                multi = float(width) / (8 * cm) 
205                width = float(width) / multi
206                height = float(height) / multi
207                xpos = xcenter - (width / 2.0)
208                ypos -= height
209                c.drawImage(logo, xpos, ypos, width, height)
210       
211        # New top
212        xpos = pagesize[0] / 5.0
213        ypos -= (1 * cm) + 20
214       
215        printername = self.getVar("PYKOTAPRINTERNAME")
216        username = self.getVar("PYKOTAUSERNAME")
217        accountbanner = self.config.getAccountBanner(printername)
218       
219        # Outputs the username
220        ypos -= self.printVar(c, xcenter, ypos, _("Username"), username, 20, savetoner) 
221       
222        # Printer and Job Id
223        job = "%s - %s" % (printername, self.getVar("PYKOTAJOBID"))
224        ypos -= self.printVar(c, xcenter, ypos, _("Job"), job, 14, savetoner) 
225       
226        # Current date (TODO : at the time the banner was printed ! Change this to job's submission date)
227        datetime = time.strftime("%c", time.localtime())
228        ypos -= self.printVar(c, xcenter, ypos, _("Date"), datetime, 14, savetoner) 
229       
230        # Result of the print job
231        action = self.getVar("PYKOTAACTION")
232        if action == "ALLOW" :
233            action = _("Allowed")
234        elif action == "DENY" :   
235            action = _("Denied")
236        elif action == "WARN" :   
237            action = _("Allowed with Warning")
238        ypos -= self.printVar(c, xcenter, ypos, _("Result"), action, 14, savetoner) 
239       
240        # skip some space
241        ypos -= 20
242       
243        # Outputs title and filename
244        # We put them at x=0.25*pagewidth so that the line is long enough to hold them
245        title = self.getVar("PYKOTATITLE")
246        ypos -= self.printVar(c, xcenter / 2.0, ypos, _("Title"), title, 10, savetoner) 
247       
248        filename = self.getVar("PYKOTAFILENAME")
249        ypos -= self.printVar(c, xcenter / 2.0, ypos, _("Filename"), filename, 10, savetoner) 
250       
251        # skip some space
252        ypos -= 20
253       
254        # Now outputs the user's account balance or page counter
255        ypos -= self.printVar(c, xcenter, ypos, _("Pages printed so far on %s") % printername, self.getVar("PYKOTAPAGECOUNTER"), 14, savetoner) 
256        limitby = self.getVar("PYKOTALIMITBY")
257        if limitby == "balance" : 
258            ypos -= self.printVar(c, xcenter, ypos, _("Account balance"), self.getVar("PYKOTABALANCE"), 14, savetoner) 
259        else :
260            ypos -= self.printVar(c, xcenter, ypos, _("Soft Limit"), self.getVar("PYKOTASOFTLIMIT"), 14, savetoner) 
261            ypos -= self.printVar(c, xcenter, ypos, _("Hard Limit"), self.getVar("PYKOTAHARDLIMIT"), 14, savetoner) 
262            ypos -= self.printVar(c, xcenter, ypos, _("Date Limit"), self.getVar("PYKOTADATELIMIT"), 14, savetoner) 
263           
264        # URL
265        if url :
266            c.saveState()
267            c.setFont("Courier-Bold", 16)
268            (r, g, b) =  [ color + (savetoner * (1.0 - color)) for color in (0, 0, 1) ] # Blue * savetoner
269            c.setFillColorRGB(r, g, b)
270            c.drawCentredString(xcenter, 2 * cm, url)
271            c.restoreState()
272       
273        c.showPage()
274        c.save()
275        return document.getvalue()
276       
277    def main(self, files, options) :
278        """Generates a banner."""
279        if not hasRL :
280            raise PyKotaToolError, "The ReportLab module is missing. Download it from http://www.reportlab.org"
281        if not hasPIL :
282            raise PyKotaToolError, "The Python Imaging Library is missing. Download it from http://www.pythonware.com/downloads"
283           
284        try :
285            savetoner = int(options["savetoner"])
286            if (savetoner < 0) or (savetoner > 99) :
287                raise ValueError, _("Allowed range is (0..99)")
288            savetoner /= 100.0   
289        except (TypeError, ValueError), msg :
290            self.printInfo(_("Invalid 'savetoner' option %s : %s") % (options["savetoner"], msg), "warn")
291            savetoner = 0.0
292           
293        pagesize = self.getPageSize(options["pagesize"])
294        if pagesize is None :
295            pagesize = self.getPageSize("a4")
296            self.printInfo(_("Invalid 'pagesize' option %s, defaulting to A4.") % options["pagesize"], "warn")
297           
298        self.logdebug("Generating the banner in PDF format...")   
299        doc = self.genPDF(pagesize, options["logo"].strip(), options["url"].strip(), savetoner)
300       
301        self.logdebug("Converting the banner to PostScript...")   
302        os.environ["PATH"] = "%s:/bin:/usr/bin:/usr/local/bin:/opt/bin:/sbin:/usr/sbin" % os.environ.get("PATH", "")
303        child = popen2.Popen3("gs -q -dNOPAUSE -dBATCH -dPARANOIDSAFER -sDEVICE=pswrite -sOutputFile=- - 2>/tmp/errgs")
304        child.tochild.write(doc)
305        child.tochild.close()
306        sys.stdout.write(child.fromchild.read())
307        sys.stdout.flush()
308        child.fromchild.close()
309        status = child.wait()
310        if os.WIFEXITED(status) :
311            status = os.WEXITSTATUS(status)
312        self.logdebug("PDF to PostScript converter exit code is %s" % str(status))
313        self.logdebug("Banner completed.")
314        return status
315
316if __name__ == "__main__" :
317    # TODO : --papertray : to print banners on a different paper (colored for example)
318    retcode = 0
319    try :
320        defaults = { \
321                     "savetoner" : "0", \
322                     "pagesize" : "a4", \
323                     "logo" : "/usr/share/pykota/logos/pykota.jpeg",
324                     "url" : "http://www.librelogiciel.com/software/",
325                   }
326        short_options = "vhs:l:p:u:"
327        long_options = ["help", "version", "savetoner=", "pagesize=", "logo=", "url="]
328       
329        # Initializes the command line tool
330        banner = PyKotaBanner(doc=__doc__)
331       
332        # parse and checks the command line
333        (options, args) = banner.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=1)
334       
335        # sets long options
336        options["help"] = options["h"] or options["help"]
337        options["version"] = options["v"] or options["version"]
338        options["savetoner"] = options["s"] or options["savetoner"] or defaults["savetoner"]
339        options["pagesize"] = options["p"] or options["pagesize"] or defaults["pagesize"]
340        options["url"] = options["u"] or options["url"] or defaults["url"]
341       
342        options["logo"] = options["l"] or options["logo"]
343        if options["logo"] is None : # Allows --logo="" to disable the logo entirely
344            options["logo"] = defaults["logo"] 
345       
346        if options["help"] :
347            banner.display_usage_and_quit()
348        elif options["version"] :
349            banner.display_version_and_quit()
350        else :
351            retcode = banner.main(args, options)
352    except SystemExit :       
353        pass
354    except :
355        try :
356            banner.crashed("pkbanner failed")
357        except :   
358            crashed("pkbanner failed")
359        retcode = -1
360       
361    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.