updates for gtk gui
[electrum-nvc.git] / gui / gtk.py
index 0eab4dd..ed8d608 100644 (file)
 # You should have received a copy of the GNU General Public License
 # along with this program. If not, see <http://www.gnu.org/licenses/>.
 
-# use this because this file is named gtk.py
-from __future__ import absolute_import
 
 import datetime
 import thread, time, ast, sys, re
 import socket, traceback
-import pygtk
-pygtk.require('2.0')
-import gtk, gobject
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk, Gdk, GObject, cairo
 from decimal import Decimal
 from electrum.util import print_error
 from electrum.bitcoin import is_valid
-from electrum import mnemonic, pyqrnative, WalletStorage, Wallet
+from electrum import mnemonic, WalletStorage, Wallet
 
-gtk.gdk.threads_init()
+Gdk.threads_init()
 APP_NAME = "Electrum"
 import platform
 MONOSPACE_FONT = 'Lucida Console' if platform.system() == 'Windows' else 'monospace'
 
-from electrum.util import format_satoshis
+from electrum.util import format_satoshis, parse_URI
 from electrum.network import DEFAULT_SERVERS
 from electrum.bitcoin import MIN_RELAY_TX_FEE
 
@@ -51,12 +49,12 @@ def numbify(entry, is_int = False):
             s = s[:p] + '.' + s[p:p+8]
         try:
             amount = int( Decimal(s) * 100000000 )
-        except:
+        except Exception:
             amount = None
     else:
         try:
             amount = int( s )
-        except:
+        except Exception:
             amount = None
     entry.set_text(s)
     return amount
@@ -64,22 +62,17 @@ def numbify(entry, is_int = False):
 
 
 
-def show_seed_dialog(wallet, password, parent):
-    if not wallet.seed:
+def show_seed_dialog(seed, parent):
+    if not seed:
         show_message("No seed")
         return
-    try:
-        seed = wallet.get_seed(password)
-    except:
-        show_message("Incorrect password")
-        return
-    dialog = gtk.MessageDialog(
+
+    dialog = Gtk.MessageDialog(
         parent = parent,
-        flags = gtk.DIALOG_MODAL, 
-        buttons = gtk.BUTTONS_OK, 
-        message_format = "Your wallet generation seed is:\n\n" + seed \
-            + "\n\nPlease keep it in a safe place; if you lose it, you will not be able to restore your wallet.\n\n" \
-            + "Equivalently, your wallet seed can be stored and recovered with the following mnemonic code:\n\n\"" + ' '.join(mnemonic.mn_encode(seed)) + "\"" )
+        flags = Gtk.DialogFlags.MODAL, 
+        buttons = Gtk.ButtonsType.OK, 
+        message_format = "Your wallet generation seed is:\n\n" + '"' + seed + '"'\
+            + "\n\nPlease keep it in a safe place; if you lose it, you will not be able to restore your wallet.\n\n" )
     dialog.set_title("Seed")
     dialog.show()
     dialog.run()
@@ -89,13 +82,13 @@ def restore_create_dialog():
 
     # ask if the user wants to create a new wallet, or recover from a seed. 
     # if he wants to recover, and nothing is found, do not create wallet
-    dialog = gtk.Dialog("electrum", parent=None, 
-                        flags=gtk.DIALOG_MODAL|gtk.DIALOG_NO_SEPARATOR, 
+    dialog = Gtk.Dialog("electrum", parent=None, 
+                        flags=Gtk.DialogFlags.MODAL,
                         buttons= ("create", 0, "restore",1, "cancel",2)  )
 
-    label = gtk.Label("Wallet file not found.\nDo you want to create a new wallet,\n or to restore an existing one?"  )
+    label = Gtk.Label("Wallet file not found.\nDo you want to create a new wallet,\n or to restore an existing one?"  )
     label.show()
-    dialog.vbox.pack_start(label)
+    dialog.vbox.pack_start(label, True, True, 0)
     dialog.show()
     r = dialog.run()
     dialog.destroy()
@@ -107,22 +100,22 @@ def restore_create_dialog():
 
 def run_recovery_dialog():
     message = "Please enter your wallet seed or the corresponding mnemonic list of words, and the gap limit of your wallet."
-    dialog = gtk.MessageDialog(
+    dialog = Gtk.MessageDialog(
         parent = None,
-        flags = gtk.DIALOG_MODAL, 
-        buttons = gtk.BUTTONS_OK_CANCEL,
+        flags = Gtk.DialogFlags.MODAL, 
+        buttons = Gtk.ButtonsType.OK_CANCEL,
         message_format = message)
 
     vbox = dialog.vbox
-    dialog.set_default_response(gtk.RESPONSE_OK)
+    dialog.set_default_response(Gtk.ResponseType.OK)
 
     # ask seed, server and gap in the same dialog
-    seed_box = gtk.HBox()
-    seed_label = gtk.Label('Seed or mnemonic:')
+    seed_box = Gtk.HBox()
+    seed_label = Gtk.Label(label='Seed or mnemonic:')
     seed_label.set_size_request(150,-1)
     seed_box.pack_start(seed_label, False, False, 10)
     seed_label.show()
-    seed_entry = gtk.Entry()
+    seed_entry = Gtk.Entry()
     seed_entry.show()
     seed_entry.set_size_request(450,-1)
     seed_box.pack_start(seed_entry, False, False, 10)
@@ -135,19 +128,14 @@ def run_recovery_dialog():
     seed = seed_entry.get_text()
     dialog.destroy()
 
-    if r==gtk.RESPONSE_CANCEL:
+    if r==Gtk.ResponseType.CANCEL:
         return False
 
-    try:
-        seed.decode('hex')
-    except:
-        print_error("Warning: Not hex, trying decode")
-        seed = mnemonic.mn_decode( seed.split(' ') )
-    if not seed:
-        show_message("no seed")
-        return False
-        
-    return seed
+    if Wallet.is_seed(seed):
+        return seed
+
+    show_message("no seed")
+    return False
 
 
 
@@ -155,24 +143,24 @@ def run_settings_dialog(self):
 
     message = "Here are the settings of your wallet. For more explanations, click on the question mark buttons next to each input field."
         
-    dialog = gtk.MessageDialog(
+    dialog = Gtk.MessageDialog(
         parent = self.window,
-        flags = gtk.DIALOG_MODAL, 
-        buttons = gtk.BUTTONS_OK_CANCEL,
+        flags = Gtk.DialogFlags.MODAL, 
+        buttons = Gtk.ButtonsType.OK_CANCEL,
         message_format = message)
 
-    image = gtk.Image()
-    image.set_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_DIALOG)
+    image = Gtk.Image()
+    image.set_from_stock(Gtk.STOCK_PREFERENCES, Gtk.IconSize.DIALOG)
     image.show()
     dialog.set_image(image)
     dialog.set_title("Settings")
 
     vbox = dialog.vbox
-    dialog.set_default_response(gtk.RESPONSE_OK)
+    dialog.set_default_response(Gtk.ResponseType.OK)
 
-    fee = gtk.HBox()
-    fee_entry = gtk.Entry()
-    fee_label = gtk.Label('Transaction fee:')
+    fee = Gtk.HBox()
+    fee_entry = Gtk.Entry()
+    fee_label = Gtk.Label(label='Transaction fee:')
     fee_label.set_size_request(150,10)
     fee_label.show()
     fee.pack_start(fee_label,False, False, 10)
@@ -184,9 +172,9 @@ def run_settings_dialog(self):
     fee.show()
     vbox.pack_start(fee, False,False, 5)
             
-    nz = gtk.HBox()
-    nz_entry = gtk.Entry()
-    nz_label = gtk.Label('Display zeros:')
+    nz = Gtk.HBox()
+    nz_entry = Gtk.Entry()
+    nz_label = Gtk.Label(label='Display zeros:')
     nz_label.set_size_request(150,10)
     nz_label.show()
     nz.pack_start(nz_label,False, False, 10)
@@ -204,12 +192,12 @@ def run_settings_dialog(self):
     nz = nz_entry.get_text()
         
     dialog.destroy()
-    if r==gtk.RESPONSE_CANCEL:
+    if r==Gtk.ResponseType.CANCEL:
         return
 
     try:
         fee = int( 100000000 * Decimal(fee) )
-    except:
+    except Exception:
         show_message("error")
         return
     self.wallet.set_fee(fee)
@@ -217,7 +205,7 @@ def run_settings_dialog(self):
     try:
         nz = int( nz )
         if nz>8: nz = 8
-    except:
+    except Exception:
         show_message("error")
         return
 
@@ -230,8 +218,8 @@ def run_settings_dialog(self):
 
 
 def run_network_dialog( network, parent ):
-    image = gtk.Image()
-    image.set_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_DIALOG)
+    image = Gtk.Image()
+    image.set_from_stock(Gtk.STOCK_NETWORK, Gtk.IconSize.DIALOG)
     if parent:
         if network.is_connected():
             interface = network.interface
@@ -242,40 +230,44 @@ def run_network_dialog( network, parent ):
         import random
         status = "Please choose a server.\nSelect cancel if you are offline."
 
-    server = interface.server
-    host, port, protocol = server.split(':')
+    if network.is_connected():
+        server = interface.server
+        host, port, protocol = server.split(':')
 
     servers = network.get_servers()
 
-    dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                                    gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, status)
+    dialog = Gtk.MessageDialog( parent, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                                    Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, status)
     dialog.set_title("Server")
     dialog.set_image(image)
     image.show()
     
     vbox = dialog.vbox
-    host_box = gtk.HBox()
-    host_label = gtk.Label('Connect to:')
+    host_box = Gtk.HBox()
+    host_label = Gtk.Label(label='Connect to:')
     host_label.set_size_request(100,-1)
     host_label.show()
     host_box.pack_start(host_label, False, False, 10)
-    host_entry = gtk.Entry()
+    host_entry = Gtk.Entry()
     host_entry.set_size_request(200,-1)
-    host_entry.set_text(server)
+    if network.is_connected():
+        host_entry.set_text(server)
+    else:
+        host_entry.set_text("Not Connected")
     host_entry.show()
     host_box.pack_start(host_entry, False, False, 10)
     add_help_button(host_box, 'The name, port number and protocol of your Electrum server, separated by a colon. Example: "ecdsa.org:50002:s". Some servers allow you to connect through http (port 80) or https (port 443)')
     host_box.show()
 
-    p_box = gtk.HBox(False, 10)
+    p_box = Gtk.HBox(False, 10)
     p_box.show()
 
-    p_label = gtk.Label('Protocol:')
+    p_label = Gtk.Label(label='Protocol:')
     p_label.set_size_request(100,-1)
     p_label.show()
     p_box.pack_start(p_label, False, False, 10)
 
-    combobox = gtk.combo_box_new_text()
+    combobox = Gtk.ComboBoxText()
     combobox.show()
     combobox.append_text("TCP")
     combobox.append_text("SSL")
@@ -286,7 +278,7 @@ def run_network_dialog( network, parent ):
 
     def current_line():
         return unicode(host_entry.get_text()).split(':')
-    
+
     def set_combobox(protocol):
         combobox.set_active('tshg'.index(protocol))
 
@@ -300,31 +292,32 @@ def run_network_dialog( network, parent ):
         host_entry.set_text( host + ':' + port + ':' + protocol)
 
     combobox.connect("changed", lambda x:set_protocol('tshg'[combobox.get_active()]))
-    set_combobox(protocol)
+    if network.is_connected():
+        set_combobox(protocol)
         
-    server_list = gtk.ListStore(str)
+    server_list = Gtk.ListStore(str)
     for host in servers.keys():
         server_list.append([host])
     
-    treeview = gtk.TreeView(model=server_list)
+    treeview = Gtk.TreeView(model=server_list)
     treeview.show()
 
     label = 'Active Servers' if network.irc_servers else 'Default Servers'
-    tvcolumn = gtk.TreeViewColumn(label)
+    tvcolumn = Gtk.TreeViewColumn(label)
     treeview.append_column(tvcolumn)
-    cell = gtk.CellRendererText()
+    cell = Gtk.CellRendererText()
     tvcolumn.pack_start(cell, False)
     tvcolumn.add_attribute(cell, 'text', 0)
 
     vbox.pack_start(host_box, False,False, 5)
     vbox.pack_start(p_box, True, True, 0)
 
-    #scroll = gtk.ScrolledWindow()
-    #scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
+    #scroll = Gtk.ScrolledWindow()
+    #scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.ALWAYS)
     #scroll.add_with_viewport(treeview)
     #scroll.show()
     #vbox.pack_start(scroll, True)
-    vbox.pack_start(treeview, True)
+    vbox.pack_start(treeview, True, True, 0)
 
     def my_treeview_cb(treeview):
         path, view_column = treeview.get_cursor()
@@ -346,7 +339,7 @@ def run_network_dialog( network, parent ):
     server = host_entry.get_text()
     dialog.destroy()
 
-    if r==gtk.RESPONSE_CANCEL:
+    if r==Gtk.ResponseType.CANCEL:
         return False
 
     try:
@@ -354,7 +347,7 @@ def run_network_dialog( network, parent ):
         proxy = network.config.get('proxy')
         auto_connect = network.config.get('auto_cycle')
         network.set_parameters(host, port, protocol, proxy, auto_connect)
-    except:
+    except Exception:
         show_message("error:" + server)
         return False
 
@@ -363,22 +356,22 @@ def run_network_dialog( network, parent ):
 
 
 def show_message(message, parent=None):
-    dialog = gtk.MessageDialog(
+    dialog = Gtk.MessageDialog(
         parent = parent,
-        flags = gtk.DIALOG_MODAL, 
-        buttons = gtk.BUTTONS_CLOSE, 
+        flags = Gtk.DialogFlags.MODAL, 
+        buttons = Gtk.ButtonsType.CLOSE, 
         message_format = message )
     dialog.show()
     dialog.run()
     dialog.destroy()
 
 def password_line(label):
-    password = gtk.HBox()
-    password_label = gtk.Label(label)
+    password = Gtk.HBox()
+    password_label = Gtk.Label(label=label)
     password_label.set_size_request(120,10)
     password_label.show()
     password.pack_start(password_label,False, False, 10)
-    password_entry = gtk.Entry()
+    password_entry = Gtk.Entry()
     password_entry.set_size_request(300,-1)
     password_entry.set_visibility(False)
     password_entry.show()
@@ -387,36 +380,34 @@ def password_line(label):
     return password, password_entry
 
 def password_dialog(parent):
-    dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                                gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL,  "Please enter your password.")
+    dialog = Gtk.MessageDialog( parent, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                                Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL,  "Please enter your password.")
     dialog.get_image().set_visible(False)
     current_pw, current_pw_entry = password_line('Password:')
-    current_pw_entry.connect("activate", lambda entry, dialog, response: dialog.response(response), dialog, gtk.RESPONSE_OK)
+    current_pw_entry.connect("activate", lambda entry, dialog, response: dialog.response(response), dialog, Gtk.ResponseType.OK)
     dialog.vbox.pack_start(current_pw, False, True, 0)
     dialog.show()
     result = dialog.run()
     pw = current_pw_entry.get_text()
     dialog.destroy()
-    if result != gtk.RESPONSE_CANCEL: return pw
+    if result != Gtk.ResponseType.CANCEL: return pw
 
-def change_password_dialog(wallet, parent, icon):
-    if not wallet.seed:
-        show_message("No seed")
-        return
+
+def change_password_dialog(is_encrypted, parent):
 
     if parent:
-        msg = 'Your wallet is encrypted. Use this dialog to change the password. To disable wallet encryption, enter an empty new password.' if wallet.use_encryption else 'Your wallet keys are not encrypted'
+        msg = 'Your wallet is encrypted. Use this dialog to change the password. To disable wallet encryption, enter an empty new password.' if is_encrypted else 'Your wallet keys are not encrypted'
     else:
         msg = "Please choose a password to encrypt your wallet keys"
 
-    dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, msg)
+    dialog = Gtk.MessageDialog( parent, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, msg)
     dialog.set_title("Change password")
-    image = gtk.Image()
-    image.set_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_DIALOG)
+    image = Gtk.Image()
+    image.set_from_stock(Gtk.STOCK_DIALOG_AUTHENTICATION, Gtk.IconSize.DIALOG)
     image.show()
     dialog.set_image(image)
 
-    if wallet.use_encryption:
+    if is_encrypted:
         current_pw, current_pw_entry = password_line('Current password:')
         dialog.vbox.pack_start(current_pw, False, True, 0)
 
@@ -427,44 +418,37 @@ def change_password_dialog(wallet, parent, icon):
 
     dialog.show()
     result = dialog.run()
-    password = current_pw_entry.get_text() if wallet.use_encryption else None
+    password = current_pw_entry.get_text() if is_encrypted else None
     new_password = password_entry.get_text()
     new_password2 = password2_entry.get_text()
     dialog.destroy()
-    if result == gtk.RESPONSE_CANCEL: 
-        return
-
-    try:
-        wallet.get_seed(password)
-    except:
-        show_message("Incorrect password")
+    if result == Gtk.ResponseType.CANCEL: 
         return
 
     if new_password != new_password2:
         show_message("passwords do not match")
-        return
+        return change_password_dialog(is_encrypted, parent)
 
-    wallet.update_password(password, new_password)
+    if not new_password:
+        new_password = None
+
+    return True, password, new_password
 
-    if icon:
-        if wallet.use_encryption:
-            icon.set_tooltip_text('wallet is encrypted')
-        else:
-            icon.set_tooltip_text('wallet is unencrypted')
 
 
 def add_help_button(hbox, message):
-    button = gtk.Button('?')
+    button = Gtk.Button('?')
     button.connect("clicked", lambda x: show_message(message))
     button.show()
-    hbox.pack_start(button,False, False)
+    hbox.pack_start(button,False, False, 0)
 
 
-class MyWindow(gtk.Window): __gsignals__ = dict( mykeypress = (gobject.SIGNAL_RUN_LAST | gobject.SIGNAL_ACTION, None, (str,)) )
+class MyWindow(Gtk.Window): __gsignals__ = dict( mykeypress = (GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, (str,)) )
 
-gobject.type_register(MyWindow)
-gtk.binding_entry_add_signal(MyWindow, gtk.keysyms.W, gtk.gdk.CONTROL_MASK, 'mykeypress', str, 'ctrl+W')
-gtk.binding_entry_add_signal(MyWindow, gtk.keysyms.Q, gtk.gdk.CONTROL_MASK, 'mykeypress', str, 'ctrl+Q')
+GObject.type_register(MyWindow)
+#FIXME: can't find docs how to create keybindings in PyGI
+#Gtk.binding_entry_add_signall(MyWindow, Gdk.KEY_W, Gdk.ModifierType.CONTROL_MASK, 'mykeypress', ['ctrl+W'])
+#Gtk.binding_entry_add_signall(MyWindow, Gdk.KEY_Q, Gdk.ModifierType.CONTROL_MASK, 'mykeypress', ['ctrl+Q'])
 
 
 class ElectrumWindow:
@@ -479,19 +463,19 @@ class ElectrumWindow:
         self.funds_error = False # True if not enough funds
         self.num_zeros = int(self.config.get('num_zeros',0))
 
-        self.window = MyWindow(gtk.WINDOW_TOPLEVEL)
+        self.window = MyWindow(Gtk.WindowType.TOPLEVEL)
         title = 'Electrum ' + self.wallet.electrum_version + '  -  ' + self.config.path
         if not self.wallet.seed: title += ' [seedless]'
         self.window.set_title(title)
-        self.window.connect("destroy", gtk.main_quit)
+        self.window.connect("destroy", Gtk.main_quit)
         self.window.set_border_width(0)
-        self.window.connect('mykeypress', gtk.main_quit)
+        self.window.connect('mykeypress', Gtk.main_quit)
         self.window.set_default_size(720, 350)
         self.wallet_updated = False
 
-        vbox = gtk.VBox()
+        vbox = Gtk.VBox()
 
-        self.notebook = gtk.Notebook()
+        self.notebook = Gtk.Notebook()
         self.create_history_tab()
         if self.wallet.seed:
             self.create_send_tab()
@@ -501,20 +485,20 @@ class ElectrumWindow:
         self.notebook.show()
         vbox.pack_start(self.notebook, True, True, 2)
         
-        self.status_bar = gtk.Statusbar()
+        self.status_bar = Gtk.Statusbar()
         vbox.pack_start(self.status_bar, False, False, 0)
 
-        self.status_image = gtk.Image()
-        self.status_image.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_MENU)
+        self.status_image = Gtk.Image()
+        self.status_image.set_from_stock(Gtk.STOCK_NO, Gtk.IconSize.MENU)
         self.status_image.set_alignment(True, 0.5  )
         self.status_image.show()
 
-        self.network_button = gtk.Button()
+        self.network_button = Gtk.Button()
         self.network_button.connect("clicked", lambda x: run_network_dialog(self.network, self.window) )
         self.network_button.add(self.status_image)
-        self.network_button.set_relief(gtk.RELIEF_NONE)
+        self.network_button.set_relief(Gtk.ReliefStyle.NONE)
         self.network_button.show()
-        self.status_bar.pack_end(self.network_button, False, False)
+        self.status_bar.pack_end(self.network_button, False, False, 0)
 
         if self.wallet.seed:
             def seedb(w, wallet):
@@ -522,40 +506,47 @@ class ElectrumWindow:
                     password = password_dialog(self.window)
                     if not password: return
                 else: password = None
-                show_seed_dialog(wallet, password, self.window)
-            button = gtk.Button('S')
-            button.connect("clicked", seedb, wallet )
-            button.set_relief(gtk.RELIEF_NONE)
+                seed = wallet.get_mnemonic(password)
+                show_seed_dialog(seed, self.window)
+            button = Gtk.Button('S')
+            button.connect("clicked", seedb, self.wallet )
+            button.set_relief(Gtk.ReliefStyle.NONE)
             button.show()
-            self.status_bar.pack_end(button,False, False)
+            self.status_bar.pack_end(button,False, False, 0)
 
-        settings_icon = gtk.Image()
-        settings_icon.set_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU)
+        settings_icon = Gtk.Image()
+        settings_icon.set_from_stock(Gtk.STOCK_PREFERENCES, Gtk.IconSize.MENU)
         settings_icon.set_alignment(0.5, 0.5)
         settings_icon.set_size_request(16,16 )
         settings_icon.show()
 
-        prefs_button = gtk.Button()
+        prefs_button = Gtk.Button()
         prefs_button.connect("clicked", lambda x: run_settings_dialog(self) )
         prefs_button.add(settings_icon)
         prefs_button.set_tooltip_text("Settings")
-        prefs_button.set_relief(gtk.RELIEF_NONE)
+        prefs_button.set_relief(Gtk.ReliefStyle.NONE)
         prefs_button.show()
-        self.status_bar.pack_end(prefs_button,False,False)
+        self.status_bar.pack_end(prefs_button,False,False, 0)
 
-        pw_icon = gtk.Image()
-        pw_icon.set_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_MENU)
-        pw_icon.set_alignment(0.5, 0.5)
-        pw_icon.set_size_request(16,16 )
-        pw_icon.show()
+        self.pw_icon = Gtk.Image()
+        self.pw_icon.set_from_stock(Gtk.STOCK_DIALOG_AUTHENTICATION, Gtk.IconSize.MENU)
+        self.pw_icon.set_alignment(0.5, 0.5)
+        self.pw_icon.set_size_request(16,16 )
+        self.pw_icon.show()
 
         if self.wallet.seed:
-            password_button = gtk.Button()
-            password_button.connect("clicked", lambda x: change_password_dialog(self.wallet, self.window, pw_icon))
-            password_button.add(pw_icon)
-            password_button.set_relief(gtk.RELIEF_NONE)
+
+            if self.wallet.use_encryption:
+                self.pw_icon.set_tooltip_text('Wallet is encrypted')
+            else:
+                self.pw_icon.set_tooltip_text('Wallet is unencrypted')
+
+            password_button = Gtk.Button()
+            password_button.connect("clicked", self.do_update_password, self.wallet)
+            password_button.add(self.pw_icon)
+            password_button.set_relief(Gtk.ReliefStyle.NONE)
             password_button.show()
-            self.status_bar.pack_end(password_button,False,False)
+            self.status_bar.pack_end(password_button,False,False, 0)
 
         self.window.add(vbox)
         self.window.show_all()
@@ -569,7 +560,7 @@ class ElectrumWindow:
 
         def update_status_bar_thread():
             while True:
-                gobject.idle_add( self.update_status_bar )
+                GObject.idle_add( self.update_status_bar )
                 time.sleep(0.5)
 
 
@@ -586,11 +577,11 @@ class ElectrumWindow:
                     if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r):
                         try:
                             to_address = self.wallet.get_alias(r, interactive=False)
-                        except:
+                        except Exception:
                             continue
                         if to_address:
                             s = r + ' <' + to_address + '>'
-                            gobject.idle_add( lambda: self.payto_entry.set_text(s) )
+                            GObject.idle_add( lambda: self.payto_entry.set_text(s) )
                 
 
         thread.start_new_thread(update_status_bar_thread, ())
@@ -601,62 +592,84 @@ class ElectrumWindow:
     def update_callback(self):
         self.wallet_updated = True
 
+    def do_update_password(self, button, wallet):
+        if not wallet.seed:
+            show_message("No seed")
+            return
+
+        res = change_password_dialog(wallet.use_encryption, self.window)
+        if res:
+            _, password, new_password = res
+
+            try:
+                wallet.get_seed(password)
+            except Exception:
+                show_message("Incorrect password")
+                return
+
+            wallet.update_password(password, new_password)
+
+            if wallet.use_encryption:
+                self.pw_icon.set_tooltip_text('Wallet is encrypted')
+            else:
+                self.pw_icon.set_tooltip_text('Wallet is unencrypted')
+
 
     def add_tab(self, page, name):
-        tab_label = gtk.Label(name)
+        tab_label = Gtk.Label(label=name)
         tab_label.show()
         self.notebook.append_page(page, tab_label)
 
 
     def create_send_tab(self):
         
-        page = vbox = gtk.VBox()
+        page = vbox = Gtk.VBox()
         page.show()
 
-        payto = gtk.HBox()
-        payto_label = gtk.Label('Pay to:')
+        payto = Gtk.HBox()
+        payto_label = Gtk.Label(label='Pay to:')
         payto_label.set_size_request(100,-1)
-        payto.pack_start(payto_label, False)
-        payto_entry = gtk.Entry()
+        payto.pack_start(payto_label, False, False, 0)
+        payto_entry = Gtk.Entry()
         payto_entry.set_size_request(450, 26)
-        payto.pack_start(payto_entry, False)
+        payto.pack_start(payto_entry, False, False, 0)
         vbox.pack_start(payto, False, False, 5)
 
-        message = gtk.HBox()
-        message_label = gtk.Label('Description:')
+        message = Gtk.HBox()
+        message_label = Gtk.Label(label='Description:')
         message_label.set_size_request(100,-1)
-        message.pack_start(message_label, False)
-        message_entry = gtk.Entry()
+        message.pack_start(message_label, False, False, 0)
+        message_entry = Gtk.Entry()
         message_entry.set_size_request(450, 26)
-        message.pack_start(message_entry, False)
+        message.pack_start(message_entry, False, False, 0)
         vbox.pack_start(message, False, False, 5)
 
-        amount_box = gtk.HBox()
-        amount_label = gtk.Label('Amount:')
+        amount_box = Gtk.HBox()
+        amount_label = Gtk.Label(label='Amount:')
         amount_label.set_size_request(100,-1)
-        amount_box.pack_start(amount_label, False)
-        amount_entry = gtk.Entry()
+        amount_box.pack_start(amount_label, False, False, 0)
+        amount_entry = Gtk.Entry()
         amount_entry.set_size_request(120, -1)
-        amount_box.pack_start(amount_entry, False)
+        amount_box.pack_start(amount_entry, False, False, 0)
         vbox.pack_start(amount_box, False, False, 5)
 
-        self.fee_box = fee_box = gtk.HBox()
-        fee_label = gtk.Label('Fee:')
+        self.fee_box = fee_box = Gtk.HBox()
+        fee_label = Gtk.Label(label='Fee:')
         fee_label.set_size_request(100,-1)
-        fee_box.pack_start(fee_label, False)
-        fee_entry = gtk.Entry()
+        fee_box.pack_start(fee_label, False, False, 0)
+        fee_entry = Gtk.Entry()
         fee_entry.set_size_request(60, 26)
-        fee_box.pack_start(fee_entry, False)
+        fee_box.pack_start(fee_entry, False, False, 0)
         vbox.pack_start(fee_box, False, False, 5)
 
-        end_box = gtk.HBox()
-        empty_label = gtk.Label('')
+        end_box = Gtk.HBox()
+        empty_label = Gtk.Label(label='')
         empty_label.set_size_request(100,-1)
-        end_box.pack_start(empty_label, False)
-        send_button = gtk.Button("Send")
+        end_box.pack_start(empty_label, False, False, 0)
+        send_button = Gtk.Button("Send")
         send_button.show()
         end_box.pack_start(send_button, False, False, 0)
-        clear_button = gtk.Button("Clear")
+        clear_button = Gtk.Button("Clear")
         clear_button.show()
         end_box.pack_start(clear_button, False, False, 15)
         send_button.connect("clicked", self.do_send, (payto_entry, message_entry, amount_entry, fee_entry))
@@ -665,9 +678,9 @@ class ElectrumWindow:
         vbox.pack_start(end_box, False, False, 5)
 
         # display this line only if there is a signature
-        payto_sig = gtk.HBox()
-        payto_sig_id = gtk.Label('')
-        payto_sig.pack_start(payto_sig_id, False)
+        payto_sig = Gtk.HBox()
+        payto_sig_id = Gtk.Label(label='')
+        payto_sig.pack_start(payto_sig_id, False, False, 0)
         vbox.pack_start(payto_sig, True, True, 5)
         
 
@@ -680,18 +693,19 @@ class ElectrumWindow:
             if not is_fee: fee = None
             if amount is None:
                 return
-            inputs, total, fee = self.wallet.choose_tx_inputs( amount, fee )
+            #assume two outputs - one for change
+            inputs, total, fee = self.wallet.choose_tx_inputs( amount, fee, 2 )
             if not is_fee:
                 fee_entry.set_text( str( Decimal( fee ) / 100000000 ) )
                 self.fee_box.show()
             if inputs:
-                amount_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
-                fee_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
+                amount_entry.modify_text(Gtk.StateType.NORMAL, Gdk.color_parse("#000000"))
+                fee_entry.modify_text(Gtk.StateType.NORMAL, Gdk.color_parse("#000000"))
                 send_button.set_sensitive(True)
             else:
                 send_button.set_sensitive(False)
-                amount_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#cc0000"))
-                fee_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#cc0000"))
+                amount_entry.modify_text(Gtk.StateType.NORMAL, Gdk.color_parse("#cc0000"))
+                fee_entry.modify_text(Gtk.StateType.NORMAL, Gdk.color_parse("#cc0000"))
                 self.funds_error = True
 
         amount_entry.connect('changed', entry_changed, False)
@@ -709,37 +723,31 @@ class ElectrumWindow:
         if frozen:
             entry.set_editable(False)
             entry.set_has_frame(False)
-            entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#eeeeee"))
+            entry.modify_base(Gtk.StateType.NORMAL, Gdk.color_parse("#eeeeee"))
         else:
             entry.set_editable(True)
             entry.set_has_frame(True)
-            entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff"))
+            entry.modify_base(Gtk.StateType.NORMAL, Gdk.color_parse("#ffffff"))
 
     def set_url(self, url):
-        payto, amount, label, message, signature, identity, url = self.wallet.parse_url(url, self.show_message, self.question)
+        payto, amount, label, message, payment_request = parse_URI(url)
         self.notebook.set_current_page(1)
         self.payto_entry.set_text(payto)
         self.message_entry.set_text(message)
         self.amount_entry.set_text(amount)
-        if identity:
-            self.set_frozen(self.payto_entry,True)
-            self.set_frozen(self.amount_entry,True)
-            self.set_frozen(self.message_entry,True)
-            self.payto_sig_id.set_text( '      The bitcoin URI was signed by ' + identity )
-        else:
-            self.payto_sig.set_visible(False)
+        self.payto_sig.set_visible(False)
 
     def create_about_tab(self):
-        import pango
-        page = gtk.VBox()
+        from gi.repository import Pango
+        page = Gtk.VBox()
         page.show()
-        tv = gtk.TextView()
+        tv = Gtk.TextView()
         tv.set_editable(False)
         tv.set_cursor_visible(False)
-        tv.modify_font(pango.FontDescription(MONOSPACE_FONT))
-        scroll = gtk.ScrolledWindow()
+        tv.modify_font(Pango.FontDescription(MONOSPACE_FONT))
+        scroll = Gtk.ScrolledWindow()
         scroll.add(tv)
-        page.pack_start(scroll)
+        page.pack_start(scroll, True, True, 0)
         self.info = tv.get_buffer()
         self.add_tab(page, 'Wall')
 
@@ -751,11 +759,11 @@ class ElectrumWindow:
             entry.set_text('')
 
     def question(self,msg):
-        dialog = gtk.MessageDialog( self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, msg)
+        dialog = Gtk.MessageDialog( self.window, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, msg)
         dialog.show()
         result = dialog.run()
         dialog.destroy()
-        return result == gtk.RESPONSE_OK
+        return result == Gtk.ResponseType.OK
 
     def do_send(self, w, data):
         payto_entry, label_entry, amount_entry, fee_entry = data
@@ -784,12 +792,12 @@ class ElectrumWindow:
 
         try:
             amount = int( Decimal(amount_entry.get_text()) * 100000000 )
-        except:
+        except Exception:
             self.show_message( "invalid amount")
             return
         try:
             fee = int( Decimal(fee_entry.get_text()) * 100000000 )
-        except:
+        except Exception:
             self.show_message( "invalid fee")
             return
 
@@ -802,7 +810,7 @@ class ElectrumWindow:
 
         try:
             tx = self.wallet.mktx( [(to_address, amount)], password, fee )
-        except BaseException, e:
+        except Exception as e:
             self.show_message(str(e))
             return
 
@@ -828,7 +836,7 @@ class ElectrumWindow:
 
 
     def treeview_button_press(self, treeview, event):
-        if event.type == gtk.gdk._2BUTTON_PRESS:
+        if event.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
             c = treeview.get_cursor()[0]
             if treeview == self.history_treeview:
                 tx_details = self.history_list.get_value( self.history_list.get_iter(c), 8)
@@ -847,11 +855,11 @@ class ElectrumWindow:
 
     def treeview_key_press(self, treeview, event):
         c = treeview.get_cursor()[0]
-        if event.keyval == gtk.keysyms.Up:
+        if event.keyval == Gdk.KEY_Up:
             if c and c[0] == 0:
                 treeview.parent.grab_focus()
                 treeview.set_cursor((0,))
-        elif event.keyval == gtk.keysyms.Return:
+        elif event.keyval == Gdk.KEY_Return:
             if treeview == self.history_treeview:
                 tx_details = self.history_list.get_value( self.history_list.get_iter(c), 8)
                 self.show_message(tx_details)
@@ -870,36 +878,35 @@ class ElectrumWindow:
 
     def create_history_tab(self):
 
-        self.history_list = gtk.ListStore(str, str, str, str, 'gboolean',  str, str, str, str)
-        treeview = gtk.TreeView(model=self.history_list)
+        self.history_list = Gtk.ListStore(str, str, str, str, 'gboolean',  str, str, str, str)
+        treeview = Gtk.TreeView(model=self.history_list)
         self.history_treeview = treeview
         treeview.set_tooltip_column(7)
         treeview.show()
         treeview.connect('key-press-event', self.treeview_key_press)
         treeview.connect('button-press-event', self.treeview_button_press)
 
-        tvcolumn = gtk.TreeViewColumn('')
+        tvcolumn = Gtk.TreeViewColumn('')
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererPixbuf()
+        cell = Gtk.CellRendererPixbuf()
         tvcolumn.pack_start(cell, False)
         tvcolumn.set_attributes(cell, stock_id=1)
 
-        tvcolumn = gtk.TreeViewColumn('Date')
+        tvcolumn = Gtk.TreeViewColumn('Date')
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererText()
+        cell = Gtk.CellRendererText()
         tvcolumn.pack_start(cell, False)
         tvcolumn.add_attribute(cell, 'text', 2)
 
-        tvcolumn = gtk.TreeViewColumn('Description')
+        tvcolumn = Gtk.TreeViewColumn('Description')
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererText()
+        cell = Gtk.CellRendererText()
         cell.set_property('foreground', 'grey')
         cell.set_property('family', MONOSPACE_FONT)
         cell.set_property('editable', True)
         def edited_cb(cell, path, new_text, h_list):
             tx = h_list.get_value( h_list.get_iter(path), 0)
-            self.wallet.labels[tx] = new_text
-            self.wallet.save() 
+            self.wallet.set_label(tx,new_text)
             self.update_history_tab()
         cell.connect('edited', edited_cb, self.history_list)
         def editing_started(cell, entry, path, h_list):
@@ -910,31 +917,31 @@ class ElectrumWindow:
         tvcolumn.pack_start(cell, True)
         tvcolumn.set_attributes(cell, text=3, foreground_set = 4)
 
-        tvcolumn = gtk.TreeViewColumn('Amount')
+        tvcolumn = Gtk.TreeViewColumn('Amount')
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererText()
+        cell = Gtk.CellRendererText()
         cell.set_alignment(1, 0.5)
         cell.set_property('family', MONOSPACE_FONT)
         tvcolumn.pack_start(cell, False)
         tvcolumn.add_attribute(cell, 'text', 5)
 
-        tvcolumn = gtk.TreeViewColumn('Balance')
+        tvcolumn = Gtk.TreeViewColumn('Balance')
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererText()
+        cell = Gtk.CellRendererText()
         cell.set_alignment(1, 0.5)
         cell.set_property('family', MONOSPACE_FONT)
         tvcolumn.pack_start(cell, False)
         tvcolumn.add_attribute(cell, 'text', 6)
 
-        tvcolumn = gtk.TreeViewColumn('Tooltip')
+        tvcolumn = Gtk.TreeViewColumn('Tooltip')
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererText()
+        cell = Gtk.CellRendererText()
         tvcolumn.pack_start(cell, False)
         tvcolumn.add_attribute(cell, 'text', 7)
         tvcolumn.set_visible(False)
 
-        scroll = gtk.ScrolledWindow()
-        scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+        scroll = Gtk.ScrolledWindow()
+        scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
         scroll.add(treeview)
 
         self.add_tab(scroll, 'History')
@@ -942,40 +949,39 @@ class ElectrumWindow:
 
 
     def create_recv_tab(self):
-        self.recv_list = gtk.ListStore(str, str, str)
+        self.recv_list = Gtk.ListStore(str, str, str, str, str)
         self.add_tab( self.make_address_list(True), 'Receive')
         self.update_receiving_tab()
 
     def create_book_tab(self):
-        self.addressbook_list = gtk.ListStore(str, str, str)
+        self.addressbook_list = Gtk.ListStore(str, str, str)
         self.add_tab( self.make_address_list(False), 'Contacts')
         self.update_sending_tab()
 
     def make_address_list(self, is_recv):
         liststore = self.recv_list if is_recv else self.addressbook_list
-        treeview = gtk.TreeView(model= liststore)
+        treeview = Gtk.TreeView(model= liststore)
         treeview.connect('key-press-event', self.treeview_key_press)
         treeview.connect('button-press-event', self.treeview_button_press)
         treeview.show()
         if not is_recv:
             self.contacts_treeview = treeview
 
-        tvcolumn = gtk.TreeViewColumn('Address')
+        tvcolumn = Gtk.TreeViewColumn('Address')
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererText()
+        cell = Gtk.CellRendererText()
         cell.set_property('family', MONOSPACE_FONT)
         tvcolumn.pack_start(cell, True)
         tvcolumn.add_attribute(cell, 'text', 0)
 
-        tvcolumn = gtk.TreeViewColumn('Label')
+        tvcolumn = Gtk.TreeViewColumn('Label')
         tvcolumn.set_expand(True)
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererText()
+        cell = Gtk.CellRendererText()
         cell.set_property('editable', True)
         def edited_cb2(cell, path, new_text, liststore):
             address = liststore.get_value( liststore.get_iter(path), 0)
-            self.wallet.labels[address] = new_text
-            self.wallet.save() 
+            self.wallet.set_label(address, new_text)
             self.update_receiving_tab()
             self.update_sending_tab()
             self.update_history_tab()
@@ -983,54 +989,72 @@ class ElectrumWindow:
         tvcolumn.pack_start(cell, True)
         tvcolumn.add_attribute(cell, 'text', 1)
 
-        tvcolumn = gtk.TreeViewColumn('Tx')
+        tvcolumn = Gtk.TreeViewColumn('Tx')
         treeview.append_column(tvcolumn)
-        cell = gtk.CellRendererText()
+        cell = Gtk.CellRendererText()
         tvcolumn.pack_start(cell, True)
         tvcolumn.add_attribute(cell, 'text', 2)
 
-        scroll = gtk.ScrolledWindow()
-        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        if is_recv:
+            tvcolumn = Gtk.TreeViewColumn('Balance')
+            treeview.append_column(tvcolumn)
+            cell = Gtk.CellRendererText()
+            tvcolumn.pack_start(cell, True)
+            tvcolumn.add_attribute(cell, 'text', 3)
+            tvcolumn = Gtk.TreeViewColumn('Type')
+            treeview.append_column(tvcolumn)
+            cell = Gtk.CellRendererText()
+            tvcolumn.pack_start(cell, True)
+            tvcolumn.add_attribute(cell, 'text', 4)
+
+        scroll = Gtk.ScrolledWindow()
+        scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
         scroll.add(treeview)
 
-        hbox = gtk.HBox()
+        hbox = Gtk.HBox()
         if not is_recv:
-            button = gtk.Button("New")
+            button = Gtk.Button("New")
             button.connect("clicked", self.newaddress_dialog)
             button.show()
-            hbox.pack_start(button,False)
+            hbox.pack_start(button,False, False, 0)
 
         def showqrcode(w, treeview, liststore):
+            import qrcode
             path, col = treeview.get_cursor()
             if not path: return
             address = liststore.get_value(liststore.get_iter(path), 0)
-            qr = pyqrnative.QRCode(4, pyqrnative.QRErrorCorrectLevel.H)
-            qr.addData(address)
-            qr.make()
+            qr = qrcode.QRCode()
+            qr.add_data(address)
             boxsize = 7
-            size = qr.getModuleCount()*boxsize
-            def area_expose_cb(area, event):
+            matrix = qr.get_matrix()
+            boxcount_row = len(matrix)
+            size = (boxcount_row + 4) * boxsize
+            def area_expose_cb(area, cr):
                 style = area.get_style()
-                k = qr.getModuleCount()
-                for r in range(k):
-                    for c in range(k):
-                        gc = style.black_gc if qr.isDark(r, c) else style.white_gc
-                        area.window.draw_rectangle(gc, True, c*boxsize, r*boxsize, boxsize, boxsize)
-            area = gtk.DrawingArea()
+                Gdk.cairo_set_source_color(cr, style.white)
+                cr.rectangle(0, 0, size, size)
+                cr.fill()
+                Gdk.cairo_set_source_color(cr, style.black)
+                for r in range(boxcount_row):
+                    for c in range(boxcount_row):
+                        if matrix[r][c]:
+                            cr.rectangle((c + 2) * boxsize, (r + 2) * boxsize, boxsize, boxsize)
+                            cr.fill()
+            area = Gtk.DrawingArea()
             area.set_size_request(size, size)
-            area.connect("expose-event", area_expose_cb)
+            area.connect("draw", area_expose_cb)
             area.show()
-            dialog = gtk.Dialog(address, parent=self.window, flags=gtk.DIALOG_MODAL|gtk.DIALOG_NO_SEPARATOR, buttons = ("ok",1))
+            dialog = Gtk.Dialog(address, parent=self.window, flags=Gtk.DialogFlags.MODAL, buttons = ("ok",1))
             dialog.vbox.add(area)
             dialog.run()
             dialog.destroy()
 
-        button = gtk.Button("QR")
+        button = Gtk.Button("QR")
         button.connect("clicked", showqrcode, treeview, liststore)
         button.show()
-        hbox.pack_start(button,False)
+        hbox.pack_start(button,False, False, 0)
 
-        button = gtk.Button("Copy to clipboard")
+        button = Gtk.Button("Copy to clipboard")
         def copy2clipboard(w, treeview, liststore):
             import platform
             path, col =  treeview.get_cursor()
@@ -1044,14 +1068,30 @@ class ElectrumWindow:
                     r.clipboard_append( address )
                     r.destroy()
                 else:
-                    c = gtk.clipboard_get()
-                    c.set_text( address )
+                    atom = Gdk.atom_intern('CLIPBOARD', True)
+                    c = Gtk.Clipboard.get(atom)
+                    c.set_text( address, len(address) )
         button.connect("clicked", copy2clipboard, treeview, liststore)
         button.show()
-        hbox.pack_start(button,False)
+        hbox.pack_start(button,False, False, 0)
+
+        if is_recv:
+            button = Gtk.Button("Freeze")
+            def freeze_address(w, treeview, liststore, wallet):
+                path, col = treeview.get_cursor()
+                if path:
+                    address = liststore.get_value( liststore.get_iter(path), 0)
+                    if address in wallet.frozen_addresses:
+                        wallet.unfreeze(address)
+                    else:
+                        wallet.freeze(address)
+                    self.update_receiving_tab()
+            button.connect("clicked", freeze_address, treeview, liststore, self.wallet)
+            button.show()
+            hbox.pack_start(button,False, False, 0)
 
         if not is_recv:
-            button = gtk.Button("Pay to")
+            button = Gtk.Button("Pay to")
             def payto(w, treeview, liststore):
                 path, col =  treeview.get_cursor()
                 if path:
@@ -1062,11 +1102,11 @@ class ElectrumWindow:
 
             button.connect("clicked", payto, treeview, liststore)
             button.show()
-            hbox.pack_start(button,False)
+            hbox.pack_start(button,False, False, 0)
 
-        vbox = gtk.VBox()
-        vbox.pack_start(scroll,True)
-        vbox.pack_start(hbox, False)
+        vbox = Gtk.VBox()
+        vbox.pack_start(scroll,True, True, 0)
+        vbox.pack_start(hbox, False, False, 0)
         return vbox
 
     def update_status_bar(self):
@@ -1076,16 +1116,16 @@ class ElectrumWindow:
         elif interface and interface.is_connected:
             self.network_button.set_tooltip_text("Connected to %s:%d.\n%d blocks"%(interface.host, interface.port, self.network.blockchain.height()))
             if not self.wallet.up_to_date:
-                self.status_image.set_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU)
+                self.status_image.set_from_stock(Gtk.STOCK_REFRESH, Gtk.IconSize.MENU)
                 text = "Synchronizing..."
             else:
-                self.status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU)
+                self.status_image.set_from_stock(Gtk.STOCK_YES, Gtk.IconSize.MENU)
                 self.network_button.set_tooltip_text("Connected to %s:%d.\n%d blocks"%(interface.host, interface.port, self.network.blockchain.height()))
                 c, u = self.wallet.get_balance()
                 text =  "Balance: %s "%( format_satoshis(c,False,self.num_zeros) )
                 if u: text +=  "[%s unconfirmed]"%( format_satoshis(u,True,self.num_zeros).strip() )
         else:
-            self.status_image.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_MENU)
+            self.status_image.set_from_stock(Gtk.STOCK_NO, Gtk.IconSize.MENU)
             self.network_button.set_tooltip_text("Not connected.")
             text = "Not connected"
 
@@ -1102,12 +1142,18 @@ class ElectrumWindow:
     def update_receiving_tab(self):
         self.recv_list.clear()
         for address in self.wallet.addresses(True):
-            if self.wallet.is_change(address):continue
+            Type = "R"
+            c = u = 0
+            if self.wallet.is_change(address): Type = "C"
+            if address in self.wallet.imported_keys.keys():
+                Type = "I"
+            c, u = self.wallet.get_addr_balance(address)
+            if address in self.wallet.frozen_addresses: Type = Type + "F"
             label = self.wallet.labels.get(address)
             h = self.wallet.history.get(address,[])
             n = len(h)
-            tx = "None" if n==0 else "%d"%n
-            self.recv_list.append((address, label, tx ))
+            tx = "0" if n==0 else "%d"%n
+            self.recv_list.append((address, label, tx, format_satoshis(c,False,self.num_zeros), Type ))
 
     def update_sending_tab(self):
         # detect addresses that are not mine in history, add them here...
@@ -1131,15 +1177,15 @@ class ElectrumWindow:
             if conf > 0:
                 try:
                     time_str = datetime.datetime.fromtimestamp( timestamp).isoformat(' ')[:-3]
-                except:
+                except Exception:
                     time_str = "------"
-                conf_icon = gtk.STOCK_APPLY
+                conf_icon = Gtk.STOCK_APPLY
             elif conf == -1:
                 time_str = 'unverified'
                 conf_icon = None
             else:
                 time_str = 'pending'
-                conf_icon = gtk.STOCK_EXECUTE
+                conf_icon = Gtk.STOCK_EXECUTE
 
             label, is_default_label = self.wallet.get_label(tx_hash)
             tooltip = tx_hash + "\n%d confirmations"%conf if tx_hash else ''
@@ -1164,7 +1210,7 @@ class ElectrumWindow:
             time_str = 'pending'
 
         inputs = map(lambda x: x.get('address'), tx.inputs)
-        outputs = map(lambda x: x.get('address'), tx.d['outputs'])
+        outputs = map(lambda x: x[0], tx.get_outputs())
         tx_details = "Transaction Details" +"\n\n" \
             + "Transaction ID:\n" + tx_hash + "\n\n" \
             + "Status: %d confirmations\n"%conf
@@ -1189,30 +1235,30 @@ class ElectrumWindow:
     def newaddress_dialog(self, w):
 
         title = "New Contact" 
-        dialog = gtk.Dialog(title, parent=self.window, 
-                            flags=gtk.DIALOG_MODAL|gtk.DIALOG_NO_SEPARATOR, 
+        dialog = Gtk.Dialog(title, parent=self.window, 
+                            flags=Gtk.DialogFlags.MODAL,
                             buttons= ("cancel", 0, "ok",1)  )
         dialog.show()
 
-        label = gtk.HBox()
-        label_label = gtk.Label('Label:')
+        label = Gtk.HBox()
+        label_label = Gtk.Label(label='Label:')
         label_label.set_size_request(120,10)
         label_label.show()
-        label.pack_start(label_label)
-        label_entry = gtk.Entry()
+        label.pack_start(label_label, True, True, 0)
+        label_entry = Gtk.Entry()
         label_entry.show()
-        label.pack_start(label_entry)
+        label.pack_start(label_entry, True, True, 0)
         label.show()
         dialog.vbox.pack_start(label, False, True, 5)
 
-        address = gtk.HBox()
-        address_label = gtk.Label('Address:')
+        address = Gtk.HBox()
+        address_label = Gtk.Label(label='Address:')
         address_label.set_size_request(120,10)
         address_label.show()
-        address.pack_start(address_label)
-        address_entry = gtk.Entry()
+        address.pack_start(address_label, True, True, 0)
+        address_entry = Gtk.Entry()
         address_entry.show()
-        address.pack_start(address_entry)
+        address.pack_start(address_entry, True, True, 0)
         address.show()
         dialog.vbox.pack_start(address, False, True, 5)
         
@@ -1226,10 +1272,10 @@ class ElectrumWindow:
                 self.wallet.add_contact(address,label)
                 self.update_sending_tab()
             else:
-                errorDialog = gtk.MessageDialog(
+                errorDialog = Gtk.MessageDialog(
                     parent=self.window,
-                    flags=gtk.DIALOG_MODAL, 
-                    buttons= gtk.BUTTONS_CLOSE, 
+                    flags=Gtk.DialogFlags.MODAL, 
+                    buttons= Gtk.ButtonsType.CLOSE, 
                     message_format = "Invalid address")
                 errorDialog.show()
                 errorDialog.run()
@@ -1257,28 +1303,38 @@ class ElectrumGui():
                 wallet.gap_limit = gap
                 wallet.storage.put('gap_limit', gap, True)
 
-            self.wallet.start_threads(self.network)
-
             if action == 'create':
-                wallet.init_seed(None)
-                wallet.save_seed()
-                wallet.create_accounts()
+                seed = wallet.make_seed()
+                show_seed_dialog(seed, None)
+                r = change_password_dialog(False, None)
+                password = r[2] if r else None
+                wallet.add_seed(seed, password)
+                wallet.create_accounts(password)
                 wallet.synchronize()  # generate first addresses offline
+
             elif action == 'restore':
                 seed = self.seed_dialog()
-                wallet.init_seed(seed)
-                wallet.save_seed()
-                self.restore_wallet(wallet)
+                if not seed:
+                    exit()
+                r = change_password_dialog(False, None)
+                password = r[2] if r else None
+                wallet.add_seed(seed, password)
+                wallet.create_accounts(password)
                 
             else:
                 exit()
         else:
             self.wallet = Wallet(storage)
-            self.wallet.start_threads(self.network)
+            action = None
+
+        self.wallet.start_threads(self.network)
+
+        if action == 'restore':
+            self.restore_wallet(wallet)
 
         w = ElectrumWindow(self.wallet, self.config, self.network)
         if url: w.set_url(url)
-        gtk.main()
+        Gtk.main()
 
     def restore_or_create(self):
         return restore_create_dialog()
@@ -1286,36 +1342,27 @@ class ElectrumGui():
     def seed_dialog(self):
         return run_recovery_dialog()
 
-    def verify_seed(self):
-        self.wallet.save_seed()
-        return True
-
     def network_dialog(self):
         return run_network_dialog( self.network, parent=None )
 
-    def show_seed(self):
-        show_seed_dialog(self.wallet, None, None)
-
-    def password_dialog(self):
-        change_password_dialog(self.wallet, None, None)
 
     def restore_wallet(self, wallet):
 
-        dialog = gtk.MessageDialog(
+        dialog = Gtk.MessageDialog(
             parent = None,
-            flags = gtk.DIALOG_MODAL, 
-            buttons = gtk.BUTTONS_CANCEL, 
+            flags = Gtk.DialogFlags.MODAL, 
+            buttons = Gtk.ButtonsType.CANCEL, 
             message_format = "Please wait..."  )
         dialog.show()
 
         def recover_thread( wallet, dialog ):
             wallet.restore(lambda x:x)
-            gobject.idle_add( dialog.destroy )
+            GObject.idle_add( dialog.destroy )
 
         thread.start_new_thread( recover_thread, ( wallet, dialog ) )
         r = dialog.run()
         dialog.destroy()
-        if r==gtk.RESPONSE_CANCEL: return False
+        if r==Gtk.ResponseType.CANCEL: return False
         if not wallet.is_found():
             show_message("No transactions found for this seed")