summaryrefslogtreecommitdiffstats
path: root/test/test_pygtk.py
blob: fc19fa97e3fb183f4059edddc8358f9d1a2e31d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/usr/bin/env python2
#------------------------------------------------------------------------
#  Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
#
#  This file is part of the ZBar Bar Code Reader.
#
#  The ZBar Bar Code Reader is free software; you can redistribute it
#  and/or modify it under the terms of the GNU Lesser Public License as
#  published by the Free Software Foundation; either version 2.1 of
#  the License, or (at your option) any later version.
#
#  The ZBar Bar Code Reader is distributed in the hope that it will be
#  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Lesser Public License for more details.
#
#  You should have received a copy of the GNU Lesser Public License
#  along with the ZBar Bar Code Reader; if not, write to the Free
#  Software Foundation, Inc., 51 Franklin St, Fifth Floor,
#  Boston, MA  02110-1301  USA
#
#  http://sourceforge.net/projects/zbar
#------------------------------------------------------------------------
import sys, os, stat
import pygtk, gtk
import zbarpygtk

def decoded(zbar, data):
    """callback invoked when a barcode is decoded by the zbar widget.
    displays the decoded data in the text box
    """
    buf = results.props.buffer
    end = buf.get_end_iter()
    buf.insert(end, data + "\n")
    results.scroll_to_iter(end, 0)

def video_enabled(zbar, param):
    """callback invoked when the zbar widget enables or disables
    video streaming.  updates the status button state to reflect the
    current video state
    """
    enabled = zbar.get_video_enabled()
    if status_button.get_active() != enabled:
        status_button.set_active(enabled)

def video_opened(zbar, param):
    """callback invoked when the zbar widget opens or closes a video
    device.  also called when a device is closed due to error.
    updates the status button state to reflect the current video state
    """
    opened = zbar.get_video_opened()
    status_button.set_sensitive(opened)
    set_status_label(opened, zbar.get_video_enabled())

def video_changed(widget):
    """callback invoked when a new video device is selected from the
    drop-down list.  sets the new device for the zbar widget,
    which will eventually cause it to be opened and enabled
    """
    dev = video_list.get_active_text()
    if dev[0] == '<':
        dev = ''
    zbar.set_video_device(dev)

def status_button_toggled(button):
    """callback invoked when the status button changes state
    (interactively or programmatically).  ensures the zbar widget
    video streaming state is consistent and updates the display of the
    button to represent the current state
    """
    opened = zbar.get_video_opened()
    active = status_button.get_active()
    if opened and (active != zbar.get_video_enabled()):
        zbar.set_video_enabled(active)
    set_status_label(opened, active)
    if active:
        status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_BUTTON)
    else:
        status_image.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_BUTTON)

def open_button_clicked(button):
    """callback invoked when the 'Open' button is clicked.  pops up an
    'Open File' dialog which the user may use to select an image file.
    if the image is successfully opened, it is passed to the zbar
    widget which displays it and scans it for barcodes.  results are
    returned using the same hook used to report video results
    """
    dialog = gtk.FileChooserDialog("Open Image File", window,
                                   gtk.FILE_CHOOSER_ACTION_OPEN,
                                   (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                    gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT))
    global open_file
    if open_file:
        dialog.set_filename(open_file)
    try:
        if dialog.run() == gtk.RESPONSE_ACCEPT:
            open_file = dialog.get_filename()
            pixbuf = gtk.gdk.pixbuf_new_from_file(open_file)
            if pixbuf:
                zbar.scan_image(pixbuf)
    finally:
        dialog.destroy()

def set_status_label(opened, enabled):
    """update status button label to reflect indicated state."""
    if not opened:
        label = "closed"
    elif enabled:
        label = "enabled"
    else:
        label = "disabled"
    status_button.set_label(label)

open_file = None
video_device = None
if len(sys.argv) > 1:
    video_device = sys.argv[1]

# threads *must* be properly initialized to use zbarpygtk
gtk.gdk.threads_init()
gtk.gdk.threads_enter()

window = gtk.Window()
window.set_title("test_pygtk")
window.set_border_width(8)
window.connect("destroy", gtk.main_quit)

zbar = zbarpygtk.Gtk()
zbar.connect("decoded-text", decoded)

# video device list combo box
video_list = gtk.combo_box_new_text()
video_list.connect("changed", video_changed)

# enable/disable status button
status_button = gtk.ToggleButton("closed")
status_image = gtk.image_new_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_BUTTON)
status_button.set_image(status_image)
status_button.set_sensitive(False)

# bind status button state and video state
status_button.connect("toggled", status_button_toggled)
zbar.connect("notify::video-enabled", video_enabled)
zbar.connect("notify::video-opened", video_opened)

# open image file button
open_button = gtk.Button(stock=gtk.STOCK_OPEN)
open_button.connect("clicked", open_button_clicked)

# populate video devices in combo box
video_list.append_text("<none>")
video_list.set_active(0)
for (root, dirs, files) in os.walk("/dev"):
    for dev in files:
        path = os.path.join(root, dev)
        if not os.access(path, os.F_OK):
            continue
        info = os.stat(path)
        if stat.S_ISCHR(info.st_mode) and os.major(info.st_rdev) == 81:
            video_list.append_text(path)
            if path == video_device:
                video_list.set_active(len(video_list.get_model()) - 1)
                video_device = None

if video_device is not None:
    video_list.append_text(video_device)
    video_list.set_active(len(video_list.get_model()) - 1)
    video_device = None

# combine combo box and buttons horizontally
hbox = gtk.HBox(spacing=8)
hbox.pack_start(video_list)
hbox.pack_start(status_button, expand=False)
hbox.pack_start(open_button, expand=False)

# text box for holding results
results = gtk.TextView()
results.set_size_request(320, 64)
results.props.editable = results.props.cursor_visible = False
results.set_left_margin(4)

# combine inputs, scanner, and results vertically
vbox = gtk.VBox(spacing=8)
vbox.pack_start(hbox, expand=False)
vbox.pack_start(zbar)
vbox.pack_start(results, expand=False)

window.add(vbox)
window.set_geometry_hints(zbar, min_width=320, min_height=240)
window.show_all()

gtk.main()
gtk.gdk.threads_leave()