add switch-gui button for qt
[electrum-nvc.git] / lib / gui_qt.py
index 6286624..1c364af 100644 (file)
@@ -137,11 +137,14 @@ class StatusBarButton(QPushButton):
 
 class QRCodeWidget(QWidget):
 
-    def __init__(self):
+    def __init__(self, data = None):
         QWidget.__init__(self)
         self.setMinimumSize(210, 210)
         self.addr = None
         self.qr = None
+        if data:
+            self.set_addr(data)
+            self.update_qr()
 
     def set_addr(self, addr):
         if self.addr != addr:
@@ -163,7 +166,6 @@ class QRCodeWidget(QWidget):
 
         black = QColor(0, 0, 0, 255)
         white = QColor(255, 255, 255, 255)
-        boxsize = 6
 
         if not self.qr:
             qp = QtGui.QPainter()
@@ -173,11 +175,16 @@ class QRCodeWidget(QWidget):
             qp.drawRect(0, 0, 198, 198)
             qp.end()
             return
-        
-        size = self.qr.getModuleCount()*boxsize
         k = self.qr.getModuleCount()
         qp = QtGui.QPainter()
         qp.begin(self)
+        r = qp.viewport()
+        boxsize = min(r.width(), r.height())*0.8/k
+        size = k*boxsize
+        left = (r.width() - size)/2
+        top = (r.height() - size)/2         
+
         for r in range(k):
             for c in range(k):
                 if self.qr.isDark(r, c):
@@ -186,7 +193,7 @@ class QRCodeWidget(QWidget):
                 else:
                     qp.setBrush(white)
                     qp.setPen(white)
-                qp.drawRect(c*boxsize, r*boxsize, boxsize, boxsize)
+                qp.drawRect(left+c*boxsize, top+r*boxsize, boxsize, boxsize)
         qp.end()
         
 
@@ -205,13 +212,11 @@ class QR_Window(QWidget):
         main_box = QHBoxLayout()
         
         self.qrw = QRCodeWidget()
-        main_box.addWidget(self.qrw)
+        main_box.addWidget(self.qrw, 1)
 
         vbox = QVBoxLayout()
         main_box.addLayout(vbox)
 
-        main_box.addStretch(1)
-
         self.address_label = QLabel("")
         self.address_label.setFont(QFont(MONOSPACE_FONT))
         vbox.addWidget(self.address_label)
@@ -223,12 +228,8 @@ class QR_Window(QWidget):
         vbox.addWidget(self.amount_label)
 
         vbox.addStretch(1)
-
         self.setLayout(main_box)
 
-    def do_save(self):
-        self.filename = "qrcode.bmp"
-        bmp.save_qrcode(self.qrw.qr, self.filename)
 
     def set_content(self, addr, label, amount):
         self.address = addr
@@ -293,6 +294,7 @@ class ElectrumWindow(QMainWindow):
 
     def __init__(self, wallet, config):
         QMainWindow.__init__(self)
+        self.lite = None
         self.wallet = wallet
         self.config = config
         self.wallet.interface.register_callback('updated', self.update_callback)
@@ -309,8 +311,7 @@ class ElectrumWindow(QMainWindow):
 
         self.tabs = tabs = QTabWidget(self)
         tabs.addTab(self.create_history_tab(), _('History') )
-        if self.wallet.seed:
-            tabs.addTab(self.create_send_tab(), _('Send') )
+        tabs.addTab(self.create_send_tab(), _('Send') )
         tabs.addTab(self.create_receive_tab(), _('Receive') )
         tabs.addTab(self.create_contacts_tab(), _('Contacts') )
         tabs.addTab(self.create_wall_tab(), _('Wall') )
@@ -348,9 +349,8 @@ class ElectrumWindow(QMainWindow):
             self.qr_window = None
 
     def connect_slots(self, sender):
-        if self.wallet.seed:
-            self.connect(sender, QtCore.SIGNAL('timersignal'), self.timer_actions)
-            self.previous_payto_e=''
+        self.connect(sender, QtCore.SIGNAL('timersignal'), self.timer_actions)
+        self.previous_payto_e=''
 
     def timer_actions(self):
         if self.qr_window:
@@ -602,6 +602,8 @@ class ElectrumWindow(QMainWindow):
             item.setFont(2, QFont(MONOSPACE_FONT))
             item.setFont(3, QFont(MONOSPACE_FONT))
             item.setFont(4, QFont(MONOSPACE_FONT))
+            if value < 0:
+                item.setForeground(3, QBrush(QColor("#BC1E1E")))
             if tx_hash:
                 item.setToolTip(0, tx_hash)
             if is_default_label:
@@ -708,6 +710,7 @@ class ElectrumWindow(QMainWindow):
                 self.funds_error = True
             self.amount_e.setPalette(palette)
             self.fee_e.setPalette(palette)
+            self.update_wallet()
 
         self.amount_e.textChanged.connect(lambda: entry_changed(False) )
         self.fee_e.textChanged.connect(lambda: entry_changed(True) )
@@ -769,21 +772,27 @@ class ElectrumWindow(QMainWindow):
             password = None
 
         try:
-            tx = self.wallet.mktx( to_address, amount, label, password, fee)
+            tx = self.wallet.mktx( [(to_address, amount)], label, password, fee)
         except BaseException, e:
             self.show_message(str(e))
             return
-            
-        h = self.wallet.send_tx(tx)
-        waiting_dialog(lambda: False if self.wallet.tx_event.isSet() else _("Please wait..."))
-        status, msg = self.wallet.receive_tx( h )
 
-        if status:
-            QMessageBox.information(self, '', _('Payment sent.')+'\n'+msg, _('OK'))
-            self.do_clear()
-            self.update_contacts_tab()
+        if self.wallet.seed:
+            h = self.wallet.send_tx(tx)
+            waiting_dialog(lambda: False if self.wallet.tx_event.isSet() else _("Please wait..."))
+            status, msg = self.wallet.receive_tx( h )
+            if status:
+                QMessageBox.information(self, '', _('Payment sent.')+'\n'+msg, _('OK'))
+                self.do_clear()
+                self.update_contacts_tab()
+            else:
+                QMessageBox.warning(self, _('Error'), msg, _('OK'))
         else:
-            QMessageBox.warning(self, _('Error'), msg, _('OK'))
+            filename = 'unsigned_tx'
+            f = open(filename,'w')
+            f.write(tx)
+            f.close()
+            QMessageBox.information(self, _('Unsigned transaction'), _("Unsigned transaction was saved to file:") + " " +filename, _('OK'))
 
 
     def set_url(self, url):
@@ -874,20 +883,10 @@ class ElectrumWindow(QMainWindow):
         self.connect(l, SIGNAL('currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)'), lambda a,b: self.recv_changed(a))
         self.receive_list = l
         self.receive_buttons_hbox = hbox
-        view_combo = QComboBox()
-        view_combo.addItems([_('Simple View'), _('Detailed View'), _('Point of Sale')])
-        view_combo.setCurrentIndex(self.receive_tab_mode)
-        hbox.addWidget(view_combo)
-        view_combo.currentIndexChanged.connect(self.receive_tab_set_mode)
         hbox.addStretch(1)
         return w
 
 
-    def print_qr(self):
-        if self.qr_window:
-            self.qr_window.do_save()
-            self.show_message(_("QR code saved to file") + " " + self.qr_window.filename)
-
 
     def receive_tab_set_mode(self, i):
         self.receive_tab_mode = i
@@ -922,14 +921,16 @@ class ElectrumWindow(QMainWindow):
         menu.addAction(_("Copy to clipboard"), lambda: self.app.clipboard().setText(addr))
         if self.receive_tab_mode == 2:
             menu.addAction(_("Request amount"), lambda: self.edit_amount())
-            menu.addAction(_("Print QR"), self.print_qr)
+        menu.addAction(_("View QR"), lambda: ElectrumWindow.show_qrcode("Address","bitcoin:"+addr) )
         menu.addAction(_("Edit label"), lambda: self.edit_label(True))
         menu.addAction(_("Sign message"), lambda: self.sign_message(addr))
 
-        t = _("Unfreeze") if addr in self.wallet.frozen_addresses else _("Freeze")
-        menu.addAction(t, lambda: self.toggle_freeze(addr))
-        t = _("Unprioritize") if addr in self.wallet.prioritized_addresses else _("Prioritize")
-        menu.addAction(t, lambda: self.toggle_priority(addr))
+        if self.receive_tab_mode == 1:
+            t = _("Unfreeze") if addr in self.wallet.frozen_addresses else _("Freeze")
+            menu.addAction(t, lambda: self.toggle_freeze(addr))
+            t = _("Unprioritize") if addr in self.wallet.prioritized_addresses else _("Prioritize")
+            menu.addAction(t, lambda: self.toggle_priority(addr))
+            
         menu.exec_(self.receive_list.viewport().mapToGlobal(position))
 
 
@@ -972,7 +973,7 @@ class ElectrumWindow(QMainWindow):
         menu = QMenu()
         menu.addAction(_("Copy to Clipboard"), lambda: self.app.clipboard().setText(addr))
         menu.addAction(_("Pay to"), lambda: self.payto(x, is_alias))
-        menu.addAction(_("View QR code"),lambda: self.show_address_qrcode(addr))
+        menu.addAction(_("View QR code"),lambda: self.show_qrcode("Address","bitcoin:"+addr))
         if not is_alias:
             menu.addAction(_("Edit label"), lambda: self.edit_label(False))
         else:
@@ -998,10 +999,11 @@ class ElectrumWindow(QMainWindow):
         balance = format_satoshis( c + u, False, self.wallet.num_zeros )
         item.setData(4,0,balance)
 
-        if address in self.wallet.frozen_addresses: 
-            item.setBackgroundColor(1, QColor('lightblue'))
-        elif address in self.wallet.prioritized_addresses: 
-            item.setBackgroundColor(1, QColor('lightgreen'))
+        if self.receive_tab_mode == 1:
+            if address in self.wallet.frozen_addresses: 
+                item.setBackgroundColor(1, QColor('lightblue'))
+            elif address in self.wallet.prioritized_addresses: 
+                item.setBackgroundColor(1, QColor('lightgreen'))
         
 
     def update_receive_tab(self):
@@ -1107,6 +1109,9 @@ class ElectrumWindow(QMainWindow):
     def create_status_bar(self):
         sb = QStatusBar()
         sb.setFixedHeight(35)
+        qtVersion = qVersion()
+        if (int(qtVersion[0]) >= 4 and int(qtVersion[2]) >= 7):
+            sb.addPermanentWidget( StatusBarButton( QIcon(":icons/switchgui.png"), "Switch to Lite Mode", self.go_lite ) )
         if self.wallet.seed:
             sb.addPermanentWidget( StatusBarButton( QIcon(":icons/lock.png"), "Password", lambda: self.change_password_dialog(self.wallet, self) ) )
         sb.addPermanentWidget( StatusBarButton( QIcon(":icons/preferences.png"), "Preferences", self.settings_dialog ) )
@@ -1115,6 +1120,15 @@ class ElectrumWindow(QMainWindow):
         self.status_button = StatusBarButton( QIcon(":icons/status_disconnected.png"), "Network", lambda: self.network_dialog(self.wallet, self) ) 
         sb.addPermanentWidget( self.status_button )
         self.setStatusBar(sb)
+        
+    def go_lite(self):
+        import gui_lite
+        self.hide()
+        if self.lite:
+            self.lite.mini.show()
+        else:
+            self.lite = gui_lite.ElectrumGui(self.wallet, self.config, self)
+            self.lite.main(None)
 
     def new_contact_dialog(self):
         text, ok = QInputDialog.getText(self, _('New Contact'), _('Address') + ':')
@@ -1176,7 +1190,7 @@ class ElectrumWindow(QMainWindow):
         copy_button = QPushButton(_("Copy to Clipboard"))
         copy_button.clicked.connect(copy_function)
 
-        show_qr_function = lambda: ElectrumWindow.show_seed_qrcode(seed)
+        show_qr_function = lambda: ElectrumWindow.show_qrcode(_("Seed"), seed)
         qr_button = QPushButton(_("View as QR Code"))
         qr_button.clicked.connect(show_qr_function)
 
@@ -1195,17 +1209,29 @@ class ElectrumWindow(QMainWindow):
         dialog.exec_()
 
     @staticmethod
-    def show_seed_qrcode(seed):
-        if not seed: return
+    def show_qrcode(title, data):
+        if not data: return
         d = QDialog(None)
         d.setModal(1)
-        d.setWindowTitle(_("Seed"))
+        d.setWindowTitle(title)
         d.setMinimumSize(270, 300)
         vbox = QVBoxLayout()
-        vbox.addWidget(QRCodeWidget(seed))
+        qrw = QRCodeWidget(data)
+        vbox.addWidget(qrw, 1)
+        vbox.addWidget(QLabel(data), 0, Qt.AlignHCenter)
         hbox = QHBoxLayout()
         hbox.addStretch(1)
-        b = QPushButton(_("OK"))
+
+        def print_qr(self):
+            filename = "qrcode.bmp"
+            bmp.save_qrcode(qrw.qr, filename)
+            QMessageBox.information(None, _('Message'), _("QR code saved to file") + " " + filename, _('OK'))
+
+        b = QPushButton(_("Print"))
+        hbox.addWidget(b)
+        b.clicked.connect(print_qr)
+
+        b = QPushButton(_("Close"))
         hbox.addWidget(b)
         b.clicked.connect(d.accept)
 
@@ -1246,7 +1272,7 @@ class ElectrumWindow(QMainWindow):
                 password = None
 
             try:
-                signature = self.wallet.sign_message(sign_address.text(), sign_message.toPlainText(), password)
+                signature = self.wallet.sign_message(sign_address.text(), str(sign_message.toPlainText()), password)
                 sign_signature.setText(signature)
             except BaseException, e:
                 self.show_message(str(e))
@@ -1280,7 +1306,7 @@ class ElectrumWindow(QMainWindow):
 
         def do_verify():
             try:
-                self.wallet.verify_message(verify_address.text(), verify_signature.text(), verify_message.toPlainText())
+                self.wallet.verify_message(verify_address.text(), verify_signature.text(), str(verify_message.toPlainText()))
                 self.show_message("Signature verified")
             except BaseException, e:
                 self.show_message(str(e))
@@ -1418,7 +1444,7 @@ class ElectrumWindow(QMainWindow):
 
         if new_password != new_password2:
             QMessageBox.warning(parent, _('Error'), _('Passwords do not match'), _('OK'))
-            return
+            return ElectrumWindow.change_password_dialog(wallet, parent) # Retry
 
         wallet.update_password(seed, password, new_password)
 
@@ -1479,55 +1505,61 @@ class ElectrumWindow(QMainWindow):
 
     def settings_dialog(self):
         d = QDialog(self)
+        d.setWindowTitle(_('Electrum Settings'))
         d.setModal(1)
         vbox = QVBoxLayout()
-        msg = _('Here are the settings of your wallet.') + '\n'\
-              + _('For more explanations, click on the help buttons next to each field.')
 
-        label = QLabel(msg)
-        label.setFixedWidth(250)
-        label.setWordWrap(True)
-        label.setAlignment(Qt.AlignJustify)
-        vbox.addWidget(label)
+        tabs = QTabWidget(self)
+        vbox.addWidget(tabs)
 
-        grid = QGridLayout()
-        grid.setSpacing(8)
-        vbox.addLayout(grid)
+        tab = QWidget()
+        grid_wallet = QGridLayout(tab)
+        grid_wallet.setColumnStretch(0,1)
+        tabs.addTab(tab, _('Wallet') )
+        
+        tab2 = QWidget()
+        grid_ui = QGridLayout(tab2)
+        grid_ui.setColumnStretch(0,1)
+        tabs.addTab(tab2, _('Display') )
 
         fee_label = QLabel(_('Transaction fee'))
-        grid.addWidget(fee_label, 2, 0)
+        grid_wallet.addWidget(fee_label, 2, 0)
         fee_e = QLineEdit()
         fee_e.setText("%s"% str( Decimal( self.wallet.fee)/100000000 ) )
-        grid.addWidget(fee_e, 2, 1)
+        grid_wallet.addWidget(fee_e, 2, 1)
         msg = _('Fee per transaction input. Transactions involving multiple inputs tend to require a higher fee.') + ' ' \
             + _('Recommended value') + ': 0.001'
-        grid.addWidget(HelpButton(msg), 2, 2)
+        grid_wallet.addWidget(HelpButton(msg), 2, 2)
         fee_e.textChanged.connect(lambda: numbify(fee_e,False))
         if not self.config.is_modifiable('fee'):
             for w in [fee_e, fee_label]: w.setEnabled(False)
 
         nz_label = QLabel(_('Display zeros'))
-        grid.addWidget(nz_label, 3, 0)
+        grid_ui.addWidget(nz_label, 3, 0)
         nz_e = QLineEdit()
         nz_e.setText("%d"% self.wallet.num_zeros)
-        grid.addWidget(nz_e, 3, 1)
+        grid_ui.addWidget(nz_e, 3, 1)
         msg = _('Number of zeros displayed after the decimal point. For example, if this is set to 2, "1." will be displayed as "1.00"')
-        grid.addWidget(HelpButton(msg), 3, 2)
+        grid_ui.addWidget(HelpButton(msg), 3, 2)
         nz_e.textChanged.connect(lambda: numbify(nz_e,True))
         if not self.config.is_modifiable('num_zeros'):
             for w in [nz_e, nz_label]: w.setEnabled(False)
 
-        usechange_cb = QCheckBox(_('Use change addresses'))
-        grid.addWidget(usechange_cb, 5, 0)
-        usechange_cb.setChecked(self.wallet.use_change)
-        grid.addWidget(HelpButton(_('Using change addresses makes it more difficult for other people to track your transactions. ')), 5, 2)
-        if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False)
+
+        usechange_label = QLabel(_('Use change addresses'))
+        grid_wallet.addWidget(usechange_label, 5, 0)
+        usechange_combo = QComboBox()
+        usechange_combo.addItems(['Yes', 'No'])
+        usechange_combo.setCurrentIndex(not self.wallet.use_change)
+        grid_wallet.addWidget(usechange_combo, 5, 1)
+        grid_wallet.addWidget(HelpButton(_('Using change addresses makes it more difficult for other people to track your transactions. ')), 5, 2)
+        if not self.config.is_modifiable('use_change'): usechange_combo.setEnabled(False)
 
         gap_label = QLabel(_('Gap limit'))
-        grid.addWidget(gap_label, 6, 0)
+        grid_wallet.addWidget(gap_label, 6, 0)
         gap_e = QLineEdit()
         gap_e.setText("%d"% self.wallet.gap_limit)
-        grid.addWidget(gap_e, 6, 1)
+        grid_wallet.addWidget(gap_e, 6, 1)
         msg =  _('The gap limit is the maximal number of contiguous unused addresses in your sequence of receiving addresses.') + '\n' \
               + _('You may increase it if you need more receiving addresses.') + '\n\n' \
               + _('Your current gap limit is') + ': %d'%self.wallet.gap_limit + '\n' \
@@ -1535,23 +1567,56 @@ class ElectrumWindow(QMainWindow):
               + _('Warning') + ': ' \
               + _('The gap limit parameter must be provided in order to recover your wallet from seed.') + ' ' \
               + _('Do not modify it if you do not understand what you are doing, or if you expect to recover your wallet without knowing it!') + '\n\n' 
-        grid.addWidget(HelpButton(msg), 6, 2)
+        grid_wallet.addWidget(HelpButton(msg), 6, 2)
         gap_e.textChanged.connect(lambda: numbify(nz_e,True))
         if not self.config.is_modifiable('gap_limit'):
             for w in [gap_e, gap_label]: w.setEnabled(False)
         
         gui_label=QLabel(_('Default GUI') + ':')
-        grid.addWidget(gui_label , 7, 0)
+        grid_ui.addWidget(gui_label , 7, 0)
         gui_combo = QComboBox()
         gui_combo.addItems(['Lite', 'Classic', 'Gtk', 'Text'])
         index = gui_combo.findText(self.config.get("gui","classic").capitalize())
         if index==-1: index = 1
         gui_combo.setCurrentIndex(index)
-        grid.addWidget(gui_combo, 7, 1)
-        grid.addWidget(HelpButton(_('Select which GUI mode to use at start up. ')), 7, 2)
+        grid_ui.addWidget(gui_combo, 7, 1)
+        grid_ui.addWidget(HelpButton(_('Select which GUI mode to use at start up. ')), 7, 2)
         if not self.config.is_modifiable('gui'):
             for w in [gui_combo, gui_label]: w.setEnabled(False)
 
+        lang_label=QLabel(_('Language') + ':')
+        grid_ui.addWidget(lang_label , 8, 0)
+        lang_combo = QComboBox()
+        languages = {'':_('Default'), 'br':_('Brasilian'), 'cs':_('Czech'), 'de':_('German'),
+                     'eo':_('Esperanto'), 'en':_('English'), 'es':_('Spanish'), 'fr':_('French'),
+                     'it':_('Italian'), 'lv':_('Latvian'), 'nl':_('Dutch'), 'ru':_('Russian'),
+                     'sl':_('Slovenian'), 'vi':_('Vietnamese'), 'zh':_('Chinese')
+                     }
+        lang_combo.addItems(languages.values())
+        try:
+            index = languages.keys().index(self.config.get("language",''))
+        except:
+            index = 0
+        lang_combo.setCurrentIndex(index)
+        grid_ui.addWidget(lang_combo, 8, 1)
+        grid_ui.addWidget(HelpButton(_('Select which language is used in the GUI (after restart). ')), 8, 2)
+        if not self.config.is_modifiable('language'):
+            for w in [lang_combo, lang_label]: w.setEnabled(False)
+
+
+        view_label=QLabel(_('Receive Tab') + ':')
+        grid_ui.addWidget(view_label , 9, 0)
+        view_combo = QComboBox()
+        view_combo.addItems([_('Simple'), _('Advanced'), _('Point of Sale')])
+        view_combo.setCurrentIndex(self.receive_tab_mode)
+        grid_ui.addWidget(view_combo, 9, 1)
+        hh = _('This selects the interaction mode of the "Receive" tab. ') + '\n\n' \
+             + _('Simple') +   ': ' + _('Show only addresses and labels.') + '\n\n' \
+             + _('Advanced') + ': ' + _('Show address balances and add extra menu items to freeze/prioritize addresses.') + '\n\n' \
+             + _('Point of Sale') + ': ' + _('Show QR code window and amounts requested for each address. Add menu item to request amount.') + '\n\n' 
+        
+        grid_ui.addWidget(HelpButton(hh), 9, 2)
+        
         vbox.addLayout(ok_cancel_buttons(d))
         d.setLayout(vbox) 
 
@@ -1583,8 +1648,9 @@ class ElectrumWindow(QMainWindow):
             self.update_history_tab()
             self.update_receive_tab()
 
-        if self.wallet.use_change != usechange_cb.isChecked():
-            self.wallet.use_change = usechange_cb.isChecked()
+        usechange_result = usechange_combo.currentIndex() == 0
+        if self.wallet.use_change != usechange_result:
+            self.wallet.use_change = usechange_result
             self.config.set_key('use_change', self.wallet.use_change, True)
         
         try:
@@ -1600,9 +1666,23 @@ class ElectrumWindow(QMainWindow):
                 self.config.set_key('gap_limit', self.wallet.gap_limit, True)
             else:
                 QMessageBox.warning(self, _('Error'), _('Invalid value'), _('OK'))
-                    
-        self.config.set_key("gui", str(gui_combo.currentText()).lower(), True)
 
+        need_restart = False
+
+        gui_request = str(gui_combo.currentText()).lower()
+        if gui_request != self.config.get('gui'):
+            self.config.set_key('gui', gui_request, True)
+            need_restart = True
+            
+        lang_request = languages.keys()[lang_combo.currentIndex()]
+        if lang_request != self.config.get('language'):
+            self.config.set_key("language", lang_request, True)
+            need_restart = True
+
+        if need_restart:
+            QMessageBox.warning(self, _('Success'), _('Please restart Electrum to activate the new GUI settings'), _('OK'))
+
+        self.receive_tab_set_mode(view_combo.currentIndex())
 
 
     @staticmethod 
@@ -1679,7 +1759,7 @@ class ElectrumWindow(QMainWindow):
         servers_list_widget.setMaximumHeight(150)
         servers_list_widget.setColumnWidth(0, 240)
         for _host in servers_list.keys():
-            _type = 'pruning' if servers_list[_host].get('pruning') else 'full'
+            _type = 'P' if servers_list[_host].get('pruning') else 'F'
             servers_list_widget.addTopLevelItem(QTreeWidgetItem( [ _host, _type ] ))
 
         def change_server(host, protocol=None):
@@ -1720,6 +1800,12 @@ class ElectrumWindow(QMainWindow):
         if not wallet.config.is_modifiable('server'):
             for w in [server_host, server_port, server_protocol, servers_list_widget]: w.setEnabled(False)
 
+        # auto cycle
+        autocycle_cb = QCheckBox('Try random servers if disconnected')
+        autocycle_cb.setChecked(wallet.config.get('auto_cycle', False))
+        grid.addWidget(autocycle_cb, 3, 1, 3, 2)
+        if not wallet.config.is_modifiable('auto_cycle'): autocycle_cb.setEnabled(False)
+
         # proxy setting
         proxy_mode = QComboBox()
         proxy_host = QLineEdit()
@@ -1767,7 +1853,7 @@ class ElectrumWindow(QMainWindow):
         wallet.config.set_key("proxy", proxy, True)
         wallet.config.set_key("server", server, True)
         interface.set_server(server, proxy)
-                
+        wallet.config.set_key('auto_cycle', autocycle_cb.isChecked(), True)
         return True
 
     def closeEvent(self, event):