tMore work on label cloud plugin - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 9df4451c6f7847203a5b24b152b0912e7c910562 DIR parent ad88b296bb0d99b918c4cafe9e6843feacb8ddae HTML Author: Maran <maran.hidskes@gmail.com> Date: Tue, 12 Mar 2013 21:20:18 +0100 More work on label cloud plugin Diffstat: M gui/gui_classic.py | 5 +++-- M plugins/labels.py | 141 ++++++++++++++++++++++--------- 2 files changed, 105 insertions(+), 41 deletions(-) --- DIR diff --git a/gui/gui_classic.py b/gui/gui_classic.py t@@ -374,7 +374,8 @@ 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 t@@ -2110,7 +2111,7 @@ class ElectrumWindow(QMainWindow): self.config.set_key('currency', cur_request, True) self.update_wallet() - self.run_hook('close_setting_dialog', (self,)) + self.run_hook('close_settings_dialog', (self,)) if need_restart: QMessageBox.warning(self, _('Success'), _('Please restart Electrum to activate the new GUI settings'), _('OK')) DIR diff --git a/plugins/labels.py b/plugins/labels.py t@@ -1,4 +1,5 @@ from electrum.util import print_error +from electrum_gui.i18n import _ import httplib, urllib import hashlib import json t@@ -14,83 +15,136 @@ import PyQt4.QtCore as QtCore import PyQt4.QtGui as QtGui target_host = 'labelectrum.herokuapp.com' +config = {} + +def is_available(): + return True + +def auth_token(): + global config + return config.get("plugin_label_api_key") def init(gui): """If you want to give this a spin create a account at the target_host url and put it in your user dir config file with the label_api_key.""" - global auth_token - auth_token = gui.config.get("label_api_key") - if not auth_token: - return + global config + config = gui.config + + if config.get('plugin_label_enabled'): + gui.set_hook('create_settings_tab', add_settings_tab) + gui.set_hook('close_settings_dialog', close_settings_dialog) + + if not auth_token(): + return - cloud_wallet = CloudWallet(gui.wallet) - gui.set_hook('create_settings_tab', add_settings_tab) - gui.set_hook('label_changed', label_changed) - cloud_wallet.full_pull() + cloud_wallet = CloudWallet(gui.wallet) + gui.set_hook('set_label', set_label) -def wallet_id(wallet): - return hashlib.sha256(str(wallet.get_master_public_key())).digest().encode('hex') + cloud_wallet.full_pull() + +def wallet_id(): + global config + return hashlib.sha256(str(config.get("master_public_key"))).digest().encode('hex') + +def set_label(item,label, changed): + if not changed: + return -def label_changed(gui,item,label): print "Label changed! Item: %s Label: %s label" % ( item, label) - global auth_token, target_host + global target_host hashed = hashlib.sha256(item).digest().encode('hex') bundle = {"label": {"external_id": hashed, "text": label}} params = json.dumps(bundle) connection = httplib.HTTPConnection(target_host) - wallet = wallet_id(gui.wallet) - connection.request("POST", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet, auth_token)), params, {'Content-Type': 'application/json'}) + connection.request("POST", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet_id(), auth_token())), params, {'Content-Type': 'application/json'}) response = connection.getresponse() if response.reason == httplib.responses[httplib.NOT_FOUND]: return response = json.loads(response.read()) +def close_settings_dialog(gui): + global config + + # When you enable the plugin for the first time this won't exist. + if is_enabled(): + if hasattr(gui, 'auth_token_edit'): + config.set_key("plugin_label_api_key", str(gui.auth_token_edit.text())) + else: + QMessageBox.information(None, _("Cloud plugin loaded"), _("Please open the settings again to configure the label-cloud plugin.")) + def add_settings_tab(gui, tabs): - cloud_tab = QWidget() - layout = QGridLayout(cloud_tab) - layout.addWidget(QLabel("API Key: "),0,0) - layout.addWidget(QLineEdit(auth_token), 0,2) + def check_for_api_key(api_key): + global config + if api_key and len(api_key) > 12: + config.set_key("plugin_label_api_key", str(gui.auth_token_edit.text())) + upload.setEnabled(True) + download.setEnabled(True) + else: + upload.setEnabled(False) + download.setEnabled(False) + + cloud_tab = QWidget() + layout = QGridLayout(cloud_tab) + layout.addWidget(QLabel("API Key: "),0,0) - layout.addWidget(QLabel("Label sync options: "),1,0) + # TODO: I need to add it to the Electrum GUI here so I can retrieve it later when the settings dialog is closed, is there a better way to do this? + gui.auth_token_edit = QLineEdit(auth_token()) + gui.auth_token_edit.textChanged.connect(check_for_api_key) - upload = QPushButton("Force upload") - upload.clicked.connect(lambda: full_push(gui.wallet)) - layout.addWidget(upload, 1,1) + layout.addWidget(gui.auth_token_edit, 0,1,1,2) + layout.addWidget(QLabel("Label cloud options: "),1,0) - download = QPushButton("Force download") - download.clicked.connect(lambda: full_pull(gui.wallet)) - layout.addWidget(download, 1,2) + upload = QPushButton("Force upload") + upload.clicked.connect(lambda: full_push(gui.wallet)) + layout.addWidget(upload, 1,1) - tabs.addTab(cloud_tab, "Label cloud") + download = QPushButton("Force download") + download.clicked.connect(lambda: full_pull(gui.wallet)) + layout.addWidget(download, 1,2) + + gui.cloud_tab = cloud_tab + check_for_api_key(auth_token()) + + tabs.addTab(cloud_tab, "Label cloud") def full_push(wallet): cloud_wallet = CloudWallet(wallet) cloud_wallet.full_push() - print "Labels pushed" + QMessageBox.information(None, _("Labels synced"), _("Your labels have been uploaded.")) def full_pull(wallet): cloud_wallet = CloudWallet(wallet) cloud_wallet.full_pull(True) - print "Labels pulled, please restart your client" + QMessageBox.information(None, _("Labels synced"), _("Your labels have been synced, please restart Electrum for the changes to take effect.")) def show(): print 'showing' def get_info(): - return 'Label sync', "Syncs your labels with LabElectrum. Labels are not encrypted, transactions and addresses are however. This code might increase the load of your wallet with a few micoseconds as it will sync labels on each startup." + return 'Label sync', "Syncs your labels with 'the cloud'. Labels are not encrypted, transactions and addresses are however. This code might increase the load of your wallet with a few micoseconds as it will sync labels on each startup." def is_enabled(): - return True + return config.get('plugin_label_enabled') is True def toggle(gui): - return is_enabled() + if not is_enabled(): + enabled = True + else: + enabled = False + gui.unset_hook('create_settings_tab', add_settings_tab) + gui.unset_hook('close_settings_dialog', close_settings_dialog) + + config.set_key('plugin_label_enabled', enabled, True) + + if enabled: + init(gui) + return enabled # This can probably be refactored into plain top level methods instead of a class class CloudWallet(): def __init__(self, wallet): - self.mpk = hashlib.sha256(str(wallet.get_master_public_key())).digest().encode('hex') self.labels = wallet.labels self.transactions = wallet.transactions t@@ -101,11 +155,10 @@ class CloudWallet(): self.addresses = addresses - def full_pull(self, force = False): - global target_host, auth_token + global target_host connection = httplib.HTTPConnection(target_host) - connection.request("GET", ("/api/wallets/%s/labels.json?auth_token=%s" % (self.mpk, auth_token)),"", {'Content-Type': 'application/json'}) + connection.request("GET", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet_id(), auth_token())),"", {'Content-Type': 'application/json'}) response = connection.getresponse() if response.reason == httplib.responses[httplib.NOT_FOUND]: return t@@ -114,6 +167,10 @@ class CloudWallet(): except ValueError as e: return + if "error" in response: + QMessageBox.warning(None, _("Error"),_("Could not sync labels: %s" % response["error"])) + return + for label in response: for key in self.addresses: target_hashed = hashlib.sha256(key).digest().encode('hex') t@@ -127,7 +184,7 @@ class CloudWallet(): self.labels[key] = label["text"] def full_push(self): - global target_host, auth_token + global target_host bundle = {"labels": {}} for key, value in self.labels.iteritems(): t@@ -136,10 +193,16 @@ class CloudWallet(): params = json.dumps(bundle) connection = httplib.HTTPConnection(target_host) - connection.request("POST", ("/api/wallets/%s/labels/batch.json?auth_token=%s" % (self.mpk, auth_token)), params, {'Content-Type': 'application/json'}) + connection.request("POST", ("/api/wallets/%s/labels/batch.json?auth_token=%s" % (wallet_id(), auth_token())), params, {'Content-Type': 'application/json'}) response = connection.getresponse() if response.reason == httplib.responses[httplib.NOT_FOUND]: return - response = json.loads(response.read()) - print response + try: + response = json.loads(response.read()) + except ValueError as e: + return + + if "error" in response: + QMessageBox.warning(None, _("Error"),_("Could not sync labels: %s" % response["error"])) + return