move point of sale mode into plugins
[electrum-nvc.git] / plugins / qrscanner.py
1 from electrum.util import print_error
2
3 try:
4     import zbar
5 except ImportError:    
6     print_error("Install zbar package to enable QR scans")
7     zbar = None
8
9 from urlparse import urlparse, parse_qs
10
11
12 def init(wallet):
13     pass
14
15 def init_gui(gui):
16     if is_enabled():
17         gui.wallet.set_hook('create_send_tab', create_send_tab)
18     else:
19         gui.wallet.unset_hook('create_send_tab', create_send_tab)
20
21 def get_info():
22     return 'QR scans', "QR Scans"
23
24 def is_enabled():
25     return is_available()
26
27 def toggle(gui):
28     return is_enabled()
29
30
31 def is_available():
32     if not zbar:
33         return False
34
35     try:
36         proc = zbar.Processor()
37         proc.init()
38     except zbar.SystemError:
39         # Cannot open video device
40         return False
41
42     return True
43
44 def scan_qr():
45     proc = zbar.Processor()
46     proc.init()
47     proc.visible = True
48
49     while True:
50         try:
51             proc.process_one()
52         except:
53             # User closed the preview window
54             return {}
55
56         for r in proc.results:
57             if str(r.type) != 'QRCODE':
58                 continue
59
60             return parse_uri(r.data)
61         
62 def parse_uri(uri):
63     if ':' not in uri:
64         # It's just an address (not BIP21)
65         return {'address': uri}
66
67     if '//' not in uri:
68         # Workaround for urlparse, it don't handle bitcoin: URI properly
69         uri = uri.replace(':', '://')
70         
71     uri = urlparse(uri)
72     result = {'address': uri.netloc} 
73     
74     if uri.path.startswith('?'):
75         params = parse_qs(uri.path[1:])
76     else:
77         params = parse_qs(uri.path)    
78
79     for k,v in params.items():
80         if k in ('amount', 'label', 'message'):
81             result[k] = v[0]
82         
83     return result    
84
85
86
87 def fill_from_qr(self):
88     qrcode = qrscanner.scan_qr()
89     if 'address' in qrcode:
90         self.payto_e.setText(qrcode['address'])
91     if 'amount' in qrcode:
92         self.amount_e.setText(str(qrcode['amount']))
93     if 'label' in qrcode:
94         self.message_e.setText(qrcode['label'])
95     if 'message' in qrcode:
96         self.message_e.setText("%s (%s)" % (self.message_e.text(), qrcode['message']))
97                 
98
99 def create_send_tab(gui, grid):
100     if qrscanner.is_available():
101         b = QPushButton(_("Scan QR code"))
102         b.clicked.connect(lambda: fill_from_qr(gui))
103         grid.addWidget(b, 1, 5)
104
105
106
107 if __name__ == '__main__':
108     # Run some tests
109     
110     assert(parse_uri('1Marek48fwU7mugmSe186do2QpUkBnpzSN') ==
111            {'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'})
112
113     assert(parse_uri('bitcoin://1Marek48fwU7mugmSe186do2QpUkBnpzSN') ==
114            {'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'})
115     
116     assert(parse_uri('bitcoin:1Marek48fwU7mugmSe186do2QpUkBnpzSN') ==
117            {'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'})
118     
119     assert(parse_uri('bitcoin:1Marek48fwU7mugmSe186do2QpUkBnpzSN?amount=10') ==
120            {'amount': '10', 'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'})
121     
122     assert(parse_uri('bitcoin:1Marek48fwU7mugmSe186do2QpUkBnpzSN?amount=10&label=slush&message=Small%20tip%20to%20slush') ==
123            {'amount': '10', 'label': 'slush', 'message': 'Small tip to slush', 'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'})
124     
125