root / pykota / trunk / bin / pkbanner @ 1926

Revision 1926, 13.0 kB (checked in by jalet, 19 years ago)

Moved title and filename to the left to free some space.

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