~thomas-deruyter-3/qreator/qreator

14 by David Planella
Added support to display maps with libchamplain. python-osmgpsmap, as an alternative without Clutter, does not seem to work because it's not introspectable -gtk3 branch is still WIP. Commented out GSettings code, at it seems to crash Winpdb (settings schema not found)
1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2
### BEGIN LICENSE
20 by David Planella
Added license
3
# Copyright (C) 2012 David Planella <david.planella@ubuntu.com>
4
# This program is free software: you can redistribute it and/or modify it 
5
# under the terms of the GNU General Public License version 3, as published 
6
# by the Free Software Foundation.
7
# 
8
# This program is distributed in the hope that it will be useful, but 
9
# WITHOUT ANY WARRANTY; without even the implied warranties of 
10
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
11
# PURPOSE.  See the GNU General Public License for more details.
12
# 
13
# You should have received a copy of the GNU General Public License along 
14
# with this program.  If not, see <http://www.gnu.org/licenses/>.
14 by David Planella
Added support to display maps with libchamplain. python-osmgpsmap, as an alternative without Clutter, does not seem to work because it's not introspectable -gtk3 branch is still WIP. Commented out GSettings code, at it seems to crash Winpdb (settings schema not found)
15
### END LICENSE
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
16
17
import qrencode
18
import Image
19
import ImageOps
20
import cairo
21
import array
22
23
24
class QRCodeSize(object):
25
    SMALL = 120
26
    MEDIUM = 230
27
    LARGE = 350
28
61.1.6 by David Planella
Started using the gettext C API (locale module) instead of the Python one (gettext module), so that translations are loaded when installing the app in /opt. See http://askubuntu.com/questions/140552/how-to-make-glade-load-translations-from-opt. Minor whitespace fixes. Removed shebang from QRCode.py to stop Lintian complaining
29
16 by David Planella
Added some documentation, cleaned up the QRCode's object methods a bit
30
class QRCodeOutput(object):
31
    PIL_IMAGE = 0
32
    CAIRO_SURFACE = 1
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
33
61.1.6 by David Planella
Started using the gettext C API (locale module) instead of the Python one (gettext module), so that translations are loaded when installing the app in /opt. See http://askubuntu.com/questions/140552/how-to-make-glade-load-translations-from-opt. Minor whitespace fixes. Removed shebang from QRCode.py to stop Lintian complaining
34
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
35
class QRCode(object):
36
14 by David Planella
Added support to display maps with libchamplain. python-osmgpsmap, as an alternative without Clutter, does not seem to work because it's not introspectable -gtk3 branch is still WIP. Commented out GSettings code, at it seems to crash Winpdb (settings schema not found)
37
    def __init__(self, output_size=QRCodeSize.MEDIUM):
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
38
        self.output_size = output_size
39
        self.qrcode_size = 0
40
        self.pixel_size = 1
41
        self.image = None
42
        self.cr_surface = None
43
16 by David Planella
Added some documentation, cleaned up the QRCode's object methods a bit
44
    def encode(self, text, output_type=QRCodeOutput.PIL_IMAGE):
45
        '''Encodes the given text and returns a QR code in the given format'''
61.1.6 by David Planella
Started using the gettext C API (locale module) instead of the Python one (gettext module), so that translations are loaded when installing the app in /opt. See http://askubuntu.com/questions/140552/how-to-make-glade-load-translations-from-opt. Minor whitespace fixes. Removed shebang from QRCode.py to stop Lintian complaining
46
16 by David Planella
Added some documentation, cleaned up the QRCode's object methods a bit
47
        if output_type == QRCodeOutput.PIL_IMAGE:
48
            qr_code = self._encode_to_pil(text)
49
        elif output_type == QRCodeOutput.CAIRO_SURFACE:
50
            qr_code = self._encode_to_cairo(text)
51
52
        return qr_code
53
54
    def _encode_to_cairo(self, text):
55
        '''Encodes the given text and returns a Cairo surface'''
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
56
        self._encode_to_pil(text)
57
58
        # Convert the Python PIL image to a Cairo surface.
59
        # Notice the conversion to BGRA that Cairo expects
60
        # See http://cairographics.org/pythoncairopil/ and
61
        # http://mail.gnome.org/archives/gtkmm-list/2007-May/msg00111.html
62
        bytearr = array.array('B', self.image.tostring("raw", "BGRA", 0, 1))
63
        height, width = self.image.size
16 by David Planella
Added some documentation, cleaned up the QRCode's object methods a bit
64
        #print self.image.size
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
65
66
        self.cr_surface = cairo.ImageSurface.create_for_data(bytearr,
67
                                                     cairo.FORMAT_ARGB32,
68
                                                     width, height,
69
                                                     width * 4)
70
71
        return self.cr_surface
72
73
    def _encode_to_pil(self, text):
16 by David Planella
Added some documentation, cleaned up the QRCode's object methods a bit
74
        '''Encodes the given text and returns a Python PIL Image'''
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
75
        version, self.qrcode_size, self.image = qrencode.encode(text)
76
        self.image = self.image.convert('RGBA')
77
        self._resize()
78
        self._add_border()
79
80
        return self.image
81
82
    def _resize(self):
83
        self._set_pixel_size(self.qrcode_size)
17 by David Planella
First working version ready for release
84
        #print self.pixel_size, self.qrcode_size
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
85
        self.image = self.image.resize((self.pixel_size * self.qrcode_size,
86
                                        self.pixel_size * self.qrcode_size),
87
                                       Image.NEAREST)
88
89
    def _set_pixel_size(self, barcode_orig_size):
90
        pixel_size = 1
91
17 by David Planella
First working version ready for release
92
        #print pixel_size * barcode_orig_size, self.output_size
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
93
        while (pixel_size * barcode_orig_size < self.output_size):
94
            pixel_size += 1
95
96
        while ((pixel_size * barcode_orig_size > self.output_size) or \
97
                ((pixel_size * barcode_orig_size) % 2 != 0) or \
98
                (pixel_size * barcode_orig_size + 2 * pixel_size > \
99
                    self.output_size)):
100
            pixel_size -= 1
101
102
            # FIXME: it needs to automatically go up to the next size,
103
            # rather than hardcoding it as now
104
            if pixel_size == 0:
105
                self.output_size = QRCodeSize.MEDIUM
106
107
        self.pixel_size = pixel_size
108
109
    def _add_border(self):
16 by David Planella
Added some documentation, cleaned up the QRCode's object methods a bit
110
        '''Adds a border to the QR code'''
12 by David Planella
Moved the QR generation code to a separate module, independent of the UI
111
        # Add a border
112
        border_size = (self.output_size - self.image.size[0]) / 2
113
        self.image = ImageOps.expand(self.image, border=border_size,
114
                                     fill='white')