URI: 
       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