derive plugins from BasePlugin class

This commit is contained in:
thomasv 2013-03-15 09:58:05 +01:00
parent 93b98e1176
commit bd1cdc9bfb
6 changed files with 342 additions and 389 deletions

View File

@ -1 +1,2 @@
# do not remove this file
from plugins import BasePlugin

View File

@ -339,7 +339,7 @@ class ElectrumWindow(QMainWindow):
self.console.showMessage(self.wallet.banner)
# plugins that need to change the GUI do it here
self.run_hook('init')
self.run_hook('init_gui')
# plugins
@ -350,36 +350,33 @@ class ElectrumWindow(QMainWindow):
plugin_names = [name for a, name, b in pkgutil.iter_modules([pathname])]
plugin_names = filter( lambda name: os.path.exists(os.path.join(pathname,name+'.py')), plugin_names)
imp.load_module('electrum_plugins', fp, pathname, description)
self.plugins = map(lambda name: imp.load_source('electrum_plugins.'+name, os.path.join(pathname,name+'.py')), plugin_names)
plugins = map(lambda name: imp.load_source('electrum_plugins.'+name, os.path.join(pathname,name+'.py')), plugin_names)
else:
import electrum_plugins
plugin_names = [name for a, name, b in pkgutil.iter_modules(electrum_plugins.__path__)]
self.plugins = [ __import__('electrum_plugins.'+name, fromlist=['electrum_plugins']) for name in plugin_names]
plugins = [ __import__('electrum_plugins.'+name, fromlist=['electrum_plugins']) for name in plugin_names]
self.plugin_hooks = {}
for p in self.plugins:
self.plugins = []
for p in plugins:
try:
p.init(self)
self.plugins.append( p.Plugin(self) )
except:
print_msg("Error:cannot initialize plugin",p)
traceback.print_exc(file=sys.stdout)
def set_hook(self, name, callback):
h = self.plugin_hooks.get(name, [])
h.append(callback)
self.plugin_hooks[name] = h
def unset_hook(self, name, callback):
h = self.plugin_hooks.get(name,[])
if callback in h: h.remove(callback)
self.plugin_hooks[name] = h
def run_hook(self, name, *args):
args = (self,) + args
for cb in self.plugin_hooks.get(name,[]):
apply(cb, args)
for p in self.plugins:
if not p.is_enabled():
continue
try:
f = eval('p.'+name)
except:
continue
apply(f, args)
return
def set_label(self, name, text = None):
changed = False
old_text = self.wallet.labels.get(name)
@ -2002,7 +1999,7 @@ class ElectrumWindow(QMainWindow):
grid_plugins.setColumnStretch(0,1)
tabs.addTab(tab5, _('Plugins') )
def mk_toggle(cb, p):
return lambda: cb.setChecked(p.toggle(self))
return lambda: cb.setChecked(p.toggle())
for i, p in enumerate(self.plugins):
try:
name, description = p.get_info()

32
gui/plugins.py Normal file
View File

@ -0,0 +1,32 @@
class BasePlugin:
def get_info(self):
return self.fullname, self.description
def __init__(self, gui, name, fullname, description):
self.name = name
self.fullname = fullname
self.description = description
self.gui = gui
self.config = gui.config
def toggle(self):
enabled = not self.is_enabled()
self.set_enabled(enabled)
self.init_gui()
return enabled
def init_gui(self):
pass
def is_enabled(self):
return self.is_available() and self.config.get('use_'+self.name) is True
def is_available(self):
return True
def set_enabled(self, enabled):
self.config.set_key('use_'+self.name, enabled, True)

View File

@ -15,217 +15,185 @@ from electrum_gui.i18n import _
ALIAS_REGEXP = '^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$'
config = {}
def get_info():
return 'Aliases', _('Retrieve aliases using http.')
from electrum_gui import BasePlugin
class Plugin(BasePlugin):
def init(self):
global config
config = self.config
self.aliases = config.get('aliases', {}) # aliases for addresses
self.authorities = config.get('authorities', {}) # trusted addresses
self.receipts = config.get('receipts',{}) # signed URIs
do_enable(self, is_enabled())
def is_enabled():
return config.get('use_aliases') is True
def is_available():
return True
def __init__(self, gui):
BasePlugin.__init__(self, gui, 'aliases', 'Aliases', _('Retrieve aliases using http.'))
self.aliases = self.config.get('aliases', {}) # aliases for addresses
self.authorities = self.config.get('authorities', {}) # trusted addresses
self.receipts = self.config.get('receipts',{}) # signed URIs
def toggle(gui):
enabled = not is_enabled()
config.set_key('use_aliases', enabled, True)
do_enable(gui, enabled)
return enabled
def timer_actions(self):
if self.gui.payto_e.hasFocus():
return
r = unicode( self.gui.payto_e.text() )
if r != self.gui.previous_payto_e:
self.gui.previous_payto_e = r
r = r.strip()
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r):
try:
to_address = self.get_alias(r, True, self.gui.show_message, self.gui.question)
except:
return
if to_address:
s = r + ' <' + to_address + '>'
self.gui.payto_e.setText(s)
def do_enable(gui, enabled):
if enabled:
gui.set_hook('timer_actions', timer_actions)
gui.set_hook('set_url', set_url_hook)
gui.set_hook('update_contacts_tab', update_contacts_tab_hook)
gui.set_hook('update_completions', update_completions_hook)
gui.set_hook('create_contact_menu', create_contact_menu_hook)
else:
gui.unset_hook('timer_actions', timer_actions)
gui.unset_hook('set_url', set_url_hook)
gui.unset_hook('update_contacts_tab', update_contacts_tab_hook)
gui.unset_hook('update_completions', update_completions_hook)
gui.unset_hook('create_contact_menu', create_contact_menu_hook)
def get_alias(self, alias, interactive = False, show_message=None, question = None):
try:
target, signing_address, auth_name = read_alias(self, alias)
except BaseException, e:
# raise exception if verify fails (verify the chain)
if interactive:
show_message("Alias error: " + str(e))
return
print target, signing_address, auth_name
def timer_actions(self):
if self.payto_e.hasFocus():
return
r = unicode( self.payto_e.text() )
if r != self.previous_payto_e:
self.previous_payto_e = r
r = r.strip()
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r):
try:
to_address = get_alias(self, r, True, self.show_message, self.question)
except:
return
if to_address:
s = r + ' <' + to_address + '>'
self.payto_e.setText(s)
def get_alias(self, alias, interactive = False, show_message=None, question = None):
try:
target, signing_address, auth_name = read_alias(self, alias)
except BaseException, e:
# raise exception if verify fails (verify the chain)
if interactive:
show_message("Alias error: " + str(e))
return
print target, signing_address, auth_name
if auth_name is None:
a = self.aliases.get(alias)
if not a:
msg = "Warning: the alias '%s' is self-signed.\nThe signing address is %s.\n\nDo you want to add this alias to your list of contacts?"%(alias,signing_address)
if interactive and question( msg ):
self.aliases[alias] = (signing_address, target)
else:
target = None
else:
if signing_address != a[0]:
msg = "Warning: the key of alias '%s' has changed since your last visit! It is possible that someone is trying to do something nasty!!!\nDo you accept to change your trusted key?"%alias
if auth_name is None:
a = self.aliases.get(alias)
if not a:
msg = "Warning: the alias '%s' is self-signed.\nThe signing address is %s.\n\nDo you want to add this alias to your list of contacts?"%(alias,signing_address)
if interactive and question( msg ):
self.aliases[alias] = (signing_address, target)
else:
target = None
else:
if signing_address not in self.authorities.keys():
msg = "The alias: '%s' links to %s\n\nWarning: this alias was signed by an unknown key.\nSigning authority: %s\nSigning address: %s\n\nDo you want to add this key to your list of trusted keys?"%(alias,target,auth_name,signing_address)
if interactive and question( msg ):
self.authorities[signing_address] = auth_name
else:
target = None
if signing_address != a[0]:
msg = "Warning: the key of alias '%s' has changed since your last visit! It is possible that someone is trying to do something nasty!!!\nDo you accept to change your trusted key?"%alias
if interactive and question( msg ):
self.aliases[alias] = (signing_address, target)
else:
target = None
else:
if signing_address not in self.authorities.keys():
msg = "The alias: '%s' links to %s\n\nWarning: this alias was signed by an unknown key.\nSigning authority: %s\nSigning address: %s\n\nDo you want to add this key to your list of trusted keys?"%(alias,target,auth_name,signing_address)
if interactive and question( msg ):
self.authorities[signing_address] = auth_name
else:
target = None
if target:
self.aliases[alias] = (signing_address, target)
if target:
self.aliases[alias] = (signing_address, target)
return target
return target
def read_alias(self, alias):
import urllib
def read_alias(self, alias):
import urllib
m1 = re.match('([\w\-\.]+)@((\w[\w\-]+\.)+[\w\-]+)', alias)
m2 = re.match('((\w[\w\-]+\.)+[\w\-]+)', alias)
if m1:
url = 'https://' + m1.group(2) + '/bitcoin.id/' + m1.group(1)
elif m2:
url = 'https://' + alias + '/bitcoin.id'
else:
return ''
try:
lines = urllib.urlopen(url).readlines()
except:
return ''
# line 0
line = lines[0].strip().split(':')
if len(line) == 1:
auth_name = None
target = signing_addr = line[0]
else:
target, auth_name, signing_addr, signature = line
msg = "alias:%s:%s:%s"%(alias,target,auth_name)
print msg, signature
EC_KEY.verify_message(signing_addr, signature, msg)
# other lines are signed updates
for line in lines[1:]:
line = line.strip()
if not line: continue
line = line.split(':')
previous = target
print repr(line)
target, signature = line
EC_KEY.verify_message(previous, signature, "alias:%s:%s"%(alias,target))
if not is_valid(target):
raise ValueError("Invalid bitcoin address")
return target, signing_addr, auth_name
def set_url_hook(self, url, show_message, question):
payto, amount, label, message, signature, identity, url = util.parse_url(url)
if signature:
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', identity):
signing_address = get_alias(identity, True, show_message, question)
elif is_valid(identity):
signing_address = identity
m1 = re.match('([\w\-\.]+)@((\w[\w\-]+\.)+[\w\-]+)', alias)
m2 = re.match('((\w[\w\-]+\.)+[\w\-]+)', alias)
if m1:
url = 'https://' + m1.group(2) + '/bitcoin.id/' + m1.group(1)
elif m2:
url = 'https://' + alias + '/bitcoin.id'
else:
signing_address = None
if not signing_address:
return
return ''
try:
EC_KEY.verify_message(signing_address, signature, url )
self.receipt = (signing_address, signature, url)
lines = urllib.urlopen(url).readlines()
except:
show_message('Warning: the URI contains a bad signature.\nThe identity of the recipient cannot be verified.')
address = amount = label = identity = message = ''
return ''
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', address):
payto_address = get_alias(address, True, show_message, question)
if payto_address:
address = address + ' <' + payto_address + '>'
return address, amount, label, message, signature, identity, url
def update_contacts_tab_hook(self, l):
alias_targets = []
for alias, v in self.aliases.items():
s, target = v
alias_targets.append(target)
item = QTreeWidgetItem( [ target, alias, '-'] )
item.setBackgroundColor(0, QColor('lightgray'))
l.insertTopLevelItem(0,item)
item.setData(0,32,False)
item.setData(0,33,alias + ' <' + target + '>')
def update_completions_hook(self, l):
l[:] = l + self.aliases.keys()
def create_contact_menu_hook(self, menu, item):
label = unicode(item.text(1))
if label in self.aliases.keys():
addr = unicode(item.text(0))
label = unicode(item.text(1))
menu.addAction(_("View alias details"), lambda: show_contact_details(self, label))
menu.addAction(_("Delete alias"), lambda: delete_alias(self, label))
def show_contact_details(self, m):
a = self.aliases.get(m)
if a:
if a[0] in self.authorities.keys():
s = self.authorities.get(a[0])
# line 0
line = lines[0].strip().split(':')
if len(line) == 1:
auth_name = None
target = signing_addr = line[0]
else:
s = "self-signed"
msg = _('Alias:')+' '+ m + '\n'+_('Target address:')+' '+ a[1] + '\n\n'+_('Signed by:')+' ' + s + '\n'+_('Signing address:')+' ' + a[0]
QMessageBox.information(self, 'Alias', msg, 'OK')
target, auth_name, signing_addr, signature = line
msg = "alias:%s:%s:%s"%(alias,target,auth_name)
print msg, signature
EC_KEY.verify_message(signing_addr, signature, msg)
# other lines are signed updates
for line in lines[1:]:
line = line.strip()
if not line: continue
line = line.split(':')
previous = target
print repr(line)
target, signature = line
EC_KEY.verify_message(previous, signature, "alias:%s:%s"%(alias,target))
if not is_valid(target):
raise ValueError("Invalid bitcoin address")
return target, signing_addr, auth_name
def delete_alias(self, x):
if self.question(_("Do you want to remove")+" %s "%x +_("from your list of contacts?")):
if x in self.aliases:
self.aliases.pop(x)
self.update_history_tab()
self.update_contacts_tab()
self.update_completions()
def set_url(self, url, show_message, question):
payto, amount, label, message, signature, identity, url = util.parse_url(url)
if signature:
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', identity):
signing_address = get_alias(identity, True, show_message, question)
elif is_valid(identity):
signing_address = identity
else:
signing_address = None
if not signing_address:
return
try:
EC_KEY.verify_message(signing_address, signature, url )
self.receipt = (signing_address, signature, url)
except:
show_message('Warning: the URI contains a bad signature.\nThe identity of the recipient cannot be verified.')
address = amount = label = identity = message = ''
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', address):
payto_address = get_alias(address, True, show_message, question)
if payto_address:
address = address + ' <' + payto_address + '>'
return address, amount, label, message, signature, identity, url
def update_contacts_tab(self, l):
alias_targets = []
for alias, v in self.aliases.items():
s, target = v
alias_targets.append(target)
item = QTreeWidgetItem( [ target, alias, '-'] )
item.setBackgroundColor(0, QColor('lightgray'))
item.setData(0,32,False)
item.setData(0,33,alias + ' <' + target + '>')
l.insertTopLevelItem(0,item)
def update_completions(self, l):
l[:] = l + self.aliases.keys()
def create_contact_menu(self, menu, item):
label = unicode(item.text(1))
if label in self.aliases.keys():
addr = unicode(item.text(0))
label = unicode(item.text(1))
menu.addAction(_("View alias details"), lambda: self.show_contact_details(label))
menu.addAction(_("Delete alias"), lambda: delete_alias(self, label))
def show_contact_details(self, m):
a = self.aliases.get(m)
if a:
if a[0] in self.authorities.keys():
s = self.authorities.get(a[0])
else:
s = "self-signed"
msg = _('Alias:')+' '+ m + '\n'+_('Target address:')+' '+ a[1] + '\n\n'+_('Signed by:')+' ' + s + '\n'+_('Signing address:')+' ' + a[0]
QMessageBox.information(self.gui, 'Alias', msg, 'OK')
def delete_alias(self, x):
if self.gui.question(_("Do you want to remove")+" %s "%x +_("from your list of contacts?")):
if x in self.aliases:
self.aliases.pop(x)
self.update_history_tab()
self.update_contacts_tab()
self.update_completions()

View File

@ -8,8 +8,7 @@ import PyQt4.QtCore as QtCore
import PyQt4.QtGui as QtGui
from electrum_gui.qrcodewidget import QRCodeWidget
from electrum_gui import bmp, pyqrnative
from electrum_gui import bmp, pyqrnative, BasePlugin
from electrum_gui.i18n import _
@ -89,98 +88,95 @@ class QR_Window(QWidget):
self.qrw.set_addr( msg )
config = {}
def get_info():
return 'Point of Sale', _('Show QR code window and amounts requested for each address. Add menu item to request amount.')
def init(gui):
global config
config = gui.config
gui.requested_amounts = config.get('requested_amounts',{})
gui.merchant_name = config.get('merchant_name', 'Invoice')
gui.qr_window = None
do_enable(gui, is_enabled())
def is_enabled():
return config.get('pointofsale') is True
def is_available():
return True
def toggle(gui):
enabled = not is_enabled()
config.set_key('pointofsale', enabled, True)
do_enable(gui, enabled)
update_gui(gui)
return enabled
def do_enable(gui, enabled):
if enabled:
gui.expert_mode = True
gui.set_hook('item_changed', item_changed)
gui.set_hook('current_item_changed', recv_changed)
gui.set_hook('receive_menu', receive_menu)
gui.set_hook('update_receive_item', update_receive_item)
gui.set_hook('timer_actions', timer_actions)
gui.set_hook('close_main_window', close_main_window)
gui.set_hook('init', update_gui)
else:
gui.unset_hook('item_changed', item_changed)
gui.unset_hook('current_item_changed', recv_changed)
gui.unset_hook('receive_menu', receive_menu)
gui.unset_hook('update_receive_item', update_receive_item)
gui.unset_hook('timer_actions', timer_actions)
gui.unset_hook('close_main_window', close_main_window)
gui.unset_hook('init', update_gui)
def update_gui(gui):
enabled = is_enabled()
if enabled:
gui.receive_list.setHeaderLabels([ _('Address'), _('Label'), _('Balance'), _('Request')])
else:
gui.receive_list.setHeaderLabels([ _('Address'), _('Label'), _('Balance'), _('Tx')])
class Plugin(BasePlugin):
toggle_QR_window(gui, enabled)
def __init__(self, gui):
BasePlugin.__init__(self, gui, 'pointofsale', 'Point of Sale',
_('Show QR code window and amounts requested for each address. Add menu item to request amount.') )
self.qr_window = None
self.requested_amounts = self.config.get('requested_amounts',{})
self.merchant_name = self.config.get('merchant_name', 'Invoice')
def init_gui(self):
enabled = self.is_enabled()
if enabled:
self.gui.expert_mode = True
self.gui.receive_list.setHeaderLabels([ _('Address'), _('Label'), _('Balance'), _('Request')])
else:
self.gui.receive_list.setHeaderLabels([ _('Address'), _('Label'), _('Balance'), _('Tx')])
self.toggle_QR_window(enabled)
def close_main_window(self):
if self.qr_window:
self.qr_window.close()
self.qr_window = None
def toggle_QR_window(self, show):
if show and not self.qr_window:
self.qr_window = QR_Window(self.exchanger)
self.qr_window.setVisible(True)
self.qr_window_geometry = self.qr_window.geometry()
item = self.receive_list.currentItem()
if item:
address = str(item.text(1))
label = self.wallet.labels.get(address)
def timer_actions(self):
if self.qr_window:
self.qr_window.qrw.update_qr()
def toggle_QR_window(self, show):
if show and not self.qr_window:
self.qr_window = QR_Window(self.gui.exchanger)
self.qr_window.setVisible(True)
self.qr_window_geometry = self.qr_window.geometry()
item = self.gui.receive_list.currentItem()
if item:
address = str(item.text(1))
label = self.gui.wallet.labels.get(address)
amount, currency = self.requested_amounts.get(address, (None, None))
self.qr_window.set_content( address, label, amount, currency )
elif show and self.qr_window and not self.qr_window.isVisible():
self.qr_window.setVisible(True)
self.qr_window.setGeometry(self.qr_window_geometry)
elif not show and self.qr_window and self.qr_window.isVisible():
self.qr_window_geometry = self.qr_window.geometry()
self.qr_window.setVisible(False)
def update_receive_item(self, address, item):
try:
amount, currency = self.requested_amounts.get(address, (None, None))
except:
print "cannot get requested amount", address, self.requested_amounts.get(address)
amount, currency = None, None
self.requested_amounts.pop(address)
amount_str = amount + (' ' + currency if currency else '') if amount is not None else ''
item.setData(column_index,0,amount_str)
def current_item_changed(self, a):
if a is not None and self.qr_window and self.qr_window.isVisible():
address = str(a.text(0))
label = self.gui.wallet.labels.get(address)
try:
amount, currency = self.requested_amounts.get(address, (None, None))
except:
amount, currency = None, None
self.qr_window.set_content( address, label, amount, currency )
elif show and self.qr_window and not self.qr_window.isVisible():
self.qr_window.setVisible(True)
self.qr_window.setGeometry(self.qr_window_geometry)
elif not show and self.qr_window and self.qr_window.isVisible():
self.qr_window_geometry = self.qr_window.geometry()
self.qr_window.setVisible(False)
def item_changed(self, item, column):
if column == column_index:
def item_changed(self, item, column):
if column != column_index:
return
address = str( item.text(0) )
text = str( item.text(column) )
try:
seq = self.wallet.get_address_index(address)
seq = self.gui.wallet.get_address_index(address)
index = seq[-1]
except:
print "cannot get index"
@ -198,9 +194,9 @@ def item_changed(self, item, column):
currency = currency.upper()
self.requested_amounts[address] = (amount, currency)
self.wallet.config.set_key('requested_amounts', self.requested_amounts, True)
self.gui.wallet.config.set_key('requested_amounts', self.requested_amounts, True)
label = self.wallet.labels.get(address)
label = self.gui.wallet.labels.get(address)
if label is None:
label = self.merchant_name + ' - %04d'%(index+1)
self.wallet.labels[address] = label
@ -213,50 +209,20 @@ def item_changed(self, item, column):
if address in self.requested_amounts:
self.requested_amounts.pop(address)
self.update_receive_item(self.receive_list.currentItem())
def recv_changed(self, a):
if a is not None and self.qr_window and self.qr_window.isVisible():
address = str(a.text(0))
label = self.wallet.labels.get(address)
try:
amount, currency = self.requested_amounts.get(address, (None, None))
except:
amount, currency = None, None
self.qr_window.set_content( address, label, amount, currency )
self.gui.update_receive_item(self.gui.receive_list.currentItem())
def edit_amount(self):
l = self.receive_list
item = l.currentItem()
item.setFlags(Qt.ItemIsEditable|Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
l.editItem( item, column_index )
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
def receive_menu(self, menu):
menu.addAction(_("Request amount"), lambda: edit_amount(self))
def edit_amount(self):
l = self.gui.receive_list
item = l.currentItem()
item.setFlags(Qt.ItemIsEditable|Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
l.editItem( item, column_index )
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
def receive_menu(self, menu):
menu.addAction(_("Request amount"), self.edit_amount)
def update_receive_item(self, address, item):
try:
amount, currency = self.requested_amounts.get(address, (None, None))
except:
print "cannot get requested amount", address, self.requested_amounts.get(address)
amount, currency = None, None
self.requested_amounts.pop(address)
amount_str = amount + (' ' + currency if currency else '') if amount is not None else ''
item.setData(column_index,0,amount_str)
def close_main_window(self):
if self.qr_window:
self.qr_window.close()
self.qr_window = None
def timer_actions(self):
if self.qr_window:
self.qr_window.qrw.update_qr()

View File

@ -8,55 +8,62 @@ try:
except ImportError:
zbar = None
from electrum_gui import BasePlugin
class Plugin(BasePlugin):
def __init__(self, gui):
BasePlugin.__init__(self, gui, 'qrscans', 'QR scans', "QR Scans.\nInstall the zbar package to enable this plugin")
def is_available(self):
if not zbar:
return False
try:
proc = zbar.Processor()
proc.init()
except zbar.SystemError:
# Cannot open video device
return False
return True
def init(gui):
if is_enabled():
gui.set_hook('create_send_tab', create_send_tab)
else:
gui.unset_hook('create_send_tab', create_send_tab)
def get_info():
return 'QR scans', "QR Scans.\nInstall the zbar package to enable this plugin"
def is_enabled():
return is_available()
def toggle(gui):
return is_enabled()
def create_send_tab(self, grid):
b = QPushButton(_("Scan QR code"))
b.clicked.connect(self.fill_from_qr)
grid.addWidget(b, 1, 5)
def is_available():
if not zbar:
return False
try:
def scan_qr(self):
proc = zbar.Processor()
proc.init()
except zbar.SystemError:
# Cannot open video device
return False
proc.visible = True
return True
while True:
try:
proc.process_one()
except:
# User closed the preview window
return {}
def scan_qr():
proc = zbar.Processor()
proc.init()
proc.visible = True
while True:
try:
proc.process_one()
except:
# User closed the preview window
return {}
for r in proc.results:
if str(r.type) != 'QRCODE':
continue
return parse_uri(r.data)
for r in proc.results:
if str(r.type) != 'QRCODE':
continue
return parse_uri(r.data)
def fill_from_qr(self):
qrcode = self.scan_qr()
if 'address' in qrcode:
self.gui.payto_e.setText(qrcode['address'])
if 'amount' in qrcode:
self.gui.amount_e.setText(str(qrcode['amount']))
if 'label' in qrcode:
self.gui.message_e.setText(qrcode['label'])
if 'message' in qrcode:
self.gui.message_e.setText("%s (%s)" % (self.gui.message_e.text(), qrcode['message']))
def parse_uri(uri):
if ':' not in uri:
# It's just an address (not BIP21)
@ -82,24 +89,6 @@ def parse_uri(uri):
def fill_from_qr(self):
qrcode = scan_qr()
if 'address' in qrcode:
self.payto_e.setText(qrcode['address'])
if 'amount' in qrcode:
self.amount_e.setText(str(qrcode['amount']))
if 'label' in qrcode:
self.message_e.setText(qrcode['label'])
if 'message' in qrcode:
self.message_e.setText("%s (%s)" % (self.message_e.text(), qrcode['message']))
def create_send_tab(gui, grid):
if is_available():
b = QPushButton(_("Scan QR code"))
b.clicked.connect(lambda: fill_from_qr(gui))
grid.addWidget(b, 1, 5)
if __name__ == '__main__':