From 0c6a24c6be8ed41b3a7081b51fa5183499f4b57a Mon Sep 17 00:00:00 2001 From: rdymac Date: Tue, 12 Mar 2013 01:33:08 +0100 Subject: [PATCH 01/15] Successfully tricky word --- gui/gui_classic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index 4bd0cac45..108acf357 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -1706,7 +1706,7 @@ class ElectrumWindow(QMainWindow): if fileName: with open(fileName, "w+") as f: f.write(json.dumps(tx.as_dict(),indent=4) + '\n') - self.show_message(_("Transaction saved succesfully")) + self.show_message(_("Transaction saved successfully")) if dialog: dialog.done(0) except BaseException, e: @@ -1716,7 +1716,7 @@ class ElectrumWindow(QMainWindow): def send_raw_transaction(self, raw_tx, dialog = ""): result, result_message = self.wallet.sendtx( raw_tx ) if result: - self.show_message("Transaction succesfully sent: %s" % (result_message)) + self.show_message("Transaction successfully sent: %s" % (result_message)) if dialog: dialog.done(0) else: From 7fe0130a959e2a450f3e19681ed7bcef8392e6bf Mon Sep 17 00:00:00 2001 From: rdymac Date: Tue, 12 Mar 2013 02:02:09 +0100 Subject: [PATCH 02/15] Colon not in use I think that colon doesn't fit there, there's no text after that colon ':' or code to be shown as variable '%s' after it. --- gui/gui_classic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index 4bd0cac45..09f590481 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -1679,7 +1679,7 @@ class ElectrumWindow(QMainWindow): if not tx_dict["complete"]: assert "input_info" in tx_dict.keys() except: - QMessageBox.critical(None, "Unable to parse transaction", _("Electrum was unable to parse your transaction:")) + QMessageBox.critical(None, "Unable to parse transaction", _("Electrum was unable to parse your transaction")) return None return tx_dict From b1a727ef49624f11984b79b12d8ec1f709748006 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 13:48:16 +0100 Subject: [PATCH 03/15] updates fro android --- electrum | 6 ++++-- make_packages | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/electrum b/electrum index ce81f032c..c245a2a36 100755 --- a/electrum +++ b/electrum @@ -34,8 +34,10 @@ except ImportError: sys.exit("Error: AES does not seem to be installed. Try 'sudo pip install slowaes'") +is_android = 'ANDROID_DATA' in os.environ + # load local module as electrum -if os.path.exists("lib"): +if os.path.exists("lib") or is_android: import imp fp, pathname, description = imp.find_module('lib') imp.load_module('electrum', fp, pathname, description) @@ -89,7 +91,7 @@ if __name__ == '__main__': set_verbosity(options.verbose) # config is an object passed to the various constructors (wallet, interface, gui) - if 'ANDROID_DATA' in os.environ: + if is_android: config_options = {'wallet_path':"/sdcard/electrum.dat", 'portable':True, 'verbose':True, 'gui':'android'} else: config_options = eval(str(options)) diff --git a/make_packages b/make_packages index f079ab4a9..936c48a91 100755 --- a/make_packages +++ b/make_packages @@ -20,10 +20,13 @@ if __name__ == '__main__': # android os.system('rm -rf dist/e4a-%s'%version) os.mkdir('dist/e4a-%s'%version) - shutil.copyfile("electrum",'dist/e4a-%s/electrum.py'%version) + shutil.copyfile("electrum",'dist/e4a-%s/e4a.py'%version) shutil.copytree("ecdsa",'dist/e4a-%s/ecdsa'%version) shutil.copytree("aes",'dist/e4a-%s/aes'%version) - shutil.copytree("lib",'dist/e4a-%s/electrum'%version) + shutil.copytree("lib",'dist/e4a-%s/lib'%version) + os.mkdir('dist/e4a-%s/gui'%version) + shutil.copy("gui/gui_android.py",'dist/e4a-%s/gui'%version) + shutil.copy("gui/__init__.py",'dist/e4a-%s/gui'%version) os.chdir("dist") # create the zip file From f0c81abafbeafc6bc152bd8b6830597a6da76155 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 14:12:27 +0100 Subject: [PATCH 04/15] always enable auto_cycle for android --- electrum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electrum b/electrum index c245a2a36..16f942650 100755 --- a/electrum +++ b/electrum @@ -92,7 +92,7 @@ if __name__ == '__main__': # config is an object passed to the various constructors (wallet, interface, gui) if is_android: - config_options = {'wallet_path':"/sdcard/electrum.dat", 'portable':True, 'verbose':True, 'gui':'android'} + config_options = {'wallet_path':"/sdcard/electrum.dat", 'portable':True, 'verbose':True, 'gui':'android', 'auto_cycle':True} else: config_options = eval(str(options)) for k, v in config_options.items(): From cbaadf782f40a381e758a4f27c19dbebab434f53 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 14:34:35 +0100 Subject: [PATCH 05/15] rm extra space --- gui/gui_classic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index 6b47ea90b..d9d7fca44 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -1759,7 +1759,7 @@ class ElectrumWindow(QMainWindow): l = QGridLayout() dialog.setLayout(l) - l.addWidget(QLabel(_("Transaction status: ")), 3,0) + l.addWidget(QLabel(_("Transaction status:")), 3,0) l.addWidget(QLabel(_("Actions")), 4,0) if tx_dict["complete"] == False: From 80f02401acba9d5e2e3da80fe6f28fdf8a357ed3 Mon Sep 17 00:00:00 2001 From: rdymac Date: Tue, 12 Mar 2013 16:20:17 +0100 Subject: [PATCH 06/15] Latest translation version Updated the wiki page for the latest version for the upcoming version release --- lib/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/version.py b/lib/version.py index 02b042330..1ed992c93 100644 --- a/lib/version.py +++ b/lib/version.py @@ -1,4 +1,4 @@ ELECTRUM_VERSION = "1.7" # version of the client package PROTOCOL_VERSION = '0.6' # protocol version requested SEED_VERSION = 4 # bump this every time the seed generation is modified -TRANSLATION_ID = 3958 # version of the wiki page +TRANSLATION_ID = 3992 # version of the wiki page From 7d0e491a078b53e4c6126b064eb4775c3bf2727e Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 16:29:19 +0100 Subject: [PATCH 07/15] adding new languages --- gui/i18n.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gui/i18n.py b/gui/i18n.py index 9436219c5..d2a8ddef5 100644 --- a/gui/i18n.py +++ b/gui/i18n.py @@ -44,10 +44,12 @@ languages = { 'es':_('Spanish'), 'fr':_('French'), 'it':_('Italian'), + 'ja':_('Japanese'), 'lv':_('Latvian'), 'nl':_('Dutch'), 'ru':_('Russian'), 'sl':_('Slovenian'), + 'ta':_('Tamil'), 'vi':_('Vietnamese'), 'zh':_('Chinese') } From 581bf89ba0b26df968748e57adaf8cee8c020311 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 17:10:35 +0100 Subject: [PATCH 08/15] define method set_label in classic gui --- gui/gui_classic.py | 49 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index d9d7fca44..829e5469a 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -362,6 +362,20 @@ class ElectrumWindow(QMainWindow): apply(cb, args) + def set_label(self, name, text = None): + changed = False + old_text = self.wallet.labels.get(name) + if text: + if old_text != text: + self.wallet.labels[name] = text + changed = True + else: + if old_text: + self.wallet.labels.pop(name) + changed = True + return changed + + # custom wrappers for getOpenFileName and getSaveFileName, that remember the path selected by the user def getOpenFileName(self, title, filter = None): directory = self.config.get('io_dir', os.path.expanduser('~')) @@ -534,13 +548,11 @@ class ElectrumWindow(QMainWindow): self.is_edit=True tx_hash = str(item.data(0, Qt.UserRole).toString()) tx = self.wallet.transactions.get(tx_hash) - s = self.wallet.labels.get(tx_hash) text = unicode( item.text(2) ) + self.set_label(tx_hash, text) if text: - self.wallet.labels[tx_hash] = text item.setForeground(2, QBrush(QColor('black'))) else: - if s: self.wallet.labels.pop(tx_hash) text = self.wallet.get_default_label(tx_hash) item.setText(2, text) item.setForeground(2, QBrush(QColor('gray'))) @@ -574,25 +586,15 @@ class ElectrumWindow(QMainWindow): text = unicode( item.text(column_label) ) changed = False - if text: - if text not in self.wallet.aliases.keys(): - old_addr = self.wallet.labels.get(text) - if old_addr != addr: - self.wallet.labels[addr] = text - changed = True - else: - print_error("Error: This is one of your aliases") - label = self.wallet.labels.get(addr,'') - item.setText(column_label, QString(label)) + if text in self.wallet.aliases.keys(): + print_error("Error: This is one of your aliases") + label = self.wallet.labels.get(addr,'') + item.setText(column_label, QString(label)) else: - s = self.wallet.labels.get(addr) - if s: - self.wallet.labels.pop(addr) - changed = True - - if changed: - self.update_history_tab() - self.update_completions() + changed = self.set_label(addr, text) + if changed: + self.update_history_tab() + self.update_completions() self.current_item_changed(item) @@ -809,7 +811,7 @@ class ElectrumWindow(QMainWindow): self.run_hook('send_tx', (self.wallet, self, tx)) if label: - self.wallet.labels[tx.hash()] = label + self.set_label(tx.hash(), label) if tx.is_complete: h = self.wallet.send_tx(tx) @@ -1023,8 +1025,7 @@ class ElectrumWindow(QMainWindow): if self.question(_("Do you want to remove")+" %s "%x +_("from your list of contacts?")): if not is_alias and x in self.wallet.addressbook: self.wallet.addressbook.remove(x) - if x in self.wallet.labels.keys(): - self.wallet.labels.pop(x) + self.set_label(x, None) elif is_alias and x in self.wallet.aliases: self.wallet.aliases.pop(x) self.update_history_tab() From 92ea46f9f670f54821bd1a7bbad3af476778cc24 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 17:22:30 +0100 Subject: [PATCH 09/15] add set_label hook --- gui/gui_classic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index 829e5469a..ddab79734 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -373,6 +373,7 @@ class ElectrumWindow(QMainWindow): if old_text: self.wallet.labels.pop(name) changed = True + run_hook('set_label', name, text, changed) return changed From 8b08eb541aa5dc682a79e1ba031b3258153610d4 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 17:34:06 +0100 Subject: [PATCH 10/15] do not request banner twice --- lib/wallet.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/wallet.py b/lib/wallet.py index feff4fc1e..ba64ad925 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -1197,9 +1197,6 @@ class WalletSynchronizer(threading.Thread): while not self.interface.is_connected: time.sleep(1) - # request banner, because 'connected' event happens before this thread is started - self.interface.send([('server.banner',[])],'synchronizer') - # subscriptions self.subscribe_to_addresses(self.wallet.addresses(True)) From 2de6db84e45c4db51ae693d43bd05aed10db63a6 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 17:37:19 +0100 Subject: [PATCH 11/15] monospace font in console --- gui/qt_console.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gui/qt_console.py b/gui/qt_console.py index ff579f09a..49d4148ad 100644 --- a/gui/qt_console.py +++ b/gui/qt_console.py @@ -1,12 +1,19 @@ # source: http://stackoverflow.com/questions/2758159/how-to-embed-a-python-interpreter-in-a-pyqt-widget import sys, os, re -import traceback +import traceback, platform from PyQt4 import QtCore from PyQt4 import QtGui from electrum import util +if platform.system() == 'Windows': + MONOSPACE_FONT = 'Lucida Console' +elif platform.system() == 'Darwin': + MONOSPACE_FONT = 'Monaco' +else: + MONOSPACE_FONT = 'monospace' + class Console(QtGui.QPlainTextEdit): def __init__(self, prompt='>> ', startup_message='', parent=None): @@ -20,7 +27,7 @@ class Console(QtGui.QPlainTextEdit): self.setGeometry(50, 75, 600, 400) self.setWordWrapMode(QtGui.QTextOption.WrapAnywhere) self.setUndoRedoEnabled(False) - self.document().setDefaultFont(QtGui.QFont("monospace", 10, QtGui.QFont.Normal)) + self.document().setDefaultFont(QtGui.QFont(MONOSPACE_FONT, 10, QtGui.QFont.Normal)) self.showMessage(startup_message) self.updateNamespace({'run':self.run_script}) From 10bfcb918b5882b91547cefb9cd2fa3dec08b2b1 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 17:54:26 +0100 Subject: [PATCH 12/15] replace 'ElectrumKeyID' with more general 'KeyID' field in transactions --- lib/bitcoin.py | 2 +- lib/wallet.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/bitcoin.py b/lib/bitcoin.py index a3403fef1..1bfee8c92 100644 --- a/lib/bitcoin.py +++ b/lib/bitcoin.py @@ -825,7 +825,7 @@ class Transaction: for i in self.inputs: e = { 'txid':i['tx_hash'], 'vout':i['index'], 'scriptPubKey':i.get('raw_output_script'), - 'electrumKeyID':i.get('electrumKeyID'), + 'KeyID':i.get('KeyID'), 'redeemScript':i.get('redeemScript'), 'signatures':i.get('signatures'), 'pubkeys':i.get('pubkeys'), diff --git a/lib/wallet.py b/lib/wallet.py index ba64ad925..2fbae8440 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -256,7 +256,7 @@ class Wallet: if item.get('txid') == txin['tx_hash'] and item.get('vout') == txin['index']: txin['raw_output_script'] = item['scriptPubKey'] txin['redeemScript'] = item.get('redeemScript') - txin['electrumKeyID'] = item.get('electrumKeyID') + txin['KeyID'] = item.get('KeyID') break else: for item in unspent_coins: @@ -268,8 +268,9 @@ class Wallet: raise # find the address: - if txin.get('electrumKeyID'): - account, sequence = txin.get('electrumKeyID') + if txin.get('KeyID'): + account, name, sequence = txin.get('KeyID') + if name != 'Electrum': continue sec = self.sequences[account].get_private_key(sequence, seed) addr = self.sequences[account].get_address(sequence) txin['address'] = addr @@ -771,7 +772,7 @@ class Wallet: pk_addresses.append(address) continue account, sequence = self.get_address_index(address) - txin['electrumKeyID'] = (account, sequence) # used by the server to find the key + txin['KeyID'] = (account, 'Electrum', sequence) # used by the server to find the key pk_addr, redeemScript = self.sequences[account].get_input_info(sequence) if redeemScript: txin['redeemScript'] = redeemScript pk_addresses.append(pk_addr) From 6b9b8508d27b46a270be2d5163da812a9729959f Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 17:55:34 +0100 Subject: [PATCH 13/15] self.run_hook --- gui/gui_classic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index ddab79734..bb9cf7ff7 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -373,7 +373,7 @@ class ElectrumWindow(QMainWindow): if old_text: self.wallet.labels.pop(name) changed = True - run_hook('set_label', name, text, changed) + self.run_hook('set_label', name, text, changed) return changed From 06315dd9112ebbb2b8848ed674f679dd83fa98a7 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 18:07:17 +0100 Subject: [PATCH 14/15] always pass 'self' to hooks --- gui/gui_classic.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index bb9cf7ff7..c41113c07 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -357,7 +357,8 @@ class ElectrumWindow(QMainWindow): if callback in h: h.remove(callback) self.plugin_hooks[name] = h - def run_hook(self, name, args): + def run_hook(self, name, args = ()): + args = (self,) + args for cb in self.plugin_hooks.get(name,[]): apply(cb, args) @@ -373,7 +374,7 @@ class ElectrumWindow(QMainWindow): if old_text: self.wallet.labels.pop(name) changed = True - self.run_hook('set_label', name, text, changed) + self.run_hook('set_label', (name, text, changed)) return changed @@ -397,14 +398,14 @@ class ElectrumWindow(QMainWindow): def close(self): QMainWindow.close(self) - self.run_hook('close_main_window', (self,)) + self.run_hook('close_main_window') def connect_slots(self, sender): self.connect(sender, QtCore.SIGNAL('timersignal'), self.timer_actions) self.previous_payto_e='' def timer_actions(self): - self.run_hook('timer_actions', (self,)) + self.run_hook('timer_actions') if self.payto_e.hasFocus(): return @@ -599,11 +600,11 @@ class ElectrumWindow(QMainWindow): self.current_item_changed(item) - self.run_hook('item_changed',(self, item, column)) + self.run_hook('item_changed', (item, column)) def current_item_changed(self, a): - self.run_hook('current_item_changed',(self, a)) + self.run_hook('current_item_changed', (a,)) @@ -749,7 +750,7 @@ class ElectrumWindow(QMainWindow): self.amount_e.textChanged.connect(lambda: entry_changed(False) ) self.fee_e.textChanged.connect(lambda: entry_changed(True) ) - self.run_hook('create_send_tab',(self,grid)) + self.run_hook('create_send_tab', (grid,)) return w2 @@ -809,7 +810,7 @@ class ElectrumWindow(QMainWindow): self.show_message(str(e)) return - self.run_hook('send_tx', (self.wallet, self, tx)) + self.run_hook('send_tx', (tx,)) if label: self.set_label(tx.hash(), label) @@ -1005,7 +1006,7 @@ class ElectrumWindow(QMainWindow): t = _("Unprioritize") if addr in self.wallet.prioritized_addresses else _("Prioritize") menu.addAction(t, lambda: self.toggle_priority(addr)) - self.run_hook('receive_menu', (self, menu,)) + self.run_hook('receive_menu', (menu,)) menu.exec_(self.receive_list.viewport().mapToGlobal(position)) @@ -1062,7 +1063,7 @@ class ElectrumWindow(QMainWindow): label = self.wallet.labels.get(address,'') item.setData(1,0,label) - self.run_hook('update_receive_item', (self, address, item)) + self.run_hook('update_receive_item', (address, item)) c, u = self.wallet.get_addr_balance(address) balance = format_satoshis( c + u, False, self.wallet.num_zeros ) From 2c1ae1ba18b04ef3a98176f29f4a1c887abdbed3 Mon Sep 17 00:00:00 2001 From: thomasv Date: Tue, 12 Mar 2013 18:40:21 +0100 Subject: [PATCH 15/15] add a hook at the end of the gui constructor --- gui/gui_classic.py | 3 +++ plugins/pointofsale.py | 29 +++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index c41113c07..e63bf0b1a 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -325,6 +325,9 @@ class ElectrumWindow(QMainWindow): # set initial message self.console.showMessage(self.wallet.banner) + # plugins that need to change the GUI do it here + self.run_hook('init') + # plugins def init_plugins(self): diff --git a/plugins/pointofsale.py b/plugins/pointofsale.py index 87d15147b..29dedeb9d 100644 --- a/plugins/pointofsale.py +++ b/plugins/pointofsale.py @@ -103,6 +103,7 @@ def init(gui): 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 @@ -110,35 +111,47 @@ def is_enabled(): 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 + - if not is_enabled(): +def do_enable(gui, enabled): + if enabled: gui.expert_mode = True - gui.receive_list.setHeaderLabels([ _('Address'), _('Label'), _('Balance'), _('Request')]) 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) - enabled = True + gui.set_hook('init', update_gui) else: - gui.receive_list.setHeaderLabels([ _('Address'), _('Label'), _('Balance'), _('Tx')]) 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) - enabled = False + 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')]) - config.set_key('pointofsale', enabled, True) toggle_QR_window(gui, enabled) - return enabled - def toggle_QR_window(self, show): if show and not self.qr_window: self.qr_window = QR_Window(self.exchanger)