URI: 
       tupdate network settings dialog of the kivy GUI - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 73b023e9675461e5bd429d18990514e038f49525
   DIR parent 92b392a56b719830577579d719526cfdee5a9e66
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Mon, 10 Jul 2017 13:51:13 +0200
       
       update network settings dialog of the kivy GUI
       
       Diffstat:
         M gui/kivy/main.kv                    |      33 ++++++++++++++++++++++++++++++-
         M gui/kivy/main_window.py             |      85 +++++++++++++++++++++++++++++--
         M gui/kivy/uix/dialogs/amount_dialog… |       2 +-
         D gui/kivy/uix/dialogs/blockchain_di… |      63 -------------------------------
         M gui/kivy/uix/dialogs/settings.py    |     132 ++++++-------------------------
         M gui/kivy/uix/ui_screens/network.kv  |     117 +++++++++++++------------------
         M gui/kivy/uix/ui_screens/proxy.kv    |      30 ++++++++++++++++++++----------
         A gui/kivy/uix/ui_screens/server.kv   |      63 +++++++++++++++++++++++++++++++
         M gui/qt/network_dialog.py            |       4 ----
         M lib/network.py                      |       7 +++++++
       
       10 files changed, 276 insertions(+), 260 deletions(-)
       ---
   DIR diff --git a/gui/kivy/main.kv b/gui/kivy/main.kv
       t@@ -293,6 +293,34 @@
                    size: self.width - sp(4), self.height - sp(4)
        
        
       +<SettingsItem@ButtonBehavior+BoxLayout>
       +    orientation: 'vertical'
       +    title: ''
       +    description: ''
       +    size_hint: 1, None
       +    height: '60dp'
       +    canvas.before:
       +        Color:
       +            rgba: (0.192, .498, 0.745, 1) if self.state == 'down' else (0.3, 0.3, 0.3, 0)
       +        Rectangle:
       +            size: self.size
       +            pos: self.pos
       +    on_release:
       +        Clock.schedule_once(self.action)
       +    Widget
       +    TopLabel:
       +        id: title
       +        text: self.parent.title
       +        bold: True
       +        halign: 'left'
       +    TopLabel:
       +        text: self.parent.description
       +        color: 0.8, 0.8, 0.8, 1
       +        halign: 'left'
       +    Widget
       +
       +
       +
        
        <ScreenTabs@Screen>
            TabbedCarousel:
       t@@ -365,7 +393,7 @@ BoxLayout:
                        app_icon_width: '100dp'
                        with_previous: False
                        size_hint_x: None
       -                on_release: app.popup_dialog('status')
       +                on_release: app.popup_dialog('network')
        
                    ActionButton:
                        id: action_status
       t@@ -387,6 +415,9 @@ BoxLayout:
                            name: 'wallets'
                            text: _('Wallets')
                        ActionOvrButton:
       +                    name: 'network'
       +                    text: _('Network')
       +                ActionOvrButton:
                            name: 'settings'
                            text: _('Settings')
                            on_parent:
   DIR diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
       t@@ -73,10 +73,55 @@ from electrum.util import base_units
        class ElectrumWindow(App):
        
            electrum_config = ObjectProperty(None)
       -
            language = StringProperty('en')
       +
       +    # properties might be updated by the network
            num_blocks = NumericProperty(0)
            num_nodes = NumericProperty(0)
       +    server_host = StringProperty('')
       +    server_port = StringProperty('')
       +
       +    auto_connect = BooleanProperty(False)
       +    def on_auto_connect(self, instance, x):
       +        host, port, protocol, proxy, auto_connect = self.network.get_parameters()
       +        self.network.set_parameters(host, port, protocol, proxy, self.auto_connect)
       +    def toggle_auto_connect(self, x):
       +        self.auto_connect = not self.auto_connect
       +
       +    def choose_server_dialog(self, popup):
       +        from uix.dialogs.choice_dialog import ChoiceDialog
       +        protocol = 's'
       +        def cb2(host):
       +            from electrum.network import DEFAULT_PORTS
       +            pp = servers.get(host, DEFAULT_PORTS)
       +            port = pp.get(protocol, '')
       +            popup.ids.host.text = host
       +            popup.ids.port.text = port
       +        servers = self.network.get_servers()
       +        ChoiceDialog(_('Choose a server'), sorted(servers), popup.ids.host.text, cb2).open()
       +
       +    def choose_blockchain_dialog(self, dt):
       +        from uix.dialogs.choice_dialog import ChoiceDialog
       +        def cb(name):
       +            for index, b in self.network.blockchains.items():
       +                if name == self.network.get_blockchain_name(b):
       +                    self.network.follow_chain(index)
       +                    #self.block
       +        names = [self.network.get_blockchain_name(b) for b in self.network.blockchains.values()]
       +        if len(names) >1:
       +            ChoiceDialog(_('Choose your chain'), names, '', cb).open()
       +
       +    use_rbf = BooleanProperty(False)
       +    def on_use_rbf(self, instance, x):
       +        self.electrum_config.set_key('use_rbf', self.use_rbf, True)
       +
       +    use_change = BooleanProperty(False)
       +    def on_use_change(self, instance, x):
       +        self.electrum_config.set_key('use_change', self.use_change, True)
       +
       +    use_unconfirmed = BooleanProperty(False)
       +    def on_use_unconfirmed(self, instance, x):
       +        self.electrum_config.set_key('confirmed_only', not self.use_unconfirmed, True)
        
            def set_URI(self, uri):
                self.switch_to('send')
       t@@ -195,13 +240,26 @@ class ElectrumWindow(App):
                title = _('Electrum App')
                self.electrum_config = config = kwargs.get('config', None)
                self.language = config.get('language', 'en')
       +
                self.network = network = kwargs.get('network', None)
       -        self.plugins = kwargs.get('plugins', [])
       +        if self.network:
       +            self.num_blocks = self.network.get_local_height()
       +            self.num_nodes = len(self.network.get_interfaces())
       +            host, port, protocol, proxy_config, auto_connect = self.network.get_parameters()
       +            self.server_host = host
       +            self.server_port = port
       +            self.auto_connect = auto_connect
       +            self.proxy_config = proxy_config if proxy_config else {}
        
       +        self.plugins = kwargs.get('plugins', [])
                self.gui_object = kwargs.get('gui_object', None)
                self.daemon = self.gui_object.daemon
                self.fx = self.daemon.fx
        
       +        self.use_rbf = config.get('use_rbf', False)
       +        self.use_change = config.get('use_change', True)
       +        self.use_unconfirmed = not config.get('confirmed_only', True)
       +
                # create triggers so as to minimize updation a max of 2 times a sec
                self._trigger_update_wallet = Clock.create_trigger(self.update_wallet, .5)
                self._trigger_update_status = Clock.create_trigger(self.update_status, .5)
       t@@ -529,14 +587,31 @@ class ElectrumWindow(App):
                if self.network:
                    interests = ['updated', 'status', 'new_transaction', 'verified']
                    self.network.register_callback(self.on_network, interests)
       -
                self.tabs = self.root.ids['tabs']
        
       +    def blockchain_status(self):
       +        if len(self.network.blockchains)>1:
       +            msg = self.network.get_blockchain_name(self.network.blockchain())
       +        else:
       +            msg = _('Genesis block')
       +        return msg
       +
       +    def blockchain_info(self):
       +        if len(self.network.blockchains)>1:
       +            checkpoint = self.network.get_checkpoint()
       +            msg = _('Chain split detected at block %d')%checkpoint
       +        else:
       +            msg = _('No chain split detected')
       +        return msg
       +
            def on_network(self, event, *args):
       +        if self.network.interface:
       +            self.server_host = self.network.interface.host
                if event == 'updated':
                    self.num_blocks = self.network.get_local_height()
                    self.num_nodes = len(self.network.get_interfaces())
                    self._trigger_update_wallet()
       +            self._trigger_update_status()
                elif event == 'status':
                    self._trigger_update_status()
                elif event == 'new_transaction':
       t@@ -573,9 +648,11 @@ class ElectrumWindow(App):
                        text = self.format_amount(c+x+u)
                        status = str(text.strip() + ' ' + self.base_unit)
                else:
       -            status = _("Not connected")
       +            status = _("Disconnected")
       +
                n = self.wallet.basename()
                self.status = '[size=15dp]%s[/size]\n%s' %(n, status)
       +        #fiat_balance = self.fx.format_amount_and_units(c+u+x) or ''
        
            def get_max_amount(self):
                inputs = self.wallet.get_spendable_coins(None, self.electrum_config)
   DIR diff --git a/gui/kivy/uix/dialogs/amount_dialog.py b/gui/kivy/uix/dialogs/amount_dialog.py
       t@@ -79,7 +79,7 @@ Builder.load_string('''
                            id: button_fiat
                            size_hint: 1, None
                            height: '48dp'
       -                    text: (app.base_unit if kb.is_fiat else app.fiat_unit) if app.fiat_unit else ''
       +                    text: (app.base_unit if not kb.is_fiat else app.fiat_unit) if app.fiat_unit else ''
                            on_release:
                                if app.fiat_unit: popup.toggle_fiat(kb)
                        Button:
   DIR diff --git a/gui/kivy/uix/dialogs/blockchain_dialog.py b/gui/kivy/uix/dialogs/blockchain_dialog.py
       t@@ -1,63 +0,0 @@
       -from kivy.app import App
       -from kivy.factory import Factory
       -from kivy.properties import ObjectProperty
       -from kivy.lang import Builder
       -
       -from electrum.i18n import _
       -
       -Builder.load_string('''
       -#:import _ electrum_gui.kivy.i18n._
       -
       -<BlockchainDialog@Popup>
       -    id: popup
       -    title: _('Blockchain')
       -    size_hint: 1, 1
       -    cp_height: 0
       -    cp_value: ''
       -
       -    BoxLayout:
       -        orientation: 'vertical'
       -        padding: '10dp'
       -        spacing: '10dp'
       -        TopLabel:
       -            height: '48dp'
       -            id: bc_height
       -            text: _("Verified headers: %d blocks.")% app.num_blocks
       -        TopLabel:
       -            height: '48dp'
       -            id: bc_status
       -            text: _("Connected to %d nodes.")% app.num_nodes if app.num_nodes else _("Not connected?")
       -        Widget:
       -            size_hint: 1, 0.1
       -        TopLabel:
       -            text: _("Electrum connects to several nodes in order to download block headers and find out the longest blockchain.") + _("This blockchain is used to verify the transactions sent by your transaction server.")
       -            font_size: '6pt'
       -        Widget:
       -            size_hint: 1, 0.1
       -        Widget:
       -            size_hint: 1, 0.1
       -        BoxLayout:
       -            orientation: 'horizontal'
       -            size_hint: 1, 0.2
       -            Button:
       -                text: _('Cancel')
       -                size_hint: 0.5, None
       -                height: '48dp'
       -                on_release: popup.dismiss()
       -            Button:
       -                text: _('OK')
       -                size_hint: 0.5, None
       -                height: '48dp'
       -                on_release:
       -                    root.callback(root.cp_height, root.cp_value)
       -                    popup.dismiss()
       -''')
       -
       -class BlockchainDialog(Factory.Popup):
       -    def __init__(self, network, callback):
       -        Factory.Popup.__init__(self)
       -        self.network = network
       -        self.callback = callback
       -        self.is_split = len(self.network.blockchains) > 1
       -
       -        self.checkpoint_height = network.get_checkpoint()
   DIR diff --git a/gui/kivy/uix/dialogs/settings.py b/gui/kivy/uix/dialogs/settings.py
       t@@ -16,35 +16,6 @@ Builder.load_string('''
        #:import partial functools.partial
        #:import _ electrum_gui.kivy.i18n._
        
       -<SettingsItem@ButtonBehavior+BoxLayout>
       -    orientation: 'vertical'
       -    title: ''
       -    description: ''
       -    size_hint: 1, None
       -    height: '60dp'
       -
       -    canvas.before:
       -        Color:
       -            rgba: (0.192, .498, 0.745, 1) if self.state == 'down' else (0.3, 0.3, 0.3, 0)
       -        Rectangle:
       -            size: self.size
       -            pos: self.pos
       -    on_release:
       -        Clock.schedule_once(self.action)
       -
       -    Widget
       -    TopLabel:
       -        id: title
       -        text: self.parent.title
       -        bold: True
       -        halign: 'left'
       -    TopLabel:
       -        text: self.parent.description
       -        color: 0.8, 0.8, 0.8, 1
       -        halign: 'left'
       -    Widget
       -
       -
        <SettingsDialog@Popup>
            id: settings
            title: _('Electrum Settings')
       t@@ -91,40 +62,40 @@ Builder.load_string('''
                            action: partial(root.fx_dialog, self)
                        CardSeparator
                        SettingsItem:
       -                    status: root.network_status()
       -                    title: _('Server') + ': ' + self.status
       -                    description: _("Select your history server.")
       -                    action: partial(root.network_dialog, self)
       -                CardSeparator
       -                SettingsItem:
       -                    status: root.proxy_status()
       -                    title: _('Proxy') + ': ' + self.status
       -                    description: _("Proxy configuration.")
       -                    action: partial(root.proxy_dialog, self)
       -                CardSeparator
       -                SettingsItem:
                            status: 'ON' if bool(app.plugins.get('labels')) else 'OFF'
                            title: _('Labels Sync') + ': ' + self.status
                            description: _("Save and synchronize your labels.")
                            action: partial(root.plugin_dialog, 'labels', self)
                        CardSeparator
                        SettingsItem:
       -                    status: root.rbf_status()
       +                    status: 'ON' if app.use_rbf else 'OFF'
                            title: _('Replace-by-fee') + ': ' + self.status
                            description: _("Create replaceable transactions.")
       -                    action: partial(root.rbf_dialog, self)
       +                    message:
       +                        _('If you check this box, your transactions will be marked as non-final,') \
       +                        + ' ' + _('and you will have the possiblity, while they are unconfirmed, to replace them with transactions that pays higher fees.') \
       +                        + ' ' + _('Note that some merchants do not accept non-final transactions until they are confirmed.')
       +                    action: partial(root.boolean_dialog, 'use_rbf', _('Replace by fee'), self.message)
       +                CardSeparator
       +                SettingsItem:
       +                    status: _('Yes') if app.use_unconfirmed else _('No')
       +                    title: _('Spend unconfirmed') + ': ' + self.status
       +                    description: _("Use unconfirmed coins in transactions.")
       +                    message: _('Spend unconfirmed coins')
       +                    action: partial(root.boolean_dialog, 'use_unconfirmed', _('Use unconfirmed'), self.message)
       +                CardSeparator
       +                SettingsItem:
       +                    status: _('Yes') if app.use_change else _('No')
       +                    title: _('Use change addresses') + ': ' + self.status
       +                    description: _("Send your change to separate addresses.")
       +                    message: _('Send excess coins to change addresses')
       +                    action: partial(root.boolean_dialog, 'use_change', _('Use change addresses'), self.message)
                        CardSeparator
                        SettingsItem:
                            status: root.coinselect_status()
                            title: _('Coin selection') + ': ' + self.status
                            description: "Coin selection method"
                            action: partial(root.coinselect_dialog, self)
       -                CardSeparator
       -                SettingsItem:
       -                    status: "%d blocks"% app.num_blocks
       -                    title: _('Blockchain') + ': ' + self.status
       -                    description: _("Blockchain status")
       -                    action: partial(root.blockchain_dialog, self)
        ''')
        
        
       t@@ -141,13 +112,10 @@ class SettingsDialog(Factory.Popup):
                # cached dialogs
                self._fx_dialog = None
                self._fee_dialog = None
       -        self._rbf_dialog = None
       -        self._network_dialog = None
                self._proxy_dialog = None
                self._language_dialog = None
                self._unit_dialog = None
                self._coinselect_dialog = None
       -        self._blockchain_dialog = None
        
            def update(self):
                self.wallet = self.app.wallet
       t@@ -191,15 +159,6 @@ class SettingsDialog(Factory.Popup):
                    self._coinselect_dialog = ChoiceDialog(_('Coin selection'), choosers, chooser_name, cb)
                self._coinselect_dialog.open()
        
       -    def blockchain_dialog(self, item, dt):
       -        from blockchain_dialog import BlockchainDialog
       -        if self._blockchain_dialog is None:
       -            def callback(height, value):
       -                if value:
       -                    self.app.network.blockchain.set_checkpoint(height, value)
       -            self._blockchain_dialog = BlockchainDialog(self.app.network, callback)
       -        self._blockchain_dialog.open()
       -
            def proxy_status(self):
                server, port, protocol, proxy, auto_connect = self.app.network.get_parameters()
                return proxy.get('host') +':' + proxy.get('port') if proxy else _('None')
       t@@ -230,44 +189,11 @@ class SettingsDialog(Factory.Popup):
                    self._proxy_dialog = popup
                self._proxy_dialog.open()
        
       -    def network_dialog(self, item, dt):
       -        host, port, protocol, proxy, auto_connect = self.app.network.get_parameters()
       -        servers = self.app.network.get_servers()
       -        if self._network_dialog is None:
       -            def cb1(popup):
       -                host = str(popup.ids.host.text)
       -                port = str(popup.ids.port.text)
       -                auto_connect = popup.ids.auto_connect.active
       -                self.app.network.set_parameters(host, port, protocol, proxy, auto_connect)
       -                item.status = self.network_status()
       -            def cb2(host):
       -                from electrum.network import DEFAULT_PORTS
       -                pp = servers.get(host, DEFAULT_PORTS)
       -                port = pp.get(protocol, '')
       -                popup.ids.host.text = host
       -                popup.ids.port.text = port
       -            def cb3():
       -                ChoiceDialog(_('Choose a server'), sorted(servers), popup.ids.host.text, cb2).open()
       -            popup = Builder.load_file('gui/kivy/uix/ui_screens/network.kv')
       -            popup.ids.chooser.on_release = cb3
       -            popup.on_dismiss = lambda: cb1(popup)
       -            self._network_dialog = popup
       -
       -        self._network_dialog.ids.auto_connect.active = auto_connect
       -        self._network_dialog.ids.host.text = host
       -        self._network_dialog.ids.port.text = port
       -        self._network_dialog.open()
       -
       -    def network_status(self):
       -        server, port, protocol, proxy, auto_connect = self.app.network.get_parameters()
       -        return 'auto-connect' if auto_connect else server
       -
            def plugin_dialog(self, name, label, dt):
                from checkbox_dialog import CheckBoxDialog
                def callback(status):
                    self.plugins.enable(name) if status else self.plugins.disable(name)
                    label.status = 'ON' if status else 'OFF'
       -
                status = bool(self.plugins.get(name))
                dd = self.plugins.descriptions.get(name)
                descr = dd.get('description')
       t@@ -289,21 +215,9 @@ class SettingsDialog(Factory.Popup):
                    self._fee_dialog = FeeDialog(self.app, self.config, cb)
                self._fee_dialog.open()
        
       -    def rbf_status(self):
       -        return 'ON' if self.config.get('use_rbf') else 'OFF'
       -
       -    def rbf_dialog(self, label, dt):
       -        if self._rbf_dialog is None:
       -            from checkbox_dialog import CheckBoxDialog
       -            def cb(x):
       -                self.config.set_key('use_rbf', x, True)
       -                label.status = self.rbf_status()
       -            msg = [_('If you check this box, your transactions will be marked as non-final,'),
       -                   _('and you will have the possiblity, while they are unconfirmed, to replace them with transactions that pays higher fees.'),
       -                   _('Note that some merchants do not accept non-final transactions until they are confirmed.')]
       -            fullname = _('Replace by fee')
       -            self._rbf_dialog = CheckBoxDialog(fullname, ' '.join(msg), self.config.get('use_rbf', False), cb)
       -        self._rbf_dialog.open()
       +    def boolean_dialog(self, name, title, message, dt):
       +        from checkbox_dialog import CheckBoxDialog
       +        CheckBoxDialog(title, message, getattr(self.app, name), lambda x: setattr(self.app, name, x)).open()
        
            def fx_status(self):
                fx = self.app.fx
   DIR diff --git a/gui/kivy/uix/ui_screens/network.kv b/gui/kivy/uix/ui_screens/network.kv
       t@@ -1,72 +1,53 @@
        Popup:
            id: nd
       -    title: _('Server')
       -    is_connected: app.network.is_connected()
       -
       +    title: _('Network')
            BoxLayout:
                orientation: 'vertical'
       -        padding: '10dp'
       -        spacing: '10dp'
       -        TopLabel:
       -            text: _("Electrum requests your transaction history from a single server. The returned history is then checked against blockchain headers sent by other nodes, using Simple Payment Verification (SPV).")
       -            font_size: '6pt'
       -        Widget:
       -            size_hint: 1, 0.8
       -        GridLayout:
       -            cols: 3
       -            Label:
       -                height: '36dp'
       -                size_hint_x: 1
       -                size_hint_y: None
       -                text: _('Host') + ':'
       -            TextInput:
       -                id: host
       -                multiline: False
       -                height: '36dp'
       -                size_hint_x: 3
       -                size_hint_y: None
       -                text: ''
       -                disabled: auto_connect.active
       -            Button:
       -                id: chooser
       -                text:'v'
       -                height: '36dp'
       -                size_hint_x: 0.5
       -                size_hint_y: None
       -                disabled: auto_connect.active
       -            Label:
       -                height: '36dp'
       -                size_hint_x: 1
       -                size_hint_y: None
       -                text: _('Port') + ':'
       -            TextInput:
       -                id: port
       -                multiline: False
       -                input_type: 'number'
       -                height: '36dp'
       -                size_hint_x: 3
       -                size_hint_y: None
       -                text: ''
       -                disabled: auto_connect.active
       -        Widget:
       -            size_hint: 1, 0.1
       -        TopLabel:
       -            text: _("If auto-connect is checked, your history server will be selected automatically.")
       -            font_size: '6pt'
       -        BoxLayout:
       -            Label:
       -                text: _('Auto-connect')
       -            CheckBox:
       -                id: auto_connect
       -                size_hint_y: None
       -        Widget:
       -            size_hint: 1, 0.1
       -        BoxLayout:
       -            Widget:
       -                size_hint: 0.5, None
       -            Button:
       -                size_hint: 0.5, None
       -                height: '48dp'
       -                text: _('OK')
       -                on_release:
       -                    nd.dismiss()
       +        ScrollView:
       +            GridLayout:
       +                id: scrollviewlayout
       +                cols:1
       +                size_hint: 1, None
       +                height: self.minimum_height
       +                padding: '10dp'
       +                SettingsItem:
       +                    value: _("%d connections.")% app.num_nodes if app.num_nodes else _("Not connected")
       +                    title: _("Status") + ': ' + self.value
       +                    description: _("Connections with Electrum servers")
       +                    action: lambda x: x
       +
       +                CardSeparator
       +                SettingsItem:
       +                    title: _("Server") + ': ' + app.server_host
       +                    description: _("Server used to request your history.")
       +                    action: lambda x: app.popup_dialog('server')
       +
       +                CardSeparator
       +                SettingsItem:
       +                    title: _("Auto-connect") + ': ' + ('ON' if app.auto_connect else 'OFF')
       +                    description: _("Find a server automatically")
       +                    action: app.toggle_auto_connect
       +
       +                CardSeparator
       +                SettingsItem:
       +                    value: "%d blocks" % app.num_blocks
       +                    title: _("Blockchain") + ': ' + self.value
       +                    description: _("Verified block headers.")
       +                    action: lambda x: x
       +
       +                CardSeparator
       +                SettingsItem:
       +                    title: _("Checkpoint") + ': ' + app.blockchain_status()
       +                    description: app.blockchain_info()
       +                    action: app.choose_blockchain_dialog
       +
       +                CardSeparator
       +                SettingsItem:
       +                    proxy: app.proxy_config.get('mode')
       +                    host: app.proxy_config.get('host')
       +                    port: app.proxy_config.get('port')
       +                    title: _("Proxy") + ': ' + ((self.host +':' + self.port) if self.proxy else _('None'))
       +                    description: _('Proxy configuration')
       +                    action: lambda x: app.popup_dialog('proxy')
       +
       +
   DIR diff --git a/gui/kivy/uix/ui_screens/proxy.kv b/gui/kivy/uix/ui_screens/proxy.kv
       t@@ -13,8 +13,8 @@ Popup:
                        id: mode
                        height: '48dp'
                        size_hint_y: None
       -                text: ''
       -                values: ['None', 'socks4', 'socks5', 'http']
       +                text: app.proxy_config.get('mode', 'none')
       +                values: ['none', 'socks4', 'socks5', 'http']
                    Label:
                        text: _('Host')
                    TextInput:
       t@@ -22,8 +22,8 @@ Popup:
                        multiline: False
                        height: '48dp'
                        size_hint_y: None
       -                text: ''
       -                disabled: mode.text == 'None'
       +                text: app.proxy_config.get('host', '')
       +                disabled: mode.text == 'none'
                    Label:
                        text: _('Port')
                    TextInput:
       t@@ -32,8 +32,8 @@ Popup:
                        input_type: 'number'
                        height: '48dp'
                        size_hint_y: None
       -                text: ''
       -                disabled: mode.text == 'None'
       +                text: app.proxy_config.get('port', '')
       +                disabled: mode.text == 'none'
                    Label:
                        text: _('Username')
                    TextInput:
       t@@ -41,8 +41,8 @@ Popup:
                        multiline: False
                        height: '48dp'
                        size_hint_y: None
       -                text: ''
       -                disabled: mode.text == 'None'
       +                text: app.proxy_config.get('user', '')
       +                disabled: mode.text == 'none'
                    Label:
                        text: _('Password')
                    TextInput:
       t@@ -51,8 +51,8 @@ Popup:
                        password: True
                        height: '48dp'
                        size_hint_y: None
       -                text: ''
       -                disabled: mode.text == 'None'
       +                text: app.proxy_config.get('password', '')
       +                disabled: mode.text == 'none'
                Widget:
                    size_hint: 1, 0.1
                BoxLayout:
       t@@ -63,4 +63,14 @@ Popup:
                        height: '48dp'
                        text: _('OK')
                        on_release:
       +                    host, port, protocol, proxy, auto_connect = app.network.get_parameters()
       +                    proxy = {}
       +                    proxy['mode']=str(root.ids.mode.text).lower()
       +                    proxy['host']=str(root.ids.host.text)
       +                    proxy['port']=str(root.ids.port.text)
       +                    proxy['user']=str(root.ids.user.text)
       +                    proxy['password']=str(root.ids.password.text)
       +                    if proxy['mode']=='none': proxy = None
       +                    app.network.set_parameters(host, port, protocol, proxy, auto_connect)
       +                    app.proxy_config = proxy if proxy else {}
                            nd.dismiss()
   DIR diff --git a/gui/kivy/uix/ui_screens/server.kv b/gui/kivy/uix/ui_screens/server.kv
       t@@ -0,0 +1,63 @@
       +Popup:
       +    id: nd
       +    title: _('Server')
       +    BoxLayout:
       +        orientation: 'vertical'
       +        padding: '10dp'
       +        spacing: '10dp'
       +        TopLabel:
       +            text: _("Electrum requests your transaction history from a single server. The returned history is checked against blockchain headers sent by other nodes, using Simple Payment Verification (SPV).")
       +            font_size: '6pt'
       +        Widget:
       +            size_hint: 1, 0.8
       +        GridLayout:
       +            cols: 2
       +            Label:
       +                height: '36dp'
       +                size_hint_x: 1
       +                size_hint_y: None
       +                text: _('Host') + ':'
       +            TextInput:
       +                id: host
       +                multiline: False
       +                height: '36dp'
       +                size_hint_x: 3
       +                size_hint_y: None
       +                text: app.server_host
       +            Label:
       +                height: '36dp'
       +                size_hint_x: 1
       +                size_hint_y: None
       +                text: _('Port') + ':'
       +            TextInput:
       +                id: port
       +                multiline: False
       +                input_type: 'number'
       +                height: '36dp'
       +                size_hint_x: 3
       +                size_hint_y: None
       +                text: app.server_port
       +            Widget
       +            Button:
       +                id: chooser
       +                text: _('Choose from peers')
       +                height: '36dp'
       +                size_hint_x: 0.5
       +                size_hint_y: None
       +                on_release:
       +                    app.choose_server_dialog(root)
       +        Widget:
       +            size_hint: 1, 0.1
       +        BoxLayout:
       +            Widget:
       +                size_hint: 0.5, None
       +            Button:
       +                size_hint: 0.5, None
       +                height: '48dp'
       +                text: _('OK')
       +                on_release:
       +                    host, port, protocol, proxy, auto_connect = app.network.get_parameters()
       +                    host = str(root.ids.host.text)
       +                    port = str(root.ids.port.text)
       +                    app.network.set_parameters(host, port, protocol, proxy, auto_connect)
       +                    nd.dismiss()
   DIR diff --git a/gui/qt/network_dialog.py b/gui/qt/network_dialog.py
       t@@ -393,10 +393,6 @@ class NetworkChoiceLayout(object):
        
            def follow_branch(self, index):
                self.network.follow_chain(index)
       -        server = self.network.interface.server
       -        host, port, protocol, proxy, auto_connect = self.network.get_parameters()
       -        host, port, protocol = server.split(':')
       -        self.network.set_parameters(host, port, protocol, proxy, auto_connect)
                self.update()
        
            def follow_server(self, server):
   DIR diff --git a/lib/network.py b/lib/network.py
       t@@ -1040,6 +1040,13 @@ class Network(util.DaemonThread):
                else:
                    raise BaseException('blockchain not found', index)
        
       +        if self.interface:
       +            server = self.interface.server
       +            host, port, protocol, proxy, auto_connect = self.get_parameters()
       +            host, port, protocol = server.split(':')
       +            self.set_parameters(host, port, protocol, proxy, auto_connect)
       +
       +
            def get_local_height(self):
                return self.blockchain().height()