From: thomasv Date: Fri, 15 Mar 2013 08:58:05 +0000 (+0100) Subject: derive plugins from BasePlugin class X-Git-Url: https://git.novaco.in/?a=commitdiff_plain;h=bd1cdc9bfb6b82281414609068f17587389a1f9f;p=electrum-nvc.git derive plugins from BasePlugin class --- diff --git a/gui/__init__.py b/gui/__init__.py index afa8ca4..9bccd2a 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -1 +1,2 @@ # do not remove this file +from plugins import BasePlugin diff --git a/gui/gui_classic.py b/gui/gui_classic.py index 1d80132..4994438 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -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() diff --git a/gui/plugins.py b/gui/plugins.py new file mode 100644 index 0000000..bb00bab --- /dev/null +++ b/gui/plugins.py @@ -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) + diff --git a/plugins/aliases.py b/plugins/aliases.py index f8a3a5b..c44df3f 100644 --- a/plugins/aliases.py +++ b/plugins/aliases.py @@ -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.') - -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 toggle(gui): - enabled = not is_enabled() - config.set_key('use_aliases', enabled, True) - do_enable(gui, enabled) - return enabled - - -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 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 + +from electrum_gui import BasePlugin +class Plugin(BasePlugin): + + 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 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 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 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 - - - -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 + return target + + + + 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: - 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 + '>' + # 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(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 = '' - return address, amount, label, message, signature, identity, url + 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_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_hook(self, l): - l[:] = l + self.aliases.keys() + def update_completions(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)) + def create_contact_menu(self, menu, item): 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]) - 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') - - -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() + 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() diff --git a/plugins/pointofsale.py b/plugins/pointofsale.py index 29dedeb..7cc8c77 100644 --- a/plugins/pointofsale.py +++ b/plugins/pointofsale.py @@ -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()) +class Plugin(BasePlugin): -def is_enabled(): - return config.get('pointofsale') is True + 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 is_available(): - return True + 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')]) -def toggle(gui): - enabled = not is_enabled() - config.set_key('pointofsale', enabled, True) - do_enable(gui, enabled) - update_gui(gui) - return enabled + self.toggle_QR_window(enabled) + + def close_main_window(self): + if self.qr_window: + self.qr_window.close() + self.qr_window = None -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 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_gui(gui): - enabled = is_enabled() - if enabled: - gui.receive_list.setHeaderLabels([ _('Address'), _('Label'), _('Balance'), _('Request')]) - else: - gui.receive_list.setHeaderLabels([ _('Address'), _('Label'), _('Balance'), _('Tx')]) - toggle_QR_window(gui, enabled) - - -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 update_receive_item(self, address, item): + try: 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) + except: + print "cannot get requested amount", address, self.requested_amounts.get(address) + amount, currency = None, None + self.requested_amounts.pop(address) - 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) + 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 ) -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()) - + self.gui.update_receive_item(self.gui.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 ) -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 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"), lambda: edit_amount(self)) - - -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 receive_menu(self, menu): + menu.addAction(_("Request amount"), self.edit_amount) -def timer_actions(self): - if self.qr_window: - self.qr_window.qrw.update_qr() diff --git a/plugins/qrscanner.py b/plugins/qrscanner.py index cc16484..f66e60b 100644 --- a/plugins/qrscanner.py +++ b/plugins/qrscanner.py @@ -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 - - return True + 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) + -def scan_qr(): - proc = zbar.Processor() - proc.init() - proc.visible = True + 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'])) + - 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) - 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__':